Skip to content

Commit ed846f7

Browse files
authored
Merge pull request #740 from OptimumCode/kmp-json-validator-update
Update kmp-json-schema-validator library version to 0.0.4
2 parents a716ef0 + 49abc9a commit ed846f7

File tree

6 files changed

+123
-35
lines changed

6 files changed

+123
-35
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66

77
repositories {
88
mavenCentral()
9+
maven(url = "https://s01.oss.sonatype.org/content/repositories/releases/")
910
}
1011

1112
dependencies {

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[versions]
22
kotlin = "1.9.22"
3-
json-schema-validator = "0.0.2"
3+
json-schema-validator = "0.0.4"
44

55
[plugins]
66
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }

src/main/kotlin/BowtieSampsonSchemaValidatorLauncher.kt

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import io.github.optimumcode.json.schema.ErrorCollector
22
import io.github.optimumcode.json.schema.JsonSchema
3+
import io.github.optimumcode.json.schema.SchemaType
34
import kotlinx.serialization.encodeToString
45
import kotlinx.serialization.json.Json
56
import java.io.BufferedReader
@@ -29,19 +30,7 @@ fun main() {
2930

3031
private val SUPPORTED_DIALECTS: Set<String> = hashSetOf(
3132
"http://json-schema.org/draft-07/schema#",
32-
)
33-
34-
/**
35-
* All these cases are ignored because they contain remote refs
36-
* Library does not support them yet.
37-
*/
38-
private val IGNORED_CASES: Set<String> = hashSetOf(
39-
"validate definition against metaschema",
40-
"base URI change - change folder",
41-
"base URI change - change folder in subschema",
42-
"base URI change",
43-
"retrieved nested refs resolve relative to their URI not \$id",
44-
"\$ref to \$ref finds location-independent \$id",
33+
"https://json-schema.org/draft/2019-09/schema",
4534
)
4635

4736
enum class Result { CONTINUE, STOP }
@@ -51,11 +40,12 @@ class BowtieSampsonSchemaValidatorLauncher(
5140
private val json: Json,
5241
) {
5342
private var started: Boolean = false
54-
private var currentDialect: String = ""
43+
private var currentDialect: SchemaType? = null
5544
private val libraryVersion: String
5645
private val libraryHomepage: String
5746
private val libraryIssues: String
5847
private val librarySource: String
48+
private var testFilter: TestFilter = TestFilterDraft7
5949

6050
init {
6151
val attributes: Attributes = javaClass.getResourceAsStream("META-INF/MANIFEST.MF").use {
@@ -83,23 +73,9 @@ class BowtieSampsonSchemaValidatorLauncher(
8373
}
8474
}
8575

86-
private fun shouldSkipCase(caseDescription: String): String? {
87-
return when {
88-
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
89-
caseDescription in IGNORED_CASES || caseDescription.contains("remote ref") ->
90-
"remote schema loading is not yet supported"
91-
else -> null
92-
}
93-
}
94-
95-
@Suppress("detekt:UnusedPrivateMember", "detekt:FunctionOnlyReturningConstant")
96-
private fun shouldSkipTest(caseDescription: String, testDescription: String): String? {
97-
return null
98-
}
99-
10076
private fun handleRun(command: Command.Run) {
10177
requireStarted()
102-
shouldSkipCase(command.case.description)?.also { reason ->
78+
testFilter.shouldSkipCase(command.case.description)?.also { reason ->
10379
writer.writeLine(
10480
json.encodeToString(
10581
RunResponse.Skipped(
@@ -114,7 +90,7 @@ class BowtieSampsonSchemaValidatorLauncher(
11490

11591
@Suppress("detekt:TooGenericExceptionCaught")
11692
val schema = try {
117-
JsonSchema.fromJsonElement(schemaDefinition)
93+
JsonSchema.fromJsonElement(schemaDefinition, currentDialect)
11894
} catch (ex: Exception) {
11995
writer.writeLine(
12096
json.encodeToString(
@@ -135,7 +111,7 @@ class BowtieSampsonSchemaValidatorLauncher(
135111
private fun runCase(command: Command.Run, schema: JsonSchema) {
136112
val results: List<TestResult> = command.case.tests.map { test ->
137113
runCatching {
138-
shouldSkipTest(command.case.description, test.description)?.let { reason ->
114+
testFilter.shouldSkipTest(command.case.description, test.description)?.let { reason ->
139115
TestResult.Skipped(message = reason)
140116
} ?: run {
141117
val valid = schema.validate(test.instance, ErrorCollector.EMPTY)
@@ -164,6 +140,7 @@ class BowtieSampsonSchemaValidatorLauncher(
164140

165141
private fun handleDialect(command: Command.Dialect): Result {
166142
requireStarted()
143+
currentDialect = null
167144
val supported = command.dialect in SUPPORTED_DIALECTS
168145
writer.writeLine(
169146
json.encodeToString(
@@ -173,7 +150,8 @@ class BowtieSampsonSchemaValidatorLauncher(
173150
),
174151
)
175152
if (supported) {
176-
currentDialect = command.dialect
153+
currentDialect = SchemaType.find(command.dialect)
154+
testFilter = getFilter(currentDialect)
177155
}
178156
return Result.CONTINUE
179157
}

src/main/kotlin/Commands.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sealed class Command {
2424
) : Command()
2525

2626
@Serializable
27-
object Stop : Command()
27+
data object Stop : Command()
2828
}
2929

3030
@Serializable

src/main/kotlin/Responses.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import kotlinx.serialization.DeserializationStrategy
12
import kotlinx.serialization.Serializable
3+
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
24
import kotlinx.serialization.json.JsonElement
5+
import kotlinx.serialization.json.JsonObject
36

47
@Serializable
58
class StartResponse(
@@ -53,7 +56,7 @@ sealed class RunResponse {
5356
) : RunResponse()
5457
}
5558

56-
@Serializable
59+
@Serializable(with = TestResultSerializer::class)
5760
sealed class TestResult {
5861

5962
@Serializable
@@ -80,3 +83,15 @@ class ErrorContext(
8083
val traceback: String? = null,
8184
val stderr: String? = null,
8285
)
86+
87+
private class TestResultSerializer : JsonContentPolymorphicSerializer<TestResult>(TestResult::class) {
88+
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<TestResult> {
89+
require(element is JsonObject) { "command must be an object" }
90+
return when {
91+
"valid" in element -> TestResult.Executed.serializer()
92+
"skipped" in element -> TestResult.Skipped.serializer()
93+
"errored" in element -> TestResult.ExecutionError.serializer()
94+
else -> error("unknown object type")
95+
}
96+
}
97+
}

src/main/kotlin/TestFilters.kt

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import io.github.optimumcode.json.schema.SchemaType
2+
3+
interface TestFilter {
4+
/**
5+
* @return reason if test case should be skipped
6+
*/
7+
fun shouldSkipCase(caseDescription: String): String? = null
8+
9+
/**
10+
* @return reason if test in test case should be skipped
11+
*/
12+
fun shouldSkipTest(caseDescription: String, testDescription: String): String? = null
13+
}
14+
15+
fun getFilter(schemaType: SchemaType?): TestFilter =
16+
when (schemaType ?: SchemaType.entries.last()) {
17+
SchemaType.DRAFT_7 -> TestFilterDraft7
18+
SchemaType.DRAFT_2019_09 -> TestFilterDraft201909
19+
}
20+
21+
object TestFilterDraft7 : TestFilter {
22+
/**
23+
* All these cases are ignored because they contain remote refs
24+
* Library does not support them yet.
25+
*/
26+
private val IGNORED_CASES: Set<String> = hashSetOf(
27+
"validate definition against metaschema",
28+
"base URI change - change folder",
29+
"base URI change - change folder in subschema",
30+
"base URI change",
31+
"retrieved nested refs resolve relative to their URI not \$id",
32+
"\$ref to \$ref finds location-independent \$id",
33+
)
34+
35+
override fun shouldSkipCase(caseDescription: String): String? {
36+
return when {
37+
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
38+
caseDescription in IGNORED_CASES || caseDescription.contains("remote ref") ->
39+
"remote schema loading is not yet supported"
40+
41+
else -> null
42+
}
43+
}
44+
}
45+
46+
object TestFilterDraft201909 : TestFilter {
47+
/**
48+
* All these cases are ignored because they contain remote refs or meta schema
49+
* Library does not support them yet.
50+
*/
51+
private val IGNORED_CASES_WITH_REMOTE_REF: Set<String> = hashSetOf(
52+
"invalid anchors",
53+
"Invalid use of fragments in location-independent \$id",
54+
"Valid use of empty fragments in location-independent \$id",
55+
"Unnormalized \$ids are allowed but discouraged",
56+
"URN base URI with f-component",
57+
"remote HTTP ref with different \$id",
58+
"remote HTTP ref with different URN \$id",
59+
"remote HTTP ref with nested absolute ref",
60+
"\$ref to \$ref finds detached \$anchor",
61+
"schema that uses custom metaschema with with no validation vocabulary",
62+
"ignore unrecognized optional vocabulary",
63+
"validate definition against metaschema",
64+
"retrieved nested refs resolve relative to their URI not \$id",
65+
"base URI change - change folder in subschema",
66+
"base URI change - change folder",
67+
"base URI change",
68+
)
69+
70+
private val IGNORE_CASES_WITH_MIN_CONTAINS_ZERO = setOf(
71+
"minContains = 0 with no maxContains",
72+
)
73+
74+
override fun shouldSkipCase(caseDescription: String): String? {
75+
return when {
76+
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
77+
caseDescription in IGNORED_CASES_WITH_REMOTE_REF || caseDescription.contains("remote ref") ->
78+
"remote schema loading and meta schemas are not yet supported"
79+
caseDescription in IGNORE_CASES_WITH_MIN_CONTAINS_ZERO ->
80+
"'minContains' does not affect contains work - at least one element must match 'contains' schema"
81+
else -> null
82+
}
83+
}
84+
85+
override fun shouldSkipTest(caseDescription: String, testDescription: String): String? {
86+
return when {
87+
caseDescription == "minContains = 0 with maxContains" &&
88+
testDescription == "empty data" ->
89+
"'minContains' does not affect contains work -" +
90+
" at least one element must match 'contains' schema"
91+
else -> null
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)