Skip to content

Commit 1b0863d

Browse files
committed
Create a more compact (readable) version of the overrides. It now uses
XML as this is actually (much) more compact than JSon.
1 parent b6052b6 commit 1b0863d

File tree

9 files changed

+1025
-2707
lines changed

9 files changed

+1025
-2707
lines changed

.editorconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ ij_wrap_on_typing = false
2020
max_line_length = 80
2121
ij_visual_guides = 70, 80
2222

23-
[xmlschema/src/jvmTest/resources/override.json]
23+
[xmlschema/src/jvmTest/resources/override.*]
2424
indent_size = 2

xmlschema/src/commonTest/kotlin/org/w3/xml/xmschematestsuite/TSExpected.kt

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ data class TSExpected(
4444
val exception: String? = null,
4545
@XmlElement(false)
4646
val message: @Serializable(RegexSerializer::class) Regex? = null,
47+
val annotation: String? = null,
4748
@XmlOtherAttributes
4849
val otherAttributes: Map<@Serializable(QNameSerializer::class) QName, String> = emptyMap()
4950
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) 2023.
3+
*
4+
* This file is part of xmlutil.
5+
*
6+
* This file is licenced to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You should have received a copy of the license with the source distribution.
9+
* Alternatively, you may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
21+
package org.w3.xml.xmschematestsuite.override
22+
23+
import kotlinx.serialization.KSerializer
24+
import kotlinx.serialization.Serializable
25+
import kotlinx.serialization.descriptors.PrimitiveKind
26+
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
27+
import kotlinx.serialization.descriptors.SerialDescriptor
28+
import kotlinx.serialization.encoding.Decoder
29+
import kotlinx.serialization.encoding.Encoder
30+
import nl.adaptivity.xmlutil.serialization.XmlDefault
31+
import nl.adaptivity.xmlutil.serialization.XmlNamespaceDeclSpec
32+
import nl.adaptivity.xmlutil.serialization.XmlSerialName
33+
import org.w3.xml.xmschematestsuite.TSExpected
34+
35+
@Serializable
36+
@XmlSerialName("overrides", namespace = "http://pdvrieze.github.io/xmlutil/testoverride", "")
37+
@XmlNamespaceDeclSpec("ts=http://www.w3.org/XML/2004/xml-schema-test-suite/")
38+
class CompactOverride(
39+
@XmlSerialName("ignore", namespace = "http://pdvrieze.github.io/xmlutil/testoverride", "")
40+
val ignores: List<TestPath>,
41+
val overrides: List<ExpectedOverride>,
42+
) {
43+
constructor(ignores: OTSSuite) : this(
44+
ignores.findIgnoredPaths(),
45+
ignores.findOverrides()
46+
)
47+
}
48+
49+
@Serializable
50+
@XmlSerialName("test", namespace = "http://pdvrieze.github.io/xmlutil/testoverride", "")
51+
data class ExpectedOverride(val path: TestPath, val expecteds: List<TSExpected>, @XmlDefault("false") val isInstance: Boolean = false) {
52+
constructor(path: TestPath, expecteds: List<TSExpected>) : this(path, expecteds, !path.isSchema)
53+
}
54+
55+
@Serializable(TestPath.Companion::class)
56+
data class TestPath(
57+
val testSet: String,
58+
val group: String? = null,
59+
val test: String? = null,
60+
val isSchema: Boolean = true
61+
) : Comparable<TestPath> {
62+
63+
init {
64+
require(test == null || group != null) { "Group null, but test not ($test)" }
65+
}
66+
67+
override fun compareTo(other: TestPath): Int {
68+
testSet.compareTo(other.testSet).let { if (it != 0) return it }
69+
70+
when {
71+
group == null -> return if (other.group == null) 0 else -1
72+
other.group == null -> return 1
73+
else -> group.compareTo(other.group).let { if (it != 0) return it }
74+
}
75+
76+
return when {
77+
test == null -> if (other.test == null) 0 else -1
78+
other.test == null -> 1
79+
else -> test.compareTo(other.test)
80+
}
81+
82+
}
83+
84+
companion object : KSerializer<TestPath> {
85+
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("org.w3.xml.xmschematestsuite.override.TestPath", PrimitiveKind.STRING)
86+
87+
override fun deserialize(decoder: Decoder): TestPath {
88+
val decoded = decoder.decodeString().split('/')
89+
return TestPath(
90+
decoded[0],
91+
if(decoded.size>0) decoded[1] else null,
92+
if(decoded.size>1) decoded[2] else null,
93+
)
94+
}
95+
96+
override fun serialize(encoder: Encoder, value: TestPath) {
97+
val s = listOfNotNull(value.testSet, value.group, value.test).joinToString("/")
98+
encoder.encodeString(s)
99+
}
100+
}
101+
}

xmlschema/src/commonTest/kotlin/org/w3/xml/xmschematestsuite/override/OTSSuite.kt

