Skip to content

Commit 5ab77cb

Browse files
authored
Use compilations instead of multiple mpp targets for java codegen tests (#5164)
* use compilations instead of multiple mpp targets for java codegen tests * fix tests * remove warning
1 parent 77e855c commit 5ab77cb

File tree

70 files changed

+153
-219
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+153
-219
lines changed

build-logic/src/main/kotlin/Mpp.kt

Lines changed: 110 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
2+
import com.android.build.gradle.internal.tasks.factory.dependsOn
13
import org.gradle.api.Action
24
import org.gradle.api.Project
5+
import org.gradle.api.tasks.testing.Test
36
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
7+
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
8+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
49
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink
10+
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
511
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
12+
import org.jetbrains.kotlin.konan.target.Family
613

714
private val allAppleTargets = setOf(
815
"macosX64",
@@ -19,23 +26,23 @@ private val allAppleTargets = setOf(
1926
)
2027

2128
// Try to guess the dev machine to make sure the tests are running smoothly
22-
val hostTarget: String
29+
internal val hostTarget: String
2330
get() = if (System.getProperty("os.arch") == "aarch64") {
2431
"macosArm64"
2532
} else {
2633
"macosX64"
2734
}
2835

29-
val enabledAppleTargets = allAppleTargets
30-
val enabledLinux = true
31-
val enabledJs = true
36+
private val enableLinux = true
37+
private val enableJs = true
3238

3339
fun Project.configureMppDefaults(withJs: Boolean, withLinux: Boolean, withAndroid: Boolean) {
3440
configureMpp(
3541
withJvm = true,
3642
withJs = withJs,
43+
browserTest = false,
3744
withLinux = withLinux,
38-
appleTargets = enabledAppleTargets,
45+
appleTargets = allAppleTargets,
3946
withAndroid = withAndroid,
4047
)
4148
}
@@ -67,7 +74,7 @@ fun Project.configureMpp(
6774
withLinux: Boolean,
6875
withAndroid: Boolean,
6976
appleTargets: Collection<String>,
70-
browserTest: Boolean = false,
77+
browserTest: Boolean,
7178
) {
7279
val kotlinExtension = extensions.findByName("kotlin") as? KotlinMultiplatformExtension
7380
check(kotlinExtension != null) {
@@ -78,7 +85,7 @@ fun Project.configureMpp(
7885
jvm()
7986
}
8087

81-
if (enabledJs && withJs) {
88+
if (enableJs && withJs) {
8289
js(IR) {
8390
if (browserTest) {
8491
browser {
@@ -101,7 +108,7 @@ fun Project.configureMpp(
101108
}
102109
}
103110

104-
if (enabledLinux && withLinux) {
111+
if (enableLinux && withLinux) {
105112
linuxX64("linux")
106113
}
107114

@@ -111,8 +118,14 @@ fun Project.configureMpp(
111118
}
112119
}
113120

114-
createAndConfigureAppleTargets(appleTargets.toSet().intersect(enabledAppleTargets))
121+
appleTargets.toSet().intersect(allAppleTargets).forEach { presetName ->
122+
targetFromPreset(
123+
presets.getByName(presetName),
124+
presetName,
125+
)
126+
}
115127

128+
configureSourceSetGraph()
116129
addTestDependencies()
117130

118131
tasks.withType(KotlinJsIrLink::class.java).configureEach {
@@ -124,31 +137,65 @@ fun Project.configureMpp(
124137
}
125138
}
126139

127-
private fun KotlinMultiplatformExtension.createAndConfigureAppleTargets(presetNames: Collection<String>) {
128-
if (presetNames.isEmpty()) {
129-
return
140+
/**
141+
* Current Graph is something like so
142+
*
143+
* graph TB
144+
* commonMain --> jvmMain
145+
* commonMain --> appleMain
146+
* commonMain --> linuxMain
147+
* commonMain --> jsMain
148+
* appleMain --> macosX64
149+
* appleMain --> macosArm64
150+
* appleMain --> iosArm64
151+
* appleMain --> iosX64
152+
* appleMain --> iosSimulatorArm64
153+
* appleMain --> watchosArm32
154+
* appleMain --> watchosArm64
155+
* appleMain --> watchosSimulatorArm64
156+
* appleMain --> tvosArm64
157+
* appleMain --> tvosX64
158+
* appleMain --> tvosSimulatorArm64
159+
*
160+
*
161+
* commonTest --> kotlinCodegenTest
162+
* commonTest --> jvmJavaCodeGen
163+
* kotlinCodegenTest --> macOsArm64Test
164+
* kotlinCodegenTest --> jvmTest
165+
* kotlinCodegenTest --> jsTest
166+
*
167+
*
168+
*
169+
* classDef kotlinPurple fill:#A97BFF,stroke:#333,stroke-width:2px,color:#333
170+
* classDef javaOrange fill:#b07289,stroke:#333,stroke-width:2px,color:#333
171+
* classDef gray fill:#AAA,stroke:#333,stroke-width:2px,color:#333
172+
* class kotlinCodegenTest gray
173+
* class jvmJavaCodeGen,macOsArm64Test,jvmTest,jsTest kotlinPurple
174+
* class commonTest javaOrange
175+
*/
176+
private fun KotlinMultiplatformExtension.configureSourceSetGraph() {
177+
val hasAppleTarget = targets.any {
178+
it is KotlinNativeTarget && it.konanTarget.family in setOf(Family.IOS, Family.OSX, Family.WATCHOS, Family.TVOS)
130179
}
180+
if (hasAppleTarget) {
181+
val appleMain = sourceSets.create("appleMain")
182+
val appleTest = sourceSets.create("appleTest")
131183

132-
if (System.getProperty("idea.sync.active") != null) {
133-
// Early return. Inside intelliJ, only configure one target
134-
targetFromPreset(presets.getByName(hostTarget), "apple")
135-
return
136-
}
184+
appleMain.dependsOn(sourceSets.getByName("commonMain"))
185+
appleTest.dependsOn(sourceSets.getByName("commonTest"))
137186

138-
val appleMain = sourceSets.create("appleMain")
139-
val appleTest = sourceSets.create("appleTest")
187+
allAppleTargets.forEach {
188+
sourceSets.findByName("${it}Main")?.dependsOn(appleMain)
189+
sourceSets.findByName("${it}Test")?.dependsOn(appleTest)
190+
}
191+
}
140192

141-
appleMain.dependsOn(sourceSets.getByName("commonMain"))
142-
appleTest.dependsOn(sourceSets.getByName("commonTest"))
193+
val kotlinCodegentTest = sourceSets.create("kotlinCodegenTest")
143194

144-
presetNames.forEach { presetName ->
145-
targetFromPreset(
146-
presets.getByName(presetName),
147-
presetName,
148-
)
195+
kotlinCodegentTest.dependsOn(sourceSets.getByName("commonTest"))
149196

150-
sourceSets.getByName("${presetName}Main").dependsOn(appleMain)
151-
sourceSets.getByName("${presetName}Test").dependsOn(appleTest)
197+
targets.forEach {
198+
sourceSets.findByName("${it.name}Test")?.dependsOn(kotlinCodegentTest)
152199
}
153200
}
154201

@@ -159,3 +206,38 @@ private fun KotlinMultiplatformExtension.addTestDependencies() {
159206
}
160207
}
161208
}
209+
210+
fun Project.registerJavaCodegenTestTask() {
211+
val kotlin = kotlinExtension
212+
check(kotlin is KotlinMultiplatformExtension) {
213+
"Only multiplatform projects can register a javaCodegenTest task"
214+
}
215+
val jvmTarget = kotlin.targets.getByName("jvm") as KotlinJvmTarget
216+
jvmTarget.withJava()
217+
218+
val javaCodegenCompilation = jvmTarget.compilations.create("javaCodegen")
219+
javaCodegenCompilation.compileJavaTaskProvider?.configure {
220+
classpath += configurations.getByName("jvmTestCompileClasspath")
221+
}
222+
javaCodegenCompilation.configurations.compileDependencyConfiguration.extendsFrom(configurations.getByName("jvmTestCompileClasspath"))
223+
javaCodegenCompilation.defaultSourceSet.dependsOn(kotlin.sourceSets.getByName("commonTest"))
224+
javaCodegenCompilation.defaultSourceSet.kotlin.apply {
225+
srcDir("src/kotlinCodegenTest/kotlin")
226+
}
227+
228+
val task = tasks.register("javaCodegenTest", Test::class.java) {
229+
description = "Runs Java codegen tests."
230+
group = "verification"
231+
232+
testClassesDirs = javaCodegenCompilation.output.classesDirs
233+
classpath = configurations.getByName("jvmTestRuntimeClasspath") + javaCodegenCompilation.output.classesDirs
234+
235+
useJUnit()
236+
237+
testLogging {
238+
events("passed")
239+
}
240+
}
241+
242+
tasks.named("build").dependsOn(task)
243+
}

build-logic/src/main/kotlin/com/apollographql/apollo3/buildlogic/plugin/TestConventionPlugin.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import commonSetup
44
import configureJavaAndKotlinCompilers
55
import configureMppTestsDefaults
66
import configureTesting
7+
import hostTarget
78
import optIn
89
import org.gradle.api.Action
910
import org.gradle.api.Plugin
@@ -49,7 +50,7 @@ class TestConventionPlugin : Plugin<Project> {
4950
withJs = mppConfiguration.withJs.getOrElse(true),
5051
withJvm = mppConfiguration.withJvm.getOrElse(true),
5152
browserTest = mppConfiguration.browserTest.getOrElse(false),
52-
appleTargets = mppConfiguration.appleTargets.orElse(setOf("macosArm64", "macosX64")).get()
53+
appleTargets = mppConfiguration.appleTargets.getOrElse(setOf(hostTarget))
5354
)
5455
}
5556
}

tests/defer/build.gradle.kts

Lines changed: 27 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ apolloTest {
99
}
1010

1111
kotlin {
12-
/**
13-
* Extra target to test the java codegen
14-
*/
15-
jvm("javaCodegen") {
16-
withJava()
17-
}
18-
1912
sourceSets {
2013
findByName("commonMain")?.apply {
2114
dependencies {
@@ -26,6 +19,7 @@ kotlin {
2619

2720
findByName("commonTest")?.apply {
2821
dependencies {
22+
implementation(libs.apollo.normalizedcache)
2923
implementation(libs.apollo.mockserver)
3024
implementation(libs.apollo.testingsupport)
3125
}
@@ -51,47 +45,44 @@ kotlin {
5145
}
5246
}
5347

54-
apollo {
55-
service("kotlin") {
56-
packageName.set("defer")
57-
generateKotlinModels.set(true)
58-
sourceFolder.set("base")
59-
configureConnection(true)
60-
}
61-
service("java") {
62-
packageName.set("defer")
63-
generateKotlinModels.set(false)
64-
sourceFolder.set("base")
65-
configureConnection(false)
66-
}
67-
service("supergraph") {
68-
packageName.set("supergraph")
69-
sourceFolder.set("supergraph")
70-
this.addTypename.set("ifAbstract")
48+
fun configureApollo(generateKotlinModels: Boolean) {
49+
val extra = if (generateKotlinModels) "kotlin" else "java"
7150

72-
configureConnection(true)
51+
apollo {
52+
service("base-$extra") {
53+
packageName.set("defer")
54+
this.generateKotlinModels.set(generateKotlinModels)
55+
sourceFolder.set("base")
56+
configureConnection(generateKotlinModels)
57+
}
58+
service("supergraph-$extra") {
59+
packageName.set("supergraph")
60+
sourceFolder.set("supergraph")
61+
this.addTypename.set("ifAbstract")
62+
this.generateKotlinModels.set(generateKotlinModels)
63+
configureConnection(generateKotlinModels)
64+
}
7365
}
7466
}
7567

68+
configureApollo(true)
69+
if (System.getProperty("idea.sync.active") == null) {
70+
registerJavaCodegenTestTask()
71+
configureApollo(false)
72+
}
73+
7674
fun com.apollographql.apollo3.gradle.api.Service.configureConnection(generateKotlinModels: Boolean) {
7775
outputDirConnection {
78-
if (System.getProperty("idea.sync.active") == null) {
79-
if (generateKotlinModels) {
80-
connectToKotlinSourceSet("jvmTest")
81-
connectToKotlinSourceSet("jsTest")
82-
connectToKotlinSourceSet("appleTest")
83-
} else {
84-
connectToJavaSourceSet("main")
85-
}
76+
if (generateKotlinModels) {
77+
connectToKotlinSourceSet("kotlinCodegenTest")
8678
} else {
87-
// For autocomplete to work
88-
connectToKotlinSourceSet("commonTest")
79+
connectToJavaSourceSet("javaCodegen")
8980
}
9081
}
9182
}
9283

9384
tasks.withType(AbstractTestTask::class.java) {
94-
// Run the defer with Router tests only from a a specific CI job
85+
// Run the defer with Router tests only from a specific CI job
9586
val runDeferWithRouterTests = System.getenv("COM_APOLLOGRAPHQL_DEFER_WITH_ROUTER_TESTS").toBoolean()
9687
if (runDeferWithRouterTests) {
9788
filter.setIncludePatterns("test.DeferWithRouterTest")
@@ -100,41 +91,3 @@ tasks.withType(AbstractTestTask::class.java) {
10091
}
10192
}
10293

103-
// See https://youtrack.jetbrains.com/issue/KT-56019
104-
val myAttribute = Attribute.of("com.apollographql.test", String::class.java)
105-
106-
configurations.named("jvmApiElements").configure {
107-
attributes {
108-
attribute(myAttribute, "jvm")
109-
}
110-
}
111-
112-
configurations.named("javaCodegenApiElements").configure {
113-
attributes {
114-
attribute(myAttribute, "java")
115-
}
116-
}
117-
118-
configurations.named("jvmRuntimeElements").configure {
119-
attributes {
120-
attribute(myAttribute, "jvm-runtime")
121-
}
122-
}
123-
124-
configurations.named("javaCodegenRuntimeElements").configure {
125-
attributes {
126-
attribute(myAttribute, "java-runtime")
127-
}
128-
}
129-
130-
configurations.named("jvmSourcesElements").configure {
131-
attributes {
132-
attribute(myAttribute, "jvm")
133-
}
134-
}
135-
136-
configurations.named("javaCodegenSourcesElements").configure {
137-
attributes {
138-
attribute(myAttribute, "java")
139-
}
140-
}

0 commit comments

Comments
 (0)