blob: d51bc041dbadeed481f275186adf28259883f207 [file] [log] [blame]
Colin Cross21fc9bb2019-01-18 15:05:09 -08001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
Colin Crossafbb1732019-01-17 15:42:52 -080018 "strconv"
Colin Cross21fc9bb2019-01-18 15:05:09 -080019 "strings"
20 "testing"
Colin Cross0c66bc62021-07-20 09:47:41 -070021
22 "android/soong/android"
Colin Cross21fc9bb2019-01-18 15:05:09 -080023)
24
25func TestKotlin(t *testing.T) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -070026 ctx, _ := testJava(t, `
Colin Cross21fc9bb2019-01-18 15:05:09 -080027 java_library {
28 name: "foo",
29 srcs: ["a.java", "b.kt"],
30 }
31
32 java_library {
33 name: "bar",
34 srcs: ["b.kt"],
35 libs: ["foo"],
36 static_libs: ["baz"],
37 }
38
39 java_library {
40 name: "baz",
41 srcs: ["c.java"],
42 }
43 `)
44
45 fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
46 fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
47 fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
48
49 if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
50 fooKotlinc.Inputs[1].String() != "b.kt" {
51 t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
52 }
53
54 if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
55 t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
56 }
57
58 if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
59 t.Errorf("foo classpath %v does not contain %q",
60 fooJavac.Args["classpath"], fooKotlinc.Output.String())
61 }
62
63 if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
64 t.Errorf("foo jar inputs %v does not contain %q",
65 fooJar.Inputs.Strings(), fooKotlinc.Output.String())
66 }
67
68 fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
69 bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
70 barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
71
72 if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
73 t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
74 }
75
76 if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
77 t.Errorf(`expected %q in bar implicits %v`,
78 fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
79 }
80
81 if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
82 t.Errorf(`expected %q in bar implicits %v`,
83 bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
84 }
85}
Colin Crossafbb1732019-01-17 15:42:52 -080086
87func TestKapt(t *testing.T) {
Colin Cross748b2d82020-11-19 13:52:06 -080088 bp := `
Colin Crossafbb1732019-01-17 15:42:52 -080089 java_library {
90 name: "foo",
91 srcs: ["a.java", "b.kt"],
Colin Cross5a116862020-04-22 11:44:34 -070092 plugins: ["bar", "baz"],
Colin Cross748b2d82020-11-19 13:52:06 -080093 errorprone: {
94 extra_check_modules: ["my_check"],
95 },
Colin Crossafbb1732019-01-17 15:42:52 -080096 }
97
Colin Crossbe9cdb82019-01-21 21:37:16 -080098 java_plugin {
Colin Crossafbb1732019-01-17 15:42:52 -080099 name: "bar",
Colin Cross3a3e94c2019-01-23 15:39:50 -0800100 processor_class: "com.bar",
101 srcs: ["b.java"],
Colin Crossafbb1732019-01-17 15:42:52 -0800102 }
Colin Cross5a116862020-04-22 11:44:34 -0700103
104 java_plugin {
105 name: "baz",
106 processor_class: "com.baz",
107 srcs: ["b.java"],
108 }
Colin Crossafbb1732019-01-17 15:42:52 -0800109
Colin Cross748b2d82020-11-19 13:52:06 -0800110 java_plugin {
111 name: "my_check",
112 srcs: ["b.java"],
113 }
114 `
115 t.Run("", func(t *testing.T) {
116 ctx, _ := testJava(t, bp)
Colin Cross3a3e94c2019-01-23 15:39:50 -0800117
Colin Cross0c66bc62021-07-20 09:47:41 -0700118 buildOS := ctx.Config().BuildOS.String()
Colin Crossafbb1732019-01-17 15:42:52 -0800119
Colin Crossf61766e2022-03-16 18:06:48 -0700120 foo := ctx.ModuleForTests("foo", "android_common")
121 kaptStubs := foo.Rule("kapt")
122 turbineApt := foo.Description("turbine apt")
123 kotlinc := foo.Rule("kotlinc")
124 javac := foo.Rule("javac")
Colin Cross3a3e94c2019-01-23 15:39:50 -0800125
Colin Cross748b2d82020-11-19 13:52:06 -0800126 bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
127 baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
Colin Crossafbb1732019-01-17 15:42:52 -0800128
Colin Cross748b2d82020-11-19 13:52:06 -0800129 // Test that the kotlin and java sources are passed to kapt and kotlinc
Colin Crossf61766e2022-03-16 18:06:48 -0700130 if len(kaptStubs.Inputs) != 2 || kaptStubs.Inputs[0].String() != "a.java" || kaptStubs.Inputs[1].String() != "b.kt" {
131 t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kaptStubs.Inputs)
Colin Cross748b2d82020-11-19 13:52:06 -0800132 }
133 if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
134 t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
135 }
Colin Crossafbb1732019-01-17 15:42:52 -0800136
Colin Crossf61766e2022-03-16 18:06:48 -0700137 // Test that only the java sources are passed to turbine-apt and javac
138 if len(turbineApt.Inputs) != 1 || turbineApt.Inputs[0].String() != "a.java" {
139 t.Errorf(`foo turbine apt inputs %v != ["a.java"]`, turbineApt.Inputs)
140 }
Colin Cross748b2d82020-11-19 13:52:06 -0800141 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
142 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
143 }
Colin Crossafbb1732019-01-17 15:42:52 -0800144
Colin Crossf61766e2022-03-16 18:06:48 -0700145 // Test that the kapt stubs jar is a dependency of turbine-apt
146 if !inList(kaptStubs.Output.String(), turbineApt.Implicits.Strings()) {
147 t.Errorf("expected %q in turbine-apt implicits %v", kaptStubs.Output.String(), kotlinc.Implicits.Strings())
Colin Cross748b2d82020-11-19 13:52:06 -0800148 }
Colin Cross3a3e94c2019-01-23 15:39:50 -0800149
Colin Crossf61766e2022-03-16 18:06:48 -0700150 // Test that the turbine-apt srcjar is a dependency of kotlinc and javac rules
151 if !inList(turbineApt.Output.String(), kotlinc.Implicits.Strings()) {
152 t.Errorf("expected %q in kotlinc implicits %v", turbineApt.Output.String(), kotlinc.Implicits.Strings())
Colin Cross748b2d82020-11-19 13:52:06 -0800153 }
Colin Crossf61766e2022-03-16 18:06:48 -0700154 if !inList(turbineApt.Output.String(), javac.Implicits.Strings()) {
155 t.Errorf("expected %q in javac implicits %v", turbineApt.Output.String(), javac.Implicits.Strings())
156 }
157
158 // Test that the turbine-apt srcjar is extracted by the kotlinc and javac rules
159 if kotlinc.Args["srcJars"] != turbineApt.Output.String() {
160 t.Errorf("expected %q in kotlinc srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
161 }
162 if javac.Args["srcJars"] != turbineApt.Output.String() {
163 t.Errorf("expected %q in javac srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
Colin Cross748b2d82020-11-19 13:52:06 -0800164 }
Colin Cross3a3e94c2019-01-23 15:39:50 -0800165
Colin Cross748b2d82020-11-19 13:52:06 -0800166 // Test that the processors are passed to kapt
167 expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
168 " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
Colin Crossf61766e2022-03-16 18:06:48 -0700169 if kaptStubs.Args["kaptProcessorPath"] != expectedProcessorPath {
170 t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kaptStubs.Args["kaptProcessorPath"])
Colin Cross748b2d82020-11-19 13:52:06 -0800171 }
172 expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
Colin Crossf61766e2022-03-16 18:06:48 -0700173 if kaptStubs.Args["kaptProcessor"] != expectedProcessor {
174 t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kaptStubs.Args["kaptProcessor"])
175 }
176
177 // Test that the processors are passed to turbine-apt
178 expectedProcessorPath = "--processorpath " + bar + " " + baz
179 if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessorPath) {
180 t.Errorf("expected turbine-apt processorpath %q, got %q", expectedProcessorPath, turbineApt.Args["turbineFlags"])
181 }
182 expectedProcessor = "--processors com.bar com.baz"
183 if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessor) {
184 t.Errorf("expected turbine-apt processor %q, got %q", expectedProcessor, turbineApt.Args["turbineFlags"])
Colin Cross748b2d82020-11-19 13:52:06 -0800185 }
186
187 // Test that the processors are not passed to javac
188 if javac.Args["processorpath"] != "" {
189 t.Errorf("expected processorPath '', got %q", javac.Args["processorpath"])
190 }
191 if javac.Args["processor"] != "-proc:none" {
192 t.Errorf("expected processor '-proc:none', got %q", javac.Args["processor"])
193 }
194 })
195
196 t.Run("errorprone", func(t *testing.T) {
197 env := map[string]string{
198 "RUN_ERROR_PRONE": "true",
199 }
Paul Duffinb148a492021-03-22 17:31:52 +0000200
201 result := android.GroupFixturePreparers(
202 PrepareForTestWithJavaDefaultModules,
203 android.FixtureMergeEnv(env),
204 ).RunTestWithBp(t, bp)
Colin Cross748b2d82020-11-19 13:52:06 -0800205
Colin Cross0c66bc62021-07-20 09:47:41 -0700206 buildOS := result.Config.BuildOS.String()
Colin Cross748b2d82020-11-19 13:52:06 -0800207
Paul Duffinb148a492021-03-22 17:31:52 +0000208 kapt := result.ModuleForTests("foo", "android_common").Rule("kapt")
Paul Duffinb148a492021-03-22 17:31:52 +0000209 javac := result.ModuleForTests("foo", "android_common").Description("javac")
210 errorprone := result.ModuleForTests("foo", "android_common").Description("errorprone")
Colin Cross748b2d82020-11-19 13:52:06 -0800211
Paul Duffinb148a492021-03-22 17:31:52 +0000212 bar := result.ModuleForTests("bar", buildOS+"_common").Description("javac").Output.String()
213 baz := result.ModuleForTests("baz", buildOS+"_common").Description("javac").Output.String()
214 myCheck := result.ModuleForTests("my_check", buildOS+"_common").Description("javac").Output.String()
Colin Cross748b2d82020-11-19 13:52:06 -0800215
216 // Test that the errorprone plugins are not passed to kapt
217 expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
218 " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
219 if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
220 t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
221 }
222 expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
223 if kapt.Args["kaptProcessor"] != expectedProcessor {
224 t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
225 }
226
227 // Test that the errorprone plugins are not passed to javac
228 if javac.Args["processorpath"] != "" {
229 t.Errorf("expected processorPath '', got %q", javac.Args["processorpath"])
230 }
231 if javac.Args["processor"] != "-proc:none" {
232 t.Errorf("expected processor '-proc:none', got %q", javac.Args["processor"])
233 }
234
235 // Test that the errorprone plugins are passed to errorprone
236 expectedProcessorPath = "-processorpath " + myCheck
237 if errorprone.Args["processorpath"] != expectedProcessorPath {
238 t.Errorf("expected processorpath %q, got %q", expectedProcessorPath, errorprone.Args["processorpath"])
239 }
240 if errorprone.Args["processor"] != "-proc:none" {
241 t.Errorf("expected processor '-proc:none', got %q", errorprone.Args["processor"])
242 }
243 })
Colin Crossafbb1732019-01-17 15:42:52 -0800244}
245
246func TestKaptEncodeFlags(t *testing.T) {
247 // Compares the kaptEncodeFlags against the results of the example implementation at
248 // https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
249 tests := []struct {
250 in [][2]string
251 out string
252 }{
253 {
254 // empty input
255 in: [][2]string{},
256 out: "rO0ABXcEAAAAAA==",
257 },
258 {
259 // common input
260 in: [][2]string{
261 {"-source", "1.8"},
262 {"-target", "1.8"},
263 },
264 out: "rO0ABXcgAAAAAgAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjg=",
265 },
266 {
267 // input that serializes to a 255 byte block
268 in: [][2]string{
269 {"-source", "1.8"},
270 {"-target", "1.8"},
271 {"a", strings.Repeat("b", 218)},
272 },
273 out: "rO0ABXf/AAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA2mJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi",
274 },
275 {
276 // input that serializes to a 256 byte block
277 in: [][2]string{
278 {"-source", "1.8"},
279 {"-target", "1.8"},
280 {"a", strings.Repeat("b", 219)},
281 },
282 out: "rO0ABXoAAAEAAAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA22JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYg==",
283 },
284 {
285 // input that serializes to a 257 byte block
286 in: [][2]string{
287 {"-source", "1.8"},
288 {"-target", "1.8"},
289 {"a", strings.Repeat("b", 220)},
290 },
291 out: "rO0ABXoAAAEBAAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA3GJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI=",
292 },
293 }
294
295 for i, test := range tests {
296 t.Run(strconv.Itoa(i), func(t *testing.T) {
297 got := kaptEncodeFlags(test.in)
298 if got != test.out {
299 t.Errorf("\nwant %q\n got %q", test.out, got)
300 }
301 })
302 }
303}
Colin Crossa1ff7c62021-09-17 14:11:52 -0700304
305func TestKotlinCompose(t *testing.T) {
306 result := android.GroupFixturePreparers(
307 PrepareForTestWithJavaDefaultModules,
308 ).RunTestWithBp(t, `
309 java_library {
310 name: "androidx.compose.runtime_runtime",
311 }
312
313 java_library_host {
314 name: "androidx.compose.compiler_compiler-hosted",
315 }
316
317 java_library {
318 name: "withcompose",
319 srcs: ["a.kt"],
320 static_libs: ["androidx.compose.runtime_runtime"],
321 }
322
323 java_library {
324 name: "nocompose",
325 srcs: ["a.kt"],
326 }
327 `)
328
329 buildOS := result.Config.BuildOS.String()
330
331 composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted", buildOS+"_common").Rule("combineJar").Output
332 withCompose := result.ModuleForTests("withcompose", "android_common")
333 noCompose := result.ModuleForTests("nocompose", "android_common")
334
335 android.AssertStringListContains(t, "missing compose compiler dependency",
336 withCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
337
338 android.AssertStringDoesContain(t, "missing compose compiler plugin",
339 withCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
340
341 android.AssertStringListDoesNotContain(t, "unexpected compose compiler dependency",
342 noCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
343
344 android.AssertStringDoesNotContain(t, "unexpected compose compiler plugin",
345 noCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
346}