Skip to content

Commit 39d0cd7

Browse files
committed
Test that all Kotlin versions in the project are consistent
There are two different tests: the one that checks that all versions are consistent (but not equal, because some versions are major.minor.patch, but some only major.minor), and the one that checks that versions of all subprojects of the Maven projects are exactly equal (1.1-SNAPSHOT currently) #KT-16455 Fixed
1 parent 6fb83c2 commit 39d0cd7

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2010-2017 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.jetbrains.kotlin.util
18+
19+
import com.intellij.openapi.util.io.FileUtil
20+
import com.intellij.util.Processor
21+
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
22+
import org.jetbrains.kotlin.config.KotlinCompilerVersion
23+
import org.jetbrains.kotlin.config.LanguageVersion
24+
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
25+
import org.jetbrains.kotlin.utils.addIfNotNull
26+
import org.junit.Assert
27+
import org.w3c.dom.Element
28+
import java.io.File
29+
import java.util.*
30+
import javax.xml.parsers.DocumentBuilderFactory
31+
32+
class KotlinVersionsTest : KtUsefulTestCase() {
33+
fun testVersionsAreConsistent() {
34+
val versionPattern = "(\\d+)\\.(\\d+)(\\.(\\d+)|-SNAPSHOT)?".toRegex()
35+
36+
data class Version(val major: Int, val minor: Int, val patch: Int?, val versionString: String, val source: String) {
37+
fun isConsistentWith(other: Version): Boolean {
38+
return major == other.major &&
39+
minor == other.minor &&
40+
(patch == null || other.patch == null || patch == other.patch)
41+
}
42+
}
43+
44+
fun String.toVersionOrNull(source: String): Version? {
45+
val result = versionPattern.matchEntire(this) ?: return null
46+
val (major, minor, _, patch) = result.destructured
47+
return Version(major.toInt(), minor.toInt(), patch.takeUnless(String::isEmpty)?.toInt(), this, source)
48+
}
49+
50+
fun String.toVersion(source: String): Version =
51+
toVersionOrNull(source) ?: error("Version ($source) is in an unknown format: $this")
52+
53+
val versions = arrayListOf<Version>()
54+
55+
// This version is null in case of a local build when KotlinCompilerVersion.VERSION = "@snapshot@"
56+
versions.addIfNotNull(
57+
KotlinCompilerVersion.VERSION.substringBefore('-').toVersionOrNull("KotlinCompilerVersion.VERSION")
58+
)
59+
60+
versions.add(
61+
ForTestCompileRuntime.runtimeJarClassLoader().loadClass(KotlinVersion::class.qualifiedName!!)
62+
.getDeclaredField((KotlinVersion)::CURRENT.name)
63+
.get(null)
64+
.toString()
65+
.toVersion("KotlinVersion.CURRENT")
66+
)
67+
68+
versions.add(
69+
Properties().apply { load(File("resources/kotlinManifest.properties").inputStream()) }
70+
.getProperty("manifest.impl.value.kotlin.version")?.toVersion("kotlinManifest.properties")
71+
?: error("No Kotlin-Version value in kotlinManifest.properties")
72+
)
73+
74+
versions.add(
75+
loadValueFromPomXml("libraries/pom.xml", listOf("properties", "kotlin.language.version"))
76+
?.toVersion("kotlin.language.version in pom.xml")
77+
?: error("No kotlin.language.version in libraries/pom.xml")
78+
)
79+
80+
versions.add(
81+
loadValueFromPomXml("libraries/pom.xml", listOf("version"))
82+
?.toVersion("version in pom.xml")
83+
?: error("No version in libraries/pom.xml")
84+
)
85+
86+
versions.add(
87+
LanguageVersion.LATEST.versionString.toVersion("LanguageVersion.LATEST")
88+
)
89+
90+
if (versions.any { v1 -> versions.any { v2 -> !v1.isConsistentWith(v2) } }) {
91+
Assert.fail(
92+
"Some versions are inconsistent. Please change the versions so that they are consistent:\n\n" +
93+
versions.joinToString(separator = "\n") { with(it) { "$versionString ($source)" } }
94+
)
95+
}
96+
}
97+
98+
fun testMavenProjectVersionsAreEqual() {
99+
data class Pom(val path: String, val version: String)
100+
101+
val poms = arrayListOf<Pom>()
102+
103+
FileUtil.processFilesRecursively(File("libraries"), Processor { file ->
104+
if (file.name == "pom.xml") {
105+
if (loadValueFromPomXml(file.path, listOf("parent", "artifactId")) == "kotlin-project") {
106+
val version = loadValueFromPomXml(file.path, listOf("version"))
107+
?: error("No version found in pom.xml at $file")
108+
poms.add(Pom(file.path, version))
109+
}
110+
}
111+
true
112+
}, Processor { file -> file.name != "target" })
113+
114+
Assert.assertTrue(
115+
"Too few (<= 10) pom.xml files found. Something must be wrong in the test or in the project structure",
116+
poms.size > 10
117+
)
118+
119+
if (!poms.map(Pom::version).areEqual()) {
120+
Assert.fail(
121+
"Some versions in pom.xml files are different. Please change the versions so that they are equal:\n\n" +
122+
poms.joinToString(separator = "\n") { (path, version) -> "$version $path" }
123+
)
124+
}
125+
}
126+
127+
private fun loadValueFromPomXml(filePath: String, query: List<String>): String? {
128+
assert(filePath.endsWith("pom.xml")) { filePath }
129+
130+
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
131+
val input = docBuilder.parse(File(filePath).inputStream())
132+
133+
return query.fold(input.documentElement) { element, tagName ->
134+
element?.getElementsByTagName(tagName)?.item(0) as? Element
135+
}?.textContent
136+
}
137+
138+
private fun Collection<Any>.areEqual(): Boolean = all(first()::equals)
139+
}

0 commit comments

Comments
 (0)