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