KotlinToolingMetadata: Handle incompatible schemaVersions during json parsing
This commit is contained in:
committed by
TeamCityServer
parent
0406659ac8
commit
37aedba7ef
+7
-1
@@ -118,8 +118,14 @@ fun KotlinToolingMetadata.Companion.parseJsonOrThrow(value: String): KotlinTooli
|
||||
}
|
||||
|
||||
private fun JsonObject.toKotlinToolingMetadataOrThrow(): KotlinToolingMetadata {
|
||||
val schemaVersion = SchemaVersion.parseStringOrThrow(getOrThrow("schemaVersion").asString)
|
||||
if (!SchemaVersion.current.isCompatible(schemaVersion)) {
|
||||
throw IllegalArgumentException(
|
||||
"Incompatible schemaVersion='$schemaVersion' found. Current schemaVersion='${SchemaVersion.current}'"
|
||||
)
|
||||
}
|
||||
return KotlinToolingMetadata(
|
||||
schemaVersion = getOrThrow("schemaVersion").asString,
|
||||
schemaVersion = schemaVersion.toString(),
|
||||
buildSystem = getOrThrow("buildSystem").asString,
|
||||
buildSystemVersion = getOrThrow("buildSystemVersion").asString,
|
||||
buildPlugin = getOrThrow("buildPlugin").asString,
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.tooling
|
||||
|
||||
internal data class SchemaVersion(val major: Int, val minor: Int, val patch: Int) : Comparable<SchemaVersion> {
|
||||
override fun compareTo(other: SchemaVersion): Int {
|
||||
(this.major - other.major).takeIf { it != 0 }?.let { return it }
|
||||
(this.minor - other.minor).takeIf { it != 0 }?.let { return it }
|
||||
return this.patch - other.patch
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$major.$minor.$patch"
|
||||
}
|
||||
|
||||
companion object {
|
||||
val current by lazy { SchemaVersion.parseStringOrThrow(KotlinToolingMetadata.currentSchemaVersion) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun SchemaVersion.Companion.parseStringOrThrow(schemaVersion: String): SchemaVersion {
|
||||
fun throwIllegalSchemaVersion(): Nothing = throw IllegalArgumentException(
|
||||
"Illegal schemaVersion $schemaVersion. Expected {major}.{minor}.{patch}"
|
||||
)
|
||||
|
||||
val parts = schemaVersion.split(".")
|
||||
if (parts.size != 3) throwIllegalSchemaVersion()
|
||||
|
||||
return SchemaVersion(
|
||||
major = parts[0].toIntOrNull() ?: throwIllegalSchemaVersion(),
|
||||
minor = parts[1].toIntOrNull() ?: throwIllegalSchemaVersion(),
|
||||
patch = parts[2].toIntOrNull() ?: throwIllegalSchemaVersion()
|
||||
)
|
||||
}
|
||||
|
||||
internal fun SchemaVersion.isCompatible(to: SchemaVersion): Boolean {
|
||||
if (this.major != to.major) {
|
||||
return false
|
||||
}
|
||||
|
||||
return (this.minor >= to.minor)
|
||||
}
|
||||
+27
-2
@@ -24,10 +24,11 @@ class DeserializationFailureTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sample2 missing build pluginVersion`() {
|
||||
fun `sample2 missing buildPluginVersion`() {
|
||||
@Language("JSON") val json =
|
||||
"""
|
||||
{
|
||||
"schemaVersion": ${SchemaVersion.current},
|
||||
"buildSystem": "Gradle",
|
||||
"buildSystemVersion": "6.7",
|
||||
"buildPlugin": "org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper",
|
||||
@@ -45,6 +46,30 @@ class DeserializationFailureTest {
|
||||
"Expected parsing failure, because of missing pluginVersion. Actual: $result"
|
||||
)
|
||||
|
||||
assertFailsWith<IllegalArgumentException> { KotlinToolingMetadata.parseJsonOrThrow(json) }
|
||||
val exception = assertFailsWith<IllegalArgumentException> { KotlinToolingMetadata.parseJsonOrThrow(json) }
|
||||
assertTrue(
|
||||
"buildPluginVersion" in exception.message.orEmpty(),
|
||||
"Expected 'buildPluginVersion' mentioned in error message\n${exception.message}"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `sample3 incompatible schemaVersion`() {
|
||||
val majorUpgradeVersion = SchemaVersion.current.copy(major = SchemaVersion.current.major + 1)
|
||||
val metadataString = KotlinToolingMetadata(
|
||||
schemaVersion = majorUpgradeVersion.toString(),
|
||||
buildSystem = "",
|
||||
buildSystemVersion = "",
|
||||
buildPlugin = "",
|
||||
buildPluginVersion = "",
|
||||
projectSettings = KotlinToolingMetadata.ProjectSettings(false, false),
|
||||
projectTargets = emptyList()
|
||||
).toJsonString()
|
||||
|
||||
val exception = assertFailsWith<IllegalArgumentException> { KotlinToolingMetadata.parseJsonOrThrow(metadataString) }
|
||||
assertTrue(
|
||||
majorUpgradeVersion.toString() in exception.message.orEmpty(),
|
||||
"Expected bad schemaVersion mentioned in error message\n${exception.message}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.tooling
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
class SchemaVersionTest {
|
||||
|
||||
@Test
|
||||
fun `compare same version`() {
|
||||
assertTrue(SchemaVersion(1, 0, 0) <= SchemaVersion(1, 0, 0), "Expected 1.0.0 <= 1.0.0")
|
||||
assertTrue(SchemaVersion(1, 0, 0) >= SchemaVersion(1, 0, 0), "Expected 1.0.0 >= 1.0.0")
|
||||
assertFalse(SchemaVersion(1, 0, 0) > SchemaVersion(1, 0, 0), "*NOT* Expected 1.0.0 > 1.0.0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `compare higher version`() {
|
||||
assertTrue(SchemaVersion(2, 2, 2) > SchemaVersion(2, 2, 1))
|
||||
assertTrue(SchemaVersion(2, 2, 2) > SchemaVersion(2, 1, 2))
|
||||
assertTrue(SchemaVersion(2, 2, 2) > SchemaVersion(1, 3, 3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `compare lower version`() {
|
||||
assertTrue(SchemaVersion(2, 2, 2) < SchemaVersion(2, 2, 3))
|
||||
assertTrue(SchemaVersion(2, 2, 2) < SchemaVersion(2, 3, 1))
|
||||
assertTrue(SchemaVersion(2, 2, 2) < SchemaVersion(3, 1, 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parseSchemaVersion() {
|
||||
assertEquals(
|
||||
SchemaVersion(2, 15, 100), SchemaVersion.parseStringOrThrow("2.15.100")
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
SchemaVersion(0, 0, 0), SchemaVersion.parseStringOrThrow("0.0.0")
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
SchemaVersion(1, 0, 0), SchemaVersion.parseStringOrThrow("1.0.0")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parseSchemaVersion failure`() {
|
||||
assertFailsWith<IllegalArgumentException> { SchemaVersion.parseStringOrThrow("1.0") }
|
||||
assertFailsWith<IllegalArgumentException> { SchemaVersion.parseStringOrThrow("1.0.0.0") }
|
||||
assertFailsWith<IllegalArgumentException> { SchemaVersion.parseStringOrThrow("a.b.c") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toString and parse`() {
|
||||
assertEquals(
|
||||
SchemaVersion(1, 0, 0), SchemaVersion.parseStringOrThrow(SchemaVersion(1, 0, 0).toString())
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
SchemaVersion(28, 100, 900), SchemaVersion.parseStringOrThrow(SchemaVersion(28, 100, 900).toString())
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isCompatible() {
|
||||
assertTrue(SchemaVersion(1, 1, 0).isCompatible(SchemaVersion(1, 0, 0)))
|
||||
assertTrue(SchemaVersion(1, 0, 0).isCompatible(SchemaVersion(1, 0, 0)))
|
||||
assertFalse(SchemaVersion(1, 0, 0).isCompatible(SchemaVersion(1, 1, 0)))
|
||||
assertFalse(SchemaVersion(1, 0, 0).isCompatible(SchemaVersion(2, 0, 0)))
|
||||
assertFalse(SchemaVersion(2, 0, 0).isCompatible(SchemaVersion(1, 0, 0)))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user