+115-7
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,83 @@ import org.w3.xml.xmschematestsuite.*
2525

2626
@Serializable
2727
data class OTSSuite(val testSetOverrides: List<OTSTestSet>) {
28+
29+
constructor(compact: CompactOverride) : this(toTestSets(compact))
30+
2831
fun applyTo(original: TSTestSet): TSTestSet {
2932
return testSetOverrides
3033
.firstOrNull { it.name == original.name }
3134
?.applyTo(original)
3235
?: return original
3336
}
37+
38+
fun findIgnoredPaths(): List<TestPath> {
39+
return testSetOverrides.flatMap { it.findIgnoredPaths() }
40+
}
41+
42+
fun findOverrides(): List<ExpectedOverride> {
43+
return testSetOverrides.flatMap { it.findOverrides() }
44+
}
45+
46+
companion object {
47+
private fun toTestSets(compact: CompactOverride): List<OTSTestSet> {
48+
val ignoreMap = compact.ignores.groupBy { it.testSet }
49+
val overrideMap = compact.overrides.groupBy { it.path.testSet }
50+
51+
val setNames = (ignoreMap.keys + overrideMap.keys).sorted()
52+
53+
return setNames.map { tsName ->
54+
val ignores = ignoreMap[tsName]?: emptyList()
55+
val isIgnored = ignores.any { it.group==null }
56+
val overrides = overrideMap[tsName] ?: emptyList()
57+
58+
val newOverrides = toGroups(overrides, ignores)
59+
60+
OTSTestSet(tsName, newOverrides, isIgnored)
61+
}
62+
}
63+
64+
private fun toGroups(overrides: List<ExpectedOverride>, ignores: List<TestPath>): List<OTSTestGroup> {
65+
val ignoreMap = ignores.filter { it.group != null }.groupBy { it.group!! }
66+
val overrideMap = overrides.filter { it.path.group != null }.groupBy { it.path.group!! }
67+
val groupNames = (ignoreMap.keys + overrideMap.keys).sorted()
68+
69+
return groupNames.map { groupName ->
70+
val grOverrides = overrideMap[groupName] ?: emptyList()
71+
val grIgnores = ignoreMap[groupName] ?: emptyList()
72+
val isIgnored = grIgnores.any { it.test == null }
73+
74+
val schemaTest = grOverrides.singleOrNull { it.path.test!=null && !it.isInstance }?.let {
75+
val testName = it.path.test!!
76+
OTSSchemaTest(testName, expecteds = it.expecteds, isIgnored = grIgnores.any { it.test == testName })
77+
}
78+
79+
val instanceTests = grOverrides.filter { it.path.test!=null && it.isInstance }.map {
80+
val testName = it.path.test!!
81+
OTSInstanceTest(testName, expecteds = it.expecteds, isIgnored = grIgnores.any { it.test == testName })
82+
}
83+
84+
OTSTestGroup(groupName, schemaTest, instanceTests, isIgnored)
85+
}
86+
87+
return TODO()
88+
}
89+
}
3490
}
3591

