blob: 0826466e0a984cf78787de6a1f75e179c975d91d [file] [log] [blame]
Vsevolod Tolstopyatov74bcc922018-05-03 20:07:54 +03001package kotlinx.coroutines.experimental.tools
2
3import org.junit.*
4import org.junit.rules.*
5import java.io.*
6import java.util.jar.*
7
8class PublicApiTest {
9
10 /*
11 * How to add a test for your module kotlinx-coroutines-foo?
12 *
13 * Dump public declarations via PublicApiDump.kt and create file
14 * reference-public-api/kotlinx-coroutines-foo.txt with dumped declarations.
15 *
16 * Then add test:
17 *
18 * @Test
19 * fun kotlinxCorountesFoo() { // <- name pattern should match txt file from reference-public-api
20 * snapshotAPIAndCompare($relative_path_to_module)
21 * }
22 */
23
24 @Rule
25 @JvmField
26 val testName = TestName()
27
28 @Test
29 fun kotlinxCoroutinesCore() {
30 snapshotAPIAndCompare("core/kotlinx-coroutines-core", nonPublicPackages = listOf("kotlinx.coroutines.experimental.internal"))
31 }
32
33 @Test
34 fun kotlinxCoroutinesReactive() {
35 snapshotAPIAndCompare("reactive/kotlinx-coroutines-reactive")
36 }
37
38 @Test
39 fun kotlinxCoroutinesReactor() {
40 snapshotAPIAndCompare("reactive/kotlinx-coroutines-reactor")
41 }
42
43 @Test
44 fun kotlinxCoroutinesRx1() {
45 snapshotAPIAndCompare("reactive/kotlinx-coroutines-rx1")
46 }
47
48 @Test
49 fun kotlinxCoroutinesRx2() {
50 snapshotAPIAndCompare("reactive/kotlinx-coroutines-rx2")
51 }
52
53 @Test
54 fun kotlinxCoroutinesGuava() {
55 snapshotAPIAndCompare("integration/kotlinx-coroutines-guava")
56 }
57
58 @Test
59 fun kotlinxCoroutinesJdk8() {
60 snapshotAPIAndCompare("integration/kotlinx-coroutines-jdk8")
61 }
62
63
64 @Test
65 fun kotlinxCoroutinesNio() {
66 snapshotAPIAndCompare("integration/kotlinx-coroutines-nio")
67 }
68
69 @Test
70 fun kotlinxCoroutinesQuasar() {
71 snapshotAPIAndCompare("integration/kotlinx-coroutines-quasar")
72 }
73
74 @Test
75 fun kotlinxCoroutinesAndroid() {
76 snapshotAPIAndCompare("ui/kotlinx-coroutines-android")
77 }
78
79
80 @Test
81 fun kotlinxCoroutinesJavafx() {
82 snapshotAPIAndCompare("ui/kotlinx-coroutines-javafx")
83 }
84
85 @Test
86 fun kotlinxCoroutinesSwing() {
87 snapshotAPIAndCompare("ui/kotlinx-coroutines-swing")
88 }
89
90 private fun snapshotAPIAndCompare(basePath: String, jarPattern: String = basePath.substring(basePath.indexOf("/") + 1),
91 publicPackages: List<String> = emptyList(), nonPublicPackages: List<String> = emptyList()) {
92 val base = File("../$basePath/build/libs").absoluteFile.normalize()
93 val jarFile = getJarPath(base, jarPattern)
94 val kotlinJvmMappingsFiles = listOf(base.resolve("../visibilities.json"))
95
96 println("Reading kotlin visibilities from $kotlinJvmMappingsFiles")
97 val publicPackagePrefixes = publicPackages.map { it.replace('.', '/') + '/' }
98 val visibilities =
99 kotlinJvmMappingsFiles
100 .map { readKotlinVisibilities(it).filterKeys { name -> publicPackagePrefixes.none { name.startsWith(it) } } }
101 .reduce { m1, m2 -> m1 + m2 }
102
103 println("Reading binary API from $jarFile")
104 val api = getBinaryAPI(JarFile(jarFile), visibilities).filterOutNonPublic(nonPublicPackages)
105
106 val target = File("reference-public-api")
107 .resolve(testName.methodName.replaceCamelCaseWithDashedLowerCase() + ".txt")
108
109 api.dumpAndCompareWith(target)
110 }
111
112 private fun getJarPath(base: File, jarPattern: String, kotlinVersion: String? = null): File {
113 val versionPattern = kotlinVersion?.let { "-" + Regex.escape(it) } ?: ".+"
114 val regex = Regex("$jarPattern$versionPattern\\.jar")
115 val files = (base.listFiles() ?: throw Exception("Cannot list files in $base"))
116 .filter { it.name.let {
117 it matches regex
118 && !it.endsWith("-sources.jar")
119 && !it.endsWith("-javadoc.jar")
120 && !it.endsWith("-tests.jar")} }
121
122 return files.singleOrNull() ?: throw Exception("No single file matching $regex in $base:\n${files.joinToString("\n")}")
123 }
124}