1 /*
2  * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.atomicfu.gradle.plugin.test.framework.checker
6 
7 import kotlinx.atomicfu.gradle.plugin.test.framework.runner.*
8 import kotlinx.atomicfu.gradle.plugin.test.framework.runner.GradleBuild
9 import kotlinx.atomicfu.gradle.plugin.test.framework.runner.atomicfuVersion
10 import kotlinx.atomicfu.gradle.plugin.test.framework.runner.dependencies
11 
12 private val commonAtomicfuDependency = "org.jetbrains.kotlinx:atomicfu:$atomicfuVersion"
13 private val jvmAtomicfuDependency = "org.jetbrains.kotlinx:atomicfu-jvm:$atomicfuVersion"
14 
checkAtomicfuDependencyIsPresentnull15 private fun GradleBuild.checkAtomicfuDependencyIsPresent(configurations: List<String>, atomicfuDependency: String) {
16     val dependencies = dependencies()
17     for (config in configurations) {
18         val configDependencies = dependencies.getDependenciesForConfig(config)
19         check(configDependencies.contains(atomicfuDependency)) { "Expected $atomicfuDependency in configuration $config, but it was not found." }
20     }
21 }
22 
checkAtomicfuDependencyIsAbsentnull23 private fun GradleBuild.checkAtomicfuDependencyIsAbsent(configurations: List<String>, atomicfuDependency: String) {
24     val dependencies = dependencies()
25     for (config in configurations) {
26         val configDependencies = dependencies.getDependenciesForConfig(config)
27         check(!configDependencies.contains(atomicfuDependency)) { "Dependency $atomicfuDependency should be compileOnly, but it was found in the configuration: $config" }
28     }
29 }
30 
31 /**
32  * For JVM there are 4 final configurations:
33  * compileClasspath — compile dependencies
34  * runtimeClasspath — runtime dependencies
35  * apiElements — compile dependencies that will be included in publication
36  * runtimeElements — runtime dependencies that will be included in publication
37  *
38  * The functions below check that `org.jetbrains.kotlinx:atomicfu` dependency is only included in compile configurations.
39  */
40 
41 // Checks a simple JVM project with a single target
checkJvmCompileOnlyDependenciesnull42 internal fun GradleBuild.checkJvmCompileOnlyDependencies() {
43     checkAtomicfuDependencyIsPresent(listOf("compileClasspath"), jvmAtomicfuDependency)
44     checkAtomicfuDependencyIsAbsent(listOf("runtimeClasspath", "apiElements", "runtimeElements"), jvmAtomicfuDependency)
45 }
46 
47 // Checks JVM target of an MPP project
checkMppJvmCompileOnlyDependenciesnull48 internal fun GradleBuild.checkMppJvmCompileOnlyDependencies() {
49     checkAtomicfuDependencyIsPresent(listOf("jvmCompileClasspath"), commonAtomicfuDependency)
50     checkAtomicfuDependencyIsAbsent(listOf("jvmRuntimeClasspath", "jvmApiElements", "jvmRuntimeElements"), commonAtomicfuDependency)
51 }
52 
53 // Checks wasmJs target of an MPP project
checkMppWasmJsImplementationDependenciesnull54 internal fun GradleBuild.checkMppWasmJsImplementationDependencies() {
55     checkAtomicfuDependencyIsPresent(listOf("wasmJsCompileClasspath", "wasmJsRuntimeClasspath"), commonAtomicfuDependency)
56 }
57 
checkMppWasmWasiImplementationDependenciesnull58 internal fun GradleBuild.checkMppWasmWasiImplementationDependencies() {
59     checkAtomicfuDependencyIsPresent(listOf("wasmWasiCompileClasspath", "wasmWasiRuntimeClasspath"), commonAtomicfuDependency)
60 }
61 
62 // Checks Native target of an MPP project
checkMppNativeCompileOnlyDependenciesnull63 internal fun GradleBuild.checkMppNativeCompileOnlyDependencies() {
64     // Here the name of the native target is hardcoded because the tested mpp-sample project declares this target and
65     // KGP generates the same set of dependencies for every declared native target ([mingwX64|linuxX64|macosX64...]CompileKlibraries)
66     checkAtomicfuDependencyIsPresent(listOf("macosX64CompileKlibraries"), commonAtomicfuDependency)
67     checkAtomicfuDependencyIsAbsent(listOf("macosX64MainImplementation"), commonAtomicfuDependency)
68 }
69 
70 // Checks Native target of an MPP project
checkMppNativeImplementationDependenciesnull71 internal fun GradleBuild.checkMppNativeImplementationDependencies() {
72     checkAtomicfuDependencyIsPresent(listOf("macosX64CompileKlibraries", "macosX64MainImplementation"), commonAtomicfuDependency)
73 }
74 
75 // Some dependencies may be not resolvable but consumable and will not be present in the output of :dependencies task,
76 // in this case we should check .pom or .module file of the published project.
77 // This method checks if the .module file in the sample project publication contains org.jetbrains.kotlinx:atomicfu dependency included.
78 // It searches for:
79 // "group": "org.jetbrains.kotlinx",
80 // "module": "atomicfu-*", atomicfu or atomicfu-jvm
checkConsumableDependenciesnull81 internal fun GradleBuild.checkConsumableDependencies() {
82     publishToLocalRepository()
83     val moduleFile = getSampleProjectJarModuleFile(targetDir, projectName)
84     val lines = moduleFile.readText().lines()
85     var index = 0
86     while (index < lines.size) {
87         val line = lines[index]
88         if (line.contains("\"group\": \"org.jetbrains.kotlinx\"") &&
89             lines[index + 1].contains("\"module\": \"atomicfu")) {
90             error("org.jetbrains.kotlinx.atomicfu dependency found in the .module file ${moduleFile.path}")
91         }
92         index++
93     }
94 }
95