3692
@Serializable
37-
data class OTSTestSet(val name: String, val groups: List<OTSTestGroup> = emptyList()) {
93+
data class OTSTestSet(val name: String, val groups: List<OTSTestGroup> = emptyList(), val isIgnored: Boolean = false) {
3894
fun applyTo(original: TSTestSet): TSTestSet {
39-
val associations = groups.associateBy { it.name }
40-
val newGroups = original.testGroups.map {
41-
associations.get(it.name)?.applyTo(it) ?: it
95+
val newGroups: List<TSTestGroup> = when {
96+
isIgnored -> emptyList()
97+
else -> {
98+
val associations = groups.associateBy { it.name }
99+
original.testGroups.map {
100+
associations.get(it.name)?.applyTo(it) ?: it
101+
}
102+
}
42103
}
104+
43105
return TSTestSet(
44106
original.contributor,
45107
original.name,
@@ -48,13 +110,25 @@ data class OTSTestSet(val name: String, val groups: List<OTSTestGroup> = emptyLi
48110
newGroups
49111
)
50112
}
113+
114+
fun findIgnoredPaths(): Sequence<TestPath> {
115+
return when {
116+
isIgnored -> sequenceOf(TestPath(name))
117+
else -> groups.asSequence().flatMap { it.findIgnoredPaths(TestPath(name)) }
118+
}
119+
}
120+
121+
fun findOverrides(): Sequence<ExpectedOverride> {
122+
return groups.asSequence().flatMap { it.findOverrides(TestPath(name)) }
123+
}
51124
}
52125

53126
@Serializable
54127
data class OTSTestGroup(
55128
val name: String,
56129
val schemaTest: OTSSchemaTest? = null,
57-
val instanceTests: List<OTSInstanceTest> = emptyList()
130+
val instanceTests: List<OTSInstanceTest> = emptyList(),
131+
val isIgnored: Boolean = false
58132
) {
59133
fun applyTo(original: TSTestGroup): TSTestGroup {
60134
val newSchemaTest = original.schemaTest?.let { ot -> schemaTest?.applyTo(ot) ?: ot }
@@ -66,6 +140,29 @@ data class OTSTestGroup(
66140
instanceTests = newInstanceTests,
67141
)
68142
}
143+
144+
fun findIgnoredPaths(base: TestPath): Sequence<TestPath> {
145+
val newBase = base.copy(group = name)
146+
return when {
147+
isIgnored -> sequenceOf(newBase)
148+
else -> sequence {
149+
if (schemaTest != null && schemaTest.isIgnored) yield(newBase.copy(test=schemaTest.name, isSchema = true))
150+
yieldAll(instanceTests.asSequence().filter { it.isIgnored }.map { newBase.copy(test=it.name, isSchema = false)})
151+
}
152+
}
153+
}
154+
155+
fun findOverrides(base: TestPath): Sequence<ExpectedOverride> {
156+
val newBase = base.copy(group=name)
157+
return sequence {
158+
if (schemaTest != null) yield(
159+
ExpectedOverride(newBase.copy(test = schemaTest.name, isSchema = true), schemaTest.expecteds)
160+
)
161+
yieldAll(instanceTests.asSequence().map {
162+
ExpectedOverride(newBase.copy(test=it.name, isSchema = false), it.expecteds)
163+
})
164+
}
165+
}
69166
}
70167

71168
private fun mergeExpecteds(originalExpected: List<TSExpected>, overridden: List<TSExpected>): List<TSExpected> {
@@ -104,7 +201,13 @@ private fun mergeExpecteds(originalExpected: List<TSExpected>, overridden: List<
104201

105202

106203
@Serializable
107-
data class OTSSchemaTest(val name: String, val version: String? = null, val expecteds: List<TSExpected> = emptyList()) {
204+
data class OTSSchemaTest(
205+
val name: String,
206+
val version: String? = null,
207+
val expecteds: List<TSExpected> = emptyList(),
208+
val isIgnored: Boolean = false,
209+
) {
210+
108211
fun applyTo(original: TSSchemaTest): TSSchemaTest {
109212
val newExpected: List<TSExpected> = mergeExpecteds(original.expected, expecteds)
110213
return original.copy(version = version ?: original.version, expected = newExpected)
@@ -113,7 +216,12 @@ data class OTSSchemaTest(val name: String, val version: String? = null, val expe
113216
}
114217

115218
@Serializable
116-
data class OTSInstanceTest(val name: String, val version: String? = null, val expecteds: List<TSExpected> = emptyList()) {
219+
data class OTSInstanceTest(
220+
val name: String,
221+
val version: String? = null,
222+
val expecteds: List<TSExpected> = emptyList(),
223+
val isIgnored: Boolean = false,
224+
) {
117225
fun applyTo(original: TSInstanceTest): TSInstanceTest {
118226
val newExpected: List<TSExpected> = mergeExpecteds(original.expected, expecteds)
119227
return original.copy(version = version ?: original.version, expected = newExpected)

xmlschema/src/jvmTest/kotlin/io/github/pdvrieze/formats/xmlschema/test/TestXSTestSuite.kt

+7-3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import nl.adaptivity.xmlutil.serialization.structure.*
3939
import org.junit.jupiter.api.*
4040
import org.junit.jupiter.api.Assertions.assertNotNull
4141
import org.w3.xml.xmschematestsuite.*
42+
import org.w3.xml.xmschematestsuite.override.CompactOverride
4243
import org.w3.xml.xmschematestsuite.override.OTSSuite
4344
import java.net.URI
4445
import java.net.URL
@@ -61,7 +62,10 @@ class TestXSTestSuite {
6162
fun testFromTestSetRef(): List<DynamicNode> {
6263
val suiteURL: URL = javaClass.getResource("/xsts/suite.xml")
6364

64-
val override = javaClass.getResource("/override.json").readText().let { Json.decodeFromString<OTSSuite>(it) }
65+
val override = javaClass.getResource("/override.xml").withXmlReader {
66+
val compact = XML { recommended() }.decodeFromReader<CompactOverride>(it)
67+
OTSSuite(compact)
68+
}
6569

6670
val nodes = mutableListOf<DynamicNode>()
6771
suiteURL.withXmlReader { xmlReader ->
@@ -481,8 +485,8 @@ private suspend fun SequenceScope<DynamicNode>.addSchemaDocTest(
481485
}
482486

483487
val expecteds = schemaTest.expected
484-
// .filter { it.version != "1.0" }
485-
.associateBy { it.version?.let{ ResolvedSchema.Version(it) } }
488+
// .filter { (it.version ?: schemaTest.version) != "1.0" }
489+
.associateBy { it.version?.let { ResolvedSchema.Version(it) } }
486490

487491
for ((version, expected) in expecteds) {
488492
val versionLabel = when {

0 commit comments

Comments
 (0)