Skip to content

Commit e066a6f

Browse files
authored
Moved pre-release smoke tests from external repository (#372)
* Imported existing smoke tests * Reimplement tests using gradle test kit
1 parent 821b1bc commit e066a6f

File tree

22 files changed

+1252
-1
lines changed

22 files changed

+1252
-1
lines changed

build-logic/src/main/kotlin/kotlinx/io/conventions/kotlinx-io-publish.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication)
109109
project.extensions.configure<SigningExtension>("signing") {
110110
useInMemoryPgpKeys(keyId, signingKey, signingKeyPassphrase)
111111
sign(publication)
112+
113+
// Temporary workaround, see https://github.com/gradle/gradle/issues/26091#issuecomment-1722947958
114+
tasks.withType<AbstractPublishToMaven>().configureEach {
115+
val signingTasks = tasks.withType<Sign>()
116+
mustRunAfter(signingTasks)
117+
}
112118
}
113119
}
114120
}

build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ allprojects {
2323

2424
@OptIn(ExperimentalBCVApi::class)
2525
apiValidation {
26-
ignoredProjects.add("kotlinx-io-benchmarks")
26+
ignoredProjects.addAll(listOf(
27+
"kotlinx-io-benchmarks",
28+
"kotlinx-io-smoke-tests"
29+
))
2730
klib.enabled = true
2831
}
2932

settings.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ rootProject.name = "kotlinx-io"
2222
include(":kotlinx-io-core")
2323
include(":kotlinx-io-benchmarks")
2424
include(":kotlinx-io-bytestring")
25+
include(":kotlinx-io-smoke-tests")
26+
2527
project(":kotlinx-io-core").projectDir = file("./core")
2628
project(":kotlinx-io-benchmarks").projectDir = file("./benchmarks")
2729
project(":kotlinx-io-bytestring").projectDir = file("./bytestring")
30+
project(":kotlinx-io-smoke-tests").projectDir = file("./smoke-tests")

smoke-tests/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Tests aimed to verify that all artifacts are published correctly
2+
and there are no dependency related issues.
3+
4+
There are two sets of tests: one targeting Gradle projects and another targeting Maven projects.
5+
Each set could be invoked independently via `verifyGradleProjects` and `verifyMavenProjects` tasks
6+
correspondingly. Both tasks are aggregated by the `smokeTest` task.
7+
8+
Note that `check` and `test` tasks are no-op.
9+
10+
Tests could be executed against arbitrary `kotlinx-io` version. The version could be set using
11+
`smokeTest.kotlinxIoVersion` property. If the property is unset or has a blank value, current project
12+
version will be used instead. In that case, local maven repo will be used and publication tasks
13+
will be executed before any tests.
14+
15+
For projects published to a staging Sonatype repository it's possible to specify repository ID
16+
using `smokeTest.stagingRepository` property.
17+
18+
### How to run
19+
20+
`./gradlew :kotlinx-io-smoke-tests:smokeTest -PsmokeTest.kotlinxIoVersion=0.5.3-test -PsmokeTest.stagingRepository=orgjetbrainskotlinx-3482`

smoke-tests/build.gradle.kts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import org.apache.tools.ant.taskdefs.condition.Os
2+
3+
plugins {
4+
kotlin("jvm")
5+
}
6+
7+
val stagingRepositoryIdRawValue = project.findProperty("smokeTest.stagingRepository")?.toString()
8+
9+
val stagingRepositoryId: String = if (stagingRepositoryIdRawValue != null) {
10+
stagingRepositoryIdRawValue
11+
} else {
12+
logger.warn("smokeTest.stagingRepository was not set.")
13+
""
14+
}
15+
16+
val stagingRepository: String = "https://oss.sonatype.org/content/repositories/$stagingRepositoryId"
17+
18+
val kotlinxIoVersionRawValue = project.findProperty("smokeTest.kotlinxIoVersion")?.toString()
19+
var useLocalBuild = false
20+
21+
val kotlinxIoVersion: String = if (kotlinxIoVersionRawValue.isNullOrBlank()) {
22+
useLocalBuild = true
23+
val v = version.toString()
24+
logger.warn("smokeTest.kotlinxIoVersion was not specified, using $v instead.")
25+
v
26+
} else {
27+
kotlinxIoVersionRawValue
28+
}
29+
30+
repositories {
31+
mavenCentral()
32+
}
33+
34+
tasks {
35+
val kotlinVersion: String = libs.versions.kotlin.get()
36+
37+
val verifyMavenProjects by registering(Exec::class) {
38+
workingDir = projectDir.resolve("src").resolve("test").resolve("resources").resolve("maven-projects")
39+
executable = workingDir.resolve(getMavenWrapperName()).absolutePath
40+
args = buildList {
41+
add("-DKOTLIN_VERSION=$kotlinVersion")
42+
add("-DKOTLINX_IO_VERSION=$kotlinxIoVersion")
43+
if (stagingRepository.isNotBlank()) {
44+
add("-DSTAGING_REPOSITORY_URL=$stagingRepository")
45+
add("-Pstaging")
46+
}
47+
add("verify")
48+
}
49+
if (useLocalBuild) {
50+
dependsOn(project(":kotlinx-io-core").tasks.named("publishToMavenLocal"))
51+
dependsOn(project(":kotlinx-io-bytestring").tasks.named("publishToMavenLocal"))
52+
}
53+
}
54+
val cleanMavenProjects by registering(Exec::class) {
55+
workingDir = projectDir.resolve("src").resolve("test").resolve("resources").resolve("maven-projects")
56+
executable = workingDir.resolve(getMavenWrapperName()).absolutePath
57+
args = listOf("-DKOTLIN_VERSION=$kotlinVersion", "-DKOTLINX_IO_VERSION=$kotlinxIoVersion", "clean")
58+
}
59+
60+
val verifyGradleProjects = create("verifyGradleProjects", Test::class) {
61+
useJUnit()
62+
if (useLocalBuild) {
63+
dependsOn(project(":kotlinx-io-core").tasks.named("publishToMavenLocal"))
64+
dependsOn(project(":kotlinx-io-bytestring").tasks.named("publishToMavenLocal"))
65+
}
66+
67+
systemProperty("kotlinxIoVersion", kotlinxIoVersion)
68+
systemProperty("stagingRepository", stagingRepository)
69+
systemProperty("useLocalBuild", useLocalBuild)
70+
systemProperty("kotlinVersion", kotlinVersion)
71+
}
72+
73+
create("smokeTest") {
74+
dependsOn(verifyMavenProjects)
75+
dependsOn(verifyGradleProjects)
76+
}
77+
78+
named("clean").configure {
79+
dependsOn(cleanMavenProjects)
80+
}
81+
82+
check.configure {
83+
enabled = false
84+
}
85+
test.configure {
86+
enabled = false
87+
}
88+
}
89+
90+
dependencies {
91+
testImplementation(kotlin("test"))
92+
testImplementation(gradleTestKit())
93+
}
94+
95+
fun getMavenWrapperName(): String =
96+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
97+
"mvnw.cmd"
98+
} else {
99+
"mvnw"
100+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
4+
*/
5+
6+
package kotlinx.io
7+
8+
import org.gradle.testkit.runner.BuildResult
9+
import org.gradle.testkit.runner.GradleRunner
10+
import org.gradle.testkit.runner.TaskOutcome
11+
import org.junit.Rule
12+
import org.junit.rules.TemporaryFolder
13+
import kotlin.io.path.outputStream
14+
import kotlin.test.Test
15+
import kotlin.test.assertEquals
16+
17+
private const val buildScriptFilename = "build.gradle.kts"
18+
private const val settingsFilename = "settings.gradle.kts"
19+
20+
public class GradleProjectsTest {
21+
@JvmField
22+
@Rule
23+
public val projectDir = TemporaryFolder()
24+
25+
private val kotlinxIoVersion: String = System.getProperty("kotlinxIoVersion")!!
26+
private val kotlinVersion: String = System.getProperty("kotlinVersion")!!
27+
private val useLocalBuild: String = System.getProperty("useLocalBuild")!!
28+
private val stagingRepository: String = System.getProperty("stagingRepository")!!
29+
private val bytestringDependency: String = "org.jetbrains.kotlinx:kotlinx-io-bytestring:$kotlinxIoVersion"
30+
private val coreDependency: String = "org.jetbrains.kotlinx:kotlinx-io-core:$kotlinxIoVersion"
31+
32+
private fun generateBuildScript(multiplatform: Boolean, dependencyName: String) {
33+
val templateFile = (if (multiplatform) "kmp" else "jvm") + "." + buildScriptFilename
34+
var template = GradleProjectsTest::class.java.getResourceAsStream(
35+
"/templates/$templateFile")!!.reader().readText()
36+
37+
template = template.replace("%DEPENDENCY%", dependencyName)
38+
.replace("%KOTLIN_VERSION%", kotlinVersion)
39+
.replace("%USE_LOCAL_REPO%", useLocalBuild)
40+
.replace("%STAGING_REPOSITORY%", stagingRepository)
41+
42+
val outFile = projectDir.newFile(buildScriptFilename)
43+
outFile.writeText(template)
44+
}
45+
46+
private fun setupTest(testCase: String, multiplatform: Boolean, dependencyName: String) {
47+
copySrcFile(testCase, multiplatform)
48+
49+
projectDir.newFile(settingsFilename).outputStream().use {
50+
GradleProjectsTest::class.java.getResourceAsStream("/templates/$settingsFilename")!!.copyTo(it)
51+
}
52+
53+
generateBuildScript(multiplatform, dependencyName)
54+
}
55+
56+
private fun copySrcFile(testCase: String, multiplatform: Boolean) {
57+
val testSubdir = if (multiplatform) "commonTest" else "test"
58+
val srcDir = projectDir.newFolder("src", testSubdir, "kotlin")
59+
val resource = GradleProjectsTest::class.java.getResourceAsStream("/gradle-projects/$testCase/SmokeTest.kt")!!
60+
val outFile = srcDir.toPath().resolve("SmokeTest.kt")
61+
outFile.outputStream().use {
62+
resource.copyTo(it)
63+
}
64+
}
65+
66+
private fun assertTestPassed(buildResult: BuildResult, taskName: String = ":test") {
67+
assertEquals(TaskOutcome.SUCCESS, buildResult.task(taskName)?.outcome,
68+
"Task \"$taskName\" should pass.\n" + buildResult.output)
69+
}
70+
71+
@Test
72+
fun bytestringJvm() {
73+
setupTest("bytestring-jvm", false, bytestringDependency)
74+
val results = GradleRunner.create()
75+
.withProjectDir(projectDir.root)
76+
.withArguments(":test")
77+
.run()
78+
79+
assertTestPassed(results)
80+
}
81+
82+
@Test
83+
fun coreJvm() {
84+
setupTest("core-jvm", false, coreDependency)
85+
val results = GradleRunner.create()
86+
.withProjectDir(projectDir.root)
87+
.withArguments(":test")
88+
.run()
89+
90+
assertTestPassed(results)
91+
}
92+
93+
@Test
94+
fun bytestringMultiplatform() {
95+
setupTest("bytestring-multiplatform", true, bytestringDependency)
96+
val results = GradleRunner.create()
97+
.withProjectDir(projectDir.root)
98+
.withArguments(":allTests")
99+
.run()
100+
101+
assertTestPassed(results, ":allTests")
102+
}
103+
104+
@Test
105+
fun coreMultiplatform() {
106+
setupTest("core-multiplatform", true, coreDependency)
107+
val results = GradleRunner.create()
108+
.withProjectDir(projectDir.root)
109+
.withArguments(":allTests")
110+
.run()
111+
112+
assertTestPassed(results, ":allTests")
113+
}
114+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
4+
*/
5+
6+
package org.example
7+
8+
import kotlinx.io.bytestring.ByteString
9+
import kotlin.test.Test
10+
import kotlin.test.assertEquals
11+
12+
class SmokeTest {
13+
@Test
14+
fun test() {
15+
assertEquals("ByteString(size=1 hex=42)", ByteString(0x42).toString())
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
4+
*/
5+
6+
import kotlinx.io.bytestring.ByteString
7+
import kotlin.test.Test
8+
import kotlin.test.assertEquals
9+
10+
class SmokeTest {
11+
@Test
12+
fun test() {
13+
assertEquals("ByteString(size=1 hex=42)", ByteString(0x42).toString())
14+
}
15+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
4+
*/
5+
6+
package org.example
7+
8+
import kotlinx.io.Buffer
9+
import kotlinx.io.bytestring.ByteString
10+
import kotlinx.io.readByteArray
11+
import kotlinx.io.readByteString
12+
import kotlinx.io.write
13+
import kotlin.test.Test
14+
import kotlin.test.assertContentEquals
15+
import kotlin.test.assertEquals
16+
17+
class SmokeTest {
18+
@Test
19+
fun testCore() {
20+
val buffer = Buffer()
21+
buffer.writeLong(0)
22+
assertContentEquals(ByteArray(8), buffer.readByteArray())
23+
}
24+
25+
@Test
26+
fun testByteString() {
27+
val byteString = ByteString(0x42)
28+
val buffer = Buffer()
29+
buffer.write(byteString)
30+
31+
assertEquals(ByteString(0x42), buffer.readByteString())
32+
}
33+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
4+
*/
5+
6+
import kotlinx.io.Buffer
7+
import kotlinx.io.bytestring.ByteString
8+
import kotlinx.io.files.Path
9+
import kotlinx.io.files.SystemFileSystem
10+
import kotlinx.io.readByteArray
11+
import kotlinx.io.readByteString
12+
import kotlinx.io.write
13+
import kotlin.test.Test
14+
import kotlin.test.assertContentEquals
15+
import kotlin.test.assertEquals
16+
17+
class SmokeTest {
18+
@Test
19+
fun testCore() {
20+
val buffer = Buffer()
21+
buffer.writeLong(0)
22+
assertContentEquals(ByteArray(8), buffer.readByteArray())
23+
}
24+
25+
@Test
26+
fun testByteString() {
27+
val byteString = ByteString(0x42)
28+
val buffer = Buffer()
29+
buffer.write(byteString)
30+
31+
assertEquals(ByteString(0x42), buffer.readByteString())
32+
}
33+
34+
@Test
35+
fun testUseFiles() {
36+
try {
37+
SystemFileSystem.exists(Path("."))
38+
} catch (t: Throwable) {
39+
// that's fine
40+
}
41+
}
42+
}
Binary file not shown.

0 commit comments

Comments
 (0)