1 /*
2  * Copyright 2022 The Android Open Source Project
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 androidx.build.buildInfo
18 
19 import androidx.build.PlatformIdentifier
20 import androidx.build.buildInfo.CreateLibraryBuildInfoFileTask.Companion.asBuildInfoDependencies
21 import androidx.build.jetpad.LibraryBuildInfoFile
22 import androidx.testutils.gradle.ProjectSetupRule
23 import com.google.common.truth.Truth.assertThat
24 import com.google.gson.Gson
25 import java.io.File
26 import net.saff.checkmark.Checkmark.Companion.check
27 import org.gradle.api.artifacts.ModuleDependency
28 import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
29 import org.gradle.testkit.runner.GradleRunner
30 import org.junit.Before
31 import org.junit.Rule
32 import org.junit.Test
33 import org.junit.rules.TemporaryFolder
34 
35 class CreateLibraryBuildInfoFileTaskTest {
36     @get:Rule val distDir = TemporaryFolder()
37 
38     @get:Rule val projectSetup = ProjectSetupRule()
39     private lateinit var gradleRunner: GradleRunner
40 
41     @Before
setUpnull42     fun setUp() {
43         gradleRunner =
44             GradleRunner.create()
45                 .withProjectDir(projectSetup.rootDir)
46                 .withPluginClasspath()
47                 .withEnvironment(mapOf("DIST_DIR" to distDir.root.absolutePath))
48     }
49 
50     @Test
buildInfoDependenciesnull51     fun buildInfoDependencies() {
52         val deps: List<ModuleDependency> =
53             listOf(DefaultExternalModuleDependency("androidx.group", "artifact", "version"))
54         deps
55             .asBuildInfoDependencies()
56             .single()
57             .check { it.groupId == "androidx.group" }
58             .check { it.artifactId == "artifact" }
59             .check { it.version == "version" }
60             .check { !it.isTipOfTree }
61     }
62 
63     @Test
suffixnull64     fun suffix() {
65         computeTaskSuffix(projectName = "cubane", artifactId = "cubane").check { it == "" }
66         computeTaskSuffix(projectName = "cubane", artifactId = "cubane-jvm").check { it == "Jvm" }
67         computeTaskSuffix(projectName = "cubane", artifactId = "cubane-jvm-linux-x64").check {
68             it == "JvmLinuxX64"
69         }
70     }
71 
72     @Test
buildInfoTaskCreatesSimpleFilenull73     fun buildInfoTaskCreatesSimpleFile() {
74         setupBuildInfoProject()
75         gradleRunner.withArguments("createLibraryBuildInfoFiles").build()
76 
77         val buildInfoFile =
78             distDir.root.resolve("build-info/androidx.build_info_test_test_build_info.txt")
79         assertThat(buildInfoFile.exists()).isTrue()
80 
81         val buildInfo = parseBuildInfo(buildInfoFile)
82 
83         assertThat(buildInfo.groupId).isEqualTo("androidx.build_info_test")
84         assertThat(buildInfo.artifactId).isEqualTo("test")
85         assertThat(buildInfo.version).isEqualTo("0.0.1")
86         assertThat(buildInfo.kotlinVersion).isEqualTo(projectSetup.props.kgpVersion)
87         assertThat(buildInfo.groupIdRequiresSameVersion).isFalse()
88         assertThat(buildInfo.dependencies).hasSize(1)
89         assertThat(buildInfo.dependencies.single().groupId).isEqualTo("androidx.core")
90         assertThat(buildInfo.dependencies.single().artifactId).isEqualTo("core")
91         assertThat(buildInfo.dependencyConstraints).hasSize(1)
92         assertThat(buildInfo.dependencyConstraints.single().groupId).isEqualTo("androidx.core")
93         assertThat(buildInfo.dependencyConstraints.single().artifactId).isEqualTo("core-ktx")
94         assertThat(buildInfo.shouldPublishDocs).isFalse()
95         assertThat(buildInfo.isKmp).isFalse()
96         assertThat(buildInfo.target).isEqualTo("androidx")
97         assertThat(buildInfo.kmpChildren)
98             .isEqualTo(setOf("android", "jvm", "jvmstubs", "linuxx64stubs", "wasm-js"))
99     }
100 
101     @Test
buildInfoTaskAddsTestModuleNamesnull102     fun buildInfoTaskAddsTestModuleNames() {
103         setupBuildInfoProject()
104         gradleRunner.withArguments("createLibraryBuildInfoFiles").build()
105 
106         val buildInfoFile =
107             distDir.root.resolve("build-info/androidx.build_info_test_test_build_info.txt")
108         assertThat(buildInfoFile.exists()).isTrue()
109 
110         val buildInfo = parseBuildInfo(buildInfoFile)
111 
112         assertThat(buildInfo.testModuleNames).containsExactly("test.xml")
113     }
114 
115     @Test
buildInfoTaskWithSuffixSkipsTestModuleNamesnull116     fun buildInfoTaskWithSuffixSkipsTestModuleNames() {
117         setupBuildInfoProjectForArtifactWithSuffix()
118         gradleRunner.withArguments("createLibraryBuildInfoFiles").build()
119 
120         val buildInfoFile =
121             distDir.root.resolve("build-info/androidx.build_info_test_test-jvm_build_info.txt")
122         assertThat(buildInfoFile.exists()).isTrue()
123 
124         val buildInfo = parseBuildInfo(buildInfoFile)
125 
126         assertThat(buildInfo.testModuleNames).isEmpty()
127     }
128 
129     @Test
hasApplePlatform_withAtLeastOnePlatformIdentifierTargetingAnApplePlatform_returnsTruenull130     fun hasApplePlatform_withAtLeastOnePlatformIdentifierTargetingAnApplePlatform_returnsTrue() {
131         val platforms =
132             setOf(
133                 PlatformIdentifier.ANDROID,
134                 PlatformIdentifier.IOS_ARM_64,
135                 PlatformIdentifier.JVM,
136             )
137         assertThat(hasApplePlatform(platforms)).isTrue()
138     }
139 
140     @Test
hasApplePlatform_withNoPlatformIdentifiersTargetingAnApplePlatform_returnsFalsenull141     fun hasApplePlatform_withNoPlatformIdentifiersTargetingAnApplePlatform_returnsFalse() {
142         val platforms =
143             setOf(
144                 PlatformIdentifier.ANDROID,
145                 PlatformIdentifier.JVM,
146             )
147         assertThat(hasApplePlatform(platforms)).isFalse()
148     }
149 
setupBuildInfoProjectnull150     private fun setupBuildInfoProject() {
151         // Set the project name to be equal to artifact id, so that it is not adding a suffix to
152         // the task name.
153         File(projectSetup.rootDir, "settings.gradle").writeText("rootProject.name = \"test\"")
154         projectSetup.writeDefaultBuildGradle(
155             prefix =
156                 """
157                 import androidx.build.buildInfo.CreateLibraryBuildInfoFileTaskKt
158                 plugins {
159                     id("com.android.library")
160                     id("maven-publish")
161                     id("kotlin-android")
162                 }
163                 ext {
164                     supportRootFolder = new File("${projectSetup.rootDir}")
165                 }
166             """
167                     .trimIndent(),
168             suffix =
169                 """
170             version = "0.0.1"
171             dependencies {
172                 constraints {
173                     implementation("androidx.core:core-ktx:1.1.0")
174                 }
175                 implementation("androidx.core:core:1.1.0")
176             }
177             android {
178                  namespace 'androidx.build_info'
179             }
180             group = "androidx.build_info_test"
181             afterEvaluate {
182                 publishing {
183                     publications {
184                         maven(MavenPublication) {
185                             groupId = 'androidx.build_info_test'
186                             artifactId = 'test'
187                             version = '0.0.1'
188                             from(components.release)
189                         }
190                     }
191                     publications.withType(MavenPublication) {
192                         CreateLibraryBuildInfoFileTaskKt.createBuildInfoTask(
193                             project,
194                             it,
195                             null,
196                             it.artifactId,
197                             project.provider { "fakeSha" },
198                             false,
199                             false,
200                             "androidx",
201                             ["android", "jvm", "jvmStubs", "linuxx64Stubs", "wasmJs"].toSet(),
202                             project.provider { ["test.xml"] },
203                         )
204                     }
205                 }
206             }
207             """
208                     .trimIndent()
209         )
210     }
211 
setupBuildInfoProjectForArtifactWithSuffixnull212     private fun setupBuildInfoProjectForArtifactWithSuffix() {
213         File(projectSetup.rootDir, "settings.gradle").writeText("rootProject.name = \"test\"")
214         projectSetup.writeDefaultBuildGradle(
215             prefix =
216                 """
217                 import androidx.build.buildInfo.CreateLibraryBuildInfoFileTaskKt
218                 plugins {
219                     id("com.android.library")
220                     id("maven-publish")
221                     id("kotlin-android")
222                 }
223                 ext {
224                     supportRootFolder = new File("${projectSetup.rootDir}")
225                 }
226             """
227                     .trimIndent(),
228             suffix =
229                 """
230             version = "0.0.1"
231             dependencies {
232                 constraints {
233                     implementation("androidx.core:core-ktx:1.1.0")
234                 }
235                 implementation("androidx.core:core:1.1.0")
236             }
237             android {
238                  namespace 'androidx.build_info'
239             }
240             group = "androidx.build_info_test"
241             afterEvaluate {
242                 publishing {
243                     publications {
244                         maven(MavenPublication) {
245                             groupId = 'androidx.build_info_test'
246                             artifactId = 'test-jvm'
247                             version = '0.0.1'
248                             from(components.release)
249                         }
250                     }
251                     publications.withType(MavenPublication) {
252                         CreateLibraryBuildInfoFileTaskKt.createBuildInfoTask(
253                             project,
254                             it,
255                             null,
256                             it.artifactId,
257                             project.provider { "fakeSha" },
258                             false,
259                             false,
260                             "androidx",
261                             ["android", "jvm"].toSet(),
262                             project.provider { ["test.xml"] },
263                         )
264                     }
265                 }
266             }
267             """
268                     .trimIndent()
269         )
270     }
271 
parseBuildInfonull272     private fun parseBuildInfo(buildInfoFile: File): LibraryBuildInfoFile {
273         val gson = Gson()
274         val contents = buildInfoFile.readText(Charsets.UTF_8)
275         return gson.fromJson(contents, LibraryBuildInfoFile::class.java)
276     }
277 }
278