blob: 7154f5e37708f4d4d32cb1eaded9047a20d06668 [file] [log] [blame]
Colin Cross72bb3632017-07-13 16:23:21 -07001// 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 (
18 "android/soong/android"
Colin Cross0f37af02017-09-27 17:42:05 -070019 "android/soong/genrule"
Colin Cross72bb3632017-07-13 16:23:21 -070020 "fmt"
21 "io/ioutil"
22 "os"
23 "path/filepath"
Colin Cross227d4362017-08-30 14:14:52 -070024 "reflect"
Colin Cross72bb3632017-07-13 16:23:21 -070025 "strings"
26 "testing"
27)
28
29var buildDir string
30
31func setUp() {
32 var err error
33 buildDir, err = ioutil.TempDir("", "soong_java_test")
34 if err != nil {
35 panic(err)
36 }
37}
38
39func tearDown() {
40 os.RemoveAll(buildDir)
41}
42
43func TestMain(m *testing.M) {
44 run := func() int {
45 setUp()
46 defer tearDown()
47
48 return m.Run()
49 }
50
51 os.Exit(run())
52}
53
54func testJava(t *testing.T, bp string) *android.TestContext {
Colin Cross4c428df2017-09-15 17:36:05 -070055 config := android.TestArchConfig(buildDir)
Colin Cross72bb3632017-07-13 16:23:21 -070056
Colin Cross4c428df2017-09-15 17:36:05 -070057 ctx := android.NewTestArchContext()
Colin Cross72bb3632017-07-13 16:23:21 -070058 ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
Colin Crossf506d872017-07-19 15:53:04 -070059 ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
Colin Cross2acdae82017-09-15 19:44:24 -070060 ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
Colin Cross74d73e22017-08-02 11:05:49 -070061 ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
Colin Cross89536d42017-07-07 14:35:50 -070062 ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
Colin Cross0f37af02017-09-27 17:42:05 -070063 ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
Colin Cross5ea9bcc2017-07-27 15:41:32 -070064 ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
65 ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
Colin Cross89536d42017-07-07 14:35:50 -070066 ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
Colin Cross72bb3632017-07-13 16:23:21 -070067 ctx.Register()
68
Colin Cross4c428df2017-09-15 17:36:05 -070069 extraModules := []string{
70 "core-oj",
71 "core-libart",
72 "framework",
73 "ext",
74 "okhttp",
Colin Cross2acdae82017-09-15 19:44:24 -070075 "android_stubs_current",
76 "android_system_stubs_current",
77 "android_test_stubs_current",
Colin Cross4c428df2017-09-15 17:36:05 -070078 }
Colin Cross72bb3632017-07-13 16:23:21 -070079
80 for _, extra := range extraModules {
81 bp += fmt.Sprintf(`
82 java_library {
83 name: "%s",
Colin Cross0a6e0072017-08-30 14:24:55 -070084 srcs: ["a.java"],
Colin Cross76b5f0c2017-08-29 16:02:06 -070085 no_standard_libs: true,
Colin Cross72bb3632017-07-13 16:23:21 -070086 }
87 `, extra)
88 }
89
90 ctx.MockFileSystem(map[string][]byte{
Colin Crossfc3674a2017-09-18 17:41:52 -070091 "Android.bp": []byte(bp),
92 "a.java": nil,
93 "b.java": nil,
94 "c.java": nil,
95 "a.jar": nil,
96 "b.jar": nil,
Colin Cross0f37af02017-09-27 17:42:05 -070097 "res/a": nil,
98 "res/b": nil,
Colin Crossfc3674a2017-09-18 17:41:52 -070099 "prebuilts/sdk/14/android.jar": nil,
100 "prebuilts/sdk/14/framework.aidl": nil,
Colin Cross72bb3632017-07-13 16:23:21 -0700101 })
102
103 _, errs := ctx.ParseBlueprintsFiles("Android.bp")
104 fail(t, errs)
105 _, errs = ctx.PrepareBuildActions(config)
106 fail(t, errs)
107
108 return ctx
109}
110
Colin Cross2acdae82017-09-15 19:44:24 -0700111func moduleToPath(name string) string {
112 switch {
113 case name == `""`:
114 return name
Colin Crossfc3674a2017-09-18 17:41:52 -0700115 case strings.HasSuffix(name, ".jar"):
116 return name
Colin Cross2acdae82017-09-15 19:44:24 -0700117 default:
Colin Cross8649b262017-09-27 18:03:17 -0700118 return filepath.Join(buildDir, ".intermediates", name, "android_common", "classes-compiled.jar")
Colin Cross2acdae82017-09-15 19:44:24 -0700119 }
120}
121
Colin Cross72bb3632017-07-13 16:23:21 -0700122func TestSimple(t *testing.T) {
123 ctx := testJava(t, `
124 java_library {
125 name: "foo",
126 srcs: ["a.java"],
Colin Crosse8dc34a2017-07-19 11:22:16 -0700127 libs: ["bar"],
128 static_libs: ["baz"],
Colin Cross72bb3632017-07-13 16:23:21 -0700129 }
130
131 java_library {
132 name: "bar",
133 srcs: ["b.java"],
134 }
135
136 java_library {
137 name: "baz",
138 srcs: ["c.java"],
139 }
140 `)
141
Colin Cross4c428df2017-09-15 17:36:05 -0700142 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
143 combineJar := ctx.ModuleForTests("foo", "android_common").Rule("combineJar")
Colin Cross72bb3632017-07-13 16:23:21 -0700144
145 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
146 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
147 }
148
Colin Cross8649b262017-09-27 18:03:17 -0700149 bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-compiled.jar")
150 baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-compiled.jar")
Colin Cross0a6e0072017-08-30 14:24:55 -0700151
Colin Cross72bb3632017-07-13 16:23:21 -0700152 if !strings.Contains(javac.Args["classpath"], bar) {
153 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
154 }
155
Colin Cross0a6e0072017-08-30 14:24:55 -0700156 if !strings.Contains(javac.Args["classpath"], baz) {
157 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], baz)
158 }
159
160 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
161 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
Colin Cross72bb3632017-07-13 16:23:21 -0700162 }
163}
164
Colin Cross2acdae82017-09-15 19:44:24 -0700165var classpathTestcases = []struct {
166 name string
167 host android.OsClass
168 properties string
169 bootclasspath []string
170 classpath []string
171}{
172 {
173 name: "default",
174 bootclasspath: []string{"core-oj", "core-libart"},
175 classpath: []string{"ext", "framework", "okhttp"},
176 },
177 {
178 name: "blank sdk version",
179 properties: `sdk_version: "",`,
180 bootclasspath: []string{"core-oj", "core-libart"},
181 classpath: []string{"ext", "framework", "okhttp"},
182 },
183 {
Colin Cross4c428df2017-09-15 17:36:05 -0700184
Colin Cross2acdae82017-09-15 19:44:24 -0700185 name: "sdk v14",
186 properties: `sdk_version: "14",`,
Colin Crossfc3674a2017-09-18 17:41:52 -0700187 bootclasspath: []string{`""`},
188 classpath: []string{"prebuilts/sdk/14/android.jar"},
Colin Cross2acdae82017-09-15 19:44:24 -0700189 },
190 {
Colin Cross72bb3632017-07-13 16:23:21 -0700191
Colin Cross2acdae82017-09-15 19:44:24 -0700192 name: "current",
193 properties: `sdk_version: "current",`,
194 bootclasspath: []string{"android_stubs_current"},
195 classpath: []string{},
196 },
197 {
Colin Cross72bb3632017-07-13 16:23:21 -0700198
Colin Cross2acdae82017-09-15 19:44:24 -0700199 name: "system_current",
200 properties: `sdk_version: "system_current",`,
201 bootclasspath: []string{"android_system_stubs_current"},
202 classpath: []string{},
203 },
204 {
Colin Cross72bb3632017-07-13 16:23:21 -0700205
Colin Cross2acdae82017-09-15 19:44:24 -0700206 name: "test_current",
207 properties: `sdk_version: "test_current",`,
208 bootclasspath: []string{"android_test_stubs_current"},
209 classpath: []string{},
210 },
211 {
Colin Cross72bb3632017-07-13 16:23:21 -0700212
Colin Cross2acdae82017-09-15 19:44:24 -0700213 name: "nostdlib",
214 properties: `no_standard_libs: true`,
215 bootclasspath: []string{`""`},
216 classpath: []string{},
217 },
218 {
Colin Cross72bb3632017-07-13 16:23:21 -0700219
Colin Cross2acdae82017-09-15 19:44:24 -0700220 name: "host default",
221 host: android.Host,
222 properties: ``,
223 classpath: []string{},
224 },
225 {
226 name: "host nostdlib",
227 host: android.Host,
228 properties: `no_standard_libs: true`,
229 classpath: []string{},
230 },
231}
Colin Cross72bb3632017-07-13 16:23:21 -0700232
Colin Cross2acdae82017-09-15 19:44:24 -0700233func TestClasspath(t *testing.T) {
234 for _, testcase := range classpathTestcases {
235 t.Run(testcase.name, func(t *testing.T) {
236 hostExtra := ""
237 if testcase.host == android.Host {
238 hostExtra = "_host"
239 }
240 ctx := testJava(t, `
241 java_library`+hostExtra+` {
242 name: "foo",
243 srcs: ["a.java"],
244 `+testcase.properties+`
245 }
246 `)
Colin Cross72bb3632017-07-13 16:23:21 -0700247
Colin Cross2acdae82017-09-15 19:44:24 -0700248 convertModulesToPaths := func(cp []string) []string {
249 ret := make([]string, len(cp))
250 for i, e := range cp {
251 ret[i] = moduleToPath(e)
252 }
253 return ret
254 }
Colin Cross72bb3632017-07-13 16:23:21 -0700255
Colin Cross2acdae82017-09-15 19:44:24 -0700256 bootclasspath := convertModulesToPaths(testcase.bootclasspath)
257 classpath := convertModulesToPaths(testcase.classpath)
Colin Cross72bb3632017-07-13 16:23:21 -0700258
Colin Cross2acdae82017-09-15 19:44:24 -0700259 variant := "android_common"
260 if testcase.host == android.Host {
261 variant = android.BuildOs.String() + "_common"
262 }
263 javac := ctx.ModuleForTests("foo", variant).Rule("javac")
264
Colin Cross72bb3632017-07-13 16:23:21 -0700265 got := strings.TrimPrefix(javac.Args["bootClasspath"], "-bootclasspath ")
Colin Cross2acdae82017-09-15 19:44:24 -0700266 bc := strings.Join(bootclasspath, ":")
267 if got != bc {
268 t.Errorf("bootclasspath expected %q != got %q", bc, got)
Colin Cross72bb3632017-07-13 16:23:21 -0700269 }
Colin Cross72bb3632017-07-13 16:23:21 -0700270
Colin Cross2acdae82017-09-15 19:44:24 -0700271 got = strings.TrimPrefix(javac.Args["classpath"], "-classpath ")
272 c := strings.Join(classpath, ":")
273 if got != c {
274 t.Errorf("classpath expected %q != got %q", c, got)
275 }
276
277 var deps []string
278 if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
279 deps = append(deps, bootclasspath...)
280 }
281 deps = append(deps, classpath...)
282
283 if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
284 t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
285 }
286 })
Colin Cross72bb3632017-07-13 16:23:21 -0700287 }
288
Colin Cross72bb3632017-07-13 16:23:21 -0700289}
290
291func TestPrebuilts(t *testing.T) {
292 ctx := testJava(t, `
293 java_library {
294 name: "foo",
295 srcs: ["a.java"],
Colin Crosse8dc34a2017-07-19 11:22:16 -0700296 libs: ["bar"],
297 static_libs: ["baz"],
Colin Cross72bb3632017-07-13 16:23:21 -0700298 }
299
Colin Cross74d73e22017-08-02 11:05:49 -0700300 java_import {
Colin Cross72bb3632017-07-13 16:23:21 -0700301 name: "bar",
Colin Cross74d73e22017-08-02 11:05:49 -0700302 jars: ["a.jar"],
Colin Cross72bb3632017-07-13 16:23:21 -0700303 }
304
Colin Cross74d73e22017-08-02 11:05:49 -0700305 java_import {
Colin Cross72bb3632017-07-13 16:23:21 -0700306 name: "baz",
Colin Cross74d73e22017-08-02 11:05:49 -0700307 jars: ["b.jar"],
Colin Cross72bb3632017-07-13 16:23:21 -0700308 }
309 `)
310
Colin Cross4c428df2017-09-15 17:36:05 -0700311 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
312 combineJar := ctx.ModuleForTests("foo", "android_common").Rule("combineJar")
Colin Cross72bb3632017-07-13 16:23:21 -0700313
314 bar := "a.jar"
315 if !strings.Contains(javac.Args["classpath"], bar) {
316 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
317 }
318
Colin Cross0a6e0072017-08-30 14:24:55 -0700319 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != "b.jar" {
320 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, "b.jar")
Colin Cross72bb3632017-07-13 16:23:21 -0700321 }
322}
323
Colin Cross89536d42017-07-07 14:35:50 -0700324func TestDefaults(t *testing.T) {
325 ctx := testJava(t, `
326 java_defaults {
327 name: "defaults",
328 srcs: ["a.java"],
329 libs: ["bar"],
330 static_libs: ["baz"],
331 }
332
333 java_library {
334 name: "foo",
335 defaults: ["defaults"],
336 }
337
338 java_library {
339 name: "bar",
340 srcs: ["b.java"],
341 }
342
343 java_library {
344 name: "baz",
345 srcs: ["c.java"],
346 }
347 `)
348
Colin Cross4c428df2017-09-15 17:36:05 -0700349 javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
350 combineJar := ctx.ModuleForTests("foo", "android_common").Rule("combineJar")
Colin Cross89536d42017-07-07 14:35:50 -0700351
352 if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
353 t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
354 }
355
Colin Cross8649b262017-09-27 18:03:17 -0700356 bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-compiled.jar")
Colin Cross89536d42017-07-07 14:35:50 -0700357 if !strings.Contains(javac.Args["classpath"], bar) {
358 t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
359 }
360
Colin Cross8649b262017-09-27 18:03:17 -0700361 baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-compiled.jar")
Colin Cross0a6e0072017-08-30 14:24:55 -0700362 if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
363 t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
Colin Cross89536d42017-07-07 14:35:50 -0700364 }
365}
366
Colin Cross0f37af02017-09-27 17:42:05 -0700367func TestResources(t *testing.T) {
368 var table = []struct {
369 name string
370 prop string
371 extra string
372 args string
373 }{
374 {
375 // Test that a module with java_resource_dirs includes a file list file
376 name: "resource dirs",
377 prop: `java_resource_dirs: ["res"]`,
378 args: "-C res -l ",
379 },
380 {
381 // Test that a module with java_resources includes the files
382 name: "resource files",
383 prop: `java_resources: ["res/a", "res/b"]`,
384 args: "-C . -f res/a -C . -f res/b",
385 },
386 {
387 // Test that a module with a filegroup in java_resources includes the files with the
388 // path prefix
389 name: "resource filegroup",
390 prop: `java_resources: [":foo-res"]`,
391 extra: `
392 filegroup {
393 name: "foo-res",
394 path: "res",
395 srcs: ["res/a", "res/b"],
396 }`,
397 args: "-C res -f res/a -C res -f res/b",
398 },
399 {
400 // Test that a module with "include_srcs: true" includes its source files in the resources jar
401 name: "include sources",
402 prop: `include_srcs: true`,
403 args: "-C . -f a.java -C . -f b.java -C . -f c.java",
404 },
405 }
406
407 for _, test := range table {
408 t.Run(test.name, func(t *testing.T) {
409 ctx := testJava(t, `
410 java_library {
411 name: "foo",
412 srcs: [
413 "a.java",
414 "b.java",
415 "c.java",
416 ],
417 `+test.prop+`,
418 }
419 `+test.extra)
420
421 foo := ctx.ModuleForTests("foo", "android_common").Output("classes.jar")
422 fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar")
423
424 if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
425 t.Errorf("foo combined jars %v does not contain %q",
426 foo.Inputs.Strings(), fooRes.Output.String())
427 }
428
429 if !strings.Contains(fooRes.Args["jarArgs"], test.args) {
430 t.Errorf("foo resource jar args %q does not contain %q",
431 fooRes.Args["jarArgs"], test.args)
432 }
433 })
434 }
435}
436
Colin Cross72bb3632017-07-13 16:23:21 -0700437func fail(t *testing.T, errs []error) {
438 if len(errs) > 0 {
439 for _, err := range errs {
440 t.Error(err)
441 }
442 t.FailNow()
443 }
444}