diff --git a/tools/dwf-validator-cli/.gitignore b/tools/dwf-validator-cli/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/tools/dwf-validator-cli/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/tools/dwf-validator-cli/build.gradle b/tools/dwf-validator-cli/build.gradle new file mode 100644 index 0000000..c6c9bd2 --- /dev/null +++ b/tools/dwf-validator-cli/build.gradle @@ -0,0 +1,33 @@ +plugins { + id("org.jetbrains.kotlin.jvm") + id("application") +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'commons-cli:commons-cli:1.5.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + implementation project(':dwf-validator') + testImplementation 'junit:junit:4.13.2' +} + +application { + mainClass = 'com.google.wear.watchface.validator.cli.AppKt' +} + +jar { + duplicatesStrategy(DuplicatesStrategy.EXCLUDE) + + from { + configurations.runtimeClasspath.collect { + it.isDirectory() ? it : zipTree(it) + } + } + + manifest { + attributes 'Main-Class': application.mainClass + } +} diff --git a/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/App.kt b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/App.kt new file mode 100644 index 0000000..63d4e18 --- /dev/null +++ b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/App.kt @@ -0,0 +1,100 @@ +package com.google.wear.watchface.validator.cli + +import com.google.wear.watchface.validator.JvmWatchFaceDocument +import com.google.wear.watchface.validator.WatchFaceValidator +import com.google.wear.watchface.validator.XmlReader +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.specification.WFF_SPECIFICATION +import java.nio.file.NoSuchFileException +import java.util.zip.ZipFile +import kotlin.system.exitProcess + +internal const val FAILURE = 1 +internal const val SUCCESS = 0 + +/** + * Command line application which validates .xml files in the res/raw/ directory of a specified .apk + * file. + * + * The .apk file should be passed as the first argument to the application. If the raw watch face + * xml file fails validation then the application will exit with exit code 1. + */ +fun main(args: Array) { + Settings.parseFromArguments(args)?.let { App.run(it) } +} + +object App { + /** + * Runs the validator on a specified .apk file. The validator is invoked on the xml file in + * res/raw/ and the results are printed to stderr. + * + * @param settings The settings parsed from the command line arguments. + */ + fun run(settings: Settings) { + val validationResult = + if (settings.rawXml) { + validateRawXml(settings.sourcePath) + } else { + validateApk(settings.sourcePath) + } + + exitProcess(if (validationResult is ValidationResult.Failure) FAILURE else SUCCESS) + } + + fun validateApk(apkPath: String): ValidationResult { + val zipFile = ZipFile(apkPath) + val entries = zipFile.entries() + + while (entries.hasMoreElements()) { + val entry = entries.nextElement() + if (entry.name.startsWith("res/raw/") && entry.name.endsWith(".xml")) { + val document = + JvmWatchFaceDocument.of( + XmlReader.readFromInputStream(zipFile.getInputStream(entry)) + ) + val validationResult = + WatchFaceValidator(WFF_SPECIFICATION).getValidationResult(document) + + printValidationReport(zipFile.name, validationResult) + return validationResult + } + } + + throw NoSuchFileException("No XML file found in res/raw/ in ${zipFile.name}") + } + + fun validateRawXml(xmlPath: String): ValidationResult { + val document = JvmWatchFaceDocument.of(XmlReader.fromFilePath(xmlPath)) + val validator = WatchFaceValidator(WFF_SPECIFICATION) + val validationResult = validator.getValidationResult(document) + + printValidationReport(xmlPath, validationResult) + return validationResult + } + + private fun printValidationReport(fileName: String, validationResult: ValidationResult) { + val messageBuilder = StringBuilder() + + when (validationResult) { + is ValidationResult.Success -> + messageBuilder.appendLine("Validation Succeeded for file: $fileName.") + + is ValidationResult.PartialSuccess -> + messageBuilder + .appendLine( + "Validation Succeeded for file: $fileName with some invalid versions." + ) + .appendLine( + "Valid for versions: ${validationResult.validVersions.joinToString(", ")}.\n" + ) + .appendLine(ValidationFailureMessage(validationResult.errorMap)) + + is ValidationResult.Failure -> + messageBuilder + .appendLine("Validation Failed for file: $fileName.\n") + .appendLine(ValidationFailureMessage(validationResult.errorMap)) + } + + System.err.println(messageBuilder.toString()) + } +} diff --git a/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/Settings.kt b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/Settings.kt new file mode 100644 index 0000000..7b63bf0 --- /dev/null +++ b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/Settings.kt @@ -0,0 +1,43 @@ +package com.google.wear.watchface.validator.cli + +import org.apache.commons.cli.DefaultParser +import org.apache.commons.cli.HelpFormatter +import org.apache.commons.cli.Option +import org.apache.commons.cli.Options +import org.apache.commons.cli.ParseException + +class Settings(val sourcePath: String, val rawXml: Boolean = false) { + companion object { + val cliInvokeCommand = "java -jar dwf-validator-cli.jar" + + fun parseFromArguments(arguments: Array): Settings? { + val sourcePathOption = + Option.builder() + .longOpt("source") + .desc("Path to the watch face package to be validated.") + .hasArg() + .required() + .build() + + val rawXmlOption = + Option.builder("x") + .longOpt("raw-xml") + .desc("Flag to indicate the source is a raw xml file rather than an apk.") + .build() + + val options = Options() + options.addOption(sourcePathOption) + options.addOption(rawXmlOption) + + val parser = DefaultParser() + try { + val line = parser.parse(options, arguments) + return Settings(line.getOptionValue(sourcePathOption), line.hasOption(rawXmlOption)) + } catch (e: ParseException) { + println("Error: " + e.localizedMessage) + HelpFormatter().printHelp(cliInvokeCommand, options, true) + return null + } + } + } +} diff --git a/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/ValidationFailureMessage.kt b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/ValidationFailureMessage.kt new file mode 100644 index 0000000..b9cddaf --- /dev/null +++ b/tools/dwf-validator-cli/src/main/java/com/google/wear/watchface/validator/cli/ValidationFailureMessage.kt @@ -0,0 +1,113 @@ +package com.google.wear.watchface.validator.cli + +import com.google.wear.watchface.validator.error.AttributeValueError +import com.google.wear.watchface.validator.error.ContentError +import com.google.wear.watchface.validator.error.ErrorMap +import com.google.wear.watchface.validator.error.ExpressionSyntaxError +import com.google.wear.watchface.validator.error.ExpressionVersionEliminationError +import com.google.wear.watchface.validator.error.IllegalAttributeError +import com.google.wear.watchface.validator.error.IllegalTagError +import com.google.wear.watchface.validator.error.RequiredConditionFailedError +import com.google.wear.watchface.validator.error.TagOccurrenceError +import com.google.wear.watchface.validator.error.UnknownError +import com.google.wear.watchface.validator.error.ValidationError +import com.google.wear.watchface.validator.error.VersionEliminationError + +internal const val GLOBAL_ERROR_KEY = 0 +internal const val BULLET = " - " +internal const val INDENT = " " + +/** + * Class for formatting validation failure messages. + * + * @param errorMap The map of errors to format. + */ +class ValidationFailureMessage(private val errorMap: ErrorMap) { + private val stringBuilder = StringBuilder() + + override fun toString(): String { + errorMap.forEach { (key, errors) -> + stringBuilder.appendLine( + if (key == GLOBAL_ERROR_KEY) "Global Errors:\n" else "Error: Version $key Failed:\n" + ) + + val pathMap = errors.groupBy(ValidationError::elementPath) + + pathMap.forEach { (elementPath, validationErrors) -> + stringBuilder + .appendLine("${elementPath.joinToString(" > ")}:") + .appendErrors(validationErrors) + } + } + return stringBuilder.toString() + } + + private fun StringBuilder.appendErrors(errors: List) = + errors.forEach { error: ValidationError -> + when (error) { + is IllegalTagError -> this.appendLine(BULLET + "Illegal Tag: \"${error.tagName}\"") + + is RequiredConditionFailedError -> + this.appendLine(BULLET + "Requirement Failed:") + .appendLine(wrapErrorMessage(error.conditionMessage)) + + is ExpressionSyntaxError -> + this.appendLine(BULLET + "Expression syntax error:") + .appendLine(wrapErrorMessage(error.errorMessage)) + + is ExpressionVersionEliminationError -> + this.appendLine(BULLET + "Version Eliminated:") + .appendLine( + wrapErrorMessage( + "\"${error.expressionResource}\" is exclusive to versions: " + + error.permittedVersions.joinToString(", ") + ) + ) + + is VersionEliminationError -> + this.appendLine(BULLET + "Version Eliminated:") + .appendLine( + wrapErrorMessage( + "Condition: \"${error.conditionMessage}\" passed which is exclusive to versions: " + + error.permittedVersions.joinToString(", ") + ) + ) + + is IllegalAttributeError -> + this.appendLine(BULLET + "Illegal Attribute: \"${error.attributeName}\"") + + is ContentError -> + this.appendLine(BULLET + "Illegal Content:") + .appendLine(wrapErrorMessage(error.errorMessage)) + + is AttributeValueError -> + this.appendLine(BULLET + "Illegal Attribute Value:") + .appendLine( + wrapErrorMessage( + "Attribute: \"${error.attributeName}\" has illegal value: \"${error.attributeValue}\"." + ) + ) + .appendLine(wrapErrorMessage(error.errorMessage)) + + is TagOccurrenceError -> + this.appendLine(BULLET + "Illegal Tag Occurrence:") + .appendLine( + wrapErrorMessage( + "Tag: \"${error.tagName}\" occurs ${error.actualCount} times, but must occur between ${error.expectedRange} times." + ) + ) + + is UnknownError -> + this.appendLine(BULLET + "Unknown error:") + .appendLine(wrapErrorMessage("\"${error.errorMessage}\"")) + } + } + + /** Helper function for spreading long error messages across multiple lines */ + private fun wrapErrorMessage(message: String, wordsPerLine: Int = 15): String { + val words = message.split(" ") + return words.chunked(wordsPerLine).joinToString("") { wordList -> + INDENT + wordList.joinToString(" ") + "\n" + } + } +} diff --git a/tools/dwf-validator-cli/src/test/java/com/google/wear/watchface/validator/cli/WatchFaceValidatorSampleTest.kt b/tools/dwf-validator-cli/src/test/java/com/google/wear/watchface/validator/cli/WatchFaceValidatorSampleTest.kt new file mode 100644 index 0000000..db6d6f2 --- /dev/null +++ b/tools/dwf-validator-cli/src/test/java/com/google/wear/watchface/validator/cli/WatchFaceValidatorSampleTest.kt @@ -0,0 +1,86 @@ +package com.google.wear.watchface.validator.cli + +import com.google.wear.watchface.validator.error.ValidationResult +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.Path +import java.util.stream.Collectors +import javax.xml.parsers.DocumentBuilderFactory +import javax.xml.xpath.XPathConstants +import javax.xml.xpath.XPathFactory +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.w3c.dom.Document + +internal const val DEFAULT_FORMAT_VERSION = "1" +internal const val MAX_WFF_VERSION = 4 +internal const val DWF_SAMPLES = "../samples" + +@RunWith(Parameterized::class) +class WatchFaceValidatorSampleTest(val expectedVersions: Set, val filePath: String) { + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "{index}: \"{1}\" = \"{0}\"") + fun testCases(): List> = findAllSamplesWatchfaceXml() + + private fun findAllSamplesWatchfaceXml(): List> { + val samplesDir = Path.of(DWF_SAMPLES) + Files.walk(samplesDir).use { allFilesInSamples -> + val watchfaceXmlMatcher = + FileSystems.getDefault().getPathMatcher("glob:**/res/raw/watchface*.xml") + + return allFilesInSamples + .filter { watchfaceXmlMatcher.matches(it) } + .map { path -> + val associatedManifestPath = + path.resolve("../../../AndroidManifest.xml").normalize() + val minVersion = getDwfVersionFromManifest(associatedManifestPath) + val expectedVersions = (minVersion..MAX_WFF_VERSION).toSet() + + arrayOf(expectedVersions, path.toAbsolutePath().normalize().toString()) + } + .collect(Collectors.toList()) + } + } + + private fun getDwfVersionFromManifest(manifestPath: Path): Int { + var version: String = DEFAULT_FORMAT_VERSION + if (Files.exists(manifestPath)) { + val manifest: Document? = + DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(manifestPath.toFile()) + + val dwfVersionXPath = + XPathFactory.newInstance() + .newXPath() + .compile( + "//property[@name='com.google.wear.watchface.format.version']/@value" + ) + + val formatVersionOption = + dwfVersionXPath.evaluate(manifest, XPathConstants.STRING) as String? + if (!formatVersionOption.isNullOrEmpty()) { + version = formatVersionOption + } + } + + return version.toInt() + } + } + + @Test + fun test() { + val result = App.validateRawXml(filePath) + assertTrue(result !is ValidationResult.Failure) + /* Each expected version must have passed. However it is possible for a versioned dwf to be naturally backwards compatible.*/ + assertTrue( + "Versions did not match. Expected: $expectedVersions, Found: ${result.validVersions}", + result.validVersions.containsAll(expectedVersions), + ) + } +} diff --git a/tools/dwf-validator/build.gradle.kts b/tools/dwf-validator/build.gradle.kts new file mode 100644 index 0000000..883fce2 --- /dev/null +++ b/tools/dwf-validator/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { kotlin("multiplatform") } + +kotlin { + jvm { testRuns["test"].executionTask.configure { useJUnit() } } + js { + nodejs { testTask { useKarma { useChromeHeadless() } } } + binaries.executable() + } + + sourceSets { + val commonTest by getting { dependencies { implementation(kotlin("test")) } } + val jsTest by getting { dependencies { implementation(kotlin("test")) } } + } +} + +tasks.register("test") { + // dependsOn(":dwf-validator:jsTest") + dependsOn(":dwf-validator:jvmTest") +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/Constants.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/Constants.kt new file mode 100644 index 0000000..45451eb --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/Constants.kt @@ -0,0 +1,6 @@ +package com.google.wear.watchface.validator + +internal const val MIN_WFF_VERSION = 1 +internal const val MAX_WFF_VERSION = 4 +internal val ALL_WFF_VERSIONS = (MIN_WFF_VERSION..MAX_WFF_VERSION).toSet() +internal const val DEFAULT_CONDITION_MESSAGE = "Condition check failed." diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceDocument.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceDocument.kt new file mode 100644 index 0000000..f08334c --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceDocument.kt @@ -0,0 +1,10 @@ +package com.google.wear.watchface.validator + +/** + * An interface for a Declarative Watchface XML Document. + * + * @property rootElement the root node of the XML element tree. + */ +interface WatchFaceDocument { + val rootElement: WatchFaceElement +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElement.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElement.kt new file mode 100644 index 0000000..e593353 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElement.kt @@ -0,0 +1,15 @@ +package com.google.wear.watchface.validator + +/** + * A data class for storing an abstract XML element. + * + * @property tagName the elements name. + * @property attributes key value pairs stored in the element's tag. + * @property children a list of immediately nested elements. + */ +data class WatchFaceElement( + val tagName: String, + val attributes: Map, + val children: List, + val textContent: String = "", +) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElementContext.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElementContext.kt new file mode 100644 index 0000000..c06287b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceElementContext.kt @@ -0,0 +1,42 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.constraint.AttributeConstraint +import com.google.wear.watchface.validator.constraint.ChildConstraint +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.ContentConstraint + +typealias ConstraintPointer = () -> Constraint + +typealias AttributeConstraintMap = MutableMap + +typealias ChildConstraintMap = MutableMap + +typealias ContentConstraintList = MutableList + +/** + * A data class for keeping track of relevant information about previously visited nodes when + * traversing the element tree. + * + * @property scope a map of attributes which have been declared inside parent tags. + * @property elementPath a list of tag names representing the path to the current element. + * @property expressionAttributes a list of attribute names in the current element which contain + * expressions. + * @property permittedAttributes a mutable list of attribute names that are allowed for the + * current element. + * @property permittedChildElements a mutable list of pairs of tag names and their associated + * constraints that are allowed as children of the current element. + * @property expressionContentCheck a flag indicating whether the text content of the current + * element should be checked for expressions. + */ +data class WatchFaceElementContext( + val scope: Map, + val elementPath: List, + val attributeConstraintMap: AttributeConstraintMap = mutableMapOf(), + val childConstraintMap: ChildConstraintMap = mutableMapOf(), + val contentConstraints: ContentConstraintList = mutableListOf(), +) { + companion object { + fun emptyContext(): WatchFaceElementContext = + WatchFaceElementContext(emptyMap(), emptyList()) + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceValidator.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceValidator.kt new file mode 100644 index 0000000..e8a2587 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/WatchFaceValidator.kt @@ -0,0 +1,117 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.constraint.AttributeConstraint +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.error.IllegalAttributeError +import com.google.wear.watchface.validator.error.IllegalTagError +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.error.combineWith +import com.google.wear.watchface.validator.specification.WatchFaceSpecification + +/** Type aliases */ +typealias Version = Int + +typealias Tag = String + +/** + * Validator for a declarative watchface as a [[WatchFaceDocument]] which applies a set of custom + * constraints. + * + * @param specification the watch face format . + */ +class WatchFaceValidator(private val specification: WatchFaceSpecification) { + + /** + * Validates a declarative watch face document against the constraints defined in the + * constraints map. It returns a set of versions for which the document is valid. + * + * @param document the declarative watch face document to validate. + * @return a set of valid versions for which the document is valid. + */ + fun findValidVersions(document: WatchFaceDocument): Set = + getValidationResult( + document.rootElement, + specification.constraintTree, + WatchFaceElementContext.emptyContext(), + ) + .validVersions intersect specification.targetVersions + + /** + * Validates a declarative watch face document against the constraints defined in the + * constraints map. It returns a [[ValidationResult]] containing the versions for which the + * document is valid and any errors encountered during validation. + * + * @param document the declarative watch face document to validate. + * @return the result of the validation. + */ + fun getValidationResult(document: WatchFaceDocument): ValidationResult = + getValidationResult( + document.rootElement, + specification.constraintTree, + WatchFaceElementContext.emptyContext(), + ) + + /** + * Validates a watch face element against the constraints defined in the constraints map. It + * recursively traverses the element tree and returns the intersection of valid versions from + * each node. + * + * @param element the current element node to validate. + * @param ctx the current context containing the scope, element path, and version range. + */ + private fun getValidationResult( + element: WatchFaceElement, + constraint: Constraint, + ctx: WatchFaceElementContext, + ): ValidationResult { + + val newCtx = + WatchFaceElementContext( + ctx.scope + element.attributes, + ctx.elementPath + element.tagName, + ) + + /* validating the element against the constraint. + Also queues up further validation (for attributes, children and content) in the context. */ + var result: ValidationResult = constraint.check(element, newCtx) + + /* validate attributes */ + for (attr in element.attributes.keys) { + if (attr in newCtx.attributeConstraintMap) { + val attributeConstraint: AttributeConstraint = newCtx.attributeConstraintMap[attr]!! + + result = result combineWith attributeConstraint.check(element, newCtx) + } else { + /* return a failure if an unrecognised attribute is found. */ + result = ValidationResult.Failure(IllegalAttributeError(attr, newCtx.elementPath)) + } + } + + /* validate content */ + for (contentConstraint in newCtx.contentConstraints) { + result = result combineWith contentConstraint.check(element, newCtx) + } + + /* validate child elements */ + for (child in element.children) { + if (result.validVersions.isEmpty()) break + + /* The child must be declared in the constraint and have an associated sub-constraint */ + if (newCtx.childConstraintMap.contains(child.tagName)) { + val childConstraint = newCtx.childConstraintMap[child.tagName]!! + val nextConstraint = childConstraint.getConstraintTree() + + /* apply constraint to this element (usually an occurrence range check). */ + result = result combineWith childConstraint.check(element, newCtx) + + /* recurse to validate the child element itself. */ + result = result combineWith getValidationResult(child, nextConstraint, newCtx) + } else { + result = + ValidationResult.Failure(IllegalTagError(child.tagName, newCtx.elementPath)) + } + } + + return result + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/Constraint.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/Constraint.kt new file mode 100644 index 0000000..96d8ada --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/Constraint.kt @@ -0,0 +1,281 @@ +package com.google.wear.watchface.validator.constraint + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.Version +import com.google.wear.watchface.validator.WatchFaceElement +import com.google.wear.watchface.validator.WatchFaceElementContext +import com.google.wear.watchface.validator.constraint.condition.Condition +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.condition.ExpressionCondition +import com.google.wear.watchface.validator.constraint.condition.ValueCondition +import com.google.wear.watchface.validator.error.AttributeValueError +import com.google.wear.watchface.validator.error.ContentError +import com.google.wear.watchface.validator.error.RequiredConditionFailedError +import com.google.wear.watchface.validator.error.TagOccurrenceError +import com.google.wear.watchface.validator.error.UnknownError +import com.google.wear.watchface.validator.error.ValidationError +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.error.VersionEliminationError +import com.google.wear.watchface.validator.error.combineWith +import com.google.wear.watchface.validator.expression.ExpressionParser +import kotlin.collections.minus + +/** Interface for constraints that can be applied to watch face elements. */ +sealed interface Constraint { + /** + * Checks if the given watch face element satisfies the constraint. Returns the set of versions + * that are still valid after this constraint has been evaluated + * + * @param element The watch face element to check against the constraint. + * @param context The context in which the watch face element is being evaluated. + */ + fun check(element: WatchFaceElement, context: WatchFaceElementContext): ValidationResult +} + +/** + * A composite constraint that checks if two constraints are satisfied. It returns the intersection + * of the version sets returned by both constraints. This is useful for combining multiple + * constraints that must all be satisfied for a watch face. + * + * @property c1 The first constraint to check. + * @property c2 The second constraint to check. + */ +data class And(val c1: Constraint, val c2: Constraint) : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + return c1.check(element, context) combineWith c2.check(element, context) + } +} + +/** + * A constraint that requires specific conditions to be satisfied for a watch face to be valid for + * certain versions. If any of the conditions fail, the watch face is invalid for the specified + * versions; otherwise, it is valid for all versions. + * + * @property conditions The list of conditions that must be satisfied. + * @property versions The set of versions for which this constraint applies if all conditions are + * met. + */ +data class RequiredConstraint( + private val conditions: List, + val versions: VersionSet, +) : Constraint { + + /** + * Checks if all conditions are satisfied for the watch face element. If all conditions are + * satisfied, it returns all versions; otherwise, it returns all other versions except the + * specified versions. + */ + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + var newVersions: VersionSet = ALL_WFF_VERSIONS + val errors: MutableMap> = mutableMapOf() + for (condition in conditions) { + if (!condition.check(element, context)) { + versions.forEach { v: Version -> + errors + .getOrPut(v) { mutableListOf() } + .add( + RequiredConditionFailedError( + condition.errorMessage, + context.elementPath, + ) + ) + } + newVersions = ALL_WFF_VERSIONS - versions + } + } + return ValidationResult.of(newVersions, errors) + } +} + +/** + * A constraint that allows specific conditions to be satisfied for a watch face to be valid for + * certain versions. If any of the conditions are satisfied, the watch face is valid for the + * specified versions; otherwise, it defaults to all versions. + * + * @property conditions The list of conditions that can allow the watch face to be valid. + * @property versions The set of versions for which this constraint applies if any condition is met. + */ +data class AllowedConstraint( + private val conditions: List, + val versions: VersionSet, +) : Constraint { + + /** + * Checks if any of the conditions are satisfied for the watch face element. If any condition is + * satisfied, it returns the specified versions; otherwise, it returns all versions. + */ + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + var newVersions: VersionSet = ALL_WFF_VERSIONS + val errors: MutableMap> = mutableMapOf() + for (condition in conditions) { + if (condition.check(element, context)) { + (ALL_WFF_VERSIONS - versions).forEach { v: Version -> + errors + .getOrPut(v) { mutableListOf() } + .add( + VersionEliminationError( + condition.errorMessage, + versions, + context.elementPath, + ) + ) + } + newVersions = versions + } + } + + return ValidationResult.of(newVersions, errors) + } +} + +/** + * A constraint that checks if a specific attribute of a watch face element satisfies a given + * condition. If the attribute is not present, the constraint is considered satisfied by default. + * + * @property attributeName The name of the attribute to check. + * @property condition The condition to check against the attribute's value. + */ +data class AttributeConstraint(val attributeName: String, val condition: Condition) : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + + /* Ignore the condition if the attribute is not found. */ + val attributeValue = element.attributes[attributeName] ?: return ValidationResult.Success + + when (condition) { + is ExpressionCondition -> { + return ExpressionParser.getValidationResult(attributeValue, context) + } + + is ElementCondition -> { + /* Check the condition against the node and context. */ + if (!condition.check(element, context)) { + return ValidationResult.Failure( + AttributeValueError( + attributeName, + attributeValue, + condition.errorMessage, + context.elementPath, + ) + ) + } + } + + is ValueCondition -> { + /* Check the condition against the attributes value. */ + if (!condition.check(attributeValue)) { + return ValidationResult.Failure( + AttributeValueError( + attributeName, + attributeValue, + condition.errorMessage, + context.elementPath, + ) + ) + } + } + } + + return ValidationResult.Success + } +} + +/** + * A constraint that checks if the content (text) of a watch face element satisfies a given + * condition. + * + * @property condition The condition to check against the attribute's value. + */ +data class ContentConstraint(val condition: Condition) : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + val content = element.textContent + when (condition) { + is ExpressionCondition -> { + return ExpressionParser.getValidationResult(content, context) + } + + is ElementCondition -> { + /* Check the condition against the node and context. */ + if (!condition.check(element, context)) { + return ValidationResult.Failure( + ContentError(content, condition.errorMessage, context.elementPath) + ) + } + } + + is ValueCondition -> { + /* Check the condition against the attributes value. */ + if (!condition.check(element.textContent)) { + return ValidationResult.Failure( + ContentError(content, condition.errorMessage, context.elementPath) + ) + } + } + } + + return ValidationResult.Success + } +} + +/** + * A constraint that checks if the occurrences of a specific child element within a watch face + * element fall within a specified range. It also provides a way to retrieve the constraint tree for + * the child element. + * + * @param tagName The name of the child element to check. + * @param getConstraintTree A function that returns the constraint tree for the child element. + * @param occurrenceRange The range of valid occurrences for the child element (inclusive). + */ +data class ChildConstraint( + val tagName: String, + val getConstraintTree: () -> Constraint, + private val occurrenceRange: IntRange, +) : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + val occurrences = element.children.count { it.tagName == tagName } + if (occurrences !in occurrenceRange) { + return ValidationResult.Failure( + TagOccurrenceError(tagName, occurrences, occurrenceRange, context.elementPath) + ) + } else { + return ValidationResult.Success + } + } +} + +/** A utility constraint that always returns ALL_WFF_VERSIONS. */ +object PassAllVersions : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + return ValidationResult.Success + } +} + +/** A utility constraint that always fails, returning the empty set. */ +object FailAllVersions : Constraint { + override fun check( + element: WatchFaceElement, + context: WatchFaceElementContext, + ): ValidationResult { + return ValidationResult.Failure(UnknownError("Instantiated by FailAllVersions.check()")) + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilder.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilder.kt new file mode 100644 index 0000000..fff3986 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilder.kt @@ -0,0 +1,143 @@ +package com.google.wear.watchface.validator.constraint + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.Tag +import com.google.wear.watchface.validator.Version +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ConditionScope +import com.google.wear.watchface.validator.constraint.condition.ElementCondition + +typealias VersionSet = Set + +/** + * A DSL builder for constructing a complex [Constraint] from a set of version-specific rules. + * + * Within the builder's scope, you can define validation rules declaratively. The typical pattern + * is: + * 1. Define a set of watch face format (WFF) versions using [versions] or [versions]. + * 2. Chain a call to [require] or [allow] on the resulting [VersionSet]. + * 3. Pass the necessary conditions (e.g., + * [com.google.wear.watchface.validator.constraint.condition.ConditionScope.hasChild], + * [com.google.wear.watchface.validator.constraint.condition.ConditionScope.attributeIsIn]) to + * these methods. + * + * This class implements [com.google.wear.watchface.validator.constraint.condition.ConditionScope] + * by delegation, making all standard condition factories directly available within the builder's + * lambda. + * + * ### Example + * + * ```kotlin + * val constraint = constraint("MyElement") { + * versions(1, 2, 3).require( + * attribute("width", integer()) + * attribute("height", integer()) + * + * childElement("ChildElement". ::childElement), + * ) + * ``` + */ +class ConstraintBuilder(private val tagName: Tag) : ConditionScope by ConditionLibrary { + /** + * List of constraints that will be combined to form the final [Constraint]. Starts with a base + * case that passes all versions. + */ + private val constraintList = mutableListOf(PassAllVersions) + + /** + * Represents all WFF versions. This is a convenience function that returns a set of all + * versions that the constraint applies to. + */ + fun allVersions(): VersionSet = ALL_WFF_VERSIONS + + /** Represents a set of WFF versions for the constraint builder DSL. */ + fun versions(versions: Set): VersionSet = versions + + /** Represents a set of WFF versions for the constraint builder DSL. */ + fun versions(vararg versions: Int): VersionSet = versions.toSet() + + /** + * Convenience function for creating a set of versions that this constraint applies to. Takes in + * a pair which can be written as `Pair(1, 4)` or `1 to 4`, the latter being more readable. + * + * @param versionRange the versions for which the constraint is active. + */ + fun versions(versionRange: Pair): VersionSet = + (versionRange.first..versionRange.second).toSet() + + /** + * Represents a list of conditions that 'must' be satisfied for the watch face to be valid for + * the specified versions. This method creates a constraint based on the set of versions it is + * called on together with the conditions passed in. + * + * @param conditions the conditions that must be satisfied for the constraint to pass. + * @return the set of versions for which the constraint is for (for chaining constraints to + * avoid duplication). + * @receiver the set of versions for which the constraint is for. + */ + fun VersionSet.require(vararg conditions: ElementCondition): VersionSet { + constraintList.add(RequiredConstraint(conditions.toList(), this)) + return this + } + + /** + * Represents a list of conditions that are permitted in the specified versions. If these + * conditions are satisfied, then the watch can only be valid for the versions which 'allow' + * this behaviour. This method adds a constraint based on the set of versions it is called on + * together with the conditions passed in. + * + * @param conditions the permitted conditions for the specified versions. + * @return the set of versions for which the constraint is for (for chaining constraints to + * * avoid duplication). + * + * @receiver the set of versions for which the constraint is for. + */ + fun VersionSet.allow(vararg conditions: ElementCondition): VersionSet { + constraintList.add(AllowedConstraint(conditions.toList(), this)) + return this + } + + /** Adds an empty constraint that restricts the versions for which an element is valid. */ + fun exclusiveToVersions(vararg versions: Int) { + exclusiveToVersions(versions.toSet()) + } + + /** Adds an empty constraint that restricts the versions for which an element is valid. */ + fun exclusiveToVersions(versions: Set) { + constraintList.add( + AllowedConstraint( + listOf(condition(alwaysPass(), "Exclusive to versions: $versions")), + versions, + ) + ) + } + + /** Creates a composite constraint that combines all the constraints added to the builder. */ + fun build(): Constraint { + constraintList.add( + RequiredConstraint( + listOf( + ElementCondition( + "Expected tag: $tagName", + { node, _ -> node.tagName == tagName }, + ) + ), + ALL_WFF_VERSIONS, + ) + ) + return constraintList.reduce { acc, nextRule -> And(acc, nextRule) } + } +} + +/** + * Creates a [Constraint] using the [ConstraintBuilder] DSL. + * + * This function is the primary entry point for declaratively building a complex `Constraint`. See + * [ConstraintBuilder] for a detailed explanation and examples of the available DSL methods. + * + * @param block A lambda with [ConstraintBuilder] as its receiver, where you define the validation + * rules. + * @return The final, composite [Constraint] that combines all defined rules. + */ +fun constraint(tagName: Tag, block: ConstraintBuilder.() -> Unit): Constraint = + ConstraintBuilder(tagName).apply(block).build() diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/Condition.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/Condition.kt new file mode 100644 index 0000000..0901905 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/Condition.kt @@ -0,0 +1,43 @@ +package com.google.wear.watchface.validator.constraint.condition + +import com.google.wear.watchface.validator.DEFAULT_CONDITION_MESSAGE +import com.google.wear.watchface.validator.WatchFaceElement + +sealed interface Condition + +/** + * Data class representing a condition that can be checked against a + * [com.google.wear.watchface.validator.WatchFaceElement] with a given context. A Constraint also + * contains a message that can be used to report errors if the condition fails. + * + * @property errorMessage The error message to report if the condition check fails. + * @property check A function that takes an element (node) and a context, which evaluates the logic + * of the condition. + */ +data class ValueCondition( + val errorMessage: String = DEFAULT_CONDITION_MESSAGE, + val check: ValueConditionFunction, +) : Condition + +/** + * Data class representing a condition that can be checked against a [WatchFaceElement] with a given + * context. A Constraint also contains a message that can be used to report errors if the condition + * fails. + * + * @property errorMessage The error message to report if the condition check fails. + * @property check A function that takes an element (node) and a context, which evaluates the logic + * of the condition. + */ +data class ElementCondition( + val errorMessage: String = DEFAULT_CONDITION_MESSAGE, + val check: ElementConditionFunction, +) : Condition + +/** + * Data class representing an expression condition. Expressions are validated by the + * [[com.google.wear.watchface.validator.expression.ExpressionParser]] which is invoked by the + * constraint. + * + * @property errorMessage The error message to report if the condition check fails. + */ +data class ExpressionCondition(val errorMessage: String = DEFAULT_CONDITION_MESSAGE) : Condition diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ConditionLibrary.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ConditionLibrary.kt new file mode 100644 index 0000000..fc48ba2 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ConditionLibrary.kt @@ -0,0 +1,175 @@ +package com.google.wear.watchface.validator.constraint.condition + +import com.google.wear.watchface.validator.constraint.AttributeConstraint +import com.google.wear.watchface.validator.constraint.ChildConstraint +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.ContentConstraint + +/** + * A scope that combines [ElementConditions] and [ValueConditions] to provide a unified interface + * for accessing both types of conditions. + */ +interface ConditionScope : ElementConditions, ValueConditions { + + /** + * Declare that this element can have between minOccurs and maxOccurs children with the given + * tagName. + */ + fun childElement( + tagName: String, + constraintTree: () -> Constraint, + minOccurs: Int = 1, + maxOccurs: Int = Int.MAX_VALUE, + errorMessage: String = "Child element: $tagName.", + ): ElementCondition + + /** + * This condition declares the attribute as permitted, and associates it with the given + * condition which is delegated to the validator via context. The condition also asserts that + * the attribute is present. + */ + fun attribute( + name: String, + conditionFunction: ValueConditionFunction, + errorMessage: String = "Attribute: $name.", + default: String? = null, + ): ElementCondition + + /** + * This condition declares the attribute as permitted, and associates it with the given + * condition which is delegated to the validator via context. The condition also asserts that + * the attribute is present. + */ + fun attribute( + name: String, + condition: Condition = alwaysPass(), + errorMessage: String = "Attribute: $name.", + default: String? = null, + ): ElementCondition + + /** + * Declare that the content of this element must satisfy the given condition. This validation is + * added to the context to be invoked by the validator later. + */ + fun content( + condition: Condition, + errorMessage: String = "Content does not meet condition.", + ): ElementCondition + + /** Wrap an existing ElementCondition, optionally overriding its error message. */ + fun condition(elementCondition: ElementCondition, errorMessage: String?): ElementCondition + + /** Create a new ElementCondition from a condition function and error message. */ + fun condition( + conditionFunction: ElementConditionFunction, + errorMessage: String, + ): ElementCondition + + /** + * A choice condition where between minOccurs and maxOccurs of the given conditions must hold. + */ + fun choice( + vararg conditions: ElementCondition, + minOccurs: Int = 1, + maxOccurs: Int = 1, + errorMessage: String = + "Between $minOccurs and $maxOccurs of the given conditions must be satisfied.", + ): ElementCondition +} + +object ConditionLibrary : + ConditionScope, + ElementConditions by ElementConditionLibrary, + ValueConditions by ValueConditionLibrary { + + override fun childElement( + tagName: String, + constraintTree: () -> Constraint, + minOccurs: Int, + maxOccurs: Int, + errorMessage: String, + ) = + ElementCondition( + errorMessage, + { node, ctx -> + /* declare this child element as a permitted child with its associated constraint */ + ctx.childConstraintMap[tagName] = + ChildConstraint(tagName, constraintTree, minOccurs..maxOccurs) + + /* assert that there are between min and max children with this name */ + node.children.any { it.tagName == tagName } + }, + ) + + override fun attribute( + name: String, + conditionFunction: ValueConditionFunction, + errorMessage: String, + default: String?, + ) = + ElementCondition( + errorMessage, + { node, ctx -> + /* Declare the attribute as permitted by adding it to the attributeConstraintMap in + the context along with its associated constraint. */ + val attributeConstraint = + AttributeConstraint(name, ValueCondition(errorMessage, conditionFunction)) + ctx.attributeConstraintMap[name] = attributeConstraint + + /* assert that the attribute is present */ + node.attributes.containsKey(name) + }, + ) + + override fun attribute( + name: String, + condition: Condition, + errorMessage: String, + default: String?, + ) = + ElementCondition( + errorMessage, + { node, ctx -> + /* Declare the attribute as permitted by adding it to the attributeConstraintMap in + the context along with its associated constraint. */ + val attributeConstraint = AttributeConstraint(name, condition) + ctx.attributeConstraintMap[name] = attributeConstraint + + /* assert that the attribute is present */ + node.attributes.containsKey(name) + }, + ) + + override fun content(condition: Condition, errorMessage: String) = + ElementCondition( + errorMessage, + { node, ctx -> + /* delegate the content condition to the validator via context. + This ensures that every content condition is checked.*/ + ctx.contentConstraints.add(ContentConstraint(condition)) + + /* assert that the content is non-empty */ + node.textContent.isNotEmpty() + }, + ) + + override fun condition(elementCondition: ElementCondition, errorMessage: String?) = + ElementCondition(errorMessage ?: elementCondition.errorMessage, elementCondition.check) + + override fun condition(conditionFunction: ElementConditionFunction, errorMessage: String) = + ElementCondition(errorMessage, conditionFunction) + + override fun choice( + vararg conditions: ElementCondition, + minOccurs: Int, + maxOccurs: Int, + errorMessage: String, + ): ElementCondition = + ElementCondition( + errorMessage, + { node, ctx -> + val count = conditions.count { it.check(node, ctx) } + count in minOccurs..maxOccurs + }, + ) +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ElementConditionLibrary.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ElementConditionLibrary.kt new file mode 100644 index 0000000..aed00db --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ElementConditionLibrary.kt @@ -0,0 +1,120 @@ +package com.google.wear.watchface.validator.constraint.condition + +import com.google.wear.watchface.validator.WatchFaceElement +import com.google.wear.watchface.validator.WatchFaceElementContext + +typealias ElementConditionFunction = (WatchFaceElement, WatchFaceElementContext) -> Boolean + +interface ElementConditions { + + /** Condition that checks if an element has a child with the specified tag name. */ + fun hasChild(tagName: String): ElementCondition + + /** Condition that checks if an element has a specific number of children. */ + fun hasNumberOfChildren(num: Int): ElementCondition + + /** Condition that checks if a node has a nonempty child list */ + fun hasAtLeastOneChild(): ElementCondition + + /** Condition that checks if a given attribute is unique across all child elements */ + fun childrenHaveUniqueAttribute(attribute: String): ElementCondition + + /** Condition that checks a given attribute value against a custom condition function */ + fun checkAttribute( + attribute: String, + valueConditionFunction: ValueConditionFunction, + errorMessage: String = "Attribute $attribute must satisfy condition", + default: String? = null, + ): ElementCondition + + /** Condition that checks a given attribute value against a value condition */ + fun checkAttribute( + attribute: String, + valueCondition: ValueCondition, + default: String? = null, + ): ElementCondition + + /** Checks a 'then' condition only if the 'if' condition is met */ + fun ifThen(`if`: ElementCondition, then: ElementCondition) = + ElementCondition( + errorMessage = "If (${`if`.errorMessage}) passes, then apply constraint (${then.errorMessage})", + check = { node, ctx -> !`if`.check(node, ctx) || then.check(node, ctx) }, + ) + + /** Combines two conditions with a logical OR */ + infix fun ElementCondition.or(other: ElementCondition) = + ElementCondition( + errorMessage = "(${this.errorMessage}) OR (${other.errorMessage})", + check = { node, ctx -> this.check(node, ctx) || other.check(node, ctx) }, + ) + + /** Combines two conditions with a logical AND */ + infix fun ElementCondition.and(other: ElementCondition) = + ElementCondition( + errorMessage = "(${this.errorMessage}) AND (${other.errorMessage})", + check = { node, ctx -> this.check(node, ctx) && other.check(node, ctx) }, + ) + + /** Condition that always passes */ + fun alwaysPass() = ElementCondition("", { _, _ -> true }) + + /** Condition that always fails */ + fun alwaysFail() = ElementCondition("WARNING: Configured to always fail.", { _, _ -> false }) +} + +object ElementConditionLibrary : ElementConditions { + + override fun hasChild(tagName: String) = + ElementCondition( + "Must have child element with tag name $tagName.", + { node, _ -> node.children.any { it.tagName == tagName } }, + ) + + override fun hasNumberOfChildren(num: Int) = + ElementCondition( + "Must have exactly $num child elements.", + { node, _ -> node.children.size == num }, + ) + + override fun hasAtLeastOneChild() = + ElementCondition( + "Must have at least one child element.", + { node, _ -> node.children.isNotEmpty() }, + ) + + override fun childrenHaveUniqueAttribute(attribute: String) = + ElementCondition( + "Each child must have a unique value for: $attribute.", + { node, _ -> + val names = node.children.mapNotNull { it.attributes[attribute] } + names.toSet().size == names.size + }, + ) + + override fun checkAttribute( + attribute: String, + valueConditionFunction: ValueConditionFunction, + errorMessage: String, + default: String?, + ) = + ElementCondition( + errorMessage, + { node, _ -> + val attrValue = node.attributes[attribute] ?: default + attrValue?.let(valueConditionFunction) ?: true + }, + ) + + override fun checkAttribute( + attribute: String, + valueCondition: ValueCondition, + default: String?, + ) = + ElementCondition( + valueCondition.errorMessage, + { node, _ -> + val attrValue = node.attributes[attribute] ?: default + attrValue?.let(valueCondition.check) ?: true + }, + ) +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ValueConditionLibrary.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ValueConditionLibrary.kt new file mode 100644 index 0000000..a3246c7 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/constraint/condition/ValueConditionLibrary.kt @@ -0,0 +1,204 @@ +package com.google.wear.watchface.validator.constraint.condition + +typealias ValueConditionFunction = (String) -> Boolean + +interface ValueConditions { + /** Condition asserting that an attribute is 'equal' to a given value. */ + fun equals(expectedValue: String): ValueCondition + + /** Condition asserting that an attribute is an integer. */ + fun integer(): ValueCondition + + /** Condition asserting that an attribute is an integer within a given range. */ + fun integer(min: Int = Int.MIN_VALUE, max: Int = Int.MAX_VALUE): ValueCondition + + /** Condition asserting that an attribute is a float. */ + fun float(): ValueCondition + + /** Condition asserting that an attribute is a float within a given range. */ + fun float( + min: Float = Float.NEGATIVE_INFINITY, + max: Float = Float.POSITIVE_INFINITY, + ): ValueCondition + + /** Condition asserting that an attribute is a color in #AARRGGBB or #RRGGBB format. */ + fun color(): ValueCondition + + /** Condition asserting that an attribute is a time in HH:MM:SS format. */ + fun time(): ValueCondition + + /** Condition asserting that an attribute is non-empty. */ + fun nonEmpty(): ValueCondition + + /** Condition asserting that an attribute is a string of length n. */ + fun stringOfLength(n: Int): ValueCondition + + /** Condition asserting that an attribute is a vector of n floats. */ + fun floatVector(n: Int): ValueCondition + + /** Condition asserting that an attribute is a vector of floats of any length. */ + fun floatVector(): ValueCondition + + /** Condition asserting that an attribute is a vector of colors of any length. */ + fun argbVector(): ValueCondition + + /** Condition asserting that an attribute is a vector of colors with a maximum length. */ + fun argbVector(maxLength: Int): ValueCondition + + /** Condition asserting that an attribute is a boolean ('true' or 'false'). */ + fun boolean(): ValueCondition + + /** Condition asserting that an attribute is a data source in a [DATA.SOURCE] format. */ + fun dataSource(): ValueCondition + + /** Condition asserting that an attribute is one of a predefined set of string options. */ + fun enum(vararg options: String) = enum(options.toSet()) + + /** Condition asserting that an attribute is one of a predefined set of string options. */ + fun enum(options: Set): ValueCondition + + /** Condition asserting that an attribute is a valid time text format. */ + fun timeTextFormat(): ValueCondition + + /** Condition asserting that an attribute is a deep link in a valid format. */ + fun deepLink(): ValueCondition + + /** Condition asserting that an attribute is a valid expression. */ + fun validExpression(): ExpressionCondition + + /** Combines two conditions with a logical AND */ + infix fun ValueCondition.and(other: ValueCondition) = + ValueCondition( + "${this.errorMessage} AND ${other.errorMessage}", + { value -> this.check(value) && other.check(value) }, + ) + + /** Combines two conditions with a logical OR */ + infix fun ValueCondition.or(other: ValueCondition) = + ValueCondition( + "${this.errorMessage} OR ${other.errorMessage}", + { value -> this.check(value) || other.check(value) }, + ) +} + +object ValueConditionLibrary : ValueConditions { + private const val ARGB_MATCHER = "#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6})" + private const val TIME_MATCHER = "([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]" + private const val OPTIONAL_DECIMAL_MATCHER = "([-+]?[0-9]*(\\.[0-9]+)?)" + private const val DATA_SOURCE_MATCHER = "\\[[A-Z0-9]+([._]\\w+)*\\]" + private const val TIME_TEXT_FORMAT_MATCHER = + "h{2}_(10|1)|m{2}_(10|1)|s{2}_(10|1)|((h{1,2}):m{1,2}:s{1,2}|(h{1,2}):m{1,2})|(h{1,2})|m{1,2}|s{1,2}" + private const val DEEP_LINK_MATCHER = + "([a-zA-Z][a-zA-Z0-9+.-]*):\\/\\/([^?#]*)(?:\\?([^#]*))?(?:#(.*))?" + + override fun equals(expectedValue: String) = + ValueCondition("Value must equal '$expectedValue'.", { value -> value == expectedValue }) + + override fun integer() = + ValueCondition("Value must be an integer.", { value -> value.toIntOrNull() != null }) + + override fun integer(min: Int, max: Int) = + ValueCondition( + "Value must be an integer in the range [$min, $max].", + { value -> value.toIntOrNull() != null && value.toInt() in min..max }, + ) + + override fun float() = + ValueCondition("Value must be a float.", { value -> value.toFloatOrNull() != null }) + + override fun float(min: Float, max: Float) = + ValueCondition( + "Value must be a float in the range [$min, $max].", + { value -> value.toFloatOrNull() != null && value.toFloat() in min..max }, + ) + + override fun color() = + ValueCondition( + "Value must be a color in #AARRGGBB or #RRGGBB format.", + { value -> value.matches(Regex("^$ARGB_MATCHER$")) }, + ) + + override fun time() = + ValueCondition( + "Value must be a time in hh:mm:ss format.", + { value -> value.matches(Regex("^$TIME_MATCHER$")) }, + ) + + override fun nonEmpty() = + ValueCondition("Value cannot be empty.", { value -> value.isNotEmpty() }) + + override fun stringOfLength(n: Int): ValueCondition = + ValueCondition("Value must be a string of length $n.", { value -> value.length == n }) + + override fun floatVector(n: Int) = + ValueCondition( + "Value must be a space separated list of $n floats.", + { value -> + val vectorMatcher = + Regex("^($OPTIONAL_DECIMAL_MATCHER(\\s$OPTIONAL_DECIMAL_MATCHER){${n-1}})$") + value.matches(vectorMatcher) + }, + ) + + override fun floatVector() = + ValueCondition( + "Value must be a space separated list of floats.", + { value -> + val vectorMatcher = + Regex("^($OPTIONAL_DECIMAL_MATCHER(\\s$OPTIONAL_DECIMAL_MATCHER)*)$") + value.matches(vectorMatcher) + }, + ) + + override fun argbVector() = + ValueCondition( + "Value must be a space separated list of colors in #AARRGGBB or #RRGGBB format.", + { value -> + val colorVectorMatcher = Regex("^($ARGB_MATCHER(\\s$ARGB_MATCHER)*)$") + value.matches(colorVectorMatcher) + }, + ) + + override fun argbVector(maxLength: Int) = + ValueCondition( + "Value must be a space separated list of up to $maxLength colors in #AARRGGBB or #RRGGBB format.", + { value -> + val colorVectorMatcher = + Regex("^($ARGB_MATCHER(\\s$ARGB_MATCHER){0,${maxLength - 1}})$") + value.matches(colorVectorMatcher) + }, + ) + + override fun boolean() = + ValueCondition( + "Value must be 'true' or 'false'.", + { value -> value.lowercase() == "true" || value.lowercase() == "false" }, + ) + + override fun dataSource() = + ValueCondition( + "Value must be a source in the [SOURCE.DATA] format.", + { value -> value.matches(Regex("^$DATA_SOURCE_MATCHER$")) }, + ) + + override fun enum(options: Set) = + ValueCondition( + "Value must be in {${options.joinToString(", ") }}}", + { value -> value in options }, + ) + + override fun timeTextFormat() = + ValueCondition( + "Value must be a valid time text format.", + { value -> value.matches(Regex("^$TIME_TEXT_FORMAT_MATCHER$")) }, + ) + + override fun deepLink() = + ValueCondition( + "Value must be a deep link in a valid format: app://open.my.app", + { value -> value.matches(Regex("^$DEEP_LINK_MATCHER$")) }, + ) + + override fun validExpression() = + ExpressionCondition(errorMessage = "Must be a valid expression") +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/Constants.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/Constants.kt new file mode 100644 index 0000000..b333c7b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/Constants.kt @@ -0,0 +1,3 @@ +package com.google.wear.watchface.validator.error + +internal const val GLOBAL_ERROR_KEY = 0 diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationError.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationError.kt new file mode 100644 index 0000000..0e0a302 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationError.kt @@ -0,0 +1,83 @@ +package com.google.wear.watchface.validator.error + +import com.google.wear.watchface.validator.Version + +/** An interface representing a validation error in the DWF validator. */ +sealed interface ValidationError { + val elementPath: List +} + +/** An error generated when the validator finds an unexpected tagName. */ +data class IllegalTagError( + val tagName: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when a tag occurs an invalid number of times. */ +data class TagOccurrenceError( + val tagName: String, + val actualCount: Int, + val expectedRange: IntRange, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when an attribute is not allowed on a given element. */ +data class IllegalAttributeError( + val attributeName: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when a condition fails that belongs to a required constraint. */ +data class RequiredConditionFailedError( + val conditionMessage: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when the validator encounters an expression syntax error. */ +data class ExpressionSyntaxError( + val errorMessage: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when an expression is exclusive to certain versions */ +data class ExpressionVersionEliminationError( + val expressionResource: String, + val permittedVersions: Set, + override val elementPath: List = emptyList(), +) : ValidationError + +/** + * An error generated when a condition is exclusive to certain other versions. This is used to + * indicate that a condition passed which is not valid for the current version of the watch face. + * + * This error is used in an allowed constraint. + */ +data class VersionEliminationError( + val conditionMessage: String, + val permittedVersions: Set, + override val elementPath: List = emptyList(), +) : ValidationError + +/** + * An error generated when the validator encounters an unknown error that does not fit any specific + * category. + */ +data class UnknownError( + val errorMessage: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when an attribute has an invalid value. */ +data class AttributeValueError( + val attributeName: String, + val attributeValue: String, + val errorMessage: String, + override val elementPath: List = emptyList(), +) : ValidationError + +/** An error generated when the content of an element is invalid. */ +data class ContentError( + val content: String, + val errorMessage: String, + override val elementPath: List = emptyList(), +) : ValidationError diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationResult.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationResult.kt new file mode 100644 index 0000000..83230c9 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/error/ValidationResult.kt @@ -0,0 +1,98 @@ +package com.google.wear.watchface.validator.error + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.Version +import com.google.wear.watchface.validator.constraint.VersionSet + +typealias ErrorMap = Map> + +/** + * A sealed interface representing the different types of result that the validator can produce. + * + * @property validVersions a set of [Version]s that are still valid after the validation process. + * @property errorMap a map from [Version] to a list of [ValidationError]s that occurred that have + * invalidated that version. + */ +sealed interface ValidationResult { + val validVersions: VersionSet + val errorMap: ErrorMap + + /** + * Represents a successful validation, in which the document is valid for all versions and has + * no errors. + */ + object Success : ValidationResult { + override val validVersions: Set = ALL_WFF_VERSIONS + override val errorMap: ErrorMap = emptyMap() + } + + /** + * Represents a validation failure, where the document is invalid for all versions. It contains + * a map of errors that occurred during validation. + * + * @param errorMap a map from [Version] to a list of [ValidationError]s that occurred during + * validation. + * @constructor creates a [ValidationResult.Failure] with the provided [errorMap] or a single + * global Error. + */ + data class Failure(override val errorMap: ErrorMap) : ValidationResult { + override val validVersions: VersionSet = emptySet() + + /** + * A convenience constructor for creating a failure with a single global error. ie an error + * which causes a failure for all versions. + */ + constructor( + globalError: ValidationError + ) : this(mapOf(GLOBAL_ERROR_KEY to mutableListOf(globalError))) + } + + /** + * Represents a partial success in validation, where some versions are valid, but there are + * still errors present. It contains a set of valid versions and a map of errors that occurred + * during validation. + * + * @param validVersions a set of [Version]s that are still valid after the validation process. + * @param errorMap a map from [Version] to a list of [ValidationError]s that occurred during + * validation. + */ + data class PartialSuccess( + override val validVersions: VersionSet, + override val errorMap: ErrorMap = emptyMap(), + ) : ValidationResult + + companion object { + /** + * Creates a [ValidationResult] based on the provided [versions] and [errorMap]. If the + * [versions] set is empty, it returns a [Failure] with the provided [errorMap]. If the + * [errorMap] is not empty, it returns a [PartialSuccess] with the provided [versions] and + * [errorMap]. Otherwise, it returns a [Success] result. + * + * @param versions a set of [Version]s that are still valid after the validation process. + * @param errorMap a map from [Version] to a list of [ValidationError]s that occurred during + * validation. + * @return a [ValidationResult] representing the outcome of the validation. + */ + fun of(versions: VersionSet, errorMap: ErrorMap): ValidationResult { + return when { + versions.isEmpty() -> Failure(errorMap) + errorMap.isNotEmpty() -> PartialSuccess(versions, errorMap) + else -> Success + } + } + } +} + +/** + * Combines two [ValidationResult]s by intersecting their valid versions and merging their error + * maps. + */ +infix fun ValidationResult.combineWith(other: ValidationResult): ValidationResult { + val newValidVersions = this.validVersions intersect other.validVersions + val combinedErrors = + (this.errorMap.asSequence() + other.errorMap.asSequence()) + .groupBy({ it.key }, { it.value }) + .mapValues { (_, lists) -> lists.flatten().toMutableList() } + + return ValidationResult.of(newValidVersions, combinedErrors) +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Exceptions.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Exceptions.kt new file mode 100644 index 0000000..3a84b93 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Exceptions.kt @@ -0,0 +1,20 @@ +package com.google.wear.watchface.validator.expression + +/** Exceptions thrown in the expression parser to categorise errors. */ +sealed class ExpressionParsingException(message: String) : Exception(message) + +class UnknownTokenException(message: String) : ExpressionParsingException(message) + +class UnexpectedTokenException(message: String) : ExpressionParsingException(message) + +class TokensNotConsumedException(message: String) : ExpressionParsingException(message) + +class EndOfFileException(message: String) : ExpressionParsingException(message) + +class MissingTokenException(message: String) : ExpressionParsingException(message) + +class FunctionNotFoundException(message: String) : ExpressionParsingException(message) + +class SourceNotFoundException(message: String) : ExpressionParsingException(message) + +class VersionConflictException(message: String) : ExpressionParsingException(message) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Expression.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Expression.kt new file mode 100644 index 0000000..1324dff --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Expression.kt @@ -0,0 +1,66 @@ +package com.google.wear.watchface.validator.expression + +sealed interface Expression + +/** Ternary Operations (alternative to if/else expressions) */ +data class Ternary(val condition: Expression, val ifTrue: Expression, val ifFalse: Expression) : + Expression + +/** Boolean Binary Operations */ +data class BitwiseOr(val left: Expression, val right: Expression) : Expression + +data class LogicalOr(val left: Expression, val right: Expression) : Expression + +data class BitwiseAnd(val left: Expression, val right: Expression) : Expression + +data class LogicalAnd(val left: Expression, val right: Expression) : Expression + +/** Comparison Operations */ +data class Equal(val left: Expression, val right: Expression) : Expression + +data class NotEqual(val left: Expression, val right: Expression) : Expression + +data class LessThan(val left: Expression, val right: Expression) : Expression + +data class LessThanOrEqual(val left: Expression, val right: Expression) : Expression + +data class GreaterThan(val left: Expression, val right: Expression) : Expression + +data class GreaterThanOrEqual(val left: Expression, val right: Expression) : Expression + +/** Binary Operations */ +data class Add(val left: Expression, val right: Expression) : Expression + +data class Sub(val left: Expression, val right: Expression) : Expression + +data class Mul(val left: Expression, val right: Expression) : Expression + +data class Div(val left: Expression, val right: Expression) : Expression + +data class Mod(val left: Expression, val right: Expression) : Expression + +/** Unary Operations */ +data class Pos(val operand: Expression) : Expression + +data class Neg(val operand: Expression) : Expression + +data class BitwiseNot(val operand: Expression) : Expression + +data class LogicalNot(val operand: Expression) : Expression + +/** Atomic Expressions */ +data class FunctionCall(val name: String, val arguments: List) : Expression + +data class NumLiteral(val value: Double) : Expression + +data class NumList(val value: List) : Expression + +data class Color(val value: String) : Expression + +data class ColorList(val value: List) : Expression + +data class BooleanLiteral(val value: Boolean) : Expression + +data class StringLiteral(val value: String) : Expression + +data class Variable(val name: String) : Expression diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/ExpressionParser.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/ExpressionParser.kt new file mode 100644 index 0000000..05a5912 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/ExpressionParser.kt @@ -0,0 +1,421 @@ +package com.google.wear.watchface.validator.expression + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.MIN_WFF_VERSION +import com.google.wear.watchface.validator.WatchFaceElementContext +import com.google.wear.watchface.validator.error.ExpressionSyntaxError +import com.google.wear.watchface.validator.error.ValidationResult +import kotlin.math.max +import kotlin.math.min + +typealias TokenStream = Sequence + +/** A parser for expressions embedded in the xml elements */ +class ExpressionParser(tokens: TokenStream, val ctx: WatchFaceElementContext) { + private val tokenIterator: Iterator = tokens.iterator() + private var minVersion: Int = MIN_WFF_VERSION + private var maxVersion: Int = MAX_WFF_VERSION + private var current: Token + private var previous: Token + + init { + require(tokenIterator.hasNext()) + current = tokenIterator.next() + previous = current + + if (current is Token.Unknown) + throw UnknownTokenException("Unrecognised Token: ${current.value}") + } + + /** + * The top level function for parsing the sequence of tokens. + * + * This function will parse the tokens into an [Expression] object. Preserving the + * precedence/order of operations. Operations are naturally right associative ie. `1 + 2 + 3` is + * parsed as `1 + (2 + 3)`. + */ + private fun parse(): Expression { + val expr = expression() + + /* All the tokens should have been consumed */ + if (current !is Token.EOF) + throw TokensNotConsumedException( + "Expression Parser Finished Early: ${current.value} not consumed" + ) + + return expr + } + + /* (Ternary) Expression -> OrExpression ('?' Expression ':' Expression)? */ + private fun expression(): Expression { + val expr: Expression = orExpression() + + return when { + match("?") -> { + val ifBody: Expression = expression() + expect(":") + val elseBody: Expression = expression() + Ternary(expr, ifBody, elseBody) + } + + else -> expr + } + } + + /* OrExpression -> AndExpression ('||' AndExpression)* */ + private fun orExpression(): Expression { + var expr: Expression = andExpression() + + while (match("||")) { + val right: Expression = orExpression() + expr = LogicalOr(expr, right) + } + + return expr + } + + /* AndExpression -> BitWiseOr ('&&' BitWiseOr)* */ + private fun andExpression(): Expression { + var expr: Expression = bitwiseOr() + + while (match("&&")) { + val right: Expression = andExpression() + expr = LogicalAnd(expr, right) + } + + return expr + } + + /* BitWiseOr -> BitWiseAnd ('|' BitWiseAnd)* */ + private fun bitwiseOr(): Expression { + var expr: Expression = bitwiseAnd() + + while (match("|")) { + val right: Expression = bitwiseOr() + expr = BitwiseOr(expr, right) + } + + return expr + } + + /* BitWiseAnd -> Equality ('&' Equality)* */ + private fun bitwiseAnd(): Expression { + var expr: Expression = equality() + + while (match("&")) { + val right: Expression = bitwiseAnd() + expr = BitwiseAnd(expr, right) + } + + return expr + } + + /* Equality -> Comparison (('=='|'!=') Comparison)? */ + private fun equality(): Expression { + val expr: Expression = comparison() + + return when { + match("==") -> Equal(expr, comparison()) + match("!=") -> NotEqual(expr, comparison()) + + else -> expr + } + } + + /* Comparison -> AddSubExpression (('<'|'<='|'>'|'>=') AddSubExpression)? */ + private fun comparison(): Expression { + val expr: Expression = addSubExpression() + + return when { + match("<") -> LessThan(expr, addSubExpression()) + match(">") -> GreaterThan(expr, addSubExpression()) + match("<=") -> LessThanOrEqual(expr, addSubExpression()) + match(">=") -> GreaterThanOrEqual(expr, addSubExpression()) + + else -> expr + } + } + + /* AddSubExpression -> MulDivExpression (('+'|'-') MulDivExpression)* */ + private fun addSubExpression(): Expression { + var expr: Expression = mulDivExpression() + + while (match("+", "-")) { + val operator: Token = previous + val right: Expression = mulDivExpression() + expr = + when (operator.value) { + "+" -> Add(expr, right) + "-" -> Sub(expr, right) + else -> throw IllegalStateException("Unexpected operator: $operator") + } + } + + return expr + } + + /* MulDivExpression -> UnaryExpression (('*' | '/' | '%') UnaryExpression)* */ + private fun mulDivExpression(): Expression { + var expr: Expression = unaryExpression() + + while (match("*", "/", "%")) { + val operator: Token = previous + val right: Expression = mulDivExpression() + expr = + when (operator.value) { + "*" -> Mul(expr, right) + "/" -> Div(expr, right) + "%" -> Mod(expr, right) + else -> throw IllegalStateException("Unexpected operator: $operator") + } + } + + return expr + } + + /* UnaryExpression -> ('+' | '-' | '!' | '~')? Atom */ + private fun unaryExpression(): Expression { + return when { + match("+") -> Pos(atom()) + match("-") -> Neg(atom()) + match("!") -> LogicalNot(atom()) + match("~") -> BitwiseNot(atom()) + else -> atom() + } + } + + /* Atom -> Number | Identifier | FunctionCall | '(' Expression ')' */ + private fun atom(): Expression { + when (current) { + is Token.BooleanLiteral -> { + return BooleanLiteral(popToken().value.toBoolean()) + } + + is Token.Color -> { + val color = popToken().value + + when { + /* Special Case: Many Colours can be passed into a function as a single argument */ + current is Token.Color -> { + val colourList = mutableListOf(color) + + do { + colourList.add(popToken().value) + } while (current is Token.Color) + + return ColorList(colourList) + } + + else -> return Color(color) + } + } + + is Token.StringLiteral -> { + return StringLiteral(popToken().value.trim('"')) + } + + is Token.Number -> { + val number = popToken().value + + when { + /* Special Case: Many Numbers can be passed into a function as a single argument */ + current is Token.Number -> { + val numList = mutableListOf(number.toDouble()) + + do { + numList.add(popToken().value.toDouble()) + } while (current is Token.Number) + + return NumList(numList) + } + + else -> return NumLiteral(number.toDouble()) + } + } + + is Token.Word -> { + val name: String = popToken().value + + when { + match("(") -> { + val args = mutableListOf() + + if (current.value != ")") { + do { + args.add(expression()) + } while (match(",")) + } + + expect(")") + + /* assert that function exists and check version compatibility */ + val function = FunctionCall(name, args) + validateFunctions(function) + + return function + } + + else -> return Variable(name) + } + } + + is Token.Paren -> { + when { + match("(") -> { + val expr = expression() + expect(")") + return expr + } + + match("[") -> { + val source = popToken().value + expect("]") + + validateSource(source) + return Variable(source) + } + + else -> + throw UnexpectedTokenException( + "Unexpected token (wrong bracket): ${current.value}" + ) + } + } + + is Token.EOF -> throw EndOfFileException("Unexpected End of Expression") + + else -> throw UnexpectedTokenException("Unexpected token: ${current.value}") + } + } + + /** Checks if the current token matches a certain value. Advances to the next token if so. */ + private fun match(vararg values: String): Boolean { + return values.any { current.value == it }.also { if (it) popToken() } + } + + /** + * Consumes the current token, updates the values for current and previous. Throws an exception + * when an unrecognised token is found. + */ + private fun popToken(): Token { + if (current !is Token.EOF) { + require(tokenIterator.hasNext()) + previous = current + current = tokenIterator.next() + + if (current is Token.Unknown) + throw UnknownTokenException("Unrecognised Token: ${current.value}") + } + + return previous + } + + /** Ensures that the current token matches the expected value. Throws an exception if not. */ + private fun expect(expected: String) { + if (current.value == expected) { + popToken() + } else { + throw MissingTokenException("Expected: '$expected'. Got: '${current.value}'") + } + } + + /** + * Check that a function with this name and number of arguments actually exists. + * + * @param function the function to validate. + * @throws FunctionNotFoundException if the function/arity combination does not exist. + * @throws VersionConflictException if the function is not supported in the current version + * range. + */ + private fun validateFunctions(function: FunctionCall) { + val versionsRange = VersionRegistry.getFunctionVersions(function) + + minVersion = max(versionsRange.minVersion, minVersion) + maxVersion = min(versionsRange.maxVersion, maxVersion) + } + + /** + * Check that a source with this name actually exists. + * + * @param sourceName the name of the source to validate. + * @throws SourceNotFoundException if the source does not exist. + * @throws VersionConflictException if the source is not supported in the current version range. + */ + private fun validateSource(sourceName: String) { + val versionsRange = VersionRegistry.getSourceVersions(sourceName) + + minVersion = max(versionsRange.minVersion, minVersion) + maxVersion = min(versionsRange.maxVersion, maxVersion) + } + + companion object { + + /** + * Parses the expression and returns all the versions for which the expression is valid. + * + * @param expression the string expression to parse. + * @param ctx the validation context holding the versioning and scope data. + * @return the set of versions for which the expression is valid. + * @throws ExpressionParsingException if the tokens cannot be parsed into a valid + * * expression. + */ + fun getValidationResult( + expression: String, + ctx: WatchFaceElementContext = WatchFaceElementContext.Companion.emptyContext(), + ): ValidationResult { + val tokens = Tokenizer.tokeniseString(expression) + Token.EOF + val parser = ExpressionParser(tokens, ctx) + + // TODO(b/433917558) collect informed ValidationErrors in the expression parser, add a + // ExpressionVersionEliminationError when versions are eliminated + try { + parser.parse() + return ValidationResult.PartialSuccess( + (parser.minVersion..parser.maxVersion).toSet(), + emptyMap(), + ) + } catch (e: ExpressionParsingException) { + return ValidationResult.Failure( + ExpressionSyntaxError( + "Error in expression: '$expression'. ${e.message ?: "Syntax Error"}", + ctx.elementPath, + ) + ) + } + } + + /** + * Parses a string expression into an [Expression] object. + * + * @param expression the string expression to parse. + * @param ctx the validation context holding the versioning and scope data. + * @return the parsed [Expression]. + * @throws ExpressionParsingException if the tokens cannot be parsed into a valid + * expression. + */ + fun parse( + expression: String, + ctx: WatchFaceElementContext = WatchFaceElementContext.Companion.emptyContext(), + ): Expression { + val tokens = Tokenizer.tokeniseString(expression) + Token.EOF + return parse(tokens, ctx) + } + + /** + * Parses a list of tokens into an [Expression] object. + * + * @param tokens the list of tokens to parse. + * @param ctx the validation context holding the versioning and scope data. + * @return the parsed [Expression]. + * @throws ExpressionParsingException if the tokens cannot be parsed into a valid + * expression. + */ + fun parse( + tokens: Sequence, + ctx: WatchFaceElementContext = WatchFaceElementContext.Companion.emptyContext(), + ): Expression { + val parser = ExpressionParser(tokens, ctx) + return parser.parse() + } + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Token.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Token.kt new file mode 100644 index 0000000..8b2276b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Token.kt @@ -0,0 +1,32 @@ +package com.google.wear.watchface.validator.expression + +import kotlin.jvm.JvmInline + +/** + * An interface for Expression Tokens + * + * @property value the raw string value associated with a token. + */ +sealed interface Token { + val value: String + + @JvmInline value class Number(override val value: String) : Token + + @JvmInline value class Color(override val value: String) : Token + + @JvmInline value class BooleanLiteral(override val value: String) : Token + + @JvmInline value class StringLiteral(override val value: String) : Token + + @JvmInline value class Word(override val value: String) : Token + + @JvmInline value class Operator(override val value: String) : Token + + @JvmInline value class Paren(override val value: String) : Token + + @JvmInline value class Unknown(override val value: String) : Token + + data object EOF : Token { + override val value = "" + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Tokenizer.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Tokenizer.kt new file mode 100644 index 0000000..8b718b6 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/Tokenizer.kt @@ -0,0 +1,55 @@ +package com.google.wear.watchface.validator.expression + +import kotlin.text.get + +/** A lexer/tokeniser for dwf arithmetic expressions */ +object Tokenizer { + // TODO(b/433461048): Fine-grained numeric token matching and typing. + private const val NUMERIC_MATCHER = "\\d*\\.\\d+|\\d+" + private const val COLOR_MATCHER = "#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}" + private const val BOOLEAN_MATCHER = "true|false|True|False|TRUE|FALSE" + private const val STRING_MATCHER = "\"[^\"]*\"" + private const val WORD_MATCHER = "[a-zA-Z][a-zA-Z0-9_\\.]*" + private const val PAREN_MATCHER = "\\(|\\)|\\[|\\]" + private const val WHITESPACE_MATCHER = "\\s+" + private const val OPERATOR_MATCHER = "<=|>=|==|!=|&&|\\|\\||\\+|-|\\*|/|%|~|!|&|\\||<|>|\\?|:|," + + private val matcher by lazy { + Regex( + "(?$NUMERIC_MATCHER)|" + + "(?$COLOR_MATCHER)|" + + "(?$BOOLEAN_MATCHER)|" + + "(?$STRING_MATCHER)|" + + "(?$WORD_MATCHER)|" + + "(?$OPERATOR_MATCHER)|" + + "(?$PAREN_MATCHER)|" + + "(?$WHITESPACE_MATCHER)|" + + "(?.)" + ) + } + + /** + * Converts a raw expression string into a list of [[Token]]s using RegEx. + * + * @param expression the raw expression string to be tokenised. + */ + fun tokeniseString(expression: String): Sequence { + return matcher.findAll(expression).mapNotNull { match: MatchResult -> + when { + match.groups["number"] != null -> Token.Number(match.value) + match.groups["color"] != null -> Token.Color(match.value) + match.groups["boolean"] != null -> Token.BooleanLiteral(match.value) + match.groups["string"] != null -> Token.StringLiteral(match.value) + match.groups["word"] != null -> Token.Word(match.value) + match.groups["operator"] != null -> Token.Operator(match.value) + match.groups["paren"] != null -> Token.Paren(match.value) + match.groups["whitespace"] != null -> null + match.groups["unknown"] != null -> Token.Unknown(match.value) + else -> + throw IllegalStateException( + "Unreachable code reached for match: ${match.value}" + ) + } + } + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRange.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRange.kt new file mode 100644 index 0000000..dfd7cf0 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRange.kt @@ -0,0 +1,10 @@ +package com.google.wear.watchface.validator.expression + +/** + * A data class representing the supported versions of a function/source. + * + * @property minVersion The version in which the function was introduced. + * @property maxVersion The version after which the function is deprecated. Defaults to the current + * version. + */ +data class VersionRange(val minVersion: Int, val maxVersion: Int = Int.MAX_VALUE) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRegistry.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRegistry.kt new file mode 100644 index 0000000..5e4cde7 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/expression/VersionRegistry.kt @@ -0,0 +1,196 @@ +package com.google.wear.watchface.validator.expression + +import com.google.wear.watchface.validator.MAX_WFF_VERSION + +object VersionRegistry { + private val FUNCTIONS = + mapOf( + "round{1}" to VersionRange(1), + "floor{1}" to VersionRange(1), + "ceil{1}" to VersionRange(1), + "fract{1}" to VersionRange(1), + "sin{1}" to VersionRange(1), + "cos{1}" to VersionRange(1), + "tan{1}" to VersionRange(1), + "asin{1}" to VersionRange(1), + "acos{1}" to VersionRange(1), + "atan{1}" to VersionRange(1), + "abs{1}" to VersionRange(1), + "clamp{3}" to VersionRange(1), + "rand{2}" to VersionRange(1), + "log{1}" to VersionRange(1), + "log2{1}" to VersionRange(1), + "log10{1}" to VersionRange(1), + "sqrt{1}" to VersionRange(1), + "cbrt{1}" to VersionRange(1), + "exp{1}" to VersionRange(1), + "expm1{1}" to VersionRange(1), + "deg{1}" to VersionRange(1), + "rad{1}" to VersionRange(1), + "pow{2}" to VersionRange(1), + "numberFormat{2}" to VersionRange(1), + "icuText{1}" to VersionRange(1), + "icuText{2}" to VersionRange(2), + "icuBestText{1}" to VersionRange(1), + "icuBestText{2}" to VersionRange(2), + "subText{3}" to VersionRange(1), + "textLength{1}" to VersionRange(1), + "colorRgb{3}" to VersionRange(4), + "colorArgb{4}" to VersionRange(4), + "extractColorFromColors{3}" to VersionRange(4), + "extractColorFromWeightedColors{4}" to VersionRange(4), + ) + + private val SOURCES: Map = + mapOf( + "UTC_TIMESTAMP" to VersionRange(1), + "MILLISECOND" to VersionRange(1), + "SECOND" to VersionRange(1), + "SECOND_Z" to VersionRange(1), + "SECOND_TENS_DIGIT" to VersionRange(2), + "SECOND_UNITS_DIGIT" to VersionRange(2), + "SECOND_MILLISECOND" to VersionRange(1), + "SECONDS_IN_DAY" to VersionRange(1), + "SECONDS_SINCE_EPOCH" to VersionRange(3), + "MINUTE" to VersionRange(1), + "MINUTE_Z" to VersionRange(1), + "MINUTE_TENS_DIGIT" to VersionRange(2), + "MINUTE_UNITS_DIGIT" to VersionRange(2), + "MINUTE_SECOND" to VersionRange(1), + "MINUTES_SINCE_EPOCH" to VersionRange(3), + "HOUR_0_11" to VersionRange(1), + "HOUR_0_11_Z" to VersionRange(1), + "HOUR_0_11_MINUTE" to VersionRange(1), + "HOUR_1_12" to VersionRange(1), + "HOUR_1_12_Z" to VersionRange(1), + "HOUR_1_12_MINUTE" to VersionRange(1), + "HOUR_0_23" to VersionRange(1), + "HOUR_0_23_Z" to VersionRange(1), + "HOUR_0_23_MINUTE" to VersionRange(1), + "HOUR_1_24" to VersionRange(1), + "HOUR_1_24_Z" to VersionRange(1), + "HOUR_1_24_MINUTE" to VersionRange(1), + "HOUR_TENS_DIGIT" to VersionRange(2), + "HOUR_UNITS_DIGIT" to VersionRange(2), + "HOURS_SINCE_EPOCH" to VersionRange(3), + "DAY" to VersionRange(1), + "DAY_Z" to VersionRange(1), + "DAY_HOUR" to VersionRange(1), + "DAY_0_30" to VersionRange(1), + "DAY_0_30_HOUR" to VersionRange(1), + "DAY_OF_YEAR" to VersionRange(1), + "DAY_OF_WEEK" to VersionRange(1), + "DAY_OF_WEEK_F" to VersionRange(1), + "DAY_OF_WEEK_S" to VersionRange(1), + "FIRST_DAY_OF_WEEK" to VersionRange(2), + "MONTH" to VersionRange(1), + "MONTH_Z" to VersionRange(1), + "MONTH_F" to VersionRange(1), + "MONTH_S" to VersionRange(1), + "DAYS_IN_MONTH" to VersionRange(1), + "MONTH_DAY" to VersionRange(1), + "MONTH_0_11" to VersionRange(1), + "MONTH_0_11_DAY" to VersionRange(1), + "YEAR" to VersionRange(1), + "YEAR_S" to VersionRange(1), + "YEAR_MONTH" to VersionRange(1), + "YEAR_MONTH_DAY" to VersionRange(1), + "WEEK_IN_MONTH" to VersionRange(1), + "WEEK_IN_YEAR" to VersionRange(1), + "IS_24_HOUR_MODE" to VersionRange(1), + "IS_DAYLIGHT_SAVING_TIME" to VersionRange(1), + "TIMEZONE" to VersionRange(1), + "TIMEZONE_ABB" to VersionRange(1), + "TIMEZONE_ID" to VersionRange(1), + "TIMEZONE_OFFSET" to VersionRange(1), + "TIMEZONE_OFFSET_MINUTES" to VersionRange(3), + "TIMEZONE_OFFSET_DST" to VersionRange(1), + "TIMEZONE_OFFSET_MINUTES_DST" to VersionRange(3), + "AMPM_STATE" to VersionRange(1), + "AMPM_POSITION" to VersionRange(1), + "AMPM_STRING" to VersionRange(1), + "MOON_PHASE_POSITION" to VersionRange(1), + "MOON_PHASE_TYPE" to VersionRange(1), + "MOON_PHASE_TYPE_STRING" to VersionRange(1), + "LANGUAGE_LOCALE_NAME" to VersionRange(1), + "STEP_COUNT" to VersionRange(1), + "STEP_GOAL" to VersionRange(1), + "STEP_PERCENT" to VersionRange(1), + "HEART_RATE" to VersionRange(1), + "HEART_RATE_Z" to VersionRange(1), + "ACCELEROMETER_IS_SUPPORTED" to VersionRange(1), + "ACCELEROMETER_X" to VersionRange(1), + "ACCELEROMETER_Y" to VersionRange(1), + "ACCELEROMETER_Z" to VersionRange(1), + "ACCELEROMETER_ANGLE_X" to VersionRange(1), + "ACCELEROMETER_ANGLE_Y" to VersionRange(1), + "ACCELEROMETER_ANGLE_Z" to VersionRange(1), + "ACCELEROMETER_ANGLE_XY" to VersionRange(1), + "BATTERY_PERCENT" to VersionRange(1), + "BATTERY_CHARGING_STATUS" to VersionRange(1), + "BATTERY_IS_LOW" to VersionRange(1), + "BATTERY_TEMPERATURE_CELSIUS" to VersionRange(1), + "BATTERY_TEMPERATURE_FAHRENHEIT" to VersionRange(1), + "UNREAD_NOTIFICATION_COUNT" to VersionRange(1), + "WEATHER.IS_AVAILABLE" to VersionRange(2), + "WEATHER.IS_ERROR" to VersionRange(2), + "WEATHER.CONDITION" to VersionRange(2), + "WEATHER.CONDITION_NAME" to VersionRange(2), + "WEATHER.IS_DAY" to VersionRange(2), + "WEATHER.TEMPERATURE" to VersionRange(2), + "WEATHER.TEMPERATURE_UNIT" to VersionRange(2), + "WEATHER.DAY_TEMPERATURE_LOW" to VersionRange(2), + "WEATHER.DAY_TEMPERATURE_HIGH" to VersionRange(2), + "WEATHER.CHANCE_OF_PRECIPITATION" to VersionRange(2), + "WEATHER.UV_INDEX" to VersionRange(2), + "WEATHER.LAST_UPDATED" to VersionRange(2), + "WEATHER.HOURS.{index}.IS_AVAILABLE" to VersionRange(2), + "WEATHER.HOURS.{index}.CONDITION" to VersionRange(2), + "WEATHER.HOURS.{index}.CONDITION_NAME" to VersionRange(2), + "WEATHER.HOURS.{index}.IS_DAY" to VersionRange(2), + "WEATHER.HOURS.{index}.TEMPERATURE" to VersionRange(2), + "WEATHER.HOURS.{index}.UV_INDEX" to VersionRange(2), + "WEATHER.DAYS.{index}.IS_AVAILABLE" to VersionRange(2), + "WEATHER.DAYS.{index}.CONDITION_DAY" to VersionRange(2), + "WEATHER.DAYS.{index}.CONDITION_DAY_NAME" to VersionRange(2), + "WEATHER.DAYS.{index}.CONDITION_NIGHT" to VersionRange(2), + "WEATHER.DAYS.{index}.CONDITION_NIGHT_NAME" to VersionRange(2), + "WEATHER.DAYS.{index}.TEMPERATURE_LOW" to VersionRange(2), + "WEATHER.DAYS.{index}.TEMPERATURE_HIGH" to VersionRange(2), + "WEATHER.DAYS.{index}.CHANCE_OF_PRECIPITATION" to VersionRange(2), + "WEATHER.DAYS.{index}.CHANCE_OF_PRECIPITATION_NIGHT" to VersionRange(2), + "WEATHER.DAYS.{index}.UV_INDEX" to VersionRange(2), + ) + + /** + * Returns the supported versions for a given function name and arity. + * + * @param function the function to validate + * @return The supported versions for the function as [[VersionRange]]. + * @throws FunctionNotFoundException if the function is not found. + */ + fun getFunctionVersions(function: FunctionCall): VersionRange { + val arity: Int = function.arguments.size + return FUNCTIONS["${function.name}{$arity}"] + ?: throw FunctionNotFoundException( + "Function ${function.name} with arity $arity not found." + ) + } + + /** + * Returns the supported versions for a given source name. + * + * Source names often include an index. For example, "WEATHER.HOURS.6.IS_AVAILABLE". This method + * ignores the index and retrieves the versions for the base source name. + * + * @param sourceName The name of the source. + * @return The supported versions for the source. as [[VersionRange]]. Returns the full version + * range if source is not found. + */ + fun getSourceVersions(sourceName: String): VersionRange { + val indexMatcher = Regex("\\.\\d+") + // TODO(b/433921752): index range check + return SOURCES[sourceName.replace(indexMatcher, ".{index}")] + ?: VersionRange(1, MAX_WFF_VERSION) + } +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Attributes.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Attributes.kt new file mode 100644 index 0000000..64d2ecd --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Attributes.kt @@ -0,0 +1,188 @@ +package com.google.wear.watchface.validator.specification + +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ElementCondition + +internal val widthAndHeight: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "width", + integer(min = 0), + errorMessage = "Attribute: 'width' must be a positive integer", + ), + attribute( + "height", + integer(min = 0), + errorMessage = "Attribute: 'height' must be a positive integer", + ), + ) + } + +internal val geometricAttributes: Array = + with(ConditionLibrary) { + arrayOf( + attribute("x", integer(), errorMessage = "Attribute: 'x' must be an integer"), + attribute("y", integer(), errorMessage = "Attribute: 'y' must be an integer"), + *widthAndHeight, + ) + } + +internal val pivots: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "pivotX", + float(0.0F, 1.0F), + errorMessage = "Attribute: 'pivotX' must be a float in the range 0.0 to 1.0", + ), + attribute( + "pivotY", + float(0.0F, 1.0F), + errorMessage = "Attribute: 'pivotY' must be a float in the range 0.0 to 1.0", + ), + ) + } + +internal val angle: ElementCondition = + with(ConditionLibrary) { + attribute("angle", float(), errorMessage = "Attribute: 'angle' must be a float.") + } + +internal val alpha: ElementCondition = + with(ConditionLibrary) { + attribute( + "alpha", + integer(0, 255), + errorMessage = "Attribute: 'alpha' must be an int in the range 0 to 255", + ) + } + +internal val scaleFloatAttributes: Array = + with(ConditionLibrary) { + arrayOf( + attribute("scaleX", float(), errorMessage = "Attribute: 'scaleX' must be a float"), + attribute("scaleY", float(), errorMessage = "Attribute: 'scaleY' must be a float"), + ) + } +internal val renderMode: ElementCondition = + with(ConditionLibrary) { + attribute( + "renderMode", + enum("SOURCE", "MASK", "ALL"), + errorMessage = "Attribute: 'renderMode' must be one of 'SOURCE', 'MASK' or 'ALL'", + default = "SOURCE", + ) + } + +internal val tintColor: ElementCondition = + with(ConditionLibrary) { + attribute( + "tintColor", + color() or dataSource(), + errorMessage = "Attribute: 'tintColor' must be in the form #RRGGBB or #AARRGGBB", + ) + } + +val marginAttributes: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "marginLeft", + integer(0, Int.MAX_VALUE), + errorMessage = "Attribute: 'marginLeft' must be a non-negative integer", + ), + attribute( + "marginRight", + integer(0, Int.MAX_VALUE), + errorMessage = "Attribute: 'marginRight' must be a non-negative integer", + ), + attribute( + "marginTop", + integer(0, Int.MAX_VALUE), + errorMessage = "Attribute: 'marginTop' must be a non-negative integer", + ), + attribute( + "marginBottom", + integer(0, Int.MAX_VALUE), + errorMessage = "Attribute: 'marginBottom' must be a non-negative integer", + ), + ) + } + +internal val interpolationAndControls: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "interpolation", + enum("LINEAR", "EASE_IN", "EASE_OUT", "EASE_IN_OUT", "OVERSHOOT", "CUBIC_BEZIER"), + errorMessage = + "Attribute: 'interpolation' must be one of LINEAR, EASE_IN, EASE_OUT, EASE_IN_OUT, OVERSHOOT or CUBIC_BEZIER", + default = "LINEAR", + ), + attribute( + "controls", + floatVector(4), + errorMessage = + "Attribute: 'controls' must be a 4-component space separated vector: 0.5 0.5 0.5 0.5", + default = "0.5 0.5 0.5 0.5", + ), + ) + } + +internal val angleDirection: ElementCondition = + with(ConditionLibrary) { + attribute( + "angleDirection", + enum("CLOCKWISE", "COUNTER_CLOCKWISE", "NONE"), + errorMessage = + "Attribute: 'angleDirection' must be one of CLOCKWISE, COUNTER_CLOCKWISE or NONE", + default = "NONE", + ) + } + +internal val outlinePadding: ElementCondition = + with(ConditionLibrary) { + attribute( + "outlinePadding", + float(), + errorMessage = "Attribute: 'outlinePadding' must be a float", + default = "0.0", + ) + } + +internal val startAndEndAngles: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "startAngle", + float(), + errorMessage = "Attribute: 'startAngle' must be a float", + ), + attribute("endAngle", float(), errorMessage = "Attribute: 'endAngle' must be a float"), + ) + } + +internal val cornerRadiiAttributes: Array = + with(ConditionLibrary) { + arrayOf( + attribute( + "cornerRadiusX", + float(), + errorMessage = "Attribute: 'cornerRadiusX' must be a float", + ), + attribute( + "cornerRadiusY", + float(), + errorMessage = "Attribute: 'cornerRadiusY' must be a float", + ), + ) + } + +internal val centerXAndY: Array = + with(ConditionLibrary) { + arrayOf( + attribute("centerX", float(), errorMessage = "Attribute: 'centerX' must be a float"), + attribute("centerY", float(), errorMessage = "Attribute: 'centerY' must be a float"), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Constants.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Constants.kt new file mode 100644 index 0000000..e91da06 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/Constants.kt @@ -0,0 +1,3 @@ +package com.google.wear.watchface.validator.specification + +internal const val UNBOUNDED = Int.MAX_VALUE diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WatchFaceSpecification.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WatchFaceSpecification.kt new file mode 100644 index 0000000..cb5a8f4 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WatchFaceSpecification.kt @@ -0,0 +1,19 @@ +package com.google.wear.watchface.validator.specification + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.Version +import com.google.wear.watchface.validator.constraint.Constraint + +/** + * Represents a specification for validating am XML file. This includes all of the constraints to + * validate against as well as the format versions to validate for. + * + * @param constraintTree The root of the constraint tree to validate against. + * @param targetVersions The set of format versions to validate against. + */ +data class WatchFaceSpecification( + val constraintTree: Constraint, + val targetVersions: Set = + ALL_WFF_VERSIONS, // TODO(b/445347921) use this value to restrict validation to these + // versions +) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WffSpecification.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WffSpecification.kt new file mode 100644 index 0000000..44a9345 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/WffSpecification.kt @@ -0,0 +1,7 @@ +package com.google.wear.watchface.validator.specification + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.specification.watchFace.watchFace + +val WFF_SPECIFICATION: WatchFaceSpecification = + WatchFaceSpecification(watchFace(), ALL_WFF_VERSIONS) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/AnalogClock.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/AnalogClock.kt new file mode 100644 index 0000000..77c5e9b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/AnalogClock.kt @@ -0,0 +1,27 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.localization +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes + +/** Specification constraint for the `AnalogClock` element. */ +fun analogClock() = + constraint("AnalogClock") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes + ) + .allow( + /* Attributes */ + *clockTypeAttributes, + + /* Child Elements */ + childElement("HourHand", ::hourHand, maxOccurs = 2), + childElement("MinuteHand", ::minuteHand, maxOccurs = 2), + childElement("SecondHand", ::secondHand, maxOccurs = 2), + childElement("Localization", ::localization, maxOccurs = 1), + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/ClockTypeAttributes.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/ClockTypeAttributes.kt new file mode 100644 index 0000000..2e30c6d --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/ClockTypeAttributes.kt @@ -0,0 +1,18 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.condition.ValueConditionLibrary +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.angle +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.renderMode +import com.google.wear.watchface.validator.specification.scaleFloatAttributes +import com.google.wear.watchface.validator.specification.tintColor + +internal val clockTypeAttributes: Array = + with(ConditionLibrary) { + with(ValueConditionLibrary) { + arrayOf(*pivots, *scaleFloatAttributes, angle, alpha, renderMode, tintColor) + } + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/DigitalClock.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/DigitalClock.kt new file mode 100644 index 0000000..69f2521 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/DigitalClock.kt @@ -0,0 +1,29 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.clock.timeText.timeText +import com.google.wear.watchface.validator.specification.common.localization +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes + +/** Specification constraint for the `DigitalClock` element. */ +fun digitalClock(): Constraint = + constraint("DigitalClock") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + + /* Child Elements */ + childElement("TimeText", ::timeText), + ) + .allow( + /* Attributes */ + *clockTypeAttributes, + + /* Child Elements */ + childElement("Variant", ::variant), + childElement("Localization", ::localization, maxOccurs = 1), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/HourHand.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/HourHand.kt new file mode 100644 index 0000000..767cb26 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/HourHand.kt @@ -0,0 +1,27 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.tintColor + +fun hourHand() = + constraint("HourHand") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + attribute("resource"), + ) + .allow( + /* Attributes */ + *pivots, + alpha, + tintColor, + + /* Child Elements */ + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/MinuteHand.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/MinuteHand.kt new file mode 100644 index 0000000..7972584 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/MinuteHand.kt @@ -0,0 +1,27 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.tintColor + +fun minuteHand() = + constraint("MinuteHand") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + attribute("resource"), + ) + .allow( + /* Attributes */ + *pivots, + alpha, + tintColor, + + /* Child Elements */ + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/SecondHand.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/SecondHand.kt new file mode 100644 index 0000000..e5e9419 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/SecondHand.kt @@ -0,0 +1,36 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.tintColor + +fun secondHand() = + constraint("SecondHand") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + attribute("resource"), + + /* Child Elements */ + choice( + childElement("Sweep", ::sweep, maxOccurs = 1), + childElement("Tick", ::tick, maxOccurs = 1), + minOccurs = 0, + errorMessage = + "Cannot have both Sweep and Tick elements in the same tag.", + ), + ) + .allow( + /* Attributes */ + *pivots, + alpha, + tintColor, + + /* Child Elements */ + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Sweep.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Sweep.kt new file mode 100644 index 0000000..8fd9fd5 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Sweep.kt @@ -0,0 +1,20 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.constraint + +/** Specification constraint for the `Sweep` element. */ +fun sweep() = + constraint("Sweep") { + allVersions() + .require( + /* Attributes */ + attribute("frequency", enum("2", "5", "10", "15")) + ) + + versions(2 to MAX_WFF_VERSION) + .require( + /* Attributes */ + attribute("frequency", enum("2", "5", "10", "15", "SYNC_TO_DEVICE")) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Tick.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Tick.kt new file mode 100644 index 0000000..2ebee0c --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/Tick.kt @@ -0,0 +1,23 @@ +package com.google.wear.watchface.validator.specification.clock + +import com.google.wear.watchface.validator.constraint.constraint + +/** Specification constraint for the `Tick` element. */ +fun tick() = + constraint("Tick") { + // TODO(b/438165281) make these ranges exclusive where needed + allVersions() + .require( + /* Attributes */ + attribute( + "duration", + float(0.0F, 1.0F), + "duration must be a float in the range: (0.0, 1.0)", + ), + attribute( + "strength", + float(0.0F, 1.0F), + "strength attribute should be in range: (0.0, 1.0]", + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/BitmapFont.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/BitmapFont.kt new file mode 100644 index 0000000..f66d60e --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/BitmapFont.kt @@ -0,0 +1,23 @@ +package com.google.wear.watchface.validator.specification.clock.timeText + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType + +/** + * Specification constraint for a 'BitmapFont' element, Specifies a particular user-defined bitmap + * font inside a TimeText tag which does not permit the attribute + * * 'letterSpacing' or child elements. + */ +fun bitmapFont() = + constraint("BitmapFont") { + allVersions() + .require( + /* Attributes */ + attribute("family", nonEmpty()), + attribute("size", float(min = 0f), "size must be a positive float"), + ) + .allow( + /* Attributes */ + colorAttributeType(default = "#FFFFFFFF") + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/Font.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/Font.kt new file mode 100644 index 0000000..b2c2bd0 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/Font.kt @@ -0,0 +1,28 @@ +package com.google.wear.watchface.validator.specification.clock.timeText + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.group.part.text.FONT_WEIGHT_OPTIONS +import com.google.wear.watchface.validator.specification.group.part.text.FONT_WIDTH_OPTIONS + +/** + * This font constraint is used by TimeText element and does not permit the attribute + * 'letterSpacing' or child elements. + */ +fun font(): Constraint = + constraint("Font") { + allVersions() + .require( + /* Attributes */ + attribute("family", nonEmpty()), + attribute("size", float(min = 0f), "size must be a positive float"), + ) + .allow( + /* Attributes */ + colorAttributeType(default = "#FFFFFFFF"), + attribute("slant", enum("NORMAL", "ITALIC"), default = "NORMAL"), + attribute("width", enum(FONT_WIDTH_OPTIONS), default = "NORMAL"), + attribute("weight", enum(FONT_WEIGHT_OPTIONS), default = "NORMAL"), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/TimeText.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/TimeText.kt new file mode 100644 index 0000000..846b9b6 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/clock/timeText/TimeText.kt @@ -0,0 +1,43 @@ +package com.google.wear.watchface.validator.specification.clock.timeText + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.angle +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.tintColor + +/** Specification constraint for the `AnalogClock` element. */ +fun timeText() = + constraint("TimeText") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + attribute( + "format", + timeTextFormat(), + "'format' should be a valid placeholder such as 'hh:mm:ss', 'ss', 'hh_10' etc.", + ), + choice( + childElement("Font", ::font, maxOccurs = 1), + childElement("BitmapFont", ::bitmapFont, maxOccurs = 1), + minOccurs = 0, + errorMessage = + "A can not have both and child elements", + ), + ) + .allow( + /* Attributes */ + *pivots, + angle, + alpha, + tintColor, + attribute("hourFormat", enum("12", "24", "SYNC_TO_DEVICE")), + attribute("align", enum("START", "CENTER", "END"), default = "CENTER"), + + /* Child Elements */ + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Attributes.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Attributes.kt new file mode 100644 index 0000000..2f2faa2 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Attributes.kt @@ -0,0 +1,14 @@ +package com.google.wear.watchface.validator.specification.common + +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ElementCondition + +fun colorAttributeType(default: String? = null): ElementCondition = + with(ConditionLibrary) { + attribute( + "color", + color() or dataSource(), + errorMessage = "color must be in the form #RRGGBB or #AARRGGBB", + default, + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Condition.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Condition.kt new file mode 100644 index 0000000..71a6044 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Condition.kt @@ -0,0 +1,135 @@ +package com.google.wear.watchface.validator.specification.common + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.clock.analogClock +import com.google.wear.watchface.validator.specification.clock.digitalClock +import com.google.wear.watchface.validator.specification.group.group +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText + +/** Specification constraint for the `Condition` element. */ +fun condition(): Constraint = + constraint("Condition") { + allVersions() + .require( + /* Child Elements */ + childElement("Expressions", ::expressions), + + /* Conditions */ + condition( + { node, ctx -> + val expressionsChild = + node.children.firstOrNull { it.tagName == "Expressions" } + ?: return@condition false + val expressionNames = + expressionsChild.children + .filter { it.tagName == "Expression" } + .mapNotNull { it.attributes["name"] } + + val compareExpressions = + node.children + .filter { it.tagName == "Compare" } + .mapNotNull { it.attributes["expression"] } + + val expressionNameSet = expressionNames.toSet() + val compareExpressionSet = compareExpressions.toSet() + + expressionNameSet == compareExpressionSet && + expressionNames.size == expressionNameSet.size && + compareExpressions.size == compareExpressionSet.size + }, + "There must be a one-to-one mapping between 'name' attributes and 'expression' attributes.", + ), + ) + .allow( + /* Child Elements */ + childElement("Compare", ::compare), + childElement("Default", ::default, maxOccurs = 1), + ) + } + +/** Specification constraint for the `Expressions` element. */ +fun expressions(): Constraint = + constraint("Expressions") { + allVersions() + .require( + /* Child Elements */ + childElement("Expression", ::expression, minOccurs = 1), + + /* Conditions */ + condition( + childrenHaveUniqueAttribute("name"), + "Each Expression name must be unique", + ), + ) + } + +/** Specification constraint for the `Expression` element. */ +fun expression(): Constraint = + constraint("Expression") { + allVersions() + .require( + /* Attributes */ + attribute("name", nonEmpty()), + + /* Content */ + content( + validExpression(), + "Expression content must be a non-empty, valid expression.", + ), + ) + } + +/** Specification constraint for the `Compare` element. */ +fun compare(): Constraint = + constraint("Compare") { + allVersions() + .require( + /* Attributes */ + attribute("expression", nonEmpty()), + + /* Conditions */ + condition( + hasAtLeastOneChild(), + "A Tag must have at least one child element.", + ), + ) + .allow( + /* Child Elements */ + childElement("Group", ::group), + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + childElement("Condition", ::condition), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + ) + } + +/** Specification constraint for the `Default` element. */ +fun default() = + constraint("Default") { + allVersions() + .require( + /* Conditions */ + condition( + hasAtLeastOneChild(), + "A Tag must have at least one child element.", + ) + ) + .allow( + /* Child Elements */ + childElement("Group", ::group), + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + childElement("Condition", ::condition), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Launch.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Launch.kt new file mode 100644 index 0000000..919f990 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Launch.kt @@ -0,0 +1,28 @@ +package com.google.wear.watchface.validator.specification.common + +import com.google.wear.watchface.validator.constraint.constraint + +internal val PRE_DEFINED_TARGETS = + setOf( + "ALARM", + "BATTERY_STATUS", + "CALENDAR", + "HEALTH_HEART_RATE", + "MESSAGE", + "MUSIC_PLAYER", + "PHONE", + "SETTINGS", + ) + +/** + * Specification constraint for the `Launch` element. Attribute 'target' can be set to a developer + * customized name and hence, no validation is appropriate + */ +fun launch() = + constraint("Launch") { + allVersions() + .require( + /* Attributes */ + attribute("target", enum(PRE_DEFINED_TARGETS) or deepLink()) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Localization.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Localization.kt new file mode 100644 index 0000000..af30a6b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/Localization.kt @@ -0,0 +1,33 @@ +package com.google.wear.watchface.validator.specification.common + +import com.google.wear.watchface.validator.constraint.constraint + +internal val CALENDAR_OPTIONS = + setOf( + "BUDDHIST", + "CHINESE", + "COPTIC", + "DANGI", + "ETHIOPIC", + "ETHIOPIC_AMETE_ALEM", + "GREGORIAN", + "HEBREW", + "INDIAN", + "ISLAMIC", + "ISLAMIC_CIVIL", + "ISLAMIC_UMALQURA", + "JAPANESE", + "PERSIAN", + "ROC", + ) + +fun localization() = + constraint("Localization") { + allVersions() + .allow( + /* Attributes */ + attribute("locales"), + attribute("timeZone"), + attribute("calendar", enum(CALENDAR_OPTIONS)), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/ScreenReader.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/ScreenReader.kt new file mode 100644 index 0000000..dd94ca7 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/ScreenReader.kt @@ -0,0 +1,25 @@ +package com.google.wear.watchface.validator.specification.common + +import com.google.wear.watchface.validator.constraint.constraint + +fun screenReader() = + constraint("ScreenReader") { + allVersions() + .require( + /* Attributes */ + attribute("stringId", nonEmpty()) + ) + .allow( + /* Child Elements */ + childElement("Parameter", ::parameter) + ) + } + +fun parameter() = + constraint("Parameter") { + allVersions() + .require( + /* Attributes */ + attribute("expression", validExpression()) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/reference/Reference.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/reference/Reference.kt new file mode 100644 index 0000000..e99d776 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/reference/Reference.kt @@ -0,0 +1,15 @@ +package com.google.wear.watchface.validator.specification.common.reference + +import com.google.wear.watchface.validator.constraint.constraint + +fun reference() = + constraint("Reference") { + allVersions() + .require( + /* Attributes */ + attribute("name"), + attribute("source"), + attribute("defaultValue", color() or integer() or float()), + ) + // TODO(b/442823511): Implement correct Transform and Reference validation + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Animation.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Animation.kt new file mode 100644 index 0000000..e282512 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Animation.kt @@ -0,0 +1,27 @@ +package com.google.wear.watchface.validator.specification.common.transform + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.angleDirection +import com.google.wear.watchface.validator.specification.interpolationAndControls + +fun animation() = + constraint("Animation") { + allVersions() + .require( + /* Attributes */ + attribute("duration", float(min = 0f), "duration must be a non-negative float") + ) + .allow( + /* Attributes */ + *interpolationAndControls, + angleDirection, + attribute( + "repeat", + integer(min = -1), + errorMessage = + "repeat must be a non-negative integer (or -1 meaning the loop lasts forever)", + default = "0", + ), + attribute("fps", integer(min = 1), "fps must be a positive integer", default = "15"), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Gyro.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Gyro.kt new file mode 100644 index 0000000..925033a --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Gyro.kt @@ -0,0 +1,18 @@ +package com.google.wear.watchface.validator.specification.common.transform + +import com.google.wear.watchface.validator.constraint.constraint + +/** Specification constraint for the `Gyro` element. */ +fun gyro() = + constraint("Gyro") { + allVersions() + .allow( + /* Attributes */ + attribute("x", validExpression()), + attribute("y", validExpression()), + attribute("angle", validExpression()), + attribute("alpha", validExpression()), + attribute("scaleX", validExpression()), + attribute("scaleY", validExpression()), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Transform.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Transform.kt new file mode 100644 index 0000000..1decd86 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/transform/Transform.kt @@ -0,0 +1,21 @@ +package com.google.wear.watchface.validator.specification.common.transform + +import com.google.wear.watchface.validator.constraint.constraint + +/** Specification constraint for the `Transform` element. */ +fun transform() = + constraint("Transform") { + allVersions() + .require( + /* Attributes */ + attribute("target"), + attribute("value", validExpression()), + ) + .allow( + /* Attributes */ + attribute("mode", enum("BY", "TO"), default = "TO"), + + /* Child Elements */ + childElement("Animation", ::animation), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/variant/Variant.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/variant/Variant.kt new file mode 100644 index 0000000..7976cdb --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/common/variant/Variant.kt @@ -0,0 +1,39 @@ +package com.google.wear.watchface.validator.specification.common.variant + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.angleDirection +import com.google.wear.watchface.validator.specification.interpolationAndControls + +/** Specification constraint for the `Variant` element. */ +fun variant() = + constraint("Variant") { + allVersions() + .require( + /* Attributes */ + attribute("mode", equals("AMBIENT"), "mode value must be 'AMBIENT"), + attribute("target"), + attribute("value", validExpression()), + + // TODO(b/442823511) target transformable and it must match an attribute name + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + *interpolationAndControls, + angleDirection, + attribute( + "duration", + float(0.0f, 1.0f), + errorMessage = "duration must be a float in range: (0.0, 1.0)", + default = "1.0", + ), + attribute( + "startOffSet", + float(0.0f, 1.0f), + errorMessage = "startOffSet must be a float in range: [0.0, 1.0)", + default = "0.0", + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Bounding.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Bounding.kt new file mode 100644 index 0000000..4faca81 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Bounding.kt @@ -0,0 +1,66 @@ +package com.google.wear.watchface.validator.specification.complication + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.centerXAndY +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.outlinePadding +import com.google.wear.watchface.validator.specification.startAndEndAngles +import com.google.wear.watchface.validator.specification.widthAndHeight + +/** Specification Constraint for complications that have a bounding box, oval, or arc shape. */ +fun boundingBox(): Constraint = + constraint("BoundingBox") { allVersions().require(*geometricAttributes).allow(outlinePadding) } + +/** Specification Constraint for complications that have a bounding box with rounded corners. */ +fun boundingRoundBox(): Constraint = + constraint("BoundingRoundBox") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes + ) + .allow( + /* Attributes */ + outlinePadding, + attribute("cornerRadius", float(), "cornerRadius must be a float"), + ) + } + +/** Specification Constraint for complications that have a bounding oval shape. */ +fun boundingOval(): Constraint = + constraint("BoundingOval") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes + ) + .allow( + /* Attributes */ + outlinePadding + ) + } + +/** Specification Constraint for complications that have a bounding arc shape. */ +fun boundingArc(): Constraint = + constraint("BoundingArc") { + allVersions() + .require( + /* Attributes */ + *widthAndHeight, + *centerXAndY, + *startAndEndAngles, + attribute("thickness", float(), "thickness must be a float"), + ) + .allow( + /* Attributes */ + outlinePadding, + attribute("isRoundEdge", boolean(), "isRoundEdge must be a boolean"), + attribute( + "direction", + enum("CLOCKWISE", "COUNTER_CLOCKWISE"), + errorMessage = "direction must be CLOCKWISE or COUNTER_CLOCKWISE", + default = "CLOCKWISE", + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Complication.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Complication.kt new file mode 100644 index 0000000..0d75516 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Complication.kt @@ -0,0 +1,30 @@ +package com.google.wear.watchface.validator.specification.complication + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.condition +import com.google.wear.watchface.validator.specification.group.group +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText + +fun complication(): Constraint = + constraint("Complication") { + allVersions() + .require( + /* Attributes */ + attribute("type", enum(COMPLICATION_TYPES)) + ) + .allow( + /* Child Elements */ + childElement("Group", ::group), + childElement("Condition", ::condition), + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + ) + + // TODO(b/443247475) Add complication specific source types to arithmetic expressions + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/ComplicationSlot.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/ComplicationSlot.kt new file mode 100644 index 0000000..ebb7baf --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/ComplicationSlot.kt @@ -0,0 +1,81 @@ +package com.google.wear.watchface.validator.specification.complication + +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.angle +import com.google.wear.watchface.validator.specification.common.screenReader +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.scaleFloatAttributes +import com.google.wear.watchface.validator.specification.tintColor + +fun complicationSlot() = + constraint("ComplicationSlot") { + allVersions() + .require( + /* Attributes */ + *geometricAttributes, + attribute("slotId", integer(), "slotId must be an integer"), + attribute( + "supportedTypes", + { value -> + value + .split(Regex("\\s")) + .filter { it.isNotBlank() } + .all { it in COMPLICATION_TYPES } + }, + "must be a space separated list of supported complication types: $COMPLICATION_TYPES", + ), + // TODO(b/443260010) slotId must be unique + + /* Child Elements */ + choice( + childElement("BoundingBox", ::boundingBox), + childElement("BoundingRoundBox", ::boundingRoundBox), + childElement("BoundingOval", ::boundingOval), + childElement("BoundingArc", ::boundingArc), + errorMessage = + "A ComplicationSlot element must contain exactly one Bounding Area element.", + ), + childElement("Complication", ::complication), + + /* Conditions */ + ElementCondition( + "A ComplicationSlot must contain at least one Complication element per supported Complication Type", + { node, _ -> + val supportedTypes = + node.attributes["supportedTypes"] + ?.split(Regex("\\s")) + ?.filter { it.isNotBlank() } + ?: return@ElementCondition false + + val complicationTypes = + node.children + .asSequence() + .filter { it.tagName == "Complication" } + .mapNotNull { it.attributes["type"] } + .toSet() + + supportedTypes.all { it in complicationTypes } + }, + ), + ) + .allow( + /* Attributes */ + angle, + tintColor, + alpha, + *scaleFloatAttributes, + *pivots, + attribute("name", nonEmpty()), + attribute("displayName"), + attribute("isCustomizable", boolean(), "isCustomizable must be a boolean"), + + /* Child Elements */ + childElement("DefaultProviderPolicy", ::defaultProviderPolicy, maxOccurs = 1), + childElement("ScreenReader", ::screenReader, maxOccurs = 1), + childElement("Variant", ::variant), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Constants.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Constants.kt new file mode 100644 index 0000000..9bacc56 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/Constants.kt @@ -0,0 +1,31 @@ +package com.google.wear.watchface.validator.specification.complication + +internal val COMPLICATION_TYPES = + setOf( + "SHORT_TEXT", + "LONG_TEXT", + "MONOCHROMATIC_IMAGE", + "SMALL_IMAGE", + "PHOTO_IMAGE", + "RANGED_VALUE", + "GOAL_PROGRESS", + "WEIGHTED_ELEMENTS", + "EMPTY", + ) + +internal val DEFAULT_PROVIDERS = + setOf( + "APP_SHORTCUT", + "DATE", + "DAY_OF_WEEK", + "FAVORITE_CONTACT", + "NEXT_EVENT", + "STEP_COUNT", + "SUNRISE_SUNSET", + "TIME_AND_DATE", + "UNREAD_NOTIFICATION_COUNT", + "WATCH_BATTERY", + "WORLD_CLOCK", + "DAY_AND_DATE", + "EMPTY", + ) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/DefaultProviderPolicy.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/DefaultProviderPolicy.kt new file mode 100644 index 0000000..add00a4 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/complication/DefaultProviderPolicy.kt @@ -0,0 +1,22 @@ +package com.google.wear.watchface.validator.specification.complication + +import com.google.wear.watchface.validator.constraint.constraint + +fun defaultProviderPolicy() = + constraint("DefaultProviderPolicy") { + allVersions() + .require( + /* Attributes */ + attribute("defaultSystemProvider", enum(DEFAULT_PROVIDERS)), + attribute("defaultSystemProviderType", enum(COMPLICATION_TYPES)), + ) + .allow( + /* Attributes */ + attribute("primaryProvider"), + attribute("secondaryProvider"), + + /* Child Elements */ + attribute("primaryProviderType", enum(COMPLICATION_TYPES)), + attribute("secondaryProviderType", enum(COMPLICATION_TYPES)), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/Group.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/Group.kt new file mode 100644 index 0000000..ada1b3c --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/Group.kt @@ -0,0 +1,79 @@ +package com.google.wear.watchface.validator.specification.group + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.angle +import com.google.wear.watchface.validator.specification.clock.analogClock +import com.google.wear.watchface.validator.specification.clock.digitalClock +import com.google.wear.watchface.validator.specification.common.condition +import com.google.wear.watchface.validator.specification.common.launch +import com.google.wear.watchface.validator.specification.common.localization +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.screenReader +import com.google.wear.watchface.validator.specification.common.transform.gyro +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.group.configuration.booleanConfiguration +import com.google.wear.watchface.validator.specification.group.configuration.listConfiguration +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.renderMode +import com.google.wear.watchface.validator.specification.scaleFloatAttributes +import com.google.wear.watchface.validator.specification.tintColor + +/** + * Specification constraint for a 'Group' element in a Declarative Watch Face (DWF). + * + * A Group is a container for other elements. Child elements are rendered relative to the position, + * size, angle, and color of the group. + */ +fun group(): Constraint = + constraint("Group") { + allVersions() + .require( + /* Attributes */ + attribute("name"), + *geometricAttributes, + ) + .allow( + /* Attributes */ + attribute("id", nonEmpty()), + angle, + alpha, + renderMode, + tintColor, + *pivots, + *scaleFloatAttributes, + // TODO(b/443260010) id must be unique within the watch face. + + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Variant", ::variant), + childElement("Group", ::group), + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + childElement("Condition", ::condition), + childElement("ListConfiguration", ::listConfiguration), + childElement("BooleanConfiguration", ::booleanConfiguration), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + childElement("Launch", ::launch, maxOccurs = 1), + childElement("Localization", ::localization, maxOccurs = 1), + childElement("Gyro", ::gyro, maxOccurs = 1), + childElement("ScreenReader", ::screenReader, maxOccurs = 1), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/BooleanConfiguration.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/BooleanConfiguration.kt new file mode 100644 index 0000000..59ff2b5 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/BooleanConfiguration.kt @@ -0,0 +1,65 @@ +package com.google.wear.watchface.validator.specification.group.configuration + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.clock.analogClock +import com.google.wear.watchface.validator.specification.clock.digitalClock +import com.google.wear.watchface.validator.specification.common.condition +import com.google.wear.watchface.validator.specification.group.group +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText + +/** + * Specification constraint for a 'BooleanConfiguration' element. + * + * A BooleanConfiguration must be defined in the user configuration section of the XML. Then it may + * be referenced by id from a Scene element. + */ +fun booleanConfiguration() = + constraint("BooleanConfiguration") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + + /* Child Elements */ + childElement("BooleanOption", ::booleanOption, minOccurs = 1, maxOccurs = 2), + + /* Conditions */ + condition( + childrenHaveUniqueAttribute("id"), + "BooleanOption 'id' attributes must be unique within a BooleanConfiguration.", + ), + ) + + // TODO(b/446857123): CANNOT BE NESTED WITHIN A SCENE WHEN id uses 2 or more configuration + // options as data, + // TODO(b/443260010) validate that a BooleanConfiguration is declared first in + // UserConfiguration. + } + +/** Specification constraint for a 'BooleanOption' element. */ +private fun booleanOption() = + constraint("BooleanOption") { + allVersions() + .require( + /* Attributes */ + attribute( + "id", + enum("TRUE", "FALSE"), + "Attribute 'id' must be either 'TRUE' or 'FALSE'.", + ) + ) + .allow( + /* Child Elements */ + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + childElement("Group", ::group), + childElement("Condition", ::condition), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/ListConfiguration.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/ListConfiguration.kt new file mode 100644 index 0000000..f712d01 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/configuration/ListConfiguration.kt @@ -0,0 +1,59 @@ +package com.google.wear.watchface.validator.specification.group.configuration + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.clock.analogClock +import com.google.wear.watchface.validator.specification.clock.digitalClock +import com.google.wear.watchface.validator.specification.common.condition +import com.google.wear.watchface.validator.specification.group.group +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText + +/** + * Specification constraint for a 'ListConfiguration' element in a Declarative Watch Face (DWF). + * + * A List Configuration allows the user to select one item from a list when customizing the watch + * face in the watch face editor. + */ +fun listConfiguration() = + constraint("ListConfiguration") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + + /* Child Elements */ + childElement("ListOption", ::listOption, maxOccurs = 100), + + /* Conditions*/ + condition( + childrenHaveUniqueAttribute("id"), + "ListOption 'id' attributes must be unique within a ListConfiguration.", + ), + ) + + // TODO(b/443260010) validate that a ListConfiguration is declared first in + // UserConfiguration. + } + +/** Specification constraint for a 'ListOption' element. */ +private fun listOption() = + constraint("ListOption") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()) + ) + .allow( + /* Child Elements */ + childElement("PartText", ::partText), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("PartDraw", ::partDraw), + childElement("Group", ::group), + childElement("Condition", ::condition), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/AbstractPartType.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/AbstractPartType.kt new file mode 100644 index 0000000..879ab54 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/AbstractPartType.kt @@ -0,0 +1,50 @@ +package com.google.wear.watchface.validator.specification.group.part + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.ConstraintBuilder +import com.google.wear.watchface.validator.specification.alpha +import com.google.wear.watchface.validator.specification.angle +import com.google.wear.watchface.validator.specification.common.launch +import com.google.wear.watchface.validator.specification.common.localization +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.screenReader +import com.google.wear.watchface.validator.specification.common.transform.gyro +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.geometricAttributes +import com.google.wear.watchface.validator.specification.pivots +import com.google.wear.watchface.validator.specification.renderMode +import com.google.wear.watchface.validator.specification.scaleFloatAttributes +import com.google.wear.watchface.validator.specification.tintColor + +fun ConstraintBuilder.abstractPartType() { + allVersions() + .require( + /* Attributes */ + *geometricAttributes + ) + .allow( + /* Attributes */ + attribute("name"), + angle, + alpha, + renderMode, + tintColor, + *scaleFloatAttributes, + *pivots, + + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Variant", ::variant), + childElement("Gyro", ::gyro, maxOccurs = 1), + childElement("Launch", ::launch, maxOccurs = 1), + childElement("Localization", ::localization, maxOccurs = 1), + childElement("ScreenReader", ::screenReader, maxOccurs = 1), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) +} diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImage.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImage.kt new file mode 100644 index 0000000..60675b5 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImage.kt @@ -0,0 +1,18 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun animatedImage(): Constraint = + constraint("AnimatedImage") { + allVersions() + .require( + /* Attributes */ + attribute("resource", nonEmpty()), + attribute("format", enum("IMAGE", "AGIF", "WEBP")), + ) + .allow( + /* Attributes */ + attribute("thumbnail") + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImages.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImages.kt new file mode 100644 index 0000000..33ab22d --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimatedImages.kt @@ -0,0 +1,34 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun animatedImages(): Constraint = + constraint("AnimatedImages") { + allVersions() + .require( + /* Attributes */ + attribute( + "change", + enum("TAP", "ON_VISIBLE", "ON_NEXT_SECOND", "ON_NEXT_MINUTE", "ON_NEXT_HOUR"), + default = "TAP", + ), + + /* Child Elements */ + choice( + childElement("AnimatedImage", ::animatedImage), + childElement("SequenceImages", ::sequenceImages), + ), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute( + "changeDirection", + enum("FORWARD", "BACKWARD", "RANDOM"), + default = "FORWARD", + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimationController.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimationController.kt new file mode 100644 index 0000000..745ba32 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/AnimationController.kt @@ -0,0 +1,53 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +internal val PLAY_OPTIONS = + setOf("TAP", "ON_VISIBLE", "ON_NEXT_SECOND", "ON_NEXT_MINUTE", "ON_NEXT_HOUR") + +fun animationController(): Constraint = + constraint("AnimationController") { + allVersions() + .require( + /* Attributes */ + attribute( + "play", + { value -> + value + .split(Regex("\\s")) + .filter { it.isNotBlank() } + .all { it in PLAY_OPTIONS } + }, + "'play' must be a space separated list of play options: $PLAY_OPTIONS", + ) + ) + .allow( + /* Attributes */ + attribute( + "delayPlay", + float(min = 0.0f), + "delayPlay must be a positive float", + default = "0", + ), + attribute( + "delayRepeat", + float(min = 0.0f), + "delayRepeat must be a positive float", + default = "0", + ), + attribute( + "beforePlaying", + enum("DO_NOTHING", "FIRST_FRAME", "THUMBNAIL", "HIDE"), + default = "DO_NOTHING", + ), + attribute( + "afterPlaying", + enum("DO_NOTHING", "FIRST_FRAME", "THUMBNAIL", "HIDE"), + default = "DO_NOTHING", + ), + attribute("repeat", boolean(), default = "FALSE"), + attribute("resumePlayBack", boolean(), default = "FALSE"), + attribute("loopCount", integer(min = 0), "delayRepeat must be a positive integer"), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/PartAnimatedImage.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/PartAnimatedImage.kt new file mode 100644 index 0000000..fefafb7 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/PartAnimatedImage.kt @@ -0,0 +1,60 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.abstractPartType + +internal val BLEND_MODE_OPTIONS = + setOf( + "CLEAR", + "COLOR", + "COLOR_BURN", + "COLOR_DODGE", + "DARKEN", + "DIFFERENCE", + "DST", + "DST_ATOP", + "DST_IN", + "DST_OUT", + "DST_OVER", + "EXCLUSION", + "HARD_LIGHT", + "HUE", + "LIGHTEN", + "LUMINOSITY", + "MODULATE", + "MULTIPLY", + "OVERLAY", + "PLUS", + "SATURATION", + "SCREEN", + "SOFT_LIGHT", + "SRC", + "SRC_ATOP", + "SRC_IN", + "SRC_OUT", + "SRC_OVER", + "XOR", + ) + +fun partAnimatedImage() = + constraint("PartAnimatedImage") { + abstractPartType() + + allVersions() + .require( + /* Child Elements */ + childElement("AnimationController", ::animationController, maxOccurs = 1), + choice( + childElement("AnimatedImage", ::animatedImage, maxOccurs = 1), + childElement("AnimatedImages", ::animatedImages, maxOccurs = 1), + childElement("SequenceImages", ::sequenceImages, maxOccurs = 1), + ), + ) + .allow( + /* Attributes */ + attribute("blendMode", enum(BLEND_MODE_OPTIONS)), + + /* Child Elements */ + childElement("Thumbnail", ::thumbnail, maxOccurs = 1), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/SequenceImages.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/SequenceImages.kt new file mode 100644 index 0000000..b78114c --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/SequenceImages.kt @@ -0,0 +1,36 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.image.image + +fun sequenceImages(): Constraint = + constraint("SequenceImages") { + allVersions() + .require( + /* Child Elements */ + childElement("Image", ::image) + ) + .allow( + /* Attributes */ + attribute( + "loopCount", + integer(min = 0), + "loopCount must be a positive integer", + default = "1", + ), + attribute("thumbnail"), + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute( + "frameRate", + integer(1, 60), + "frameRate must be a positive integer", + default = "15", + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/Thumbnail.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/Thumbnail.kt new file mode 100644 index 0000000..4ec5cea --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/animatedImage/Thumbnail.kt @@ -0,0 +1,13 @@ +package com.google.wear.watchface.validator.specification.group.part.animatedImage + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun thumbnail(): Constraint = + constraint("Thumbnail") { + allVersions() + .require( + /* Attributes */ + attribute("resource", nonEmpty()) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/PartDraw.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/PartDraw.kt new file mode 100644 index 0000000..750e15f --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/PartDraw.kt @@ -0,0 +1,30 @@ +package com.google.wear.watchface.validator.specification.group.part.draw + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.UNBOUNDED +import com.google.wear.watchface.validator.specification.group.part.abstractPartType +import com.google.wear.watchface.validator.specification.group.part.draw.shape.arc +import com.google.wear.watchface.validator.specification.group.part.draw.shape.ellipse +import com.google.wear.watchface.validator.specification.group.part.draw.shape.line +import com.google.wear.watchface.validator.specification.group.part.draw.shape.rectangle +import com.google.wear.watchface.validator.specification.group.part.draw.shape.roundRectangle + +fun partDraw(): Constraint = + constraint("PartDraw") { + abstractPartType() + + allVersions() + .require( + + /* Child Elements */ + choice( + childElement("Line", ::line), + childElement("Arc", ::arc), + childElement("Rectangle", ::rectangle), + childElement("Ellipse", ::ellipse), + childElement("RoundRectangle", ::roundRectangle), + maxOccurs = UNBOUNDED, + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/LinearGradient.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/LinearGradient.kt new file mode 100644 index 0000000..d395eb0 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/LinearGradient.kt @@ -0,0 +1,39 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.gradient + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform + +fun linearGradient(): Constraint = + constraint("LinearGradient") { + allVersions() + .require( + /* Attributes */ + attribute("startX", float()), + attribute("startY", float()), + attribute("endX", float()), + attribute("endY", float()), + attribute( + "colors", + argbVector() or dataSource(), + "Attribute 'colors' must be a space separated list of hex ARGB colors", + ), + attribute( + "positions", + floatVector(), + "Attribute 'positions' must be a space separated list of floats in range [0, 1]", + ), // TODO(b/443782460) validate each float is in range [0, 1] + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform, maxOccurs = 4) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/RadialGradient.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/RadialGradient.kt new file mode 100644 index 0000000..64a05f1 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/RadialGradient.kt @@ -0,0 +1,38 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.gradient + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform + +fun radialGradient(): Constraint = + constraint("RadialGradient") { + allVersions() + .require( + /* Attributes */ + attribute("centerX", float()), + attribute("centerY", float()), + attribute("radius", float(min = 0.0F), "radius must be a positive float"), + attribute( + "colors", + argbVector() or dataSource(), + "Attribute 'colors' must be a space separated list of hex ARGB colors", + ), + attribute( + "positions", + floatVector(), + "Attribute 'positions' must be a space separated list of floats in range [0, 1]", + ), // TODO(b/443782460) validate each float is in range [0, 1] + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform, maxOccurs = 4) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/SweepGradient.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/SweepGradient.kt new file mode 100644 index 0000000..ee74e5d --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/gradient/SweepGradient.kt @@ -0,0 +1,45 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.gradient + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.startAndEndAngles + +fun sweepGradient(): Constraint = + constraint("SweepGradient") { + allVersions() + .require( + /* Attributes */ + *startAndEndAngles, + attribute("centerX", float()), + attribute("centerY", float()), + attribute( + "colors", + argbVector() or dataSource(), + "Attribute 'colors' must be a space separated list of hex ARGB colors", + ), + attribute( + "positions", + floatVector(), + "Attribute 'positions' must be a space separated list of floats in range [0, 1]", + ), // TODO(b/443782460) validate each float is in range [0, 1] + ) + .allow( + /* Attributes */ + attribute( + "direction", + enum("CLOCKWISE", "COUNTER_CLOCKWISE"), + default = "CLOCKWISE", + ), + /* Child Elements */ + childElement("Transform", ::transform, maxOccurs = 4), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Arc.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Arc.kt new file mode 100644 index 0000000..a72e2dc --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Arc.kt @@ -0,0 +1,54 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.shape + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.style.stroke +import com.google.wear.watchface.validator.specification.group.part.draw.style.weightedStroke +import com.google.wear.watchface.validator.specification.startAndEndAngles + +fun arc(): Constraint = + constraint("Arc") { + allVersions() + .require( + /* Attributes */ + *startAndEndAngles, + attribute("width", float(min = 0.0F), "width must be a positive float"), + attribute("height", float(min = 0.0F), "height must be a positive float"), + attribute("centerX", float()), + attribute("centerY", float()), + + /* Child Elements */ + choice( + childElement("Stroke", ::stroke, maxOccurs = 1), + childElement("WeightedStroke", ::weightedStroke, maxOccurs = 1), + errorMessage = + "Either Stroke or WeightedStroke is required. Note that WeightedStroke is only supported in WFFv2 and above.", + ), + ) + .allow( + /* Attributes */ + attribute( + "direction", + enum("CLOCKWISE", "COUNTER_CLOCKWISE"), + default = "CLOCKWISE", + ), + + /* Child Elements */ + childElement("Transform", ::transform), + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("WeightedStroke", ::weightedStroke, maxOccurs = 1) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Ellipse.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Ellipse.kt new file mode 100644 index 0000000..e9c1ed3 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Ellipse.kt @@ -0,0 +1,37 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.shape + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.style.fill +import com.google.wear.watchface.validator.specification.group.part.draw.style.stroke + +fun ellipse(): Constraint = + constraint("Ellipse") { + allVersions() + .require( + /* Attributes */ + attribute("x", float()), + attribute("y", float()), + attribute("width", float(min = 0.0F), "width must be a positive float"), + attribute("height", float(min = 0.0F), "height must be a positive float"), + + /* Child Elements */ + choice( + childElement("Stroke", ::stroke, maxOccurs = 1), + childElement("Fill", ::fill, maxOccurs = 1), + ), + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Line.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Line.kt new file mode 100644 index 0000000..e8308cb --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Line.kt @@ -0,0 +1,45 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.shape + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.style.stroke +import com.google.wear.watchface.validator.specification.group.part.draw.style.weightedStroke + +fun line(): Constraint = + constraint("Line") { + allVersions() + .require( + /* Attributes */ + attribute("startX", float()), + attribute("startY", float()), + attribute("endX", float()), + attribute("endY", float()), + + /* Child Elements */ + choice( + childElement("Stroke", ::stroke, maxOccurs = 1), + childElement("WeightedStroke", ::weightedStroke, maxOccurs = 1), + errorMessage = + "Either Stroke or WeightedStroke is required. Note that WeightedStroke is only supported in WFFv3 and above.", + ), + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform) + ) + + versions(3 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + childElement("WeightedStroke", ::weightedStroke, maxOccurs = 1) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Rectangle.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Rectangle.kt new file mode 100644 index 0000000..0b0f4b3 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/Rectangle.kt @@ -0,0 +1,37 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.shape + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.style.fill +import com.google.wear.watchface.validator.specification.group.part.draw.style.stroke + +fun rectangle(): Constraint = + constraint("Rectangle") { + allVersions() + .require( + /* Attributes */ + attribute("x", float()), + attribute("y", float()), + attribute("width", float(min = 0.0F), "width must be a positive float"), + attribute("height", float(min = 0.0F), "height must be a positive float"), + + /* Child Elements */ + choice( + childElement("Stroke", ::stroke, maxOccurs = 1), + childElement("Fill", ::fill, maxOccurs = 1), + ), + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/RoundRectangle.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/RoundRectangle.kt new file mode 100644 index 0000000..4a48153 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/shape/RoundRectangle.kt @@ -0,0 +1,39 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.shape + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.style.fill +import com.google.wear.watchface.validator.specification.group.part.draw.style.stroke + +fun roundRectangle(): Constraint = + constraint("RoundRectangle") { + allVersions() + .require( + /* Attributes */ + attribute("x", float()), + attribute("y", float()), + attribute("cornerRadiusX", float()), + attribute("cornerRadiusY", float()), + attribute("width", float(min = 0.0F), "width must be a positive float"), + attribute("height", float(min = 0.0F), "height must be a positive float"), + + /* Child Elements */ + choice( + childElement("Stroke", ::stroke, maxOccurs = 1), + childElement("Fill", ::fill, maxOccurs = 1), + ), + ) + .allow( + /* Child Elements */ + childElement("Transform", ::transform) + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Fill.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Fill.kt new file mode 100644 index 0000000..97be895 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Fill.kt @@ -0,0 +1,33 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.style + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.linearGradient +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.radialGradient +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.sweepGradient + +fun fill(): Constraint = + constraint("Fill") { + allVersions() + .require( + /* Attributes */ + colorAttributeType() + ) + .allow( + /* Child Elements */ + childElement("LinearGradient", ::linearGradient), + childElement("RadialGradient", ::radialGradient), + childElement("SweepGradient", ::sweepGradient), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Stroke.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Stroke.kt new file mode 100644 index 0000000..b3bee1f --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/Stroke.kt @@ -0,0 +1,46 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.style + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.linearGradient +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.radialGradient +import com.google.wear.watchface.validator.specification.group.part.draw.gradient.sweepGradient + +fun stroke(): Constraint = + constraint("Stroke") { + allVersions() + .require( + /* Attributes */ + colorAttributeType(), + attribute("thickness", float(min = 0.0F), "thickness must be a non-negative float"), + /* Child Elements */ + + /* Conditions */ + ) + .allow( + /* Attributes */ + attribute( + "dashIntervals", + floatVector(), + "dashIntervals must be a space separated vector of float", + ), + attribute("dashPhase", float(), "dashPhase must be a float"), + attribute("cap", enum("BUTT", "ROUND", "SQUARE"), default = "BUTT"), + + /* Child Elements */ + childElement("LinearGradient", ::linearGradient), + childElement("RadialGradient", ::radialGradient), + childElement("SweepGradient", ::sweepGradient), + childElement("Transform", ::transform), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/WeightedStroke.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/WeightedStroke.kt new file mode 100644 index 0000000..fa78e00 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/draw/style/WeightedStroke.kt @@ -0,0 +1,52 @@ +package com.google.wear.watchface.validator.specification.group.part.draw.style + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform + +fun weightedStroke(): Constraint = + constraint("WeightedStroke") { + allVersions() + .require( + /* Attributes */ + attribute( + "colors", + argbVector() or dataSource(), + "Attribute 'colors' must be a space separated list of hex ARGB colors or a [SOURCE]", + ), + attribute("thickness", float(min = 0f), "thickness must be a positive float"), + ) + .allow( + /* Attributes */ + attribute( + "weights", + floatVector() or dataSource(), + "Attribute 'weights' must be a space separated list of floats", + default = "0.0", + ), + attribute( + "discreteGap", + float(min = 0.0F), + "discreteGap must be a non-negative float", + default = "0.0", + ), + attribute( + "interpolate", + boolean() or dataSource(), + "interpolate must be a boolean", + default = "FALSE", + ), + attribute("cap", enum("BUTT", "ROUND", "SQUARE"), default = "BUTT"), + + /* Child Elements */ + childElement("Transform", ::transform), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Image.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Image.kt new file mode 100644 index 0000000..45831c9 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Image.kt @@ -0,0 +1,13 @@ +package com.google.wear.watchface.validator.specification.group.part.image + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun image(): Constraint = + constraint("Image") { + allVersions() + .require( + /* Attributes */ + attribute("resource", nonEmpty()) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Images.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Images.kt new file mode 100644 index 0000000..eac77dd --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Images.kt @@ -0,0 +1,32 @@ +package com.google.wear.watchface.validator.specification.group.part.image + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.default + +fun images(): Constraint = + constraint("Images") { + allVersions() + .require( + /* Attributes */ + attribute( + "change", + enum("TAP", "ON_VISIBLE", "ON_NEXT_SECOND", "ON_NEXT_MINUTE", "ON_NEXT_HOUR"), + default = "TAP", + ), + + /* Child Elements */ + childElement("Image", ::image), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute( + "changeDirection", + enum("FORWARD", "BACKWARD", "RANDOM"), + default = "FORWARD", + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/PartImage.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/PartImage.kt new file mode 100644 index 0000000..47f9a63 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/PartImage.kt @@ -0,0 +1,40 @@ +package com.google.wear.watchface.validator.specification.group.part.image + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.abstractPartType +import com.google.wear.watchface.validator.specification.group.part.animatedImage.BLEND_MODE_OPTIONS +import com.google.wear.watchface.validator.specification.group.part.image.imageFilter.imageFilters + +fun partImage(): Constraint = + constraint("PartImage") { + abstractPartType() + + allVersions() + .require( + /* Child Elements */ + choice( + childElement("Image", ::image, maxOccurs = 1), + childElement("Images", ::images, maxOccurs = 1), + childElement("Photos", ::photos, maxOccurs = 1), + errorMessage = + "One of Image, Images, or Photos is required. Note that Photos is only supported in WFFv3 and above.", + ) + ) + .allow( + /* Attributes */ + + /* Child Elements */ + childElement("ImageFilters", ::imageFilters, maxOccurs = 1) + ) + + versions(3 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute("blendMode", enum(BLEND_MODE_OPTIONS)), + + /* Child Elements */ + childElement("Photos", ::photos, maxOccurs = 1), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Photos.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Photos.kt new file mode 100644 index 0000000..f013318 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/Photos.kt @@ -0,0 +1,37 @@ +package com.google.wear.watchface.validator.specification.group.part.image + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.widthAndHeight + +fun photos(): Constraint = + constraint("Photos") { + allVersions() + .require( + /* Attributes */ + attribute("source", nonEmpty()), + attribute("defaultImageResource", nonEmpty()), + // TODO(b/443752403) 'source' must correspond to a PhotosConfiguration id + ) + .allow( + /* Attributes */ + *widthAndHeight, + attribute("change", enum("TAP", "ON_VISIBLE")), + attribute( + "changeAfterEvery", + integer(3, 10), + "changeAfterEvery must be an integer in the range [3. 10]", + ), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute( + "changeDirection", + enum("FORWARD", "BACKWARD", "RANDOM"), + default = "FORWARD", + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/HsbFilter.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/HsbFilter.kt new file mode 100644 index 0000000..40f193f --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/HsbFilter.kt @@ -0,0 +1,29 @@ +package com.google.wear.watchface.validator.specification.group.part.image.imageFilter + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun hsbFilter(): Constraint = + constraint("HsbFilter") { + allVersions() + .allow( + /* Attributes */ + attribute( + "hueRotate", + float(0.0f, 360.0f), + "hueRotate must be a float in the range [0, 360]", + ), + attribute( + "saturate", + float(0.0f, 1.0f), + "saturate must be a float in the range [0, 1]", + default = "1.0", + ), + attribute( + "brightness", + float(0.0f, 1.0f), + "brightness must be a float in the range [0, 1]", + default = "1.0", + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/ImageFilters.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/ImageFilters.kt new file mode 100644 index 0000000..d03719f --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/image/imageFilter/ImageFilters.kt @@ -0,0 +1,13 @@ +package com.google.wear.watchface.validator.specification.group.part.image.imageFilter + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun imageFilters(): Constraint = + constraint("ImageFilters") { + allVersions() + .require( + /* Child Elements */ + childElement("HsbFilter", ::hsbFilter) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/BitmapFont.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/BitmapFont.kt new file mode 100644 index 0000000..a5c5160 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/BitmapFont.kt @@ -0,0 +1,48 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +/** + * Specification constraint for a 'BitmapFont' element, Specifies a particular user-defined bitmap + * font. + */ +fun bitmapFont() = + constraint("BitmapFont") { + allVersions() + .require( + /* Attributes */ + attribute("family", nonEmpty()), + attribute("size", float(min = 0f), "size must be a positive float"), + ) + .allow( + /* Attributes */ + colorAttributeType(default = "#FFFFFFFF"), + + /* Child Elements */ + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute("letterSpacing", float(), default = "0.0") + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Font.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Font.kt new file mode 100644 index 0000000..8d9af0b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Font.kt @@ -0,0 +1,58 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.text.decoration.outGlow +import com.google.wear.watchface.validator.specification.group.part.text.decoration.outline +import com.google.wear.watchface.validator.specification.group.part.text.decoration.shadow +import com.google.wear.watchface.validator.specification.group.part.text.decoration.strikeThrough +import com.google.wear.watchface.validator.specification.group.part.text.decoration.underline +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun font(): Constraint = + constraint("Font") { + allVersions() + .require( + /* Attributes */ + attribute("family", nonEmpty()), + attribute("size", float(min = 0f), "size must be a positive float"), + ) + .allow( + /* Attributes */ + colorAttributeType(default = "#FFFFFFFF"), + attribute("slant", enum("NORMAL", "ITALIC"), default = "NORMAL"), + attribute("width", enum(FONT_WIDTH_OPTIONS), default = "NORMAL"), + attribute("weight", enum(FONT_WEIGHT_OPTIONS), default = "NORMAL"), + + /* Child Elements */ + childElement("Shadow", ::shadow), + childElement("Outline", ::outline), + childElement("OutGlow", ::outGlow), + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute("letterSpacing", float(), default = "0.0") + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/FontOptions.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/FontOptions.kt new file mode 100644 index 0000000..7805c28 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/FontOptions.kt @@ -0,0 +1,28 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +internal val FONT_WIDTH_OPTIONS = + setOf( + "ULTRA_CONDENSED", + "EXTRA_CONDENSED", + "CONDENSED", + "SEMI_CONDENSED", + "NORMAL", + "SEMI_EXPANDED", + "EXPANDED", + "EXTRA_EXPANDED", + "ULTRA_EXPANDED", + ) +internal val FONT_WEIGHT_OPTIONS = + setOf( + "THIN", + "ULTRA_LIGHT", + "EXTRA_LIGHT", + "LIGHT", + "MEDIUM", + "NORMAL", + "SEMI_BOLD", + "ULTRA_BOLD", + "EXTRA_BOLD", + "BLACK", + "EXTRA_BLACK", + ) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/PartText.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/PartText.kt new file mode 100644 index 0000000..3d56141 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/PartText.kt @@ -0,0 +1,19 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.abstractPartType + +fun partText(): Constraint = + constraint("PartText") { + abstractPartType() + + allVersions() + .require( + /* Child Elements */ + choice( + childElement("Text", ::text, maxOccurs = 1), + childElement("TextCircular", ::textCircular, maxOccurs = 1), + ) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Text.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Text.kt new file mode 100644 index 0000000..66a2119 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/Text.kt @@ -0,0 +1,26 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint + +fun text(): Constraint = + constraint("Text") { + allVersions() + .allow( + /* Attributes */ + attribute("align", enum("START", "CENTER", "END"), default = "CENTER"), + attribute("ellipsis", boolean(), default = "FALSE"), + attribute("maxLines", integer()), + + /* Child Elements */ + childElement("Font", ::font), + childElement("BitmapFont", ::bitmapFont), + ) + + versions(3 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + attribute("isAutoSize", boolean(), default = "FALSE") + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/TextCircular.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/TextCircular.kt new file mode 100644 index 0000000..8cf5f66 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/TextCircular.kt @@ -0,0 +1,42 @@ +package com.google.wear.watchface.validator.specification.group.part.text + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.centerXAndY +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.startAndEndAngles +import com.google.wear.watchface.validator.specification.widthAndHeight + +fun textCircular(): Constraint = + constraint("TextCircular") { + allVersions() + .require( + /* Attributes */ + *centerXAndY, + *widthAndHeight, + *startAndEndAngles, // TODO(b/442823511) mark as transformable + ) + .allow( + /* Attributes */ + attribute( + "direction", + enum("CLOCKWISE", "COUNTER_CLOCKWISE"), + default = "CLOCKWISE", + ), + attribute("align", enum("START", "CENTER", "END"), "CENTER"), + attribute("ellipsis", boolean(), errorMessage = "ellipsis must be a boolean"), + + /* Child Elements */ + childElement("Transform", ::transform), + childElement("BitmapFont", ::bitmapFont), + childElement("Font", ::font), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + childElement("Reference", ::reference) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/OutGlow.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/OutGlow.kt new file mode 100644 index 0000000..b58cd47 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/OutGlow.kt @@ -0,0 +1,38 @@ +package com.google.wear.watchface.validator.specification.group.part.text.decoration + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun outGlow(): Constraint = + constraint("OutGlow") { + allVersions() + .require( + /* Attributes */ + colorAttributeType(), + attribute("radius", float(min = 0.0f), default = "8.0"), + ) + .allow( + /* Child Elements */ + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Outline.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Outline.kt new file mode 100644 index 0000000..9dc3076 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Outline.kt @@ -0,0 +1,37 @@ +package com.google.wear.watchface.validator.specification.group.part.text.decoration + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun outline() = + constraint("Outline") { + allVersions() + .require( + /* Attributes */ + colorAttributeType(), + attribute("width", float(min = 0.0f), default = "2.0"), + ) + .allow( + /* Child Elements */ + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Shadow.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Shadow.kt new file mode 100644 index 0000000..ae7f19f --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Shadow.kt @@ -0,0 +1,40 @@ +package com.google.wear.watchface.validator.specification.group.part.text.decoration + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun shadow(): Constraint = + constraint("Shadow") { + allVersions() + .require( + /* Attributes */ + colorAttributeType(), + attribute("offsetX", float(), default = "2.0"), + attribute("offsetY", float(), default = "2.0"), + attribute("radius", float(min = 0.0f), default = "2.0"), + ) + .allow( + /* Child Elements */ + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/StrikeThrough.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/StrikeThrough.kt new file mode 100644 index 0000000..457ba54 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/StrikeThrough.kt @@ -0,0 +1,22 @@ +package com.google.wear.watchface.validator.specification.group.part.text.decoration + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun strikeThrough(): Constraint = + constraint("StrikeThrough") { + allVersions() + .allow( + /* Child Elements */ + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Underline.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Underline.kt new file mode 100644 index 0000000..fdf5245 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/decoration/Underline.kt @@ -0,0 +1,22 @@ +package com.google.wear.watchface.validator.specification.group.part.text.decoration + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.group.part.text.formatter.inlineImage +import com.google.wear.watchface.validator.specification.group.part.text.formatter.lower +import com.google.wear.watchface.validator.specification.group.part.text.formatter.template +import com.google.wear.watchface.validator.specification.group.part.text.formatter.upper + +fun underline(): Constraint = + constraint("Underline") { + allVersions() + .allow( + /* Child Elements */ + childElement("Underline", ::underline), + childElement("StrikeThrough", ::strikeThrough), + childElement("InlineImage", ::inlineImage), + childElement("Template", ::template), + childElement("Upper", ::upper), + childElement("Lower", ::lower), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/InlineImage.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/InlineImage.kt new file mode 100644 index 0000000..f76e4cf --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/InlineImage.kt @@ -0,0 +1,33 @@ +package com.google.wear.watchface.validator.specification.group.part.text.formatter + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.colorAttributeType +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.widthAndHeight + +fun inlineImage(): Constraint = + constraint("InlineImage") { + allVersions() + .require( + /* Attributes */ + *widthAndHeight, + attribute("resource", nonEmpty()), + ) + .allow( + /* Attributes */ + colorAttributeType(default = "#FFFFFFFF"), + attribute("source", validExpression()), + attribute("overlapLeft", float()), + attribute("overlapRight", float()), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Lower.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Lower.kt new file mode 100644 index 0000000..6257ad9 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Lower.kt @@ -0,0 +1,12 @@ +package com.google.wear.watchface.validator.specification.group.part.text.formatter + +import com.google.wear.watchface.validator.constraint.constraint + +fun lower() = + constraint("Lower") { + allVersions() + .allow( + /* Child Elements */ + childElement("Template", ::template) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Template.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Template.kt new file mode 100644 index 0000000..5b43619 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Template.kt @@ -0,0 +1,18 @@ +package com.google.wear.watchface.validator.specification.group.part.text.formatter + +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.common.parameter + +/** + * Specification constraint for a 'Template' element. These elements can contain 'c-like' string + * formatters in their content. + */ +fun template() = + constraint("Template") { + allVersions() + .allow( + /* Child Elements */ + childElement("Parameter", ::parameter) + // TODO(b/443729856): validate content as a string template + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Upper.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Upper.kt new file mode 100644 index 0000000..0b41604 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/group/part/text/formatter/Upper.kt @@ -0,0 +1,12 @@ +package com.google.wear.watchface.validator.specification.group.part.text.formatter + +import com.google.wear.watchface.validator.constraint.constraint + +fun upper() = + constraint("Upper") { + allVersions() + .allow( + /* Child Elements */ + childElement("Template", ::template) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/AbstractConfigurationType.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/AbstractConfigurationType.kt new file mode 100644 index 0000000..160c279 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/AbstractConfigurationType.kt @@ -0,0 +1,34 @@ +package com.google.wear.watchface.validator.specification.userConfiguration + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.ConstraintBuilder + +fun ConstraintBuilder.abstractConfigurationType() { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + attribute("displayName"), + attribute("defaultValue"), + ) + .allow( + /* Attributes */ + attribute("icon"), + attribute("screenReaderText"), + ) + + versions(4 to MAX_WFF_VERSION).allow(attribute("highlight")) +} + +fun ConstraintBuilder.abstractConfigurationPartType() = + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()) + ) + .allow( + /* Attributes */ + attribute("icon"), + attribute("screenReaderText"), + attribute("displayName", nonEmpty()), + ) diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/Flavor.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/Flavor.kt new file mode 100644 index 0000000..556c2dc --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/Flavor.kt @@ -0,0 +1,87 @@ +package com.google.wear.watchface.validator.specification.userConfiguration + +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.complication.defaultProviderPolicy + +/** Specification constraint for a 'Flavors' element. */ +fun flavors() = + constraint("Flavors") { + allVersions() + .require( + /* Attributes */ + attribute("defaultValue", nonEmpty()), + + /* Child Elements */ + childElement("Flavor", ::flavor, maxOccurs = 20), + + /* Conditions */ + ElementCondition( + "Attribute 'defaultValue' must match the id of one of the Flavor children.", + { node, _ -> + val defaultValue = + node.attributes["defaultValue"] ?: return@ElementCondition false + node.children.any { it.attributes["id"]?.equals(defaultValue) ?: false } + }, + ), + ) + } + +/** Specification constraint for a 'Flavor' element. */ +private fun flavor() = + constraint("Flavor") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + attribute("displayName"), + // TODO(b/443260010) make 'id' unique across user configuration. + + /* Child Elements */ + childElement("Configuration", ::configuration, maxOccurs = 100), + ) + .allow( + /* Attributes */ + attribute("icon"), + attribute("screenReaderText"), + + /* Child Elements */ + childElement("ComplicationSlot", ::complicationSlot), + ) + } + +/** Specification constraint for a 'Configuration' element. */ +private fun configuration() = + constraint("Configuration") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + attribute("optionId", nonEmpty()), + // TODO(b/443260010) 'id' should match a previously defined configuration id, + // TODO(b/443260010) should be unique optionId + ) + .allow( + /* Attributes */ + attribute("screenReaderText") + ) + } + +/** Specification constraint for a 'ComplicationSlot' element inside a flavor configuration. */ +fun complicationSlot() = + constraint("ComplicationSlot") { + allVersions() + .require( + /* Attributes */ + attribute("slotId", integer(), "slotId must be an integer"), + // TODO(b/443752403) slotId must match one of the slotIds defined in the Scene + + /* Child Elements */ + childElement( + "DefaultProviderPolicy", + ::defaultProviderPolicy, + minOccurs = 0, + maxOccurs = 1, + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/UserConfigurations.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/UserConfigurations.kt new file mode 100644 index 0000000..1e0a107 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/userConfiguration/UserConfigurations.kt @@ -0,0 +1,131 @@ +package com.google.wear.watchface.validator.specification.userConfiguration + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.constraint + +/** Specification constraint for a 'UserConfigurations' element. */ +fun userConfigurations() = + constraint("UserConfigurations") { + allVersions() + .require( + /* Conditions */ + condition( + childrenHaveUniqueAttribute("id"), + "Each configuration must have a unique 'id' attribute.", + ), + condition( + { node, _ -> node.children.size in 1..20 }, + "UserConfigurations must have between 1 and 20 child elements.", + ), + ) + .allow( + /* Child Elements */ + childElement("BooleanConfiguration", ::booleanConfiguration), + childElement("ListConfiguration", ::listConfiguration), + childElement("ColorConfiguration", ::colorConfiguration), + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Flavors", ::flavors) + ) + + versions(3 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("PhotosConfiguration", ::photosConfiguration) + ) + } + +/** + * Specification constraint for a 'ListConfiguration' element in a Declarative Watch Face (DWF). + * + * A List Configuration allows the user to select one item from a list when customizing the watch + * face in the watch face editor. + */ +fun listConfiguration() = + constraint("ListConfiguration") { + abstractConfigurationType() + allVersions() + .require( + /* Child Elements */ + childElement("ListOption", ::listOption, maxOccurs = 100), + + /* Conditions*/ + ElementCondition( + "Attribute 'defaultValue' must match the id of one of the ListOption children.", + { node, _ -> + node.children.any { + it.attributes["id"]?.equals(node.attributes["defaultValue"]) ?: false + } + }, + ), + ) + } + +/** Specification constraint for a 'ListOption' element. */ +private fun listOption() = constraint("ListOption") { abstractConfigurationPartType() } + +fun colorConfiguration() = + constraint("ColorConfiguration") { + abstractConfigurationType() + allVersions() + .require( + /* Child Elements */ + childElement("ColorOption", ::colorOption, maxOccurs = 20), + + /* Conditions */ + ElementCondition( + "Attribute 'defaultValue' must match the id of one of the ColorOption children", + { node, _ -> + node.children.any { + it.attributes["id"]?.equals(node.attributes["defaultValue"]) ?: false + } + }, + ), + ) + } + +/** Specification constraint for a 'ColorOption' element. */ +fun colorOption() = + constraint("ColorOption") { + abstractConfigurationPartType() + allVersions() + .require( + /* Attributes */ + attribute( + "colors", + argbVector(maxLength = 5), + "Attribute 'colors' must be a space separated list of hex ARGB colors. Max length is 5.", + ) + ) + } + +/** Specification constraint for a 'PhotosConfiguration' element. */ +fun photosConfiguration() = + constraint("PhotosConfiguration") { + allVersions() + .require( + /* Attributes */ + attribute("id", nonEmpty()), + attribute("configType", enum("SINGLE", "MULTIPLE")), + ) + } + +/** + * Specification constraint for a 'BooleanConfiguration' element. + * + * A BooleanConfiguration must be defined in the user configuration section of the XML. Then it may + * be referenced by id from a Scene element. + */ +fun booleanConfiguration() = + constraint("BooleanConfiguration") { + abstractConfigurationType() + allVersions() + .require( + /* Attributes */ + attribute("defaultValue", enum("TRUE", "FALSE")) + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/BitmapFonts.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/BitmapFonts.kt new file mode 100644 index 0000000..4a6b81b --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/BitmapFonts.kt @@ -0,0 +1,90 @@ +package com.google.wear.watchface.validator.specification.watchFace + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.UNBOUNDED +import com.google.wear.watchface.validator.specification.marginAttributes +import com.google.wear.watchface.validator.specification.widthAndHeight + +/** + * Specification Constraint for a 'BitmapFonts' element, a container for user-defined bitmap fonts. + */ +fun bitmapFonts(): Constraint = + constraint("BitmapFonts") { + allVersions() + .require( + /* Child Elements */ + childElement("BitmapFont", ::bitmapFont), + + /* Conditions */ + condition( + childrenHaveUniqueAttribute("name"), + "Each must have a unique 'name' attribute", + ), + ) + } + +private fun bitmapFont(): Constraint = + constraint("BitmapFont") { + allVersions() + .require( + /* Attributes */ + attribute("name", nonEmpty()), + + /* Child Elements */ + choice( + childElement("Character", ::character), + childElement("Word", ::word), + maxOccurs = UNBOUNDED, + ), + + /* Conditions */ + condition( + childrenHaveUniqueAttribute("name"), + "Each and must have, a unique 'name' attribute", + ), + ) + } + +/** + * Specification constraint for a 'Character' element, Specifies a particular character in a + * user-defined bitmap font. + */ +private fun character() = + constraint("Character") { + allVersions() + .require( + /* Attributes */ + attribute("name", stringOfLength(1)), + attribute("resource", nonEmpty()), + *widthAndHeight, + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + *marginAttributes + ) + } + +/** + * Specification constraint for a 'Word' element, Specifies a particular word in a user-defined + * bitmap font. + */ +private fun word() = + constraint("Word") { + allVersions() + .require( + /* Attributes */ + attribute("name", nonEmpty()), + attribute("resource", nonEmpty()), + *widthAndHeight, + ) + + versions(2 to MAX_WFF_VERSION) + .allow( + /* Attributes */ + *marginAttributes + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Metadata.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Metadata.kt new file mode 100644 index 0000000..d988861 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Metadata.kt @@ -0,0 +1,41 @@ +package com.google.wear.watchface.validator.specification.watchFace + +import com.google.wear.watchface.validator.constraint.constraint + +/** + * Specification constraint for a 'Metadata' element. + * + * Represents a predefined or user-defined key-value pair. + */ +fun metadata() = + constraint("Metadata") { + allVersions() + .require( + /* Attributes */ + attribute("key", nonEmpty()), + attribute("value", nonEmpty()), + + /* Conditions */ + condition( + ifThen( + `if` = checkAttribute("key", equals("PREVIEW_TIME")), + then = checkAttribute("value", time()), + ), + "If key=PREVIEW_TIME, then value must be of type time (HH:MM:SS)", + ), + condition( + ifThen( + `if` = checkAttribute("key", equals("CLOCK_TYPE")), + then = checkAttribute("value", enum("ANALOG", "DIGITAL")), + ), + "If key=CLOCK_TYPE, then value must be ANALOG or DIGITAL", + ), + condition( + ifThen( + `if` = checkAttribute("key", equals("STEP_GOAL")), + then = checkAttribute("value", integer(min = 0)), + ), + "If key=STEP_GOAL, then value must be a positive integer", + ), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Scene.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Scene.kt new file mode 100644 index 0000000..02a734a --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/Scene.kt @@ -0,0 +1,65 @@ +package com.google.wear.watchface.validator.specification.watchFace + +import com.google.wear.watchface.validator.MAX_WFF_VERSION +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.clock.analogClock +import com.google.wear.watchface.validator.specification.clock.digitalClock +import com.google.wear.watchface.validator.specification.common.condition +import com.google.wear.watchface.validator.specification.common.reference.reference +import com.google.wear.watchface.validator.specification.common.transform.transform +import com.google.wear.watchface.validator.specification.common.variant.variant +import com.google.wear.watchface.validator.specification.complication.complicationSlot +import com.google.wear.watchface.validator.specification.group.configuration.booleanConfiguration +import com.google.wear.watchface.validator.specification.group.configuration.listConfiguration +import com.google.wear.watchface.validator.specification.group.group +import com.google.wear.watchface.validator.specification.group.part.animatedImage.partAnimatedImage +import com.google.wear.watchface.validator.specification.group.part.draw.partDraw +import com.google.wear.watchface.validator.specification.group.part.image.partImage +import com.google.wear.watchface.validator.specification.group.part.text.partText + +/** + * Specification constraint for a 'Scene' element. + * + * A scene is a container of visual tags. Each watch face must contain exactly one Scene element. + */ +fun scene(): Constraint = + constraint("Scene") { + allVersions() + .require( + // "A Tag must have at least one child element" + condition( + hasAtLeastOneChild(), + "A Tag must have at least one child element.", + ) + ) + .allow( + /* Attributes */ + attribute( + "backgroundColor", + color() or dataSource(), + "'backgroundColor' must be a color in the form #RRGGBB or #AARRGGBB or a [DATA.SOURCE]", + ), + + /* Child Elements */ + childElement("PartText", ::partText), + childElement("PartDraw", ::partDraw), + childElement("PartImage", ::partImage), + childElement("PartAnimatedImage", ::partAnimatedImage), + childElement("Group", ::group), + childElement("Condition", ::condition), + childElement("ListConfiguration", ::listConfiguration), + childElement("BooleanConfiguration", ::booleanConfiguration), + childElement("Variant", ::variant), + childElement("AnalogClock", ::analogClock), + childElement("DigitalClock", ::digitalClock), + childElement("ComplicationSlot", ::complicationSlot, maxOccurs = 8), + ) + + versions(4 to MAX_WFF_VERSION) + .allow( + /* Child Elements */ + childElement("Transform", ::transform), + childElement("Reference", ::reference), + ) + } diff --git a/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/WatchFace.kt b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/WatchFace.kt new file mode 100644 index 0000000..5c7bc43 --- /dev/null +++ b/tools/dwf-validator/src/commonMain/kotlin/com/google/wear/watchface/validator/specification/watchFace/WatchFace.kt @@ -0,0 +1,39 @@ +package com.google.wear.watchface.validator.specification.watchFace + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.cornerRadiiAttributes +import com.google.wear.watchface.validator.specification.userConfiguration.userConfigurations +import com.google.wear.watchface.validator.specification.widthAndHeight + +/** + * Specification Constraint for a 'WatchFace' element, the root element of a watch face document. + * + * It contains information about the elements that should appear in the watch face preview when + * users choose which watch face to use on their Wear OS devices. + */ +fun watchFace(): Constraint = + constraint("WatchFace") { + allVersions() + .require( + /* Attributes */ + *widthAndHeight, + + /* Child Elements */ + childElement("Scene", ::scene, maxOccurs = 1), + ) + .allow( + /* Attributes */ + *cornerRadiiAttributes, + attribute( + "clipShape", + enum("NONE", "CIRCLE", "RECTANGLE"), + "Attribute: 'clipShape' must be one of 'NONE', 'CIRCLE' or 'RECTANGLE'", + ), + + /* Child Elements */ + childElement("Metadata", ::metadata), + childElement("BitmapFonts", ::bitmapFonts, maxOccurs = 1), + childElement("UserConfigurations", ::userConfigurations, maxOccurs = 1), + ) + } diff --git a/tools/dwf-validator/src/jsMain/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocument.kt b/tools/dwf-validator/src/jsMain/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocument.kt new file mode 100644 index 0000000..e154939 --- /dev/null +++ b/tools/dwf-validator/src/jsMain/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocument.kt @@ -0,0 +1,54 @@ +package com.google.wear.watchface.validator + +import org.w3c.dom.Document +import org.w3c.dom.Element +import org.w3c.dom.Node + +/** A [[WatchFaceDocument]] implementation for the JS source set. */ +class JsWatchFaceDocument private constructor(override val rootElement: WatchFaceElement) : + WatchFaceDocument { + + companion object { + /** Factory method for creating a WatchFaceDocument from a w3c Document. */ + fun of(document: Document): WatchFaceDocument { + if (document.documentElement != null) { + return JsWatchFaceDocument(toWatchFaceElement(document.documentElement!!)) + } else { + throw Exception("Watch Face element not found") + } + } + + /** Traverses the element tree and returns the corresponding WatchFaceElement tree. */ + private fun toWatchFaceElement(current: Element): WatchFaceElement = + WatchFaceElement( + current.tagName, + current.getProperties(), + current.getChildElements().map { toWatchFaceElement(it) }.toList(), + current.textContent ?: "", + ) + + /** + * Gets an elements children as a List of Elements + * + * Traverses through the 'siblings' of the first child and collects the nodes which are + * elements into a sequence. + */ + private fun Element.getChildElements(): Sequence = sequence { + var currentNode: Node? = firstChild + + while (currentNode != null) { + if (currentNode is Element) { + yield(currentNode) + } + currentNode = currentNode.nextSibling + } + } + + /** Gets an elements properties as a list of key value pairs. */ + private fun Element.getProperties(): Map = + (0 until attributes.length) + .mapNotNull { attributes.item(it) } + .filterNot { it.nodeName.startsWith("xmlns:") || it.nodeName.startsWith("xsi:") } + .associate { it.nodeName to (it.nodeValue ?: "") } + } +} diff --git a/tools/dwf-validator/src/jsTest/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocumentTest.kt b/tools/dwf-validator/src/jsTest/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocumentTest.kt new file mode 100644 index 0000000..beb9d13 --- /dev/null +++ b/tools/dwf-validator/src/jsTest/kotlin/com/google/wear/watchface/validator/JsWatchFaceDocumentTest.kt @@ -0,0 +1,86 @@ +package com.google.wear.watchface.validator + +import kotlin.test.Test +import kotlin.test.assertEquals +import org.w3c.dom.parsing.DOMParser + +class JsWatchFaceDocumentTest { + + @Test + fun ofMethodCreatesADocumentWithSingleElement() { + val doc = + DOMParser() + .parseFromString( + """ + + + """ + .trimIndent(), + "application/xml", + ) + + val result = JsWatchFaceDocument.of(doc).rootElement + + assertEquals( + WatchFaceElement( + "WatchFace", + mapOf("width" to "450", "height" to "450", "clipShape" to "NONE"), + emptyList(), + ), + result, + ) + } + + @Test + fun ofMethodCreatesADocumentWithManyChildren() { + val doc = + DOMParser() + .parseFromString( + """ + + + + + + """ + .trimIndent(), + "application/xml", + ) + + val result = JsWatchFaceDocument.of(doc).rootElement.children + + assertEquals( + listOf( + WatchFaceElement( + "Metadata", + mapOf("key" to "CLOCK_TYPE", "value" to "ANALOG"), + emptyList(), + ), + WatchFaceElement( + "Metadata", + mapOf("key" to "USE_NOTIFICATION", "value" to "TRUE"), + emptyList(), + ), + WatchFaceElement( + "Metadata", + mapOf("key" to "STEP_GOAL", "value" to "10000"), + emptyList(), + ), + ), + result, + ) + } +} diff --git a/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocument.kt b/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocument.kt new file mode 100644 index 0000000..6db63df --- /dev/null +++ b/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocument.kt @@ -0,0 +1,49 @@ +package com.google.wear.watchface.validator + +import org.w3c.dom.Document +import org.w3c.dom.Element +import org.w3c.dom.Node + +/** A [[WatchFaceDocument]] implementation for the JVM source set. */ +class JvmWatchFaceDocument private constructor(override val rootElement: WatchFaceElement) : + WatchFaceDocument { + + companion object { + /** Factory method for creating a WatchFaceDocument from a w3c Document. */ + fun of(document: Document): WatchFaceDocument = + JvmWatchFaceDocument(toWatchFaceElement(document.documentElement)) + + /** Traverses the element tree and returns the corresponding WatchFaceElement tree. */ + private fun toWatchFaceElement(current: Element): WatchFaceElement = + WatchFaceElement( + current.tagName, + current.getProperties(), + current.getChildElements().map { toWatchFaceElement(it) }.toList(), + current.textContent, + ) + + /** + * Gets an elements children as a List of Elements. + * + * Traverses through the 'siblings' of the first child and collects the nodes which are + * elements into a sequence. + */ + private fun Element.getChildElements(): Sequence = sequence { + var currentNode: Node? = firstChild + + while (currentNode != null) { + if (currentNode is Element) { + yield(currentNode) + } + currentNode = currentNode.nextSibling + } + } + + /** Gets an elements properties as a list of key value pairs. */ + private fun Element.getProperties(): Map = + (0 until attributes.length) + .map { attributes.item(it) } + .filterNot { it.nodeName.startsWith("xmlns:") || it.nodeName.startsWith("xsi:") } + .associate { it.nodeName to it.nodeValue } + } +} diff --git a/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/XmlReader.kt b/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/XmlReader.kt new file mode 100644 index 0000000..3e45aaa --- /dev/null +++ b/tools/dwf-validator/src/jvmMain/kotlin/com/google/wear/watchface/validator/XmlReader.kt @@ -0,0 +1,32 @@ +package com.google.wear.watchface.validator + +import java.io.FileNotFoundException +import java.io.InputStream +import javax.xml.parsers.DocumentBuilderFactory +import org.w3c.dom.Document + +object XmlReader { + /** Reads an Xml file and returns it as a w3c.dom.Document object */ + fun fromResource(resourcePath: String): Document { + val xmlStream = object {}.javaClass.getResourceAsStream(resourcePath) + + if (xmlStream != null) { + return readFromInputStream(xmlStream) + } else { + throw FileNotFoundException() + } + } + + fun fromFilePath(filePath: String): Document { + val xmlStream = java.io.File(filePath).inputStream() + + return readFromInputStream(xmlStream) + } + + /** Helper function for building the Document object from an xml input stream */ + fun readFromInputStream(inputStream: InputStream): Document { + val builder = DocumentBuilderFactory.newInstance().newDocumentBuilder() + + return builder.parse(inputStream) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ErrorOutput.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ErrorOutput.kt new file mode 100644 index 0000000..0abfd51 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ErrorOutput.kt @@ -0,0 +1,14 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.error.ErrorMap +import com.google.wear.watchface.validator.error.ValidationError + +sealed interface ErrorOutput + +data class GlobalError(val error: ValidationError) : ErrorOutput + +data class AllVersionsFailWithSameError(val error: ValidationError) : ErrorOutput + +data class PartialFailure(val errorMap: ErrorMap) : ErrorOutput + +data class AllVersionsFail(val errorMap: ErrorMap) : ErrorOutput diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserFailingIntegrationTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserFailingIntegrationTest.kt new file mode 100644 index 0000000..7c49b95 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserFailingIntegrationTest.kt @@ -0,0 +1,82 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.expression.EndOfFileException +import com.google.wear.watchface.validator.expression.ExpressionParser +import com.google.wear.watchface.validator.expression.ExpressionParsingException +import com.google.wear.watchface.validator.expression.FunctionNotFoundException +import com.google.wear.watchface.validator.expression.MissingTokenException +import com.google.wear.watchface.validator.expression.TokensNotConsumedException +import com.google.wear.watchface.validator.expression.UnexpectedTokenException +import com.google.wear.watchface.validator.expression.UnknownTokenException +import kotlin.reflect.KClass +import kotlin.test.assertFailsWith +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class ExpressionParserFailingIntegrationTest( + val expectedExceptionClass: KClass, + val testCaseString: String, +) { + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "{index}: \"{1}\" = \"{0}\"") + fun testCases(): List> = + listOf( + arrayOf(EndOfFileException::class, ""), + arrayOf(UnexpectedTokenException::class, "3 - - -5"), + arrayOf(TokensNotConsumedException::class, "3e-1 + 7.0"), + arrayOf(TokensNotConsumedException::class, "9 + 3e-1"), + arrayOf(UnexpectedTokenException::class, "!!0"), + arrayOf(UnknownTokenException::class, "\"lorem"), + arrayOf(EndOfFileException::class, "+"), + arrayOf(EndOfFileException::class, "-"), + arrayOf(EndOfFileException::class, "!"), + arrayOf(EndOfFileException::class, "~"), + arrayOf(EndOfFileException::class, "1 + "), + arrayOf(EndOfFileException::class, "1 * "), + arrayOf(EndOfFileException::class, "1 == "), + arrayOf(UnknownTokenException::class, "\$£`£"), + arrayOf(UnknownTokenException::class, "#fff"), + arrayOf(UnknownTokenException ::class, "#00808g"), + arrayOf(UnexpectedTokenException::class, "(++2)"), + arrayOf(UnexpectedTokenException::class, "+ +2"), + arrayOf(UnexpectedTokenException::class, "+-2"), + arrayOf(UnexpectedTokenException::class, "-+2"), + arrayOf(UnexpectedTokenException::class, "(--2)"), + arrayOf(UnexpectedTokenException::class, "- -2"), + arrayOf(TokensNotConsumedException::class, ".3f"), + arrayOf(TokensNotConsumedException::class, "3f"), + arrayOf(TokensNotConsumedException::class, "3F"), + arrayOf(TokensNotConsumedException::class, "3D"), + arrayOf(TokensNotConsumedException::class, "3d"), + arrayOf(TokensNotConsumedException::class, "3e-1"), + arrayOf(TokensNotConsumedException::class, "2fnothing"), + arrayOf(TokensNotConsumedException::class, "3dnothing"), + arrayOf(TokensNotConsumedException::class, "1lorem"), + arrayOf(TokensNotConsumedException::class, "3 5 asd"), + arrayOf(TokensNotConsumedException::class, "2147483647L"), + arrayOf( + FunctionNotFoundException::class, + "extractColorFromWeightedColors(#FF0000 #000000 #FF00FF,1, 1, true, 0.6)", + ), + arrayOf( + FunctionNotFoundException::class, + "completelyMadeUpFunction(argument, another)", + ), + ) + } + + @Test + fun testExpressionParsing() { + assertEquals( + expectedExceptionClass, + assertFailsWith { + ExpressionParser.parse(testCaseString) + }::class, + ) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserIntegrationTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserIntegrationTest.kt new file mode 100644 index 0000000..6810a9e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/ExpressionParserIntegrationTest.kt @@ -0,0 +1,359 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.expression.Add +import com.google.wear.watchface.validator.expression.BitwiseAnd +import com.google.wear.watchface.validator.expression.BitwiseNot +import com.google.wear.watchface.validator.expression.BitwiseOr +import com.google.wear.watchface.validator.expression.BooleanLiteral +import com.google.wear.watchface.validator.expression.Color +import com.google.wear.watchface.validator.expression.ColorList +import com.google.wear.watchface.validator.expression.Div +import com.google.wear.watchface.validator.expression.Equal +import com.google.wear.watchface.validator.expression.Expression +import com.google.wear.watchface.validator.expression.ExpressionParser +import com.google.wear.watchface.validator.expression.FunctionCall +import com.google.wear.watchface.validator.expression.LogicalAnd +import com.google.wear.watchface.validator.expression.LogicalNot +import com.google.wear.watchface.validator.expression.LogicalOr +import com.google.wear.watchface.validator.expression.MissingTokenException +import com.google.wear.watchface.validator.expression.Mod +import com.google.wear.watchface.validator.expression.Mul +import com.google.wear.watchface.validator.expression.Neg +import com.google.wear.watchface.validator.expression.NumList +import com.google.wear.watchface.validator.expression.NumLiteral +import com.google.wear.watchface.validator.expression.Pos +import com.google.wear.watchface.validator.expression.StringLiteral +import com.google.wear.watchface.validator.expression.Sub +import com.google.wear.watchface.validator.expression.Ternary +import com.google.wear.watchface.validator.expression.Variable +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class ExpressionParserIntegrationTest(val expected: Expression, val testCaseString: String) { + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "{index}: \"{1}\" = \"{0}\"") + fun testCases(): List> = + listOf( + arrayOf(Variable("black"), "black"), + arrayOf(Variable("BLACK"), "BLACK"), + arrayOf(Variable("darkgray"), "darkgray"), + arrayOf(Variable("DARKGRAY"), "DARKGRAY"), + arrayOf(Variable("gray"), "gray"), + arrayOf(Variable("GRAY"), "GRAY"), + arrayOf(Variable("lightgray"), "lightgray"), + arrayOf(Variable("LIGHTGRAY"), "LIGHTGRAY"), + arrayOf(Variable("white"), "white"), + arrayOf(Variable("WHITE"), "WHITE"), + arrayOf(Variable("red"), "red"), + arrayOf(Variable("RED"), "RED"), + arrayOf(Variable("green"), "green"), + arrayOf(Variable("GREEN"), "GREEN"), + arrayOf(Variable("blue"), "blue"), + arrayOf(Variable("BLUE"), "BLUE"), + arrayOf(Variable("yellow"), "yellow"), + arrayOf(Variable("YELLOW"), "YELLOW"), + arrayOf(Variable("cyan"), "cyan"), + arrayOf(Variable("CYAN"), "CYAN"), + arrayOf(Variable("magenta"), "magenta"), + arrayOf(Variable("MAGENTA"), "MAGENTA"), + arrayOf(Variable("aqua"), "aqua"), + arrayOf(Variable("AQUA"), "AQUA"), + arrayOf(Variable("fuchsia"), "fuchsia"), + arrayOf(Variable("FUCHSIA"), "FUCHSIA"), + arrayOf(Variable("darkgrey"), "darkgrey"), + arrayOf(Variable("DARKGREY"), "DARKGREY"), + arrayOf(Variable("grey"), "grey"), + arrayOf(Variable("GREY"), "GREY"), + arrayOf(Variable("lightgrey"), "lightgrey"), + arrayOf(Variable("LIGHTGREY"), "LIGHTGREY"), + arrayOf(Variable("lime"), "lime"), + arrayOf(Variable("LIME"), "LIME"), + arrayOf(Variable("maroon"), "maroon"), + arrayOf(Variable("MAROON"), "MAROON"), + arrayOf(Variable("navy"), "navy"), + arrayOf(Variable("NAVY"), "NAVY"), + arrayOf(Variable("olive"), "olive"), + arrayOf(Variable("OLIVE"), "OLIVE"), + arrayOf(Variable("purple"), "purple"), + arrayOf(Variable("PURPLE"), "PURPLE"), + arrayOf(Variable("silver"), "silver"), + arrayOf(Variable("SILVER"), "SILVER"), + arrayOf(Variable("teal"), "teal"), + arrayOf(Variable("TEAL"), "TEAL"), + // COLOR LITERALS + arrayOf(Color("#FF008080"), "#FF008080"), + // SOURCE VARIABLES + arrayOf(Variable("MONTH_S"), "[MONTH_S]"), + arrayOf(Variable("WEATHER.DAYS.6.CONDITION_DAY"), "WEATHER.DAYS.6.CONDITION_DAY"), + + // NUMERIC LITERALS + arrayOf(Neg(NumLiteral(2147483648.0)), "-2147483648"), + arrayOf(Neg(NumLiteral(2147483647.0)), "-2147483647"), + arrayOf(NumLiteral(0.3), ".3"), + // ARITHMETIC_UNARY_PLUS + arrayOf(Pos(NumLiteral(1.0)), "+1"), + arrayOf(Pos(NumLiteral(1.5)), "+1.5"), + // ARITHMETIC_UNARY_MINUS + arrayOf(Neg(NumLiteral(1.0)), "-1"), + arrayOf(Neg(NumLiteral(1.5)), "-1.5"), + arrayOf(Pos(Neg(NumLiteral(2.0))), "+(-2)"), + arrayOf(Neg(Neg(NumLiteral(2.0))), "-(-2)"), + + // ARITHMETIC_PLUS + arrayOf(Add(NumLiteral(1.0), NumLiteral(2.0)), "1 + 2"), + arrayOf(Add(NumLiteral(1.0), NumLiteral(2.5)), "1 + 2.5"), + arrayOf(Add(NumLiteral(1.5), NumLiteral(2.0)), "1.5 + 2"), + arrayOf(Add(NumLiteral(1.5), NumLiteral(2.5)), "1.5 + 2.5"), + arrayOf(Add(NumLiteral(1.5), NumLiteral(2.6)), "1.5 + 2.6"), + arrayOf( + Add(Add(NumLiteral(1.5), NumLiteral(2.6)), NumLiteral(1.9)), + "1.5 + 2.6 + 1.9", + ), + arrayOf(Add(NumLiteral(2.0), Neg(NumLiteral(3.0))), "2 + -3"), + arrayOf(Add(NumLiteral(2.0), Neg(NumLiteral(3.0))), "2 + - 3"), + arrayOf(Sub(NumLiteral(3.0), Pos(NumLiteral(2.0))), "3 - + 2"), + arrayOf(Add(Add(NumLiteral(1.0), NumLiteral(2.0)), NumLiteral(3.0)), "(1+2)+3"), + arrayOf(Add(NumLiteral(1.0), Add(NumLiteral(2.0), NumLiteral(3.0))), "1+(2+3)"), + arrayOf(Add(NumLiteral(2147483647.0), NumLiteral(10.0)), "2147483647 + 10"), + // ARITHMETIC_MINUS + arrayOf(Sub(NumLiteral(1.0), NumLiteral(2.0)), "1 - 2"), + arrayOf(Sub(NumLiteral(1.0), NumLiteral(2.5)), "1 - 2.5"), + arrayOf(Sub(NumLiteral(1.5), NumLiteral(2.0)), "1.5 - 2"), + arrayOf(Sub(NumLiteral(1.5), NumLiteral(2.5)), "1.5 - 2.5"), + arrayOf(Sub(NumLiteral(3.0), Neg(NumLiteral(5.0))), "3 - -(5)"), + arrayOf(Sub(NumLiteral(3.0), Neg(NumLiteral(5.0))), "3 - - (5)"), + arrayOf(Sub(NumLiteral(3.0), Neg(NumLiteral(5.0))), "3 - - 5"), + arrayOf(Sub(NumLiteral(3.0), Neg(Neg(NumLiteral(5.0)))), "3 - - (-5)"), + arrayOf(Sub(Sub(NumLiteral(1.0), NumLiteral(2.0)), NumLiteral(3.0)), "(1-2)-3"), + arrayOf(Sub(NumLiteral(1.0), Sub(NumLiteral(2.0), NumLiteral(3.0))), "1-(2-3)"), + // ARITHMETIC_MULTIPLY + arrayOf(Mul(NumLiteral(1.0), NumLiteral(2.0)), "1 * 2"), + arrayOf(Mul(NumLiteral(1.0), NumLiteral(2.5)), "1 * 2.5"), + arrayOf(Mul(NumLiteral(1.4), NumLiteral(2.0)), "1.4 * 2"), + arrayOf(Mul(NumLiteral(1.5), NumLiteral(2.0)), "1.5 * 2.0"), + arrayOf(Mul(NumLiteral(1.5), NumLiteral(2.5)), "1.5 * 2.5"), + arrayOf(Mul(Mul(NumLiteral(2.0), NumLiteral(2.0)), NumLiteral(4.0)), "(2 * 2) * 4"), + // ARITHMETIC_DIVISION + arrayOf(Div(NumLiteral(4.0), NumLiteral(2.0)), "4 / 2"), + arrayOf(Div(NumLiteral(4.0), NumLiteral(2.0)), "4 / 2.0"), + arrayOf(Div(NumLiteral(1.0), NumLiteral(2.0)), "1 / 2.0"), + arrayOf(Div(NumLiteral(1.0), NumLiteral(2.0)), "1 / 2"), + arrayOf(Div(NumLiteral(1.0), NumLiteral(2.0)), "1.0 / 2"), + arrayOf(Div(NumLiteral(1.0), NumLiteral(2.0)), "1.0 / 2.0"), + arrayOf(Div(NumLiteral(4.0), NumLiteral(2.0)), "4.0 / 2.0"), + arrayOf(Div(NumLiteral(1.0), NumLiteral(0.0)), "1 / 0"), + arrayOf(Div(NumLiteral(0.0), NumLiteral(1.0)), "0 / 1"), + arrayOf(Div(NumLiteral(0.0), NumLiteral(0.0)), "0 / 0"), + arrayOf(Div(Div(NumLiteral(4.0), NumLiteral(2.0)), NumLiteral(2.0)), "(4 / 2) / 2"), + // ARITHMETIC_MODULO + arrayOf(Mod(NumLiteral(3.0), NumLiteral(2.0)), "3 % 2"), + arrayOf(Mod(NumLiteral(2.0), NumLiteral(3.0)), "2 % 3"), + arrayOf(Mod(NumLiteral(2.0), NumLiteral(3.0)), "2.0 % 3"), + arrayOf(Mod(NumLiteral(2.0), NumLiteral(3.0)), "2 % 3.0"), + arrayOf(Mod(NumLiteral(2.0), NumLiteral(3.0)), "2.0 % 3.0"), + arrayOf( + FunctionCall( + "numberFormat", + listOf(StringLiteral("#.#"), Mod(NumLiteral(3.0), NumLiteral(2.9))), + ), + "numberFormat(\"#.#\", (3 % 2.9))", + ), + arrayOf(Mod(NumLiteral(2.9), NumLiteral(3.1)), "2.9 % 3.1"), + arrayOf(Mod(NumLiteral(3.2), NumLiteral(2.0)), "3.2 % 2"), + arrayOf(Mod(NumLiteral(0.0), NumLiteral(0.0)), "0 % 0"), + arrayOf(Mod(NumLiteral(0.0), NumLiteral(3.0)), "0 % 3"), + arrayOf(Mod(NumLiteral(3.0), NumLiteral(0.0)), "3 % 0"), + arrayOf( + Mod(Mod(NumLiteral(12.0), NumLiteral(7.0)), NumLiteral(3.0)), + "(12 % 7) % 3", + ), + // LOGICAL_NOT + arrayOf(LogicalNot(NumLiteral(1.0)), "!1"), + arrayOf(LogicalNot(LogicalNot(NumLiteral(2.0))), "!(!2)"), + arrayOf(LogicalNot(NumLiteral(0.0)), "!0"), + // LOGICAL_AND + arrayOf(LogicalAnd(NumLiteral(1.0), NumLiteral(1.0)), "1 && 1"), + arrayOf(LogicalAnd(NumLiteral(2.0), NumLiteral(3.0)), "2 && 3"), + arrayOf(LogicalAnd(NumLiteral(1.0), NumLiteral(0.0)), "1 && 0"), + arrayOf(LogicalAnd(NumLiteral(0.0), NumLiteral(1.0)), "0 && 1"), + arrayOf(LogicalAnd(NumLiteral(0.0), NumLiteral(0.0)), "0 && 0"), + // LOGICAL_OR + arrayOf(LogicalOr(NumLiteral(1.0), NumLiteral(1.0)), "1 || 1"), + arrayOf(LogicalOr(NumLiteral(2.0), NumLiteral(3.0)), "2 || 3"), + arrayOf(LogicalOr(NumLiteral(1.0), NumLiteral(0.0)), "1 || 0"), + arrayOf(LogicalOr(NumLiteral(0.0), NumLiteral(1.0)), "0 || 1"), + arrayOf(LogicalOr(NumLiteral(0.0), NumLiteral(0.0)), "0 || 0"), + // BITWISE_NOT + arrayOf(BitwiseNot(NumLiteral(1.0)), "~1"), + arrayOf(BitwiseNot(Neg(NumLiteral(2.0))), "~(-2)"), + arrayOf(BitwiseNot(NumLiteral(0.0)), "~0"), + arrayOf(BitwiseNot(Neg(NumLiteral(1.0))), "~(-1)"), + // BITWISE_AND + arrayOf(BitwiseAnd(NumLiteral(1.0), NumLiteral(1.0)), "1 & 1"), + arrayOf(BitwiseAnd(NumLiteral(1.0), NumLiteral(0.0)), "1 & 0"), + arrayOf(BitwiseAnd(NumLiteral(0.0), NumLiteral(1.0)), "0 & 1"), + arrayOf(BitwiseAnd(NumLiteral(0.0), NumLiteral(0.0)), "0 & 0"), + arrayOf(BitwiseAnd(NumLiteral(2.0), NumLiteral(2.0)), "2 & 2"), + arrayOf(BitwiseAnd(NumLiteral(2.0), NumLiteral(4.0)), "2 & 4"), + // BITWISE_OR + arrayOf(BitwiseOr(NumLiteral(1.0), NumLiteral(1.0)), "1 | 1"), + arrayOf(BitwiseOr(NumLiteral(1.0), NumLiteral(0.0)), "1 | 0"), + arrayOf(BitwiseOr(NumLiteral(0.0), NumLiteral(1.0)), "0 | 1"), + arrayOf(BitwiseOr(NumLiteral(0.0), NumLiteral(0.0)), "0 | 0"), + arrayOf(BitwiseOr(NumLiteral(2.0), NumLiteral(2.0)), "2 | 2"), + arrayOf(BitwiseOr(NumLiteral(2.0), NumLiteral(4.0)), "2 | 4"), + arrayOf( + BitwiseOr(NumLiteral(1.0), BitwiseOr(NumLiteral(2.0), NumLiteral(4.0))), + "1 | 2 | 4", + ), + // COMPARISON_EQUAL + arrayOf(Equal(NumLiteral(1.0), NumLiteral(1.0)), "1 == 1"), + arrayOf(Equal(NumLiteral(1.0), NumLiteral(1.0)), "1.0 == 1"), + arrayOf(Equal(NumLiteral(1.0), NumLiteral(1.0)), "1.0 == 1.0"), + arrayOf(Equal(NumLiteral(1.0), NumLiteral(2.0)), "1 == 2"), + // ... many more comparison tests omitted for brevity but follow the same pattern + // PARENTHESIS + arrayOf( + Add(Add(NumLiteral(1.5), NumLiteral(2.6)), NumLiteral(1.9)), + "(1.5 + 2.6 + 1.9)", + ), + arrayOf( + Add(NumLiteral(1.5), Add(NumLiteral(2.6), NumLiteral(1.9))), + "1.5 + (2.6 + 1.9)", + ), + arrayOf( + Add(Add(NumLiteral(1.5), NumLiteral(2.6)), NumLiteral(1.9)), + "(1.5 + 2.6) + 1.9", + ), + arrayOf(Add(NumLiteral(2.0), Mul(NumLiteral(3.0), NumLiteral(4.0))), "2 + 3 * 4"), + arrayOf(Add(NumLiteral(2.0), Mul(NumLiteral(3.0), NumLiteral(4.0))), "2 + (3 * 4)"), + arrayOf(Mul(Add(NumLiteral(2.0), NumLiteral(3.0)), NumLiteral(4.0)), "(2 + 3) * 4"), + // TERNARY + arrayOf( + Ternary(BooleanLiteral(true), NumLiteral(1.0), NumLiteral(2.0)), + "true ? 1 : 2", + ), + arrayOf( + Ternary(BooleanLiteral(false), NumLiteral(1.0), NumLiteral(2.0)), + "false ? 1 : 2", + ), + arrayOf( + Ternary( + BooleanLiteral(true), + Ternary(BooleanLiteral(true), NumLiteral(1.0), NumLiteral(2.0)), + NumLiteral(3.0), + ), + "true ? true ? 1 : 2 : 3", + ), + arrayOf( + Ternary( + BooleanLiteral(false), + NumLiteral(1.0), + Ternary(BooleanLiteral(true), NumLiteral(2.0), NumLiteral(3.0)), + ), + "false ? 1 : true ? 2 : 3", + ), + // FUNCTIONS + arrayOf(FunctionCall("round", listOf(NumLiteral(1.0))), "round(1)"), + arrayOf(FunctionCall("round", listOf(NumLiteral(1.4))), "round(1.4)"), + arrayOf( + FunctionCall("floor", listOf(NumLiteral(1.999999999))), + "floor(1.999999999)", + ), + arrayOf(FunctionCall("ceil", listOf(NumLiteral(2.000000001))), "ceil(2.000000001)"), + arrayOf(FunctionCall("sin", listOf(NumLiteral(0.0))), "sin(0)"), + arrayOf(FunctionCall("abs", listOf(Neg(NumLiteral(1.5)))), "abs(-1.5)"), + arrayOf( + FunctionCall( + "clamp", + listOf(NumLiteral(2.0), NumLiteral(0.0), NumLiteral(1.0)), + ), + "clamp(2, 0, 1)", + ), + arrayOf( + FunctionCall( + "clamp", + listOf( + Add(NumLiteral(2.0), NumLiteral(1.0)), + Sub(NumLiteral(1.0), NumLiteral(1.0)), + Add(NumLiteral(1.0), NumLiteral(1.0)), + ), + ), + "clamp((2 + 1), 1 - 1, 1 + 1)", + ), + arrayOf(FunctionCall("log", listOf(NumLiteral(10.0))), "log(10)"), + arrayOf(FunctionCall("sqrt", listOf(NumLiteral(9.0))), "sqrt(9)"), + arrayOf(FunctionCall("cbrt", listOf(NumLiteral(27.0))), "cbrt(27)"), + arrayOf( + FunctionCall("deg", listOf(Div(Variable("PI"), NumLiteral(2.0)))), + "deg(PI / 2)", + ), + arrayOf(FunctionCall("rad", listOf(NumLiteral(180.0))), "rad(180)"), + arrayOf( + FunctionCall( + "numberFormat", + listOf(StringLiteral("####.###"), NumLiteral(1234.5678)), + ), + "numberFormat(\"####.###\", 1234.5678)", + ), + arrayOf(FunctionCall("fract", listOf(NumLiteral(1.234))), "fract(1.234)"), + arrayOf(FunctionCall("pow", listOf(NumLiteral(3.0), NumLiteral(3.0))), "pow(3, 3)"), + arrayOf( + FunctionCall( + "colorArgb", + listOf( + NumLiteral(255.0), + NumLiteral(255.0), + NumLiteral(0.0), + NumLiteral(0.0), + ), + ), + "colorArgb(255, 255, 0, 0)", + ), + arrayOf( + FunctionCall( + "colorRgb", + listOf(NumLiteral(0.0), NumLiteral(0.0), NumLiteral(255.0)), + ), + "colorRgb(0, 0, 255)", + ), + arrayOf( + FunctionCall( + "extractColorFromColors", + listOf( + ColorList(listOf("#FF0000", "#000000", "#00FFFF")), + BooleanLiteral(true), + NumLiteral(0.6), + ), + ), + "extractColorFromColors(#FF0000 #000000 #00FFFF, true, 0.6)", + ), + arrayOf( + FunctionCall( + "extractColorFromWeightedColors", + listOf( + ColorList(listOf("#FF0000", "#000000", "#00FFFF")), + NumList(listOf(1.0, 1.0)), + BooleanLiteral(true), + NumLiteral(0.6), + ), + ), + "extractColorFromWeightedColors(#FF0000 #000000 #00FFFF,1 1, true, 0.6)", + ), + // QUOTED STRINGS + arrayOf(StringLiteral("abc"), "\"abc\""), + arrayOf(StringLiteral("abc + def"), "\"abc + def\""), + ) + } + + @Test + fun testExpressionParsing() { + val result: Expression = ExpressionParser.parse(testCaseString) + assertEquals(expected, result) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocumentTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocumentTest.kt new file mode 100644 index 0000000..93bbc3f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/JvmWatchFaceDocumentTest.kt @@ -0,0 +1,50 @@ +package com.google.wear.watchface.validator + +import kotlin.test.assertEquals +import org.junit.Test + +class JvmWatchFaceDocumentTest { + @Test + fun ofMethodCreatesADocumentWithSingleElement() { + val doc = XmlReader.fromResource("/emptyWatchFace.xml") + + val result = JvmWatchFaceDocument.of(doc).rootElement + + assertEquals( + WatchFaceElement( + "WatchFace", + mapOf("clipShape" to "NONE", "height" to "450", "width" to "450"), + emptyList(), + ), + result, + ) + } + + @Test + fun ofMethodCreatesADocumentWithManyChildren() { + val doc = XmlReader.fromResource("/metaDataWatchFace.xml") + + val result = JvmWatchFaceDocument.of(doc).rootElement.children + + assertEquals( + listOf( + WatchFaceElement( + "Metadata", + mapOf("key" to "CLOCK_TYPE", "value" to "ANALOG"), + emptyList(), + ), + WatchFaceElement( + "Metadata", + mapOf("key" to "USE_NOTIFICATION", "value" to "TRUE"), + emptyList(), + ), + WatchFaceElement( + "Metadata", + mapOf("key" to "STEP_GOAL", "value" to "10000"), + emptyList(), + ), + ), + result, + ) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceContextTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceContextTest.kt new file mode 100644 index 0000000..c5d04c0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceContextTest.kt @@ -0,0 +1,210 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.specification.WatchFaceSpecification +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class WatchFaceContextTest { + + @Test + fun contextShouldKeepTrackOfVisitedElements() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Metadata", emptyMap(), emptyList())), + ) + ) + val metadataConstraint: Constraint = + constraint("Metadata") { + allVersions() + .require( + ElementCondition { _, ctx -> + ctx.elementPath == listOf("WatchFace", "Metadata") + } + ) + } + val constraint: Constraint = + constraint("WatchFace") { + allVersions().require(childElement("Metadata", { metadataConstraint })) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.findValidVersions(watchFace) + + assertEquals(ALL_WFF_VERSIONS, validResult) + } + + @Test + fun contextShouldKeepAllAttributesInScope() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Metadata", mapOf("key" to "CLOCK_TYPE"), emptyList())), + ) + ) + val metadataConstraint: Constraint = + constraint("Metadata") { + allVersions() + .require( + attribute("key"), + ElementCondition { _, ctx -> ctx.scope["key"] == "CLOCK_TYPE" }, + ) + } + val constraint: Constraint = + constraint("WatchFace") { + allVersions().require(childElement("Metadata", { metadataConstraint })) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.findValidVersions(watchFace) + + assertEquals(ALL_WFF_VERSIONS, validResult) + } + + @Test + fun validatorShouldValidateAttributeExpressionIfFlaggedInContext() { + val constraint: Constraint = + constraint("WatchFace") { + allVersions().require(attribute("expression", validExpression())) + } + val validDocument = + TestWatchFace( + WatchFaceElement("WatchFace", mapOf("expression" to "1 + 2"), emptyList()) + ) + val inValidDocument = + TestWatchFace(WatchFaceElement("WatchFace", mapOf("expression" to "1 +"), emptyList())) + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.getValidationResult(validDocument) + val invalidResult = validator.getValidationResult(inValidDocument) + + assertEquals(ValidationResult.Success, validResult) + assertTrue(invalidResult is ValidationResult.Failure) + } + + @Test + fun validatorShouldValidateContentExpressionIfFlaggedInContext() { + val constraint: Constraint = + constraint("WatchFace") { allVersions().require(content(validExpression())) } + val validDocument = + TestWatchFace( + WatchFaceElement("WatchFace", emptyMap(), emptyList(), textContent = "1 + 2") + ) + val inValidDocument = + TestWatchFace( + WatchFaceElement("WatchFace", emptyMap(), emptyList(), textContent = "1 + ") + ) + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.getValidationResult(validDocument) + val invalidResult = validator.getValidationResult(inValidDocument) + + assertTrue(validResult is ValidationResult.Success) + assertTrue(invalidResult is ValidationResult.Failure, "was: $invalidResult") + } + + @Test + fun contextShouldResetExpressionContentCheckBetweenSiblings() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement( + "Expression", + emptyMap(), + emptyList(), + textContent = "1 + 2", + ), + WatchFaceElement( + "NoExpression", + emptyMap(), + emptyList(), + textContent = "1 +", + ), + ), + ) + ) + val expressionConstraint: Constraint = + constraint("Expression") { allVersions().require(content(validExpression())) } + val noExpressionConstraint: Constraint = + constraint("NoExpression") { allVersions().require(ConditionLibrary.alwaysPass()) } + val constraint: Constraint = + constraint("WatchFace") { + allVersions() + .require( + childElement("Expression", { expressionConstraint }), + childElement("NoExpression", { noExpressionConstraint }), + ) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertEquals(ValidationResult.Success, result) + } + + @Test + fun contextShouldResetExpressionContentCheckBetweenParentAndChild() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement( + "Expression", + emptyMap(), + listOf( + WatchFaceElement( + "NoExpression", + emptyMap(), + emptyList(), + textContent = "1 +", + ) + ), + textContent = "1 + 2", + ) + ), + ) + ) + val noExpressionConstraint: Constraint = + constraint("NoExpression") { allVersions().require(ConditionLibrary.alwaysPass()) } + val expressionConstraint: Constraint = + constraint("Expression") { + allVersions() + .require( + childElement("NoExpression", { noExpressionConstraint }), + content(validExpression()), + ) + } + val constraint: Constraint = + constraint("WatchFace") { + allVersions().require(childElement("Expression", { expressionConstraint })) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertEquals(ValidationResult.Success, result) + } + + private class TestWatchFace(override val rootElement: WatchFaceElement) : WatchFaceDocument {} +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorFailingIntegrationTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorFailingIntegrationTest.kt new file mode 100644 index 0000000..6435080 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorFailingIntegrationTest.kt @@ -0,0 +1,1836 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.error.AttributeValueError +import com.google.wear.watchface.validator.error.ExpressionSyntaxError +import com.google.wear.watchface.validator.error.GLOBAL_ERROR_KEY +import com.google.wear.watchface.validator.error.IllegalAttributeError +import com.google.wear.watchface.validator.error.IllegalTagError +import com.google.wear.watchface.validator.error.RequiredConditionFailedError +import com.google.wear.watchface.validator.error.TagOccurrenceError +import com.google.wear.watchface.validator.error.ValidationError +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.error.VersionEliminationError +import com.google.wear.watchface.validator.specification.WFF_SPECIFICATION +import kotlin.test.assertTrue +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class WatchFaceValidatorFailingIntegrationTest( + val expectedError: ErrorOutput, + val filePath: String, +) { + + companion object { + const val FAKE_KEY = "" + const val FAKE_VALUE = "" + const val FAKE_ERROR_MESSAGE = "Condition check failed." + + @JvmStatic + @Parameterized.Parameters(name = "{index}: \"{1}\" = \"{0}\"") + /* Validation Error thrown against failing test case path*/ + fun testCases(): List> = + listOf( + /* WatchFace */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "watchface/watchFaceMissingScene.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "watchface/watchFaceExtraAttribute.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "watchface/watchFaceNonIntegerHeight.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "watchface/watchFaceMissingAttributes.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "watchface/watchface_invalid_child.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "watchface/watchface_invalid_corner_radius_x_string.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "watchface/watchface_invalid_corner_radius_y_string.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "watchface/watchface_invalid_clipshape.xml", + ), + + /* Metadata */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "metadata/missingKeyMetadata.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "metadata/missingValueMetadata.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "metadata/invalidClockTypeMetadata.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "metadata/invalidStepGoalValuesMetadata.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "metadata/invalidPreviewTimeValuesMetadata.xml", + ), + + /* Group */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_name.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_x.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_y.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_width.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_height.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_pivotX.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_pivotY.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_alpha.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_renderMode.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_tintColor.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "group/group/group_invalid_child.xml", + ), + + /* PartAnimatedImage */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_missing_animation_controller.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_missing_animation.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_multiple_animation_types.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_missing_play.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_play_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_delayplay_value.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_missing_resource.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_missing_format.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_format_value.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_unexpected_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImage/invalid_unexpected_element.xml", + ), + + /* AnimationController */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_missing_play.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_play_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_delayplay_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_delayrepeat_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_repeat_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_loopcount_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_resumeplayback_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_beforeplaying_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_afterplaying_value.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_unexpected_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animationController/invalid_unexpected_element.xml", + ), + + /* PartAnimatedImage */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_missing_x.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_missing_y.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_missing_width.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_missing_height.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_x_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_pivotX_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_alpha_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_scaleX_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_renderMode_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_tintColor_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_blendMode_value.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_missing_animation_controller.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_multiple_animation_sources.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_unexpected_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/partAnimatedImage/invalid_unexpected_element.xml", + ), + + /* AnimatedImages */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_missing_change.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_change_value.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_missing_image_child.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_changedirection_value.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_unexpected_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "group/part/animatedImage/animatedImages/invalid_unexpected_element.xml", + ), + + /* AnalogClock */ + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_alpha_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_scalex.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_scaley.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_render_mode.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/analogclock/analog_clock_invalid_tint_color.xml", + ), + + /* DigitalClock */ + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_alpha_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_scalex.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_scaley.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_render_mode.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_tint_color.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/digitalclock/digital_clock_invalid_missing_timetext.xml", + ), + + /* HourHand */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_missing_resource.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/hourhand/hour_hand_invalid_alpha_too_high.xml", + ), + + /* MinuteHand */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_missing_resource.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/minutehand/minute_hand_invalid_alpha_too_high.xml", + ), + + /* SecondHand */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_missing_resource.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_alpha_too_high.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_both_sweep_and_tick.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_sweep_frequency.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_tick_duration_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_tick_duration_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_tick_strength_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/secondhand/second_hand_invalid_tick_strength_too_high.xml", + ), + + /* TimeText */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_missing_format.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_format.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_hour_format.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_align.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_pivotx_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_pivotx_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_pivoty_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_pivoty_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_alpha_too_low.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_alpha_too_high.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "clock/timetext/time_text_invalid_tint_color.xml", + ), + + /* Scene */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "scene/emptyScene.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "scene/invalidBackgroundColorScene.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "scene/transformChildScene.xml", + ), + + /* PartText */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/partText/invalid_parttext_multiple_text_elements.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/partText/invalid_parttext_no_text_element.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/text/invalid_text_align.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/text/invalid_text_ellipsis.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/text/invalid_text_maxlines.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/text/invalid_text_isautosize.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/textCircular/invalid_textcircular_missing_attributes.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/textCircular/invalid_textcircular_direction.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_missing_family.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_missing_size.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_color.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_slant.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_width.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/text/font/invalid_font_weight.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/decoration/invalid_shadow_missing_color.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/decoration/invalid_outline_missing_color.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/decoration/invalid_outglow_missing_color.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/formatter/invalid_inlineimage_missing_resource.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/text/formatter/invalid_inlineimage_missing_dimensions.xml", + ), + + /* PartImage */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/image/partImage/invalid_partimage_multiple_image_sources.xml", + ), + arrayOf( + GlobalError(TagOccurrenceError("Image", 2, 1..1)), + "group/part/image/partImage/invalid_partimage_duplicate_child.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/image/images/invalid_image_no_resource.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/images/invalid_images_bad_change.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/image/images/invalid_images_no_image_child.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/images/invalid_images_bad_changedirection.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError( + FAKE_ERROR_MESSAGE, + (3..MAX_WFF_VERSION).toSet(), + ), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError( + FAKE_ERROR_MESSAGE, + (3..MAX_WFF_VERSION).toSet(), + ), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "group/part/image/photos/invalid_photos_no_source.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError( + FAKE_ERROR_MESSAGE, + (3..MAX_WFF_VERSION).toSet(), + ), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError( + FAKE_ERROR_MESSAGE, + (3..MAX_WFF_VERSION).toSet(), + ), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "group/part/image/photos/invalid_photos_no_defaultimageresource.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/photos/invalid_photos_bad_change.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/photos/invalid_photos_out_of_range_changeafterevery.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/photos/invalid_photos_negative_width.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/photos/invalid_photos_negative_height.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/image/photos/invalid_photos_bad_changedirection.xml", + ), + + /* PartDraw */ + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_pivot.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_angle.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_alpha.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_scale.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_rendermode.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "group/part/draw/partDraw/invalid_partdraw_tintcolor.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/shape/invalid_line.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/shape/invalid_arc.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/shape/invalid_ellipse.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/shape/invalid_roundrectangle.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/style/invalid_fill.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/style/invalid_stroke.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError( + FAKE_ERROR_MESSAGE, + (2..MAX_WFF_VERSION).toSet(), + ), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "group/part/draw/style/invalid_weightedstroke.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/gradient/invalid_lineargradient.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/gradient/invalid_radialgradient.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "group/part/draw/gradient/invalid_sweepgradient.xml", + ), + + /* ComplicationSlot */ + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_slotid_string.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_slotid_missing.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_supportedtypes_unknown.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_supportedtypes_missing.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_complication_missing.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_complication_type_mismatch.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_boundingbox_missing.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_height_negative.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/complicationslot/invalid_complicationslot_x_float.xml", + ), + + /* BoundingBox */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_missing_x.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_missing_y.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_missing_width.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_missing_height.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_invalid_x.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_invalid_y.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_invalid_width.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_invalid_height.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_negative_width.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_negative_height.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "complication/bounding/invalid_boundingbox_invalid_child.xml", + ), + + /* DefaultProviderPolicy */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_provider.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_type.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_provider.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_type.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_child.xml", + ), + + /* Complication */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complication/invalid_complication_missing_type.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "complication/complication/invalid_complication_unknown_type.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "complication/complication/invalid_complication_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "complication/complication/invalid_complication_invalid_child.xml", + ), + + /* BitmapFonts */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/emptyBitMapFonts.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/extraAttributeCharacter.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/illegalFontElement.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/noFontElement.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/missingAttributeCharacter.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "bitmapfonts/missingBitMapFontsContainer.xml", + ), + + /* Condition */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/condition_missing_expressions.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/condition/condition_unrecognized_child.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/expressions_empty.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/condition/expressions_unrecognized_child.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/expression_missing_name.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/expression_empty_name.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/expression_missing_content.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/expression_duplicate_name.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/compare_missing_expression_attribute.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/compare_empty_expression_attribute.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/compare_expression_not_found.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/compare_empty.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/condition/default_empty.xml", + ), + + /* Localization */ + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/localization/localization_invalid_calendar.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_KEY)), + "common/localization/localization_invalid_attribute.xml", + ), + + /* ScreenReader */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/screenreader/screenreader_invalid_missing_stringid.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/screenreader/screenreader_invalid_empty_stringid.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "common/screenreader/screenreader_invalid_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/screenreader/screenreader_invalid_child.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/screenreader/parameter_invalid_missing_expression.xml", + ), + arrayOf( + GlobalError(ExpressionSyntaxError(FAKE_ERROR_MESSAGE)), + "common/screenreader/parameter_invalid_empty_expression.xml", + ), + arrayOf( + GlobalError(ExpressionSyntaxError(FAKE_ERROR_MESSAGE)), + "common/screenreader/parameter_invalid_expression.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "common/screenreader/parameter_invalid_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/screenreader/parameter_invalid_child.xml", + ), + + /* Variant */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_missing_mode.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_wrong_mode.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_missing_target.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_missing_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_duration.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_startoffset.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_interpolation.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_controls.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/variant/variant_invalid_angledirection.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "common/variant/variant_v4_duration.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "common/variant/variant_v4_startoffset.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "common/variant/variant_v4_interpolation.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "common/variant/variant_v4_controls.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "common/variant/variant_v4_angledirection.xml", + ), + + /* Gyro */ + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "common/transform/gyro/gyro_invalid_extra_attribute.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/transform/gyro/gyro_invalid_child.xml", + ), + + /* Transform */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/transform/transform/invalid_missing_target.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/transform/transform/invalid_missing_value.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/transform/invalid_mode.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "common/transform/transform/invalid_child.xml", + ), + + /* Animation */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_no_duration.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_duration.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_interpolation.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_controls.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_angleDirection.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_repeat.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "common/transform/animation/animation_invalid_fps.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_KEY)), + "common/transform/animation/animation_invalid_attribute.xml", + ), + + /* Reference */ + arrayOf( + AllVersionsFail( + /* Version elimination error should happen once for using a Reference Tag + inside a Scene element, + and again for using the Reference (entirely exclusive to v4) */ + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "common/reference/reference/reference_invalid_missing_name.xml", + ), + arrayOf( + AllVersionsFail( + /* Version elimination error should happen once for using a Reference Tag + inside a Scene element, + and again for using the Reference (entirely exclusive to v4) */ + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "common/reference/reference/reference_invalid_missing_source.xml", + ), + arrayOf( + AllVersionsFail( + /* Version elimination error should happen once for using a Reference Tag + inside a Scene element, + and again for using the Reference (entirely exclusive to v4) */ + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "common/reference/reference/reference_invalid_missing_defaultValue.xml", + ), + arrayOf( + AllVersionsFail( + /* Version elimination error should happen once for using a Reference Tag + inside a Scene element, + and again for using the Reference (entirely exclusive to v4) */ + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 4 to mutableListOf(IllegalAttributeError(FAKE_KEY)), + ) + ), + "common/reference/reference/reference_invalid_attribute.xml", + ), + + /* UserConfiguration */ + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/userConfiguration/user_configurations_no_children_invalid.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_configuration_child_in_user_configurations.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_configuration_missing_children_in_scene.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_configuration_optional_attribute_in_scene.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_configuration_required_attribute_in_scene.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "userConfiguration/booleanConfiguration/invalid_boolean_configuration_v4_attribute_in_v1.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_option_bad_id.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_boolean_option_missing_id.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_missing_defaultValue.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_missing_displayName.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/booleanConfiguration/invalid_missing_id.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_child_in_user_configurations.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_missing_children_in_scene.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_missing_id.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_missing_displayName.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_missing_defaultValue.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_bad_defaultValue.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_option_missing_id.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_option_with_child_in_user_configurations.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "userConfiguration/listConfiguration/invalid_list_configuration_attribute_in_scene.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4)) + ), + 3 to + mutableListOf(VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(4))), + ) + ), + "userConfiguration/listConfiguration/invalid_list_configuration_v4_attribute_in_v1.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 4 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + ) + ), + "userConfiguration/flavor/invalid_flavors_no_children.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/flavor/invalid_flavors_with_invalid_child.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 4 to + mutableListOf( + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + ) + ), + "userConfiguration/flavor/invalid_flavors_missing_defaultValue.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/flavor/invalid_flavor_missing_id.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/flavor/invalid_flavor_missing_displayName.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/flavor/invalid_flavor_no_children.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/flavor/invalid_configuration_missing_id.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/flavor/invalid_configuration_missing_optionId.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(2, 3, 4)) + ), + 0 to mutableListOf(TagOccurrenceError("Flavor", 21, 1..20)), + ) + ), + "userConfiguration/flavor/invalid_flavors_21_children.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/flavor/invalid_configuration_with_child.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_no_children.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_missing_id.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_missing_displayName.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_missing_defaultValue.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_bad_defaultValue.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_configuration_six_colors.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_option_missing_id.xml", + ), + arrayOf( + AllVersionsFailWithSameError(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_option_missing_color.xml", + ), + arrayOf( + GlobalError(AttributeValueError(FAKE_KEY, FAKE_VALUE, FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_option_bad_color.xml", + ), + arrayOf( + GlobalError(IllegalTagError(FAKE_ERROR_MESSAGE)), + "userConfiguration/colorConfiguration/invalid_color_option_with_child.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "userConfiguration/photosConfiguration/photos_configuration_missing_id_invalid.xml", + ), + arrayOf( + AllVersionsFail( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(3, 4)), + RequiredConditionFailedError(FAKE_ERROR_MESSAGE), + ), + 3 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + 4 to mutableListOf(RequiredConditionFailedError(FAKE_ERROR_MESSAGE)), + ) + ), + "userConfiguration/photosConfiguration/photos_configuration_missing_configType_invalid.xml", + ), + arrayOf( + GlobalError(IllegalAttributeError(FAKE_ERROR_MESSAGE)), + "userConfiguration/photosConfiguration/photos_configuration_invalid_configType_invalid.xml", + ), + arrayOf( + PartialFailure( + mapOf( + 1 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(3, 4)) + ), + 2 to + mutableListOf( + VersionEliminationError(FAKE_ERROR_MESSAGE, setOf(3, 4)) + ), + ) + ), + "userConfiguration/photosConfiguration/photos_configuration_old_version_invalid.xml", + ), + ) + } + + @Test + fun test() { + val doc: WatchFaceDocument = + JvmWatchFaceDocument.of(XmlReader.fromResource("/integration/$filePath")) + val validator = WatchFaceValidator(WFF_SPECIFICATION) + + val result: ValidationResult = validator.getValidationResult(doc) + val errorMapString = + result.errorMap + .map { (key, value) -> " VersionKey $key: $value" } + .joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") + + when (expectedError) { + /* A special 'global error' has been thrown which is not associated with any version */ + is GlobalError -> { + val error = result.errorMap[GLOBAL_ERROR_KEY]?.firstOrNull() + + assertTrue( + error != null, + "Expected a global error but was none. ErrorMap: $errorMapString", + ) + assertTrue( + result is ValidationResult.Failure, + "Expected overall failure but was $result. ErrorMap: $errorMapString", + ) + assertEquals( + "Expected ${expectedError.error::class}. But was ${error::class}. ErrorMap: $errorMapString", + expectedError.error::class, + error::class, + ) + } + + /* All versions have failed due to a common constraint */ + is AllVersionsFailWithSameError -> { + val errors: List = + ALL_WFF_VERSIONS.mapNotNull { result.errorMap[it]?.firstOrNull() } + + assertTrue( + result is ValidationResult.Failure, + "Expected overall failure but was ${result::class}. ErrorMap: $errorMapString", + ) + assertEquals( + "Expected all versions to fail. ErrorMap: $errorMapString", + ALL_WFF_VERSIONS.size, + errors.size, + ) + errors.forEach { + System.err.println("Actual error class: ${it::class}") + assertEquals( + "Expected each error to be a ${expectedError.error::class}. ErrorMap: $errorMapString", + expectedError.error::class, + it::class, + ) + } + } + + /* Some versions have failed due to version-specific constraints */ + is PartialFailure -> { + val expectedErrors = expectedError.errorMap.values.flatten() + val actualErrors = result.errorMap.values.flatten() + + assertTrue( + result is ValidationResult.PartialSuccess, + "Expected Partial Success but was $result. ErrorMap: $errorMapString", + ) + assertTrue( + expectedErrors.size == actualErrors.size, + "Expected ${expectedErrors.size} errors but found ${actualErrors.size}. Actual error map: $errorMapString", + ) + assertTrue( + (expectedErrors zip actualErrors).all { it.first::class == it.second::class }, + "Error maps did not match. Actual error map: $errorMapString", + ) + } + + is AllVersionsFail -> { + val expectedErrors = expectedError.errorMap.values.flatten() + val actualErrors = result.errorMap.values.flatten() + + assertTrue( + result is ValidationResult.Failure, + "Expected Failure but was $result. ErrorMap: $errorMapString", + ) + assertTrue( + expectedErrors.size == actualErrors.size, + "Expected ${expectedErrors.size} errors but found ${actualErrors.size}. Actual error map: $errorMapString", + ) + assertTrue( + (expectedErrors zip actualErrors).all { it.first::class == it.second::class }, + "Error maps did not match. Actual error map: $errorMapString", + ) + } + } + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorIntegrationTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorIntegrationTest.kt new file mode 100644 index 0000000..ea3cd87 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorIntegrationTest.kt @@ -0,0 +1,396 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.specification.WFF_SPECIFICATION +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class WatchFaceValidatorIntegrationTest( + val expectedValidVersions: Set, + val filePath: String, +) { + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "{index}: \"{1}\" = \"{0}\"") + fun testCases(): List> = + listOf( + /* WatchFace */ + arrayOf(ALL_WFF_VERSIONS, "watchface/watchFace.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchFaceOptionalAttributes.xml"), + arrayOf(emptySet(), "watchface/watchFaceMissingScene.xml"), + arrayOf(emptySet(), "watchface/watchFaceExtraAttribute.xml"), + arrayOf(emptySet(), "watchface/watchFaceNonIntegerHeight.xml"), + arrayOf(emptySet(), "watchface/watchFaceMissingAttributes.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchface_valid_corner_radius.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchface_valid_clipshape_circle.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchface_valid_clipshape_rectangle.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchface_valid_clipshape_none.xml"), + arrayOf(ALL_WFF_VERSIONS, "watchface/watchface_valid_clipshape_default.xml"), + arrayOf(emptySet(), "watchface/watchface_invalid_child.xml"), + arrayOf( + emptySet(), + "watchface/watchface_invalid_corner_radius_x_string.xml", + ), + arrayOf( + emptySet(), + "watchface/watchface_invalid_corner_radius_y_string.xml", + ), + arrayOf(emptySet(), "watchface/watchface_invalid_clipshape.xml"), + + /* Metadata */ + arrayOf(ALL_WFF_VERSIONS, "metadata/singleMetadata.xml"), + arrayOf(ALL_WFF_VERSIONS, "metadata/multipleMetadata.xml"), + arrayOf(emptySet(), "metadata/missingKeyMetadata.xml"), + arrayOf(emptySet(), "metadata/missingValueMetadata.xml"), + arrayOf(ALL_WFF_VERSIONS, "metadata/predefinedValuesMetadata.xml"), + arrayOf(emptySet(), "metadata/invalidClockTypeMetadata.xml"), + arrayOf(emptySet(), "metadata/invalidClockTypeMetadata.xml"), + arrayOf(emptySet(), "metadata/invalidClockTypeMetadata.xml"), + + /* Group */ + arrayOf(ALL_WFF_VERSIONS, "group/group/group_valid_optional_attributes.xml"), + arrayOf(emptySet(), "group/group/group_invalid_name.xml"), + arrayOf(emptySet(), "group/group/group_invalid_x.xml"), + arrayOf(emptySet(), "group/group/group_invalid_y.xml"), + arrayOf(emptySet(), "group/group/group_invalid_width.xml"), + arrayOf(emptySet(), "group/group/group_invalid_height.xml"), + arrayOf(emptySet(), "group/group/group_invalid_pivotX.xml"), + arrayOf(emptySet(), "group/group/group_invalid_pivotY.xml"), + arrayOf(emptySet(), "group/group/group_invalid_alpha.xml"), + arrayOf(emptySet(), "group/group/group_invalid_renderMode.xml"), + arrayOf(emptySet(), "group/group/group_invalid_tintColor.xml"), + arrayOf(emptySet(), "group/group/group_invalid_child.xml"), + + /* PartAnimatedImage */ + arrayOf(ALL_WFF_VERSIONS, "group/part/animatedImage/animatedImage/valid_basic.xml"), + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/animatedImage/valid_all_attributes.xml", + ), + + /* AnimationController */ + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/animationController/valid_basic.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/animationController/valid_all_attributes.xml", + ), + + /* PartAnimatedImage */ + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/partAnimatedImage/valid_basic.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/partAnimatedImage/valid_all_attributes.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/partAnimatedImage/valid_with_thumbnail.xml", + ), + + /* AnimatedImages */ + arrayOf( + ALL_WFF_VERSIONS, + "group/part/animatedImage/animatedImages/valid_basic.xml", + ), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "group/part/animatedImage/animatedImages/valid_all_attributes.xml", + ), + + /* ImageFilter */ + arrayOf(ALL_WFF_VERSIONS, "group/part/image/imageFilter/valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/image/imageFilter/valid_all_attributes.xml"), + + /* AnalogClock */ + arrayOf(ALL_WFF_VERSIONS, "clock/analogclock/analog_clock_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/analogclock/analog_clock_valid_attributes.xml"), + + /* DigitalClock */ + arrayOf(ALL_WFF_VERSIONS, "clock/digitalclock/digital_clock_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/digitalclock/digital_clock_valid_attributes.xml"), + + /* HourHand */ + arrayOf(ALL_WFF_VERSIONS, "clock/hourhand/hour_hand_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/hourhand/hour_hand_valid_attributes.xml"), + + /* MinuteHand */ + arrayOf(ALL_WFF_VERSIONS, "clock/minutehand/minute_hand_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/minutehand/minute_hand_valid_attributes.xml"), + + /* SecondHand */ + arrayOf(ALL_WFF_VERSIONS, "clock/secondhand/second_hand_valid_basic_sweep.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/secondhand/second_hand_valid_basic_tick.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/secondhand/second_hand_valid_no_child.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/secondhand/second_hand_valid_attributes.xml"), + + /* TimeText */ + arrayOf(ALL_WFF_VERSIONS, "clock/timetext/time_text_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "clock/timetext/time_text_valid_attributes.xml"), + + /* Scene */ + arrayOf(ALL_WFF_VERSIONS, "scene/basicScene.xml"), + arrayOf(ALL_WFF_VERSIONS, "scene/backgroundColorScene.xml"), + arrayOf(emptySet(), "scene/invalidBackgroundColorScene.xml"), + arrayOf(emptySet(), "scene/emptyScene.xml"), + arrayOf(ALL_WFF_VERSIONS, "scene/manyChildScene.xml"), + arrayOf((4..MAX_WFF_VERSION).toSet(), "scene/transformChildScene.xml"), + + /* PartText */ + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_name.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_pivot.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_angle.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_alpha.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_scale.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_renderMode.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/partText/valid_parttext_tintColor.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/text/valid_text_align.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/text/valid_text_ellipsis.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/text/valid_text_maxlines.xml"), + arrayOf(setOf(3, 4), "group/part/text/text/valid_text_isautosize.xml"), + arrayOf( + ALL_WFF_VERSIONS, + "group/part/text/textCircular/valid_textcircular_all_attributes.xml", + ), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_all_attributes.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_shadow.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_outline.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_outglow.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_underline.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_strikethrough.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_inlineimage.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_template.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_upper.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/text/font/valid_font_lower.xml"), + + /* PartImage */ + arrayOf( + ALL_WFF_VERSIONS, + "group/part/image/partImage/valid_partimage_with_image.xml", + ), + arrayOf(ALL_WFF_VERSIONS, "group/part/image/images/valid_images_with_change.xml"), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "group/part/image/images/valid_images_with_changedirection.xml", + ), + arrayOf((3..MAX_WFF_VERSION).toSet(), "group/part/image/photos/valid_photos.xml"), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "group/part/image/photos/valid_photos_with_all_attributes.xml", + ), + + /* PartDraw */ + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_name.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_pivot.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_angle.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_alpha.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_scale.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_rendermode.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/partDraw/valid_partdraw_tintcolor.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/shape/valid_line.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/shape/valid_arc.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/shape/valid_ellipse.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/shape/valid_roundrectangle.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/style/valid_fill.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/style/valid_stroke.xml"), + arrayOf( + (2..MAX_WFF_VERSION).toSet(), + "group/part/draw/style/valid_weightedstroke.xml", + ), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/gradient/valid_lineargradient.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/gradient/valid_radialgradient.xml"), + arrayOf(ALL_WFF_VERSIONS, "group/part/draw/gradient/valid_sweepgradient.xml"), + + /* ComplicationSlot */ + arrayOf( + ALL_WFF_VERSIONS, + "complication/complicationslot/valid_complicationslot.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "complication/complicationslot/valid_complicationslot_multiple_supported_types.xml", + ), + + /* BoundingBox */ + arrayOf(ALL_WFF_VERSIONS, "complication/bounding/valid_boundingbox.xml"), + + /* DefaultProviderPolicy */ + arrayOf( + ALL_WFF_VERSIONS, + "complication/defaultproviderpolicy/valid_defaultproviderpolicy.xml", + ), + + /* Complication */ + arrayOf(ALL_WFF_VERSIONS, "complication/complication/valid_complication.xml"), + + /* BitmapFonts */ + arrayOf(emptySet(), "bitmapfonts/emptyBitMapFonts.xml"), + arrayOf(emptySet(), "bitmapfonts/extraAttributeCharacter.xml"), + arrayOf(emptySet(), "bitmapfonts/illegalFontElement.xml"), + arrayOf(emptySet(), "bitmapfonts/missingAttributeCharacter.xml"), + arrayOf(emptySet(), "bitmapfonts/missingBitMapFontsContainer.xml"), + arrayOf(emptySet(), "bitmapfonts/duplicateFontName.xml"), + arrayOf(emptySet(), "bitmapfonts/duplicateArtifactName.xml"), + arrayOf(ALL_WFF_VERSIONS, "bitmapfonts/manyValidFonts.xml"), + arrayOf(ALL_WFF_VERSIONS, "bitmapfonts/manyValidArtifacts.xml"), + arrayOf(ALL_WFF_VERSIONS, "bitmapfonts/singleCharacterBitmapFont.xml"), + arrayOf(ALL_WFF_VERSIONS, "bitmapfonts/singleWordBitmapFont.xml"), + arrayOf((2..MAX_WFF_VERSION).toSet(), "bitmapfonts/singleWordWithMargin.xml"), + + /* Condition */ + arrayOf(ALL_WFF_VERSIONS, "common/condition/condition_valid.xml"), + + /* Localization */ + arrayOf(ALL_WFF_VERSIONS, "common/localization/localization_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "common/localization/localization_valid_locale.xml"), + arrayOf( + ALL_WFF_VERSIONS, + "common/localization/localization_valid_all_attributes.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "common/localization/localization_valid_no_attributes.xml", + ), + + /* ScreenReader */ + arrayOf(ALL_WFF_VERSIONS, "common/screenreader/screenreader_valid_basic.xml"), + arrayOf( + ALL_WFF_VERSIONS, + "common/screenreader/screenreader_valid_multiple_parameters.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "common/screenreader/screenreader_valid_no_parameters.xml", + ), + + /* Variant */ + arrayOf(ALL_WFF_VERSIONS, "common/variant/variant_valid_basic.xml"), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "common/variant/variant_valid_v4_attributes.xml", + ), + + /* Gyro */ + arrayOf(ALL_WFF_VERSIONS, "common/transform/gyro/gyro_valid_basic.xml"), + arrayOf(ALL_WFF_VERSIONS, "common/transform/gyro/gyro_valid_all_attributes.xml"), + + /* Transform */ + arrayOf(ALL_WFF_VERSIONS, "common/transform/transform/valid_transform.xml"), + arrayOf(ALL_WFF_VERSIONS, "common/transform/transform/valid_mode_by.xml"), + arrayOf(ALL_WFF_VERSIONS, "common/transform/transform/valid_mode_to.xml"), + + /* Animation */ + arrayOf( + ALL_WFF_VERSIONS, + "common/transform/animation/animation_valid_duration.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "common/transform/animation/animation_valid_interpolation.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "common/transform/animation/animation_valid_controls.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "common/transform/animation/animation_valid_angleDirection.xml", + ), + arrayOf(ALL_WFF_VERSIONS, "common/transform/animation/animation_valid_repeat.xml"), + arrayOf(ALL_WFF_VERSIONS, "common/transform/animation/animation_valid_fps.xml"), + + /* Reference */ + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "common/reference/reference/reference_valid_basic.xml", + ), + + /* UserConfiguration */ + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/userConfiguration/user_configurations_valid.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/booleanConfiguration/valid_boolean_configuration.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/booleanConfiguration/valid_boolean_configuration_with_optional_attributes.xml", + ), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "userConfiguration/booleanConfiguration/valid_boolean_configuration_v4.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/booleanConfiguration/valid_boolean_option_with_children.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/listConfiguration/valid_list_configuration.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/listConfiguration/valid_list_configuration_with_optional_attributes.xml", + ), + arrayOf( + (4..MAX_WFF_VERSION).toSet(), + "userConfiguration/listConfiguration/valid_list_configuration_v4.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/listConfiguration/valid_list_option_with_children.xml", + ), + arrayOf((2..MAX_WFF_VERSION).toSet(), "userConfiguration/flavor/valid_flavor.xml"), + arrayOf( + (2..MAX_WFF_VERSION).toSet(), + "userConfiguration/flavor/valid_flavor_with_optional_attributes.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/colorConfiguration/valid_color_configuration.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/colorConfiguration/valid_color_configuration_with_many_colors.xml", + ), + arrayOf( + ALL_WFF_VERSIONS, + "userConfiguration/colorConfiguration/valid_color_configuration_with_optional_attributes.xml", + ), + arrayOf( + (3..MAX_WFF_VERSION).toSet(), + "userConfiguration/photosConfiguration/photos_configuration_valid.xml", + ), + ) + } + + @Test + fun test() { + val doc: WatchFaceDocument = + JvmWatchFaceDocument.of(XmlReader.fromResource("/integration/$filePath")) + val validator = WatchFaceValidator(WFF_SPECIFICATION) + + val result: ValidationResult = validator.getValidationResult(doc) + val validVersions = result.validVersions + val errorMapString = + result.errorMap + .map { (key, value) -> " VersionKey $key: $value" } + .joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") + + assertEquals( + "Validation failed with errors: $errorMapString ", + expectedValidVersions, + validVersions, + ) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorTest.kt new file mode 100644 index 0000000..6b35cfe --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/WatchFaceValidatorTest.kt @@ -0,0 +1,530 @@ +package com.google.wear.watchface.validator + +import com.google.wear.watchface.validator.constraint.AllowedConstraint +import com.google.wear.watchface.validator.constraint.Constraint +import com.google.wear.watchface.validator.constraint.PassAllVersions +import com.google.wear.watchface.validator.constraint.RequiredConstraint +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.condition.ElementCondition +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.specification.WatchFaceSpecification +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class WatchFaceValidatorTest { + + @Test + fun validateShouldApplyConstraintsToRootNode() { + val watchFaceConstraint: Constraint = + RequiredConstraint( + listOf(ElementCondition { node, _ -> node.tagName == "WatchFace" }), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = + validator.getValidationResult( + TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + ) + val invalidResult = + validator.getValidationResult( + TestWatchFace(WatchFaceElement("BadWatchFace", emptyMap(), emptyList())) + ) + + assertTrue(validResult is ValidationResult.Success) + assertTrue(invalidResult is ValidationResult.Failure) + } + + @Test + fun validatorAllowsDeclaredChildren() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Metadata", emptyMap(), emptyList())), + ) + ) + val metadataConstraint = PassAllVersions + val watchFaceConstraint = + RequiredConstraint( + listOf(ConditionLibrary.childElement("Metadata", { metadataConstraint })), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.getValidationResult(watchFace) + + assertTrue(validResult is ValidationResult.Success) + } + + @Test + fun validatorShouldAlsoValidateDeclaredChildren() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Metadata", emptyMap(), emptyList())), + ) + ) + val passingMetaDataConstraint = + RequiredConstraint(listOf(ConditionLibrary.alwaysPass()), ALL_WFF_VERSIONS) + val passingWatchFaceConstraint = + RequiredConstraint( + listOf(ConditionLibrary.childElement("Metadata", { passingMetaDataConstraint })), + ALL_WFF_VERSIONS, + ) + val failingMetaDataConstraint = + RequiredConstraint(listOf(ConditionLibrary.alwaysFail()), ALL_WFF_VERSIONS) + val failingWatchFaceConstraint = + RequiredConstraint( + listOf(ConditionLibrary.childElement("Metadata", { failingMetaDataConstraint })), + ALL_WFF_VERSIONS, + ) + + val validSpec = WatchFaceSpecification(passingWatchFaceConstraint, ALL_WFF_VERSIONS) + val validResult = WatchFaceValidator(validSpec).getValidationResult(watchFace) + val invalidSpec = WatchFaceSpecification(failingWatchFaceConstraint, ALL_WFF_VERSIONS) + val invalidResult = WatchFaceValidator(invalidSpec).getValidationResult(watchFace) + + assertTrue(validResult is ValidationResult.Success) + assertTrue(invalidResult is ValidationResult.Failure) + } + + @Test + fun validatorShouldNotAllowUndeclaredChildren() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Metadata", emptyMap(), emptyList()), + WatchFaceElement("Unexpected", emptyMap(), emptyList()), + ), + ) + ) + val metadataConstraint = + RequiredConstraint(listOf(ConditionLibrary.alwaysPass()), ALL_WFF_VERSIONS) + val watchFaceConstraint = + RequiredConstraint( + listOf(ConditionLibrary.childElement("Metadata", { metadataConstraint })), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorShouldOnlyAllowDeclaredChildren() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Metadata", emptyMap(), emptyList())), + ) + ) + val watchFaceConstraint = RequiredConstraint(listOf(), ALL_WFF_VERSIONS) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorAllowsDeclaredAttributes() { + val watchFace = + TestWatchFace(WatchFaceElement("WatchFace", mapOf("attribute" to "value"), emptyList())) + val watchFaceConstraint = + RequiredConstraint(listOf(ConditionLibrary.attribute("attribute")), ALL_WFF_VERSIONS) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val validResult = validator.getValidationResult(watchFace) + + assertTrue(validResult is ValidationResult.Success) + } + + @Test + fun validatorShouldAlsoValidateDeclaredAttributes() { + val watchFace = + TestWatchFace(WatchFaceElement("WatchFace", mapOf("attribute" to "value"), emptyList())) + val passingWatchFaceConstraint = + RequiredConstraint( + listOf( + ConditionLibrary.attribute("attribute"), + ElementCondition { node, _ -> node.attributes["attribute"] == "value" }, + ), + ALL_WFF_VERSIONS, + ) + val failingWatchFaceConstraint = + RequiredConstraint( + listOf( + ConditionLibrary.attribute("attribute"), + ElementCondition { node, _ -> node.attributes["attribute"] == "otherValue" }, + ), + ALL_WFF_VERSIONS, + ) + + val validSpec = WatchFaceSpecification(passingWatchFaceConstraint, ALL_WFF_VERSIONS) + val validResult = WatchFaceValidator(validSpec).getValidationResult(watchFace) + val invalidSpec = WatchFaceSpecification(failingWatchFaceConstraint, ALL_WFF_VERSIONS) + val invalidResult = WatchFaceValidator(invalidSpec).getValidationResult(watchFace) + + assertTrue(validResult is ValidationResult.Success) + assertTrue(invalidResult is ValidationResult.Failure) + } + + @Test + fun validatorShouldNotAllowUndeclaredAttributes() { + val watchFace = + TestWatchFace( + WatchFaceElement("WatchFace", mapOf("unexpectedAttribute" to "value"), emptyList()) + ) + val watchFaceConstraint = RequiredConstraint(listOf(), ALL_WFF_VERSIONS) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorShouldOnlyAllowDeclaredAttributes() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + mapOf("attribute" to "value", "unexpectedAttribute" to "value"), + emptyList(), + ) + ) + val watchFaceConstraint = + RequiredConstraint(listOf(ConditionLibrary.attribute("attribute")), ALL_WFF_VERSIONS) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorShouldReturnAllVersionsIfNoConstraintsFail() { + val constraint: Constraint = + constraint("WatchFace") { + versions(1, 2, 4) + .require(ElementCondition { node, _ -> node.tagName == "WatchFace" }) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = + validator.findValidVersions( + TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + ) + + assertEquals(setOf(1, 2, 3, 4), result) + } + + @Test + fun validatorShouldTakeTheIntersectionOfVersionsBetweenParentAndChildNodes() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Scene", emptyMap(), emptyList())), + ) + ) + val sceneConstraint: Constraint = constraint("Scene") { exclusiveToVersions(2, 4) } + val watchFaceConstraint: Constraint = + constraint("WatchFace") { + exclusiveToVersions(1, 2, 4) + allVersions().allow(childElement("Scene", { sceneConstraint })) + } + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(2, 4), result) + } + + @Test + fun validatorShouldTakeTheIntersectionOfVersionsBetweenSiblingNodes() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Child1", emptyMap(), emptyList()), + WatchFaceElement("Child2", emptyMap(), emptyList()), + ), + ) + ) + val constraint: Constraint = + constraint("WatchFace") { + exclusiveToVersions(1, 2, 4) + allVersions() + .allow( + childElement( + "Child1", + { constraint("Child1") { exclusiveToVersions(2, 4) } }, + ), + childElement( + "Child2", + { constraint("Child2") { exclusiveToVersions(1, 2) } }, + ), + ) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(2), result) + } + + @Test + fun validatorShouldTakeTheIntersectionOfVersionsBetweenManySiblingNodes() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Child1", emptyMap(), emptyList()), + WatchFaceElement("Child2", emptyMap(), emptyList()), + WatchFaceElement("Child3", emptyMap(), emptyList()), + WatchFaceElement("Child4", emptyMap(), emptyList()), + ), + ) + ) + val constraint: Constraint = + constraint("WatchFace") { + exclusiveToVersions(1, 2, 3, 4) + allVersions() + .allow( + childElement( + "Child1", + { constraint("Child1") { exclusiveToVersions(2, 3, 4) } }, + ), + childElement( + "Child2", + { constraint("Child2") { exclusiveToVersions(2, 3) } }, + ), + childElement("Child3", { constraint("Child3") { exclusiveToVersions(3) } }), + childElement("Child4", { constraint("Child4") { exclusiveToVersions(3) } }), + ) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(3), result) + } + + @Test + fun validatorShouldVersionWithRespectToExpressionFunctionSupport() { + val sceneConstraint: Constraint = + constraint("Scene") { + exclusiveToVersions(1, 2, 4) + allVersions().allow(attribute("expression", validExpression())) + } + val watchFaceConstraint: Constraint = + constraint("WatchFace") { + exclusiveToVersions(1, 2, 4) + allVersions().allow(childElement("Scene", { sceneConstraint })) + } + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val versionedExpression = + "expression" to "colorArgb(1,2,3,4)" // only supported in version 4 + + val result = + validator.findValidVersions( + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Scene", mapOf(versionedExpression), emptyList())), + ) + ) + ) + + assertEquals(setOf(4), result) + } + + @Test + fun validatorShouldVersionWithRespectToExpressionSourceSupport() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement( + "Scene", + mapOf( + "expression" to "[HOURS_SINCE_EPOCH]" + ), // only supported from version 3 + emptyList(), + ) + ), + ) + ) + val sceneConstraint: Constraint = + constraint("Scene") { + exclusiveToVersions(1, 2, 4) + allVersions().allow(attribute("expression", validExpression())) + } + val watchFaceConstraint: Constraint = + constraint("WatchFace") { + exclusiveToVersions(1, 2, 4) + allVersions().allow(childElement("Scene", { sceneConstraint })) + } + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(4), result) + } + + @Test + fun validatingAWatchFaceWithAnInvalidExpressionFails() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + mapOf("expression" to "3 *", "unexpectedAttribute" to "value"), + emptyList(), + ) + ) + val watchFaceConstraint = + RequiredConstraint( + listOf(with(ConditionLibrary) { attribute("expression", validExpression()) }), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(watchFaceConstraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorShouldEnforceChildOccurrences() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Child1", emptyMap(), emptyList()), + WatchFaceElement("Child1", emptyMap(), emptyList()), + ), + ) + ) + val constraint = + RequiredConstraint( + listOf( + ConditionLibrary.childElement( + "Child1", + { PassAllVersions }, + minOccurs = 1, + maxOccurs = 1, + ) + ), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun validatorShouldEnforceChildOccurrencesInAllowsClause() { + val noChildWatchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val oneChildWatchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Child1", emptyMap(), emptyList())), + ) + ) + + val twoChildWatchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Child1", emptyMap(), emptyList()), + WatchFaceElement("Child1", emptyMap(), emptyList()), + ), + ) + ) + + val mixedChildWatchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf( + WatchFaceElement("Child1", emptyMap(), emptyList()), + WatchFaceElement("Child2", emptyMap(), emptyList()), + ), + ) + ) + val constraint = + AllowedConstraint( + listOf( + ConditionLibrary.childElement( + "Child1", + { PassAllVersions }, + minOccurs = 1, + maxOccurs = 1, + ), + ConditionLibrary.childElement("Child2", { PassAllVersions }), + ), + ALL_WFF_VERSIONS, + ) + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val zeroChildResult = validator.getValidationResult(noChildWatchFace) + val oneChildResult = validator.getValidationResult(oneChildWatchFace) + val twoChildResult = validator.getValidationResult(twoChildWatchFace) + val mixedChildResult = validator.getValidationResult(mixedChildWatchFace) + + assertTrue(zeroChildResult is ValidationResult.Success) + assertTrue(oneChildResult is ValidationResult.Success) + assertTrue(twoChildResult is ValidationResult.Failure) + assertTrue(mixedChildResult is ValidationResult.Success) + } + + private class TestWatchFace(override val rootElement: WatchFaceElement) : WatchFaceDocument {} +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/XmlReadersTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/XmlReadersTest.kt new file mode 100644 index 0000000..c8d6a16 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/XmlReadersTest.kt @@ -0,0 +1,25 @@ +package com.google.wear.watchface.validator + +import kotlin.test.assertEquals +import org.junit.Test + +class XmlReadersTest { + + @Test + fun readFromFileReturnsValidXmlDocWithCorrectRootNode() { + val doc = XmlReader.fromResource("/metaDataWatchFace.xml") + + val result = doc.documentElement.tagName + + assertEquals("WatchFace", result) + } + + @Test + fun readFromFileReturnsValidXmlDocWithCorrectChildren() { + val doc = XmlReader.fromResource("/metaDataWatchFace.xml") + + val result = doc.documentElement.getElementsByTagName("Metadata").length + + assertEquals(3, result) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilderTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilderTest.kt new file mode 100644 index 0000000..c55d36b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/constraint/ConstraintBuilderTest.kt @@ -0,0 +1,275 @@ +package com.google.wear.watchface.validator.constraint + +import com.google.wear.watchface.validator.ALL_WFF_VERSIONS +import com.google.wear.watchface.validator.WatchFaceDocument +import com.google.wear.watchface.validator.WatchFaceElement +import com.google.wear.watchface.validator.WatchFaceElementContext +import com.google.wear.watchface.validator.WatchFaceValidator +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.error.ValidationResult +import com.google.wear.watchface.validator.specification.WatchFaceSpecification +import junit.framework.TestCase.assertTrue +import kotlin.test.Test +import kotlin.test.assertEquals + +class ConstraintBuilderTest { + @Test + fun singleConstraintShouldPreserveVersions() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(ALL_WFF_VERSIONS).require(ConditionLibrary.alwaysPass()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(ALL_WFF_VERSIONS, result) + } + + @Test + fun nestedSatisfiedVersionsShouldReturnTheParentSet() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 4).require(ConditionLibrary.alwaysPass()) + versions(1 to 3).require(ConditionLibrary.alwaysPass()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(1, 2, 3, 4), result) + } + + @Test + fun failingRequiresShouldRemoveVersions() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 4).require(ConditionLibrary.alwaysPass()) + versions(1 to 3).require(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(4), result) + } + + @Test + fun passingRequiresShouldReturnAllSetsByDefault() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1).require(ConditionLibrary.alwaysPass()) + versions(3 to 4).require(ConditionLibrary.alwaysPass()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(1, 2, 3, 4), result) + } + + @Test + fun disjointFailingRequiresShouldRemove() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 2).require(ConditionLibrary.alwaysPass()) + versions(3 to 4).require(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(1, 2), result) + } + + @Test + fun validationRulesCanConstrainAllVersions() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { allVersions().require(ConditionLibrary.alwaysPass()) } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(ALL_WFF_VERSIONS, result) + } + + @Test + fun failingRequiresRemovesTheVersion() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 4).require(ConditionLibrary.alwaysPass()) + versions(3).require(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(1, 2, 4), result) + } + + @Test + fun failingAllowsDoesNotRemoveTheVersion() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 4).require(ConditionLibrary.alwaysPass()) + versions(3).allow(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(1, 2, 3, 4), result) + } + + @Test + fun passingAnAllowsClauseFiltersTheVersions() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 4).require(ConditionLibrary.alwaysPass()) + versions(2, 4).allow(ConditionLibrary.alwaysPass()) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.findValidVersions(watchFace) + + assertEquals(setOf(2, 4), result) + } + + @Test + fun requireBlockNeedsAllConstraintsToBeSatisfied() { + val missingBothWatchFace = WatchFaceElement("WatchFace", emptyMap(), emptyList()) + val missingXWatchFace = WatchFaceElement("WatchFace", mapOf("y" to "100"), emptyList()) + val missingYWatchFace = WatchFaceElement("WatchFace", mapOf("x" to "100"), emptyList()) + val hasBothWatchFace = + WatchFaceElement("WatchFace", mapOf("x" to "100", "y" to "100"), emptyList()) + + val constraint: Constraint = + constraint("WatchFace") { allVersions().require(attribute("x"), attribute("y")) } + + val missingBothResult = + constraint.check(missingBothWatchFace, WatchFaceElementContext.Companion.emptyContext()) + val missingXResult = + constraint.check(missingXWatchFace, WatchFaceElementContext.Companion.emptyContext()) + val missingYResult = + constraint.check(missingYWatchFace, WatchFaceElementContext.Companion.emptyContext()) + val hasBothResult = + constraint.check(hasBothWatchFace, WatchFaceElementContext.Companion.emptyContext()) + + assertTrue(missingBothResult is ValidationResult.Failure) + assertTrue(missingXResult is ValidationResult.Failure) + assertTrue(missingYResult is ValidationResult.Failure) + assertTrue(hasBothResult is ValidationResult.Success) + } + + @Test + fun allowsBlockNeedsAtLeastOneConstraintToBeSatisfiedToRestrictVersions() { + val missingBothWatchFace = WatchFaceElement("WatchFace", emptyMap(), emptyList()) + val missingXWatchFace = WatchFaceElement("WatchFace", mapOf("y" to "100"), emptyList()) + val missingYWatchFace = WatchFaceElement("WatchFace", mapOf("x" to "100"), emptyList()) + val hasBothWatchFace = + WatchFaceElement("WatchFace", mapOf("x" to "100", "y" to "100"), emptyList()) + val constraint: Constraint = + constraint("WatchFace") { versions(1).allow(attribute("x"), attribute("y")) } + + val missingBothResult = + constraint.check(missingBothWatchFace, WatchFaceElementContext.emptyContext()) + val missingXResult = + constraint.check(missingXWatchFace, WatchFaceElementContext.emptyContext()) + val missingYResult = + constraint.check(missingYWatchFace, WatchFaceElementContext.emptyContext()) + val hasBothResult = + constraint.check(hasBothWatchFace, WatchFaceElementContext.emptyContext()) + + assertEquals(setOf(1), hasBothResult.validVersions) + assertEquals(setOf(1), missingXResult.validVersions) + assertEquals(setOf(1), missingYResult.validVersions) + assertEquals(ALL_WFF_VERSIONS, missingBothResult.validVersions) + } + + @Test + fun choiceClauseShouldFailIfAllConditionsAreFalse() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { allVersions().require(choice(ConditionLibrary.alwaysFail())) } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + @Test + fun choiceShouldPassIfOneConditionIsTrue() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions() + .require(choice(ConditionLibrary.alwaysFail(), ConditionLibrary.alwaysPass())) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Success) + } + + @Test + fun choiceClauseShouldPassIfAllConditionsAreFalseAndMinIsZero() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions().require(choice(ConditionLibrary.alwaysFail(), minOccurs = 0)) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Success) + } + + @Test + fun choiceClauseShouldFailIfPassingConditionsExceedsMax() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions() + .require( + choice( + ConditionLibrary.alwaysPass(), + ConditionLibrary.alwaysPass(), + ConditionLibrary.alwaysPass(), + maxOccurs = 2, + ) + ) + } + + val spec = WatchFaceSpecification(constraint, ALL_WFF_VERSIONS) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + } + + private class TestWatchFace(override val rootElement: WatchFaceElement) : WatchFaceDocument {} +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/error/ValidationReportTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/error/ValidationReportTest.kt new file mode 100644 index 0000000..2f8140b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/error/ValidationReportTest.kt @@ -0,0 +1,144 @@ +package com.google.wear.watchface.validator.error + +import com.google.wear.watchface.validator.WatchFaceDocument +import com.google.wear.watchface.validator.WatchFaceElement +import com.google.wear.watchface.validator.WatchFaceValidator +import com.google.wear.watchface.validator.constraint.ConstraintBuilderTest.TestWatchFace +import com.google.wear.watchface.validator.constraint.condition.ConditionLibrary +import com.google.wear.watchface.validator.constraint.constraint +import com.google.wear.watchface.validator.specification.WatchFaceSpecification +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class ValidationReportTest { + + @Test + fun validWatchFaceReturnsSuccess() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { allVersions().require(ConditionLibrary.alwaysPass()) } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertEquals(ValidationResult.Success, result) + } + + @Test + fun undeclaredElementFailsWithIllegalTagError() { + val watchFace = + TestWatchFace( + WatchFaceElement( + "WatchFace", + emptyMap(), + listOf(WatchFaceElement("Bad", emptyMap(), emptyList())), + ) + ) + val constraint = + constraint("WatchFace") { allVersions().require(ConditionLibrary.alwaysPass()) } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + assertTrue(result is ValidationResult.Failure) + assertTrue(result.errorMap[GLOBAL_ERROR_KEY]?.firstOrNull() is IllegalTagError) + assertEquals(emptySet(), result.validVersions) + } + + @Test + fun invalidExpressionReturnsFailure() { + val watchFace = + TestWatchFace(WatchFaceElement("WatchFace", mapOf("expression" to "3 +"), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions() + .require( + ConditionLibrary.alwaysPass(), + attribute("expression", validExpression()), + ) + } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + val error = result.errorMap[GLOBAL_ERROR_KEY]?.firstOrNull() + + assertTrue(result is ValidationResult.Failure) + assertTrue(error is ExpressionSyntaxError) + assertEquals(emptySet(), result.validVersions) + } + + @Test + fun failedVersionReturnsPartialSuccess() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions().require(ConditionLibrary.alwaysPass()) + versions(4).require(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + val error = result.errorMap[4]?.firstOrNull() + + assertTrue(result is ValidationResult.PartialSuccess) + assertTrue(error is RequiredConditionFailedError) + assertEquals(setOf(1, 2, 3), result.validVersions) + } + + @Test + fun passingAllowedConstraintVersionReturnsPartialSuccess() { + + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + allVersions().require(ConditionLibrary.alwaysPass()) + versions(4).allow(ConditionLibrary.alwaysPass()) + } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + + val version1Error = result.errorMap[1]?.firstOrNull() + val version2Error = result.errorMap[2]?.firstOrNull() + val version3Error = result.errorMap[3]?.firstOrNull() + + assertTrue(result is ValidationResult.PartialSuccess) + assertTrue(version1Error is VersionEliminationError) + assertTrue(version2Error is VersionEliminationError) + assertTrue(version3Error is VersionEliminationError) + assertEquals(setOf(4), result.validVersions) + } + + @Test + fun invalidatingEveryVersionReturnsFailure() { + val watchFace = TestWatchFace(WatchFaceElement("WatchFace", emptyMap(), emptyList())) + val constraint = + constraint("WatchFace") { + versions(1 to 3).require(ConditionLibrary.alwaysFail()) + versions(4).require(ConditionLibrary.alwaysFail()) + } + + val spec = WatchFaceSpecification(constraint) + val validator = WatchFaceValidator(spec) + val result = validator.getValidationResult(watchFace) + val version1Error = result.errorMap[1]?.firstOrNull() + val version2Error = result.errorMap[2]?.firstOrNull() + val version3Error = result.errorMap[3]?.firstOrNull() + val version4Error = result.errorMap[4]?.firstOrNull() + + assertTrue(result is ValidationResult.Failure) + assertTrue(version1Error is RequiredConditionFailedError) + assertTrue(version2Error is RequiredConditionFailedError) + assertTrue(version3Error is RequiredConditionFailedError) + assertTrue(version4Error is RequiredConditionFailedError) + assertEquals(emptySet(), result.validVersions) + } + + private class TestWatchFace(override val rootElement: WatchFaceElement) : WatchFaceDocument {} +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/ExpressionParserTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/ExpressionParserTest.kt new file mode 100644 index 0000000..2108082 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/ExpressionParserTest.kt @@ -0,0 +1,284 @@ +package com.google.wear.watchface.validator.expression + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class ExpressionParserTest { + @Test + fun emptyExpressionShouldFail() { + val tokens = sequenceOf(Token.EOF) + + val exception = assertFailsWith { ExpressionParser.parse(tokens) } + + assertEquals("Unexpected End of Expression", exception.message) + } + + @Test + fun singleUnknownTokensShouldFail() { + val tokens = sequenceOf(Token.Unknown("@"), Token.EOF) + + val exception = assertFailsWith { ExpressionParser.parse(tokens) } + + assertEquals("Unrecognised Token: @", exception.message) + } + + @Test + fun embeddedUnknownTokensShouldFail() { + val tokens = + sequenceOf(Token.Number("3"), Token.Operator("+"), Token.Unknown("@"), Token.EOF) + val exception = assertFailsWith { ExpressionParser.parse(tokens) } + assertEquals("Unrecognised Token: @", exception.message) + } + + @Test + fun numericLiteralsShouldParse() { + val tokens = sequenceOf(Token.Number("3"), Token.EOF) + val expected: Expression = NumLiteral(3.0) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun variablesShouldParse() { + val tokens = sequenceOf(Token.Word("test"), Token.EOF) + val expected: Expression = Variable("test") + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun functionsShouldParse() { + val tokens = + sequenceOf( + Token.Word("round"), + Token.Paren("("), + Token.Number("3.9"), + Token.Paren(")"), + Token.EOF, + ) + val expected: Expression = FunctionCall("round", listOf(NumLiteral(3.9))) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun basicArithmeticExpressionsShouldParse() { + val tokens = + sequenceOf(Token.Number("3"), Token.Operator("+"), Token.Number("5"), Token.EOF) + val expected: Expression = Add(NumLiteral(3.0), NumLiteral(5.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun nonExistentFunctionShouldFail() { + val tokens = + sequenceOf( + Token.Word("nonExistentFunction"), + Token.Paren("("), + Token.Number("3.9"), + Token.Paren(")"), + Token.EOF, + ) + + val exception = + assertFailsWith { ExpressionParser.parse(tokens) } + } + + @Test + fun functionWithIncorrectArityShouldFail() { + val tokens = + sequenceOf( + Token.Word("round"), + Token.Paren("("), + Token.Number("3.9"), + Token.Operator(","), + Token.Number("2.1"), + Token.Paren(")"), + Token.EOF, + ) + + val exception = + assertFailsWith { ExpressionParser.parse(tokens) } + } + + @Test + fun mulShouldParseWithHigherPrecedenceThanAdd() { + val tokens = + sequenceOf( + Token.Number("3"), + Token.Operator("+"), + Token.Number("5"), + Token.Operator("*"), + Token.Number("5"), + Token.EOF, + ) + val expected: Expression = Add(NumLiteral(3.0), Mul(NumLiteral(5.0), NumLiteral(5.0))) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun parserShouldPreserveOrder() { + val tokens = + sequenceOf( + Token.Number("5"), + Token.Operator("*"), + Token.Number("5"), + Token.Operator("+"), + Token.Number("3"), + Token.EOF, + ) + val expected: Expression = Add(Mul(NumLiteral(5.0), NumLiteral(5.0)), NumLiteral(3.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun redundantBracketsShouldDoNothing() { + val tokens = + sequenceOf( + Token.Paren("("), + Token.Number("5"), + Token.Operator("*"), + Token.Number("5"), + Token.Paren(")"), + Token.Operator("+"), + Token.Number("3"), + Token.EOF, + ) + val expected: Expression = Add(Mul(NumLiteral(5.0), NumLiteral(5.0)), NumLiteral(3.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun necessaryBracketsShouldChangeOrderOfOperations() { + val tokens = + sequenceOf( + Token.Paren("("), + Token.Number("5"), + Token.Operator("+"), + Token.Number("5"), + Token.Paren(")"), + Token.Operator("*"), + Token.Number("3"), + Token.EOF, + ) + val expected: Expression = Mul(Add(NumLiteral(5.0), NumLiteral(5.0)), NumLiteral(3.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun unaryOperatorsHaveTheHighestPrecedence() { + val tokens = + sequenceOf( + Token.Number("5"), + Token.Operator("+"), + Token.Number("5"), + Token.Operator("*"), + Token.Operator("-"), + Token.Number("3"), + Token.EOF, + ) + val expected: Expression = Add(NumLiteral(5.0), Mul(NumLiteral(5.0), Neg(NumLiteral(3.0)))) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun equalityOperationsShouldParse() { + val tokens = + sequenceOf(Token.Number("3"), Token.Operator("=="), Token.Number("5"), Token.EOF) + val expected: Expression = Equal(NumLiteral(3.0), NumLiteral(5.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun equalityOperationsShouldNotChain() { + val tokens = + sequenceOf( + Token.Number("3"), + Token.Operator("=="), + Token.Number("5"), + Token.Operator("=="), + Token.Number("5"), + Token.EOF, + ) + + val exception = + assertFailsWith { ExpressionParser.parse(tokens) } + + assertEquals("Expression Parser Finished Early: == not consumed", exception.message) + } + + @Test + fun comparisonOperationsShouldParse() { + val tokens = + sequenceOf(Token.Number("3"), Token.Operator("<="), Token.Number("5"), Token.EOF) + val expected: Expression = LessThanOrEqual(NumLiteral(3.0), NumLiteral(5.0)) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } + + @Test + fun comparisonOperationsShouldNotChain() { + val tokens = + sequenceOf( + Token.Number("3"), + Token.Operator("<="), + Token.Number("5"), + Token.Operator("<"), + Token.Number("5"), + Token.EOF, + ) + + val exception = + assertFailsWith { ExpressionParser.parse(tokens) } + + assertEquals("Expression Parser Finished Early: < not consumed", exception.message) + } + + @Test + fun chainableOperationsShouldBeRightAssociative() { + val tokens = + sequenceOf( + Token.Number("3"), + Token.Operator("&"), + Token.Number("5"), + Token.Operator("&"), + Token.Number("5"), + Token.EOF, + ) + val expected = BitwiseAnd(NumLiteral(3.0), BitwiseAnd(NumLiteral(5.0), NumLiteral(5.0))) + + val result: Expression = ExpressionParser.parse(tokens) + + assertEquals(expected, result) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/TokenizerTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/TokenizerTest.kt new file mode 100644 index 0000000..2b12750 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/TokenizerTest.kt @@ -0,0 +1,153 @@ +package com.google.wear.watchface.validator.expression + +import kotlin.test.Test +import kotlin.test.assertEquals + +class TokenizerTest { + @Test + fun whiteSpacesTokeniseToEmptyList() { + val expression = " " + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(emptyList(), tokens) + } + + @Test + fun numbersTokenisedAsNumber() { + val expression = "123" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Number("123")), tokens) + } + + @Test + fun numbersCanHaveDecimalPoints() { + val expression = "12.3" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Number("12.3")), tokens) + } + + @Test + fun wordsTokeniseCorrectly() { + val expression = "ACCELEROMETER_ANGLE_X" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Word("ACCELEROMETER_ANGLE_X")), tokens) + } + + @Test + fun wordsCanHaveDotsInThem() { + val expression = "REFERENCE.headerPosition" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Word("REFERENCE.headerPosition")), tokens) + } + + @Test + fun operatorsTokenisedAsOperators() { + val expression = "+" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Operator("+")), tokens) + } + + @Test + fun invalidCharactersTokenisedAsUnknown() { + val expression = "{}" + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(listOf(Token.Unknown("{"), Token.Unknown("}")), tokens) + } + + @Test + fun arithmeticExpressionTokenises() { + val expression = "5 + 3 * 2" + val expectedTokens = + listOf( + Token.Number("5"), + Token.Operator("+"), + Token.Number("3"), + Token.Operator("*"), + Token.Number("2"), + ) + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(expectedTokens, tokens) + } + + @Test + fun arithmeticExpressionsWithBracketsTokenises() { + val expression = "(5 + 3) * 2" + val expectedTokens = + listOf( + Token.Paren("("), + Token.Number("5"), + Token.Operator("+"), + Token.Number("3"), + Token.Paren(")"), + Token.Operator("*"), + Token.Number("2"), + ) + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(expectedTokens, tokens) + } + + @Test + fun completeExpressionTokenises() { + val expression = + "(5/90)*clamp([ACCELEROMETER_ANGLE_X],0,90) + (-5/90)*clamp([ACCELEROMETER_ANGLE_X],-90,0)" + val expectedTokens = + listOf( + Token.Paren("("), + Token.Number("5"), + Token.Operator("/"), + Token.Number("90"), + Token.Paren(")"), + Token.Operator("*"), + Token.Word("clamp"), + Token.Paren("("), + Token.Paren("["), + Token.Word("ACCELEROMETER_ANGLE_X"), + Token.Paren("]"), + Token.Operator(","), + Token.Number("0"), + Token.Operator(","), + Token.Number("90"), + Token.Paren(")"), + Token.Operator("+"), + Token.Paren("("), + Token.Operator("-"), + Token.Number("5"), + Token.Operator("/"), + Token.Number("90"), + Token.Paren(")"), + Token.Operator("*"), + Token.Word("clamp"), + Token.Paren("("), + Token.Paren("["), + Token.Word("ACCELEROMETER_ANGLE_X"), + Token.Paren("]"), + Token.Operator(","), + Token.Operator("-"), + Token.Number("90"), + Token.Operator(","), + Token.Number("0"), + Token.Paren(")"), + ) + + val tokens = Tokenizer.tokeniseString(expression).toList() + + assertEquals(expectedTokens, tokens) + } +} diff --git a/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/VersionRegistryTest.kt b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/VersionRegistryTest.kt new file mode 100644 index 0000000..f9b4db0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/kotlin/com/google/wear/watchface/validator/expression/VersionRegistryTest.kt @@ -0,0 +1,75 @@ +package com.google.wear.watchface.validator.expression + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class VersionRegistryTest { + + @Test + fun nonExistentFunctionThrowsFunctionNotFoundException() { + val fakeFunction: FunctionCall = FunctionCall("fakeFunction", emptyList()) + + assertFailsWith { + VersionRegistry.getFunctionVersions(fakeFunction) + } + } + + @Test + fun existentFunctionWithIncorrectArityThrowsFunctionNotFoundException() { + val tooManyArgumentsFunction: FunctionCall = + FunctionCall("sin", listOf(NumLiteral(6.0), NumLiteral(7.0))) + + assertFailsWith { + VersionRegistry.getFunctionVersions(tooManyArgumentsFunction) + } + } + + @Test + fun functionWithCorrectArityReturnsVersions() { + val sin: FunctionCall = FunctionCall("sin", listOf(NumLiteral(6.0))) + + val versions: VersionRange = VersionRegistry.getFunctionVersions(sin) + + assertEquals(VersionRange(1), versions) + } + + @Test + fun existentSourcesReturnsVersions() { + val versions: VersionRange = VersionRegistry.getSourceVersions("HEART_RATE") + + val expectedVersions = VersionRange(1) + + assertEquals(expectedVersions, versions) + } + + @Test + fun sourcesWithIndexPlaceholderReturnsVersions() { + val versions: VersionRange = + VersionRegistry.getSourceVersions("WEATHER.HOURS.{index}.IS_AVAILABLE") + + val expectedVersions = VersionRange(2) + + assertEquals(expectedVersions, versions) + } + + @Test + fun sourcesWithIntegerIndexReturnsVersions() { + val versions: VersionRange = + VersionRegistry.getSourceVersions("WEATHER.HOURS.3.IS_AVAILABLE") + + val expectedVersions = VersionRange(2) + + assertEquals(expectedVersions, versions) + } + + @Test + fun sourcesVersionsWithDifferentIndicesPointHaveTheSameVersioning() { + val indexThree: VersionRange = + VersionRegistry.getSourceVersions("WEATHER.HOURS.3.IS_AVAILABLE") + val indexFour: VersionRange = + VersionRegistry.getSourceVersions("WEATHER.HOURS.4.IS_AVAILABLE") + + assertEquals(indexThree, indexFour) + } +} diff --git a/tools/dwf-validator/src/jvmTest/resources/basicWatchFace.xml b/tools/dwf-validator/src/jvmTest/resources/basicWatchFace.xml new file mode 100644 index 0000000..2f071af --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/basicWatchFace.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/emptyWatchFace.xml b/tools/dwf-validator/src/jvmTest/resources/emptyWatchFace.xml new file mode 100644 index 0000000..44242f0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/emptyWatchFace.xml @@ -0,0 +1 @@ + diff --git a/tools/dwf-validator/src/jvmTest/resources/expressionWatchface.xml b/tools/dwf-validator/src/jvmTest/resources/expressionWatchface.xml new file mode 100644 index 0000000..b7a41de --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/expressionWatchface.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateArtifactName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateArtifactName.xml new file mode 100644 index 0000000..17a0dc3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateArtifactName.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateFontName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateFontName.xml new file mode 100644 index 0000000..e08a1c6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/duplicateFontName.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/emptyBitMapFonts.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/emptyBitMapFonts.xml new file mode 100644 index 0000000..f951773 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/emptyBitMapFonts.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/extraAttributeCharacter.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/extraAttributeCharacter.xml new file mode 100644 index 0000000..f9f34a7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/extraAttributeCharacter.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/illegalFontElement.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/illegalFontElement.xml new file mode 100644 index 0000000..4d8f9c8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/illegalFontElement.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidArtifacts.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidArtifacts.xml new file mode 100644 index 0000000..c35cac6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidArtifacts.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidFonts.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidFonts.xml new file mode 100644 index 0000000..5e009b9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/manyValidFonts.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingAttributeCharacter.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingAttributeCharacter.xml new file mode 100644 index 0000000..1d9b24a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingAttributeCharacter.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingBitMapFontsContainer.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingBitMapFontsContainer.xml new file mode 100644 index 0000000..a0590bb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/missingBitMapFontsContainer.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/noFontElement.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/noFontElement.xml new file mode 100644 index 0000000..8a3a193 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/noFontElement.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleCharacterBitmapFont.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleCharacterBitmapFont.xml new file mode 100644 index 0000000..a1a4f1d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleCharacterBitmapFont.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordBitmapFont.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordBitmapFont.xml new file mode 100644 index 0000000..232622b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordBitmapFont.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordWithMargin.xml b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordWithMargin.xml new file mode 100644 index 0000000..ed8bb36 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/bitmapfonts/singleWordWithMargin.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_high.xml new file mode 100644 index 0000000..0bb29b4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_high.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_low.xml new file mode 100644 index 0000000..8ac146c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_alpha_too_low.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_high.xml new file mode 100644 index 0000000..15fb376 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_high.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_low.xml new file mode 100644 index 0000000..a2bfb95 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_angle_too_low.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..f62f2df --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_high.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..ab60ebe --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivotx_too_low.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..6606756 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_high.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..68575c6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_pivoty_too_low.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_render_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_render_mode.xml new file mode 100644 index 0000000..31f23cf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_render_mode.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scalex.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scalex.xml new file mode 100644 index 0000000..de5e69c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scalex.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scaley.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scaley.xml new file mode 100644 index 0000000..c43fa3e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_scaley.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_tint_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_tint_color.xml new file mode 100644 index 0000000..2047dcc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_invalid_tint_color.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_attributes.xml new file mode 100644 index 0000000..adf47be --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_attributes.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_basic.xml new file mode 100644 index 0000000..475e1dc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/analogclock/analog_clock_valid_basic.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_high.xml new file mode 100644 index 0000000..ab05fee --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_low.xml new file mode 100644 index 0000000..b9abadd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_alpha_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_high.xml new file mode 100644 index 0000000..66bf802 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_low.xml new file mode 100644 index 0000000..1909028 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_angle_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_missing_timetext.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_missing_timetext.xml new file mode 100644 index 0000000..5987651 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_missing_timetext.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..16c426f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..7f199ef --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivotx_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..a7d07da --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..8a323aa --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_pivoty_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_render_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_render_mode.xml new file mode 100644 index 0000000..d18dcfc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_render_mode.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scalex.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scalex.xml new file mode 100644 index 0000000..2015ae9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scalex.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scaley.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scaley.xml new file mode 100644 index 0000000..dc37a40 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_scaley.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_tint_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_tint_color.xml new file mode 100644 index 0000000..af1eced --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_invalid_tint_color.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_attributes.xml new file mode 100644 index 0000000..7726bc3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_attributes.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_basic.xml new file mode 100644 index 0000000..47f8f85 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/digitalclock/digital_clock_valid_basic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_high.xml new file mode 100644 index 0000000..1f7f5b6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_low.xml new file mode 100644 index 0000000..4bd7c3b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_alpha_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_high.xml new file mode 100644 index 0000000..cd195b1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_low.xml new file mode 100644 index 0000000..88327fd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_angle_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_missing_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_missing_resource.xml new file mode 100644 index 0000000..2a3578f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_missing_resource.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..334bb50 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..43c03ed --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivotx_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..6f69d06 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..4ca25f1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_invalid_pivoty_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_attributes.xml new file mode 100644 index 0000000..d43dfe2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_attributes.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_basic.xml new file mode 100644 index 0000000..3ef9d16 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/hourhand/hour_hand_valid_basic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_high.xml new file mode 100644 index 0000000..d31ee2a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_low.xml new file mode 100644 index 0000000..ba77433 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_alpha_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_high.xml new file mode 100644 index 0000000..736f4c5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_low.xml new file mode 100644 index 0000000..c3dace2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_angle_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_missing_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_missing_resource.xml new file mode 100644 index 0000000..796a9d0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_missing_resource.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..910cdfd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..24f9636 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivotx_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..d5deaaf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..4adce67 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_invalid_pivoty_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_attributes.xml new file mode 100644 index 0000000..4af6cac --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_attributes.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_basic.xml new file mode 100644 index 0000000..e5b4814 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/minutehand/minute_hand_valid_basic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_high.xml new file mode 100644 index 0000000..6f0e289 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_low.xml new file mode 100644 index 0000000..529d42a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_alpha_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_high.xml new file mode 100644 index 0000000..e7af35e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_low.xml new file mode 100644 index 0000000..3f12922 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_angle_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_both_sweep_and_tick.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_both_sweep_and_tick.xml new file mode 100644 index 0000000..d98c724 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_both_sweep_and_tick.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_resource.xml new file mode 100644 index 0000000..73f8eff --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_resource.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_sweep_or_tick.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_sweep_or_tick.xml new file mode 100644 index 0000000..ed6c7a0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_missing_sweep_or_tick.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..d8b2825 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..7f6b8e9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivotx_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..b6c201f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..c67eb5d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_pivoty_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_sweep_frequency.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_sweep_frequency.xml new file mode 100644 index 0000000..4639e52 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_sweep_frequency.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_high.xml new file mode 100644 index 0000000..b62cfe3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_low.xml new file mode 100644 index 0000000..1510762 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_duration_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_high.xml new file mode 100644 index 0000000..16f5a84 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_high.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_low.xml new file mode 100644 index 0000000..c6f72dc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_invalid_tick_strength_too_low.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_attributes.xml new file mode 100644 index 0000000..ecb5111 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_attributes.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_sweep.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_sweep.xml new file mode 100644 index 0000000..0f3dfee --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_sweep.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_tick.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_tick.xml new file mode 100644 index 0000000..2d748af --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_basic_tick.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_no_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_no_child.xml new file mode 100644 index 0000000..8fbc9ac --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/secondhand/second_hand_valid_no_child.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_align.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_align.xml new file mode 100644 index 0000000..a10c9c3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_align.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_high.xml new file mode 100644 index 0000000..66aa684 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_low.xml new file mode 100644 index 0000000..ce5da00 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_alpha_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_high.xml new file mode 100644 index 0000000..cea234b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_low.xml new file mode 100644 index 0000000..52b602f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_angle_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_format.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_format.xml new file mode 100644 index 0000000..581050e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_format.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_hour_format.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_hour_format.xml new file mode 100644 index 0000000..08e7d95 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_hour_format.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_missing_format.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_missing_format.xml new file mode 100644 index 0000000..1a5a14b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_missing_format.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_high.xml new file mode 100644 index 0000000..c512a20 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_low.xml new file mode 100644 index 0000000..dcc2c27 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivotx_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_high.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_high.xml new file mode 100644 index 0000000..b098668 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_high.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_low.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_low.xml new file mode 100644 index 0000000..2ca56cb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_pivoty_too_low.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_render_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_render_mode.xml new file mode 100644 index 0000000..d3fc465 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_render_mode.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_tint_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_tint_color.xml new file mode 100644 index 0000000..bf03448 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_invalid_tint_color.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_attributes.xml new file mode 100644 index 0000000..510fa3c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_attributes.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_basic.xml new file mode 100644 index 0000000..2f457c5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/clock/timetext/time_text_valid_basic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty.xml new file mode 100644 index 0000000..33591bd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty.xml @@ -0,0 +1,14 @@ + + + + + true + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty_expression_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty_expression_attribute.xml new file mode 100644 index 0000000..b699874 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_empty_expression_attribute.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_expression_not_found.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_expression_not_found.xml new file mode 100644 index 0000000..964d4b9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_expression_not_found.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_missing_expression_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_missing_expression_attribute.xml new file mode 100644 index 0000000..eac1f17 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_missing_expression_attribute.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_multiple_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_multiple_children.xml new file mode 100644 index 0000000..67d45f4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/compare_multiple_children.xml @@ -0,0 +1,16 @@ + + + + + true + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_missing_expressions.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_missing_expressions.xml new file mode 100644 index 0000000..f6f37b3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_missing_expressions.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_unrecognized_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_unrecognized_child.xml new file mode 100644 index 0000000..6925c17 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_unrecognized_child.xml @@ -0,0 +1,16 @@ + + + + + true + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_valid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_valid.xml new file mode 100644 index 0000000..767ca0c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/condition_valid.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_empty.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_empty.xml new file mode 100644 index 0000000..f6a3a0b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_empty.xml @@ -0,0 +1,14 @@ + + + + + true + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_multiple_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_multiple_children.xml new file mode 100644 index 0000000..b6e46bb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/default_multiple_children.xml @@ -0,0 +1,16 @@ + + + + + true + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_duplicate_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_duplicate_name.xml new file mode 100644 index 0000000..2e7e618 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_duplicate_name.xml @@ -0,0 +1,16 @@ + + + + + true + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_empty_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_empty_name.xml new file mode 100644 index 0000000..fe378bd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_empty_name.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_content.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_content.xml new file mode 100644 index 0000000..2b5e292 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_content.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_name.xml new file mode 100644 index 0000000..cc7c582 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expression_missing_name.xml @@ -0,0 +1,15 @@ + + + + + true + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_empty.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_empty.xml new file mode 100644 index 0000000..ff51765 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_empty.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_unrecognized_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_unrecognized_child.xml new file mode 100644 index 0000000..585e477 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/condition/expressions_unrecognized_child.xml @@ -0,0 +1,16 @@ + + + + + true + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_attribute.xml new file mode 100644 index 0000000..6cca9f4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_attribute.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_calendar.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_calendar.xml new file mode 100644 index 0000000..d51fd83 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_invalid_calendar.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_all_attributes.xml new file mode 100644 index 0000000..a561561 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_all_attributes.xml @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_basic.xml new file mode 100644 index 0000000..3c01251 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_basic.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_locale.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_locale.xml new file mode 100644 index 0000000..1f7d00a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_locale.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_no_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_no_attributes.xml new file mode 100644 index 0000000..f818da9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/localization/localization_valid_no_attributes.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_attribute.xml new file mode 100644 index 0000000..e61a9db --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_attribute.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_defaultValue.xml new file mode 100644 index 0000000..1cda607 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_defaultValue.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_name.xml new file mode 100644 index 0000000..1385c4e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_name.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_source.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_source.xml new file mode 100644 index 0000000..8c6fb1f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_invalid_missing_source.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_valid_basic.xml new file mode 100644 index 0000000..5186232 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/reference/reference/reference_valid_basic.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_child.xml new file mode 100644 index 0000000..66236d1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_child.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_empty_expression.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_empty_expression.xml new file mode 100644 index 0000000..5a86071 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_empty_expression.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_expression.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_expression.xml new file mode 100644 index 0000000..74f8067 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_expression.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_extra_attribute.xml new file mode 100644 index 0000000..0c7e355 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_extra_attribute.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_missing_expression.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_missing_expression.xml new file mode 100644 index 0000000..fce8fe5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/parameter_invalid_missing_expression.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_child.xml new file mode 100644 index 0000000..8cfaa0f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_child.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_empty_stringid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_empty_stringid.xml new file mode 100644 index 0000000..a8ddf7b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_empty_stringid.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_extra_attribute.xml new file mode 100644 index 0000000..ad6e6b1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_extra_attribute.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_missing_stringid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_missing_stringid.xml new file mode 100644 index 0000000..08b7a20 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_invalid_missing_stringid.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_basic.xml new file mode 100644 index 0000000..9b4db4f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_basic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_multiple_parameters.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_multiple_parameters.xml new file mode 100644 index 0000000..659a702 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_multiple_parameters.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_no_parameters.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_no_parameters.xml new file mode 100644 index 0000000..1075f0e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/screenreader/screenreader_valid_no_parameters.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_angleDirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_angleDirection.xml new file mode 100644 index 0000000..f2eda6a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_angleDirection.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_attribute.xml new file mode 100644 index 0000000..cee622d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_attribute.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_controls.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_controls.xml new file mode 100644 index 0000000..faf3f0c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_controls.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_duration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_duration.xml new file mode 100644 index 0000000..45b7f2e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_duration.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_fps.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_fps.xml new file mode 100644 index 0000000..d9de27d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_fps.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_interpolation.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_interpolation.xml new file mode 100644 index 0000000..a6a8d96 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_interpolation.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_no_duration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_no_duration.xml new file mode 100644 index 0000000..f34d34f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_no_duration.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_repeat.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_repeat.xml new file mode 100644 index 0000000..e9c2d01 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_invalid_repeat.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_angleDirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_angleDirection.xml new file mode 100644 index 0000000..a505a96 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_angleDirection.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_controls.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_controls.xml new file mode 100644 index 0000000..9f5d73a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_controls.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_duration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_duration.xml new file mode 100644 index 0000000..d07049d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_duration.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_fps.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_fps.xml new file mode 100644 index 0000000..6ba64ba --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_fps.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_interpolation.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_interpolation.xml new file mode 100644 index 0000000..da46c7c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_interpolation.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_repeat.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_repeat.xml new file mode 100644 index 0000000..60d4405 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/animation/animation_valid_repeat.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_child.xml new file mode 100644 index 0000000..7c72362 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_child.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_extra_attribute.xml new file mode 100644 index 0000000..ccd52e0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_invalid_extra_attribute.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_all_attributes.xml new file mode 100644 index 0000000..2c3765f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_all_attributes.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_basic.xml new file mode 100644 index 0000000..e0b2f81 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/gyro/gyro_valid_basic.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_child.xml new file mode 100644 index 0000000..fd8a2da --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_child.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_target.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_target.xml new file mode 100644 index 0000000..36c4f9d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_target.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_value.xml new file mode 100644 index 0000000..90e8938 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_missing_value.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_mode.xml new file mode 100644 index 0000000..2093a80 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/invalid_mode.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_by.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_by.xml new file mode 100644 index 0000000..cd8e423 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_by.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_to.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_to.xml new file mode 100644 index 0000000..bc86470 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_mode_to.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_transform.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_transform.xml new file mode 100644 index 0000000..0267274 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/transform/transform/valid_transform.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_angledirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_angledirection.xml new file mode 100644 index 0000000..409a68e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_angledirection.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_controls.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_controls.xml new file mode 100644 index 0000000..f08bed5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_controls.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_duration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_duration.xml new file mode 100644 index 0000000..3b62c83 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_duration.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_interpolation.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_interpolation.xml new file mode 100644 index 0000000..0094713 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_interpolation.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_mode.xml new file mode 100644 index 0000000..c13325a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_mode.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_target.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_target.xml new file mode 100644 index 0000000..0cd4854 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_target.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_value.xml new file mode 100644 index 0000000..21451b5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_missing_value.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_startoffset.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_startoffset.xml new file mode 100644 index 0000000..eec3a96 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_startoffset.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_wrong_mode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_wrong_mode.xml new file mode 100644 index 0000000..6b447fd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_invalid_wrong_mode.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_angledirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_angledirection.xml new file mode 100644 index 0000000..5109479 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_angledirection.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_controls.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_controls.xml new file mode 100644 index 0000000..e535f21 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_controls.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_duration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_duration.xml new file mode 100644 index 0000000..addba32 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_duration.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_interpolation.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_interpolation.xml new file mode 100644 index 0000000..5ce1c12 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_interpolation.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_startoffset.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_startoffset.xml new file mode 100644 index 0000000..ec4f8e6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_v4_startoffset.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_basic.xml new file mode 100644 index 0000000..988ccb0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_basic.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_v4_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_v4_attributes.xml new file mode 100644 index 0000000..1c54a1d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/common/variant/variant_valid_v4_attributes.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_extra_attribute.xml new file mode 100644 index 0000000..96dde2e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_extra_attribute.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_child.xml new file mode 100644 index 0000000..b5ab9c8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_child.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_height.xml new file mode 100644 index 0000000..1ebe310 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_height.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_width.xml new file mode 100644 index 0000000..8dc199f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_width.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_x.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_x.xml new file mode 100644 index 0000000..e4749d5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_x.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_y.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_y.xml new file mode 100644 index 0000000..b418254 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_invalid_y.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_height.xml new file mode 100644 index 0000000..caa4678 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_height.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_width.xml new file mode 100644 index 0000000..f8d0b6d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_width.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_x.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_x.xml new file mode 100644 index 0000000..a551b00 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_x.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_y.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_y.xml new file mode 100644 index 0000000..e70bb26 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_missing_y.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_height.xml new file mode 100644 index 0000000..b542573 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_height.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_width.xml new file mode 100644 index 0000000..0dc0876 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/invalid_boundingbox_negative_width.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/valid_boundingbox.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/valid_boundingbox.xml new file mode 100644 index 0000000..691ed40 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/bounding/valid_boundingbox.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_extra_attribute.xml new file mode 100644 index 0000000..64f7b8b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_extra_attribute.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_invalid_child.xml new file mode 100644 index 0000000..cea84fb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_invalid_child.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_missing_type.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_missing_type.xml new file mode 100644 index 0000000..01e4922 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_missing_type.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_unknown_type.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_unknown_type.xml new file mode 100644 index 0000000..4a680ec --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/invalid_complication_unknown_type.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/valid_complication.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/valid_complication.xml new file mode 100644 index 0000000..691ed40 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complication/valid_complication.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_boundingbox_missing.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_boundingbox_missing.xml new file mode 100644 index 0000000..767767b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_boundingbox_missing.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_missing.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_missing.xml new file mode 100644 index 0000000..a30752a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_missing.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_type_mismatch.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_type_mismatch.xml new file mode 100644 index 0000000..029bcf6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_complication_type_mismatch.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_height_negative.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_height_negative.xml new file mode 100644 index 0000000..21da101 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_height_negative.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_missing.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_missing.xml new file mode 100644 index 0000000..d8d725b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_missing.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_string.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_string.xml new file mode 100644 index 0000000..91d1df0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_slotid_string.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_missing.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_missing.xml new file mode 100644 index 0000000..763b8b0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_missing.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_unknown.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_unknown.xml new file mode 100644 index 0000000..21d55c2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_supportedtypes_unknown.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_width_zero.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_width_zero.xml new file mode 100644 index 0000000..3d7f21b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_width_zero.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_x_float.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_x_float.xml new file mode 100644 index 0000000..4c28888 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/invalid_complicationslot_x_float.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot.xml new file mode 100644 index 0000000..603ae5b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot_multiple_supported_types.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot_multiple_supported_types.xml new file mode 100644 index 0000000..93baaaa --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/complicationslot/valid_complicationslot_multiple_supported_types.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_extra_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_extra_attribute.xml new file mode 100644 index 0000000..1b0fe9d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_extra_attribute.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_child.xml new file mode 100644 index 0000000..72666a4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_child.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_provider.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_provider.xml new file mode 100644 index 0000000..b9ca1ce --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_provider.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_type.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_type.xml new file mode 100644 index 0000000..34e0270 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_invalid_type.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_provider.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_provider.xml new file mode 100644 index 0000000..9ad5fcd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_provider.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_type.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_type.xml new file mode 100644 index 0000000..7510bc3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/invalid_defaultproviderpolicy_missing_type.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/valid_defaultproviderpolicy.xml b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/valid_defaultproviderpolicy.xml new file mode 100644 index 0000000..81890cd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/complication/defaultproviderpolicy/valid_defaultproviderpolicy.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_alpha.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_alpha.xml new file mode 100644 index 0000000..489974f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_alpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_angle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_angle.xml new file mode 100644 index 0000000..82170ac --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_angle.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_child.xml new file mode 100644 index 0000000..d01ae19 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_child.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_height.xml new file mode 100644 index 0000000..4caa48a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_height.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_name.xml new file mode 100644 index 0000000..cc97e5c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_name.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotX.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotX.xml new file mode 100644 index 0000000..cb862aa --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotX.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotY.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotY.xml new file mode 100644 index 0000000..d3b3228 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_pivotY.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_renderMode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_renderMode.xml new file mode 100644 index 0000000..fe4c947 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_renderMode.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_tintColor.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_tintColor.xml new file mode 100644 index 0000000..3f15cbe --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_tintColor.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_width.xml new file mode 100644 index 0000000..bb2ff0b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_width.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_x.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_x.xml new file mode 100644 index 0000000..6d785b9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_x.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_y.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_y.xml new file mode 100644 index 0000000..7cae223 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_invalid_y.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_children.xml new file mode 100644 index 0000000..92f9248 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_children.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + Hello + + + + + + + + + + + + + HH:mm + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_optional_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_optional_attributes.xml new file mode 100644 index 0000000..3e71d48 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/group/group_valid_optional_attributes.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_delayplay_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_delayplay_value.xml new file mode 100644 index 0000000..52accb3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_delayplay_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_format_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_format_value.xml new file mode 100644 index 0000000..4dfae71 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_format_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation.xml new file mode 100644 index 0000000..713758f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation_controller.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation_controller.xml new file mode 100644 index 0000000..2ef4c2c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_animation_controller.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_format.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_format.xml new file mode 100644 index 0000000..52ef10e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_format.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_play.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_play.xml new file mode 100644 index 0000000..38bf36a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_play.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_resource.xml new file mode 100644 index 0000000..0c9e2a9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_missing_resource.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_multiple_animation_types.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_multiple_animation_types.xml new file mode 100644 index 0000000..2ae8047 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_multiple_animation_types.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_play_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_play_value.xml new file mode 100644 index 0000000..00d001c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_play_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_attribute.xml new file mode 100644 index 0000000..2f695bf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_attribute.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_element.xml new file mode 100644 index 0000000..7585b2d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/invalid_unexpected_element.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_all_attributes.xml new file mode 100644 index 0000000..8f0458d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_all_attributes.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_basic.xml new file mode 100644 index 0000000..58bd4a7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImage/valid_basic.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_change_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_change_value.xml new file mode 100644 index 0000000..d1d6c83 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_change_value.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_changedirection_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_changedirection_value.xml new file mode 100644 index 0000000..af7cb06 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_changedirection_value.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_change.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_change.xml new file mode 100644 index 0000000..d08141c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_change.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_image_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_image_child.xml new file mode 100644 index 0000000..2f38c35 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_missing_image_child.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_attribute.xml new file mode 100644 index 0000000..9302191 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_attribute.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_element.xml new file mode 100644 index 0000000..762cb31 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/invalid_unexpected_element.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_all_attributes.xml new file mode 100644 index 0000000..32a16b8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_all_attributes.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_basic.xml new file mode 100644 index 0000000..1e248b5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animatedImages/valid_basic.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_afterplaying_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_afterplaying_value.xml new file mode 100644 index 0000000..c99c46a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_afterplaying_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_beforeplaying_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_beforeplaying_value.xml new file mode 100644 index 0000000..1b28ca2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_beforeplaying_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayplay_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayplay_value.xml new file mode 100644 index 0000000..52accb3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayplay_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayrepeat_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayrepeat_value.xml new file mode 100644 index 0000000..200ba44 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_delayrepeat_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_loopcount_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_loopcount_value.xml new file mode 100644 index 0000000..f85dfe1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_loopcount_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_missing_play.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_missing_play.xml new file mode 100644 index 0000000..38bf36a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_missing_play.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_play_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_play_value.xml new file mode 100644 index 0000000..00d001c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_play_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_repeat_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_repeat_value.xml new file mode 100644 index 0000000..43e58e9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_repeat_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_resumeplayback_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_resumeplayback_value.xml new file mode 100644 index 0000000..cd82527 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_resumeplayback_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_attribute.xml new file mode 100644 index 0000000..9d73d43 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_attribute.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_element.xml new file mode 100644 index 0000000..1ffa6f7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/invalid_unexpected_element.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_all_attributes.xml new file mode 100644 index 0000000..06ba20b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_all_attributes.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_basic.xml new file mode 100644 index 0000000..58bd4a7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/animationController/valid_basic.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_alpha_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_alpha_value.xml new file mode 100644 index 0000000..0889653 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_alpha_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_angle_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_angle_value.xml new file mode 100644 index 0000000..6908452 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_angle_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_blendMode_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_blendMode_value.xml new file mode 100644 index 0000000..91f28e7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_blendMode_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_duplicate_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_duplicate_child.xml new file mode 100644 index 0000000..0cab2a4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_duplicate_child.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_animation_controller.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_animation_controller.xml new file mode 100644 index 0000000..2ef4c2c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_animation_controller.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_height.xml new file mode 100644 index 0000000..79bfe87 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_height.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_width.xml new file mode 100644 index 0000000..b11d55b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_width.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_x.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_x.xml new file mode 100644 index 0000000..c201d30 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_x.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_y.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_y.xml new file mode 100644 index 0000000..3accbeb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_missing_y.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_multiple_animation_sources.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_multiple_animation_sources.xml new file mode 100644 index 0000000..2ae8047 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_multiple_animation_sources.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_pivotX_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_pivotX_value.xml new file mode 100644 index 0000000..c6f82c7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_pivotX_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_renderMode_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_renderMode_value.xml new file mode 100644 index 0000000..c1da772 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_renderMode_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_scaleX_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_scaleX_value.xml new file mode 100644 index 0000000..80aa2da --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_scaleX_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_tintColor_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_tintColor_value.xml new file mode 100644 index 0000000..a8524ee --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_tintColor_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_attribute.xml new file mode 100644 index 0000000..2f695bf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_attribute.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_element.xml new file mode 100644 index 0000000..7585b2d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_unexpected_element.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_x_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_x_value.xml new file mode 100644 index 0000000..e1e3c0c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/invalid_x_value.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_all_attributes.xml new file mode 100644 index 0000000..92a55f5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_all_attributes.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_basic.xml new file mode 100644 index 0000000..58bd4a7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_basic.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_with_thumbnail.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_with_thumbnail.xml new file mode 100644 index 0000000..adb1917 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/animatedImage/partAnimatedImage/valid_with_thumbnail.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_lineargradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_lineargradient.xml new file mode 100644 index 0000000..cdfda92 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_lineargradient.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_radialgradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_radialgradient.xml new file mode 100644 index 0000000..ce0dbaf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_radialgradient.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_sweepgradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_sweepgradient.xml new file mode 100644 index 0000000..55284f6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/invalid_sweepgradient.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_lineargradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_lineargradient.xml new file mode 100644 index 0000000..605c0e6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_lineargradient.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_radialgradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_radialgradient.xml new file mode 100644 index 0000000..16c3fc2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_radialgradient.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_sweepgradient.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_sweepgradient.xml new file mode 100644 index 0000000..a22168e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/gradient/valid_sweepgradient.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_alpha.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_alpha.xml new file mode 100644 index 0000000..b1515ce --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_alpha.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_angle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_angle.xml new file mode 100644 index 0000000..fda79e4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_angle.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_pivot.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_pivot.xml new file mode 100644 index 0000000..c74f562 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_pivot.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_rendermode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_rendermode.xml new file mode 100644 index 0000000..b48688f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_rendermode.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_scale.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_scale.xml new file mode 100644 index 0000000..5a95d64 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_scale.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_tintcolor.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_tintcolor.xml new file mode 100644 index 0000000..15833fc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/invalid_partdraw_tintcolor.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_alpha.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_alpha.xml new file mode 100644 index 0000000..422599e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_alpha.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_angle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_angle.xml new file mode 100644 index 0000000..eacfcf3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_angle.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_name.xml new file mode 100644 index 0000000..71fce7e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_name.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_pivot.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_pivot.xml new file mode 100644 index 0000000..7fbc1a7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_pivot.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_rendermode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_rendermode.xml new file mode 100644 index 0000000..c646094 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_rendermode.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_scale.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_scale.xml new file mode 100644 index 0000000..b4cfc8a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_scale.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_tintcolor.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_tintcolor.xml new file mode 100644 index 0000000..9f74902 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/partDraw/valid_partdraw_tintcolor.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_arc.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_arc.xml new file mode 100644 index 0000000..e840a75 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_arc.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_ellipse.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_ellipse.xml new file mode 100644 index 0000000..78662d4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_ellipse.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_line.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_line.xml new file mode 100644 index 0000000..fdefc31 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_line.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_roundrectangle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_roundrectangle.xml new file mode 100644 index 0000000..9c08122 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/invalid_roundrectangle.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_arc.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_arc.xml new file mode 100644 index 0000000..74fbdac --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_arc.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_ellipse.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_ellipse.xml new file mode 100644 index 0000000..5de1e82 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_ellipse.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_line.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_line.xml new file mode 100644 index 0000000..0a840f9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_line.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_roundrectangle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_roundrectangle.xml new file mode 100644 index 0000000..b4aff31 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/shape/valid_roundrectangle.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_fill.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_fill.xml new file mode 100644 index 0000000..ae012c8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_fill.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_stroke.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_stroke.xml new file mode 100644 index 0000000..ac40c05 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_stroke.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_weightedstroke.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_weightedstroke.xml new file mode 100644 index 0000000..d6de8e4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/invalid_weightedstroke.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_fill.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_fill.xml new file mode 100644 index 0000000..48e2400 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_fill.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_stroke.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_stroke.xml new file mode 100644 index 0000000..2166720 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_stroke.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_weightedstroke.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_weightedstroke.xml new file mode 100644 index 0000000..11be928 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/draw/style/valid_weightedstroke.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_brightness_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_brightness_value.xml new file mode 100644 index 0000000..63b92f2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_brightness_value.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_huerotate_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_huerotate_value.xml new file mode 100644 index 0000000..f1a639e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_huerotate_value.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_saturate_value.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_saturate_value.xml new file mode 100644 index 0000000..6d1fbfc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_saturate_value.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_attribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_attribute.xml new file mode 100644 index 0000000..24bfead --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_attribute.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_element.xml new file mode 100644 index 0000000..ec22b5f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/invalid_unexpected_element.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_all_attributes.xml new file mode 100644 index 0000000..30f54cc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_all_attributes.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_basic.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_basic.xml new file mode 100644 index 0000000..58a617e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/imageFilter/valid_basic.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_image_no_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_image_no_resource.xml new file mode 100644 index 0000000..1b3a9f9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_image_no_resource.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_change.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_change.xml new file mode 100644 index 0000000..02dcdbb --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_change.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_changedirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_changedirection.xml new file mode 100644 index 0000000..8f08682 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_bad_changedirection.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_no_image_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_no_image_child.xml new file mode 100644 index 0000000..2e294f3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/invalid_images_no_image_child.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_change.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_change.xml new file mode 100644 index 0000000..f0b43e6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_change.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_changedirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_changedirection.xml new file mode 100644 index 0000000..8c6c4d2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/images/valid_images_with_changedirection.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_duplicate_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_duplicate_child.xml new file mode 100644 index 0000000..d32c3a0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_duplicate_child.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_multiple_image_sources.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_multiple_image_sources.xml new file mode 100644 index 0000000..bdeb116 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/invalid_partimage_multiple_image_sources.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/valid_partimage_with_image.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/valid_partimage_with_image.xml new file mode 100644 index 0000000..c38e61b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/partImage/valid_partimage_with_image.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_change.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_change.xml new file mode 100644 index 0000000..467372c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_change.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_changedirection.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_changedirection.xml new file mode 100644 index 0000000..6faa5af --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_bad_changedirection.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_height.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_height.xml new file mode 100644 index 0000000..206248b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_height.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_width.xml new file mode 100644 index 0000000..92092e5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_negative_width.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_defaultimageresource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_defaultimageresource.xml new file mode 100644 index 0000000..dbd067b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_defaultimageresource.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_source.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_source.xml new file mode 100644 index 0000000..f41a823 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_no_source.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_out_of_range_changeafterevery.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_out_of_range_changeafterevery.xml new file mode 100644 index 0000000..6b8086e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/invalid_photos_out_of_range_changeafterevery.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos.xml new file mode 100644 index 0000000..b5ab295 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos_with_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos_with_all_attributes.xml new file mode 100644 index 0000000..35ed2dc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/image/photos/valid_photos_with_all_attributes.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outglow_missing_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outglow_missing_color.xml new file mode 100644 index 0000000..f433e5b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outglow_missing_color.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outline_missing_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outline_missing_color.xml new file mode 100644 index 0000000..30511bd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_outline_missing_color.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_shadow_missing_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_shadow_missing_color.xml new file mode 100644 index 0000000..c761b0b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/decoration/invalid_shadow_missing_color.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_color.xml new file mode 100644 index 0000000..a7556fc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_color.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_family.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_family.xml new file mode 100644 index 0000000..bb6ae0d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_family.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_size.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_size.xml new file mode 100644 index 0000000..1107bed --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_missing_size.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_slant.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_slant.xml new file mode 100644 index 0000000..d47a130 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_slant.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_weight.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_weight.xml new file mode 100644 index 0000000..f34deb8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_weight.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_width.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_width.xml new file mode 100644 index 0000000..3a9b35a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/invalid_font_width.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_all_attributes.xml new file mode 100644 index 0000000..96f6761 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_all_attributes.xml @@ -0,0 +1,14 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_inlineimage.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_inlineimage.xml new file mode 100644 index 0000000..132e528 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_inlineimage.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_lower.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_lower.xml new file mode 100644 index 0000000..772f778 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_lower.xml @@ -0,0 +1,13 @@ + + + + + + + HELLO + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outglow.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outglow.xml new file mode 100644 index 0000000..4c830bf --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outglow.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outline.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outline.xml new file mode 100644 index 0000000..b79b658 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_outline.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_shadow.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_shadow.xml new file mode 100644 index 0000000..cc4a54e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_shadow.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_strikethrough.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_strikethrough.xml new file mode 100644 index 0000000..6b9144d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_strikethrough.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_template.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_template.xml new file mode 100644 index 0000000..6e3bb86 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_template.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_underline.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_underline.xml new file mode 100644 index 0000000..055fd8a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_underline.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_upper.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_upper.xml new file mode 100644 index 0000000..e3a7ef7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/font/valid_font_upper.xml @@ -0,0 +1,13 @@ + + + + + + + hello + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_dimensions.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_dimensions.xml new file mode 100644 index 0000000..1cb9e58 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_dimensions.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_resource.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_resource.xml new file mode 100644 index 0000000..cefa8de --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/formatter/invalid_inlineimage_missing_resource.xml @@ -0,0 +1,14 @@ + + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_multiple_text_elements.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_multiple_text_elements.xml new file mode 100644 index 0000000..37ec422 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_multiple_text_elements.xml @@ -0,0 +1,14 @@ + + + + + + + Text + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_no_text_element.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_no_text_element.xml new file mode 100644 index 0000000..71c6ced --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/invalid_parttext_no_text_element.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_alpha.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_alpha.xml new file mode 100644 index 0000000..cb97c7c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_alpha.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_angle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_angle.xml new file mode 100644 index 0000000..66dac59 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_angle.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_name.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_name.xml new file mode 100644 index 0000000..441a336 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_name.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_pivot.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_pivot.xml new file mode 100644 index 0000000..09f3f63 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_pivot.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_renderMode.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_renderMode.xml new file mode 100644 index 0000000..d506ed3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_renderMode.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_scale.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_scale.xml new file mode 100644 index 0000000..6653f19 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_scale.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_tintColor.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_tintColor.xml new file mode 100644 index 0000000..fde87cd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/partText/valid_parttext_tintColor.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_align.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_align.xml new file mode 100644 index 0000000..4f7868d --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_align.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_ellipsis.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_ellipsis.xml new file mode 100644 index 0000000..0ae1964 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_ellipsis.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_isautosize.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_isautosize.xml new file mode 100644 index 0000000..8908d92 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_isautosize.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_maxlines.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_maxlines.xml new file mode 100644 index 0000000..6883184 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/invalid_text_maxlines.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_align.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_align.xml new file mode 100644 index 0000000..43ab7e7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_align.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_ellipsis.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_ellipsis.xml new file mode 100644 index 0000000..2d8a5fc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_ellipsis.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_isautosize.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_isautosize.xml new file mode 100644 index 0000000..c36147f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_isautosize.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_maxlines.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_maxlines.xml new file mode 100644 index 0000000..f577e4c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/text/valid_text_maxlines.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_direction.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_direction.xml new file mode 100644 index 0000000..be109b8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_direction.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_missing_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_missing_attributes.xml new file mode 100644 index 0000000..fc16be4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/invalid_textcircular_missing_attributes.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/valid_textcircular_all_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/valid_textcircular_all_attributes.xml new file mode 100644 index 0000000..903cb39 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/group/part/text/textCircular/valid_textcircular_all_attributes.xml @@ -0,0 +1,13 @@ + + + + + + + Text + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidClockTypeMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidClockTypeMetadata.xml new file mode 100644 index 0000000..6092e0c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidClockTypeMetadata.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidPreviewTimeValuesMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidPreviewTimeValuesMetadata.xml new file mode 100644 index 0000000..162a315 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidPreviewTimeValuesMetadata.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidStepGoalValuesMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidStepGoalValuesMetadata.xml new file mode 100644 index 0000000..c6a8b5f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/invalidStepGoalValuesMetadata.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingKeyMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingKeyMetadata.xml new file mode 100644 index 0000000..9c227fc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingKeyMetadata.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingValueMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingValueMetadata.xml new file mode 100644 index 0000000..ef3ac6c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/missingValueMetadata.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/multipleMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/multipleMetadata.xml new file mode 100644 index 0000000..93c6626 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/multipleMetadata.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/predefinedValuesMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/predefinedValuesMetadata.xml new file mode 100644 index 0000000..cbca08b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/predefinedValuesMetadata.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/metadata/singleMetadata.xml b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/singleMetadata.xml new file mode 100644 index 0000000..7da29b8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/metadata/singleMetadata.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/backgroundColorScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/backgroundColorScene.xml new file mode 100644 index 0000000..263695e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/backgroundColorScene.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/basicScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/basicScene.xml new file mode 100644 index 0000000..836e0b1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/basicScene.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/emptyScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/emptyScene.xml new file mode 100644 index 0000000..b8f5d96 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/emptyScene.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/invalidBackgroundColorScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/invalidBackgroundColorScene.xml new file mode 100644 index 0000000..d22a814 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/invalidBackgroundColorScene.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/manyChildScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/manyChildScene.xml new file mode 100644 index 0000000..c790899 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/manyChildScene.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/scene/transformChildScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/scene/transformChildScene.xml new file mode 100644 index 0000000..0a9d0c2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/scene/transformChildScene.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_child_in_user_configurations.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_child_in_user_configurations.xml new file mode 100644 index 0000000..8e93b03 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_child_in_user_configurations.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_missing_children_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_missing_children_in_scene.xml new file mode 100644 index 0000000..83498f7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_missing_children_in_scene.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_one_child_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_one_child_in_scene.xml new file mode 100644 index 0000000..7d0945f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_one_child_in_scene.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_optional_attribute_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_optional_attribute_in_scene.xml new file mode 100644 index 0000000..e753f27 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_optional_attribute_in_scene.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_required_attribute_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_required_attribute_in_scene.xml new file mode 100644 index 0000000..986e5a6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_required_attribute_in_scene.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_v4_attribute_in_v1.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_v4_attribute_in_v1.xml new file mode 100644 index 0000000..af65a00 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_configuration_v4_attribute_in_v1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_bad_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_bad_id.xml new file mode 100644 index 0000000..8426ed4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_bad_id.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_missing_id.xml new file mode 100644 index 0000000..3459653 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_boolean_option_missing_id.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_defaultValue.xml new file mode 100644 index 0000000..61d9330 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_defaultValue.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_displayName.xml new file mode 100644 index 0000000..1c55b7f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_displayName.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_id.xml new file mode 100644 index 0000000..98efafe --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/invalid_missing_id.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration.xml new file mode 100644 index 0000000..715146e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_v4.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_v4.xml new file mode 100644 index 0000000..af65a00 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_v4.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_with_optional_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_with_optional_attributes.xml new file mode 100644 index 0000000..5caebb4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_configuration_with_optional_attributes.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_option_with_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_option_with_children.xml new file mode 100644 index 0000000..dbdb3ee --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/booleanConfiguration/valid_boolean_option_with_children.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_bad_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_bad_defaultValue.xml new file mode 100644 index 0000000..b1e2301 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_bad_defaultValue.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_defaultValue.xml new file mode 100644 index 0000000..0445cd3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_defaultValue.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_displayName.xml new file mode 100644 index 0000000..8b1c55b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_displayName.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_id.xml new file mode 100644 index 0000000..68c2ff5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_missing_id.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_no_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_no_children.xml new file mode 100644 index 0000000..5916e67 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_no_children.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_six_colors.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_six_colors.xml new file mode 100644 index 0000000..b7e9279 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_configuration_six_colors.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_bad_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_bad_color.xml new file mode 100644 index 0000000..2cd4659 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_bad_color.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_color.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_color.xml new file mode 100644 index 0000000..1eb0d20 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_color.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_displayName.xml new file mode 100644 index 0000000..331b926 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_displayName.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_id.xml new file mode 100644 index 0000000..158d6fa --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_missing_id.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_with_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_with_child.xml new file mode 100644 index 0000000..11c99ae --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/invalid_color_option_with_child.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration.xml new file mode 100644 index 0000000..1aedeed --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_many_colors.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_many_colors.xml new file mode 100644 index 0000000..ab66074 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_many_colors.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_optional_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_optional_attributes.xml new file mode 100644 index 0000000..1e45283 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/colorConfiguration/valid_color_configuration_with_optional_attributes.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_id.xml new file mode 100644 index 0000000..08e4ea0 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_id.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_optionId.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_optionId.xml new file mode 100644 index 0000000..e39d4dd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_missing_optionId.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_with_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_with_child.xml new file mode 100644 index 0000000..995d3fe --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_configuration_with_child.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_displayName.xml new file mode 100644 index 0000000..50abd0e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_displayName.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_id.xml new file mode 100644 index 0000000..58f3c3c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_missing_id.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_no_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_no_children.xml new file mode 100644 index 0000000..9f6aefd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_no_children.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_with_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_with_invalid_child.xml new file mode 100644 index 0000000..177a7ad --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavor_with_invalid_child.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_21_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_21_children.xml new file mode 100644 index 0000000..f16430b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_21_children.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_missing_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_missing_defaultValue.xml new file mode 100644 index 0000000..4cd6dc9 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_missing_defaultValue.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_no_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_no_children.xml new file mode 100644 index 0000000..6a5057e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_no_children.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_with_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_with_invalid_child.xml new file mode 100644 index 0000000..c6d67a4 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/invalid_flavors_with_invalid_child.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor.xml new file mode 100644 index 0000000..7bde7dd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor_with_optional_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor_with_optional_attributes.xml new file mode 100644 index 0000000..1d9dc7e --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/flavor/valid_flavor_with_optional_attributes.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_attribute_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_attribute_in_scene.xml new file mode 100644 index 0000000..0085421 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_attribute_in_scene.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_bad_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_bad_defaultValue.xml new file mode 100644 index 0000000..cf8ba3c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_bad_defaultValue.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_child_in_user_configurations.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_child_in_user_configurations.xml new file mode 100644 index 0000000..5941b24 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_child_in_user_configurations.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_children_in_scene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_children_in_scene.xml new file mode 100644 index 0000000..3fbf5fd --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_children_in_scene.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_defaultValue.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_defaultValue.xml new file mode 100644 index 0000000..69d6cb8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_defaultValue.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_displayName.xml new file mode 100644 index 0000000..83c0ed2 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_displayName.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_id.xml new file mode 100644 index 0000000..7c9afb7 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_missing_id.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_v4_attribute_in_v1.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_v4_attribute_in_v1.xml new file mode 100644 index 0000000..4472c08 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_configuration_v4_attribute_in_v1.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_displayName.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_displayName.xml new file mode 100644 index 0000000..5753a96 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_displayName.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_id.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_id.xml new file mode 100644 index 0000000..b55bb4c --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_missing_id.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_with_child_in_user_configurations.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_with_child_in_user_configurations.xml new file mode 100644 index 0000000..ce1793a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/invalid_list_option_with_child_in_user_configurations.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration.xml new file mode 100644 index 0000000..688f617 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_v4.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_v4.xml new file mode 100644 index 0000000..4472c08 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_v4.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_with_optional_attributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_with_optional_attributes.xml new file mode 100644 index 0000000..79d4c87 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_configuration_with_optional_attributes.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_option_with_children.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_option_with_children.xml new file mode 100644 index 0000000..2a14bbc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/listConfiguration/valid_list_option_with_children.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_invalid_configType_invalid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_invalid_configType_invalid.xml new file mode 100644 index 0000000..89ff983 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_invalid_configType_invalid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_configType_invalid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_configType_invalid.xml new file mode 100644 index 0000000..db4277f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_configType_invalid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_id_invalid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_id_invalid.xml new file mode 100644 index 0000000..9e3e609 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_missing_id_invalid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_old_version_invalid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_old_version_invalid.xml new file mode 100644 index 0000000..8a14560 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_old_version_invalid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_valid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_valid.xml new file mode 100644 index 0000000..8a14560 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/photosConfiguration/photos_configuration_valid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_no_children_invalid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_no_children_invalid.xml new file mode 100644 index 0000000..83154d5 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_no_children_invalid.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_valid.xml b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_valid.xml new file mode 100644 index 0000000..dc91f2b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/userConfiguration/userConfiguration/user_configurations_valid.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFace.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFace.xml new file mode 100644 index 0000000..836e0b1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFace.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceExtraAttribute.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceExtraAttribute.xml new file mode 100644 index 0000000..7c4391b --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceExtraAttribute.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingAttributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingAttributes.xml new file mode 100644 index 0000000..a91358f --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingAttributes.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingScene.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingScene.xml new file mode 100644 index 0000000..7053862 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceMissingScene.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceNonIntegerHeight.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceNonIntegerHeight.xml new file mode 100644 index 0000000..7fc5526 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceNonIntegerHeight.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceOptionalAttributes.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceOptionalAttributes.xml new file mode 100644 index 0000000..ff71148 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchFaceOptionalAttributes.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_child.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_child.xml new file mode 100644 index 0000000..ba3d756 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_child.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_clipshape.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_clipshape.xml new file mode 100644 index 0000000..c2cce9a --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_clipshape.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_x_string.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_x_string.xml new file mode 100644 index 0000000..b2520dc --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_x_string.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_y_string.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_y_string.xml new file mode 100644 index 0000000..636a0d3 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_invalid_corner_radius_y_string.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_circle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_circle.xml new file mode 100644 index 0000000..423b7e6 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_circle.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_default.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_default.xml new file mode 100644 index 0000000..688d1c8 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_default.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_none.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_none.xml new file mode 100644 index 0000000..adc2466 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_none.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_rectangle.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_rectangle.xml new file mode 100644 index 0000000..160abe1 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_clipshape_rectangle.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_corner_radius.xml b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_corner_radius.xml new file mode 100644 index 0000000..4d9cc15 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/integration/watchface/watchface_valid_corner_radius.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tools/dwf-validator/src/jvmTest/resources/invalidExpressionWatchface.xml b/tools/dwf-validator/src/jvmTest/resources/invalidExpressionWatchface.xml new file mode 100644 index 0000000..7dcfd84 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/invalidExpressionWatchface.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/tools/dwf-validator/src/jvmTest/resources/metaDataWatchFace.xml b/tools/dwf-validator/src/jvmTest/resources/metaDataWatchFace.xml new file mode 100644 index 0000000..92a0306 --- /dev/null +++ b/tools/dwf-validator/src/jvmTest/resources/metaDataWatchFace.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file