blob: 93d20d09ad3a919805e2d8331eafc534f052b9f0 [file] [log] [blame]
Colin Cross3bc7ffa2017-11-22 16:19:37 -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 (
18 "android/soong/android"
Colin Crossd09b0b62018-04-18 11:06:47 -070019 "fmt"
Colin Crossa4f08812018-10-02 22:03:40 -070020 "path/filepath"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080021 "reflect"
Colin Crossb69301e2017-12-01 10:48:26 -080022 "sort"
Colin Crossd09b0b62018-04-18 11:06:47 -070023 "strings"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080024 "testing"
25)
26
27var (
28 resourceFiles = []string{
29 "res/layout/layout.xml",
30 "res/values/strings.xml",
31 "res/values-en-rUS/strings.xml",
32 }
33
34 compiledResourceFiles = []string{
35 "aapt2/res/layout_layout.xml.flat",
36 "aapt2/res/values_strings.arsc.flat",
37 "aapt2/res/values-en-rUS_strings.arsc.flat",
38 }
39)
40
Colin Cross527012a2017-11-30 22:56:16 -080041func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
42 appFS := map[string][]byte{}
43 for k, v := range fs {
44 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080045 }
46
Colin Cross527012a2017-11-30 22:56:16 -080047 for _, file := range resourceFiles {
48 appFS[file] = nil
49 }
50
51 return testContext(config, bp, appFS)
52}
53
54func testApp(t *testing.T, bp string) *android.TestContext {
55 config := testConfig(nil)
56
57 ctx := testAppContext(config, bp, nil)
58
59 run(t, ctx, config)
60
61 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080062}
63
64func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070065 for _, moduleType := range []string{"android_app", "android_library"} {
66 t.Run(moduleType, func(t *testing.T) {
67 ctx := testApp(t, moduleType+` {
68 name: "foo",
69 srcs: ["a.java"],
70 }
71 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080072
Colin Crossa97c5d32018-03-28 14:58:31 -070073 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080074
Colin Cross31656952018-05-24 16:11:20 -070075 var expectedLinkImplicits []string
76
77 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
78 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080079
Colin Crossa97c5d32018-03-28 14:58:31 -070080 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
81 expectedLinkImplicits = append(expectedLinkImplicits,
82 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080083
Colin Crossa97c5d32018-03-28 14:58:31 -070084 // Test the mapping from input files to compiled output file names
85 compile := foo.Output(compiledResourceFiles[0])
86 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
87 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
88 resourceFiles, compile.Inputs.Strings())
89 }
Colin Crossb69301e2017-12-01 10:48:26 -080090
Colin Crossa97c5d32018-03-28 14:58:31 -070091 compiledResourceOutputs := compile.Outputs.Strings()
92 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080093
Colin Crossa97c5d32018-03-28 14:58:31 -070094 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080095
Colin Crossa97c5d32018-03-28 14:58:31 -070096 list := foo.Output("aapt2/res.list")
97 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080098
Colin Crossa97c5d32018-03-28 14:58:31 -070099 // Check that the link rule uses
100 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
101 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
102 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
103 expectedLinkImplicits, res.Implicits.Strings())
104 }
105 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800106 }
107}
Colin Cross890ff552017-11-30 20:13:19 -0800108
Colin Cross890ff552017-11-30 20:13:19 -0800109func TestEnforceRRO(t *testing.T) {
Colin Cross5c4791c2019-02-01 11:44:44 -0800110 testCases := []struct {
111 name string
112 enforceRROTargets []string
113 enforceRROExcludedOverlays []string
114 overlayFiles map[string][]string
115 rroDirs map[string][]string
116 }{
117 {
118 name: "no RRO",
119 enforceRROTargets: nil,
120 enforceRROExcludedOverlays: nil,
121 overlayFiles: map[string][]string{
122 "foo": []string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800123 buildDir + "/.intermediates/lib/android_common/package-res.apk",
124 "foo/res/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800125 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
126 "device/vendor/blah/overlay/foo/res/values/strings.xml",
127 },
128 "bar": []string{
129 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
130 "device/vendor/blah/overlay/bar/res/values/strings.xml",
131 },
132 },
133 rroDirs: map[string][]string{
134 "foo": nil,
135 "bar": nil,
136 },
137 },
138 {
139 name: "enforce RRO on foo",
140 enforceRROTargets: []string{"foo"},
141 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
142 overlayFiles: map[string][]string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800143 "foo": []string{
144 buildDir + "/.intermediates/lib/android_common/package-res.apk",
145 "foo/res/res/values/strings.xml",
146 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
147 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800148 "bar": []string{
149 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
150 "device/vendor/blah/overlay/bar/res/values/strings.xml",
151 },
152 },
Colin Crossc1c37552019-01-31 11:42:41 -0800153
Colin Cross5c4791c2019-02-01 11:44:44 -0800154 rroDirs: map[string][]string{
Colin Crossc1c37552019-01-31 11:42:41 -0800155 "foo": []string{
156 "device/vendor/blah/overlay/foo/res",
157 // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
158 // "device/vendor/blah/overlay/lib/res",
159 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800160 "bar": nil,
161 },
162 },
163 {
164 name: "enforce RRO on all",
165 enforceRROTargets: []string{"*"},
166 enforceRROExcludedOverlays: []string{
167 // Excluding specific apps/res directories also allowed.
168 "device/vendor/blah/static_overlay/foo",
169 "device/vendor/blah/static_overlay/bar/res",
170 },
171 overlayFiles: map[string][]string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800172 "foo": []string{
173 buildDir + "/.intermediates/lib/android_common/package-res.apk",
174 "foo/res/res/values/strings.xml",
175 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
176 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800177 "bar": []string{"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
178 },
179 rroDirs: map[string][]string{
Colin Crossc1c37552019-01-31 11:42:41 -0800180 "foo": []string{
181 "device/vendor/blah/overlay/foo/res",
182 "device/vendor/blah/overlay/lib/res",
183 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800184 "bar": []string{"device/vendor/blah/overlay/bar/res"},
185 },
186 },
187 }
188
Colin Cross890ff552017-11-30 20:13:19 -0800189 resourceOverlays := []string{
190 "device/vendor/blah/overlay",
191 "device/vendor/blah/overlay2",
192 "device/vendor/blah/static_overlay",
193 }
194
195 fs := map[string][]byte{
196 "foo/res/res/values/strings.xml": nil,
197 "bar/res/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800198 "lib/res/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800199 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
200 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800201 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800202 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
203 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
204 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
205 }
206
207 bp := `
208 android_app {
209 name: "foo",
210 resource_dirs: ["foo/res"],
Colin Cross6ed7dea2019-01-31 14:44:30 -0800211 static_libs: ["lib"],
Colin Cross890ff552017-11-30 20:13:19 -0800212 }
213
214 android_app {
215 name: "bar",
216 resource_dirs: ["bar/res"],
217 }
Colin Cross6ed7dea2019-01-31 14:44:30 -0800218
219 android_library {
220 name: "lib",
221 resource_dirs: ["lib/res"],
222 }
Colin Cross890ff552017-11-30 20:13:19 -0800223 `
224
Colin Cross5c4791c2019-02-01 11:44:44 -0800225 for _, testCase := range testCases {
Colin Cross890ff552017-11-30 20:13:19 -0800226 t.Run(testCase.name, func(t *testing.T) {
227 config := testConfig(nil)
Colin Crossa74ca042019-01-31 14:31:51 -0800228 config.TestProductVariables.ResourceOverlays = resourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800229 if testCase.enforceRROTargets != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800230 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800231 }
232 if testCase.enforceRROExcludedOverlays != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800233 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800234 }
235
236 ctx := testAppContext(config, bp, fs)
237 run(t, ctx, config)
238
239 getOverlays := func(moduleName string) ([]string, []string) {
240 module := ctx.ModuleForTests(moduleName, "android_common")
Anton Hansson94c93f32019-01-30 16:03:37 +0000241 overlayFile := module.MaybeOutput("aapt2/overlay.list")
Colin Cross890ff552017-11-30 20:13:19 -0800242 var overlayFiles []string
Anton Hansson94c93f32019-01-30 16:03:37 +0000243 if overlayFile.Rule != nil {
244 for _, o := range overlayFile.Inputs.Strings() {
Colin Cross6ed7dea2019-01-31 14:44:30 -0800245 overlayOutput := module.MaybeOutput(o)
246 if overlayOutput.Rule != nil {
247 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
248 // verify the inputs to the .arsc.flat rule.
249 overlayFiles = append(overlayFiles, overlayOutput.Inputs.Strings()...)
250 } else {
251 // Otherwise, verify the full path to the output of the other module
252 overlayFiles = append(overlayFiles, o)
253 }
Anton Hansson94c93f32019-01-30 16:03:37 +0000254 }
Colin Cross890ff552017-11-30 20:13:19 -0800255 }
256
257 rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
258
259 return overlayFiles, rroDirs
260 }
261
Anton Hansson0375a4f2019-01-24 14:39:19 +0000262 apps := []string{"foo", "bar"}
263 for _, app := range apps {
264 overlayFiles, rroDirs := getOverlays(app)
Colin Cross890ff552017-11-30 20:13:19 -0800265
Anton Hansson0375a4f2019-01-24 14:39:19 +0000266 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[app]) {
267 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
268 app, testCase.overlayFiles[app], overlayFiles)
269 }
270 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[app]) {
271 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
272 app, testCase.rroDirs[app], rroDirs)
273 }
Colin Cross890ff552017-11-30 20:13:19 -0800274 }
Colin Cross890ff552017-11-30 20:13:19 -0800275 })
276 }
277}
Colin Crossd09b0b62018-04-18 11:06:47 -0700278
279func TestAppSdkVersion(t *testing.T) {
280 testCases := []struct {
281 name string
282 sdkVersion string
283 platformSdkInt int
284 platformSdkCodename string
285 platformSdkFinal bool
286 expectedMinSdkVersion string
287 }{
288 {
289 name: "current final SDK",
290 sdkVersion: "current",
291 platformSdkInt: 27,
292 platformSdkCodename: "REL",
293 platformSdkFinal: true,
294 expectedMinSdkVersion: "27",
295 },
296 {
297 name: "current non-final SDK",
298 sdkVersion: "current",
299 platformSdkInt: 27,
300 platformSdkCodename: "OMR1",
301 platformSdkFinal: false,
302 expectedMinSdkVersion: "OMR1",
303 },
304 {
305 name: "default final SDK",
306 sdkVersion: "",
307 platformSdkInt: 27,
308 platformSdkCodename: "REL",
309 platformSdkFinal: true,
310 expectedMinSdkVersion: "27",
311 },
312 {
313 name: "default non-final SDK",
314 sdkVersion: "",
315 platformSdkInt: 27,
316 platformSdkCodename: "OMR1",
317 platformSdkFinal: false,
318 expectedMinSdkVersion: "OMR1",
319 },
320 {
321 name: "14",
322 sdkVersion: "14",
323 expectedMinSdkVersion: "14",
324 },
325 }
326
327 for _, moduleType := range []string{"android_app", "android_library"} {
328 for _, test := range testCases {
329 t.Run(moduleType+" "+test.name, func(t *testing.T) {
330 bp := fmt.Sprintf(`%s {
331 name: "foo",
332 srcs: ["a.java"],
333 sdk_version: "%s",
334 }`, moduleType, test.sdkVersion)
335
336 config := testConfig(nil)
337 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
338 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
339 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
340
341 ctx := testAppContext(config, bp, nil)
342
343 run(t, ctx, config)
344
345 foo := ctx.ModuleForTests("foo", "android_common")
346 link := foo.Output("package-res.apk")
347 linkFlags := strings.Split(link.Args["flags"], " ")
348 min := android.IndexList("--min-sdk-version", linkFlags)
349 target := android.IndexList("--target-sdk-version", linkFlags)
350
351 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
352 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
353 }
354
355 gotMinSdkVersion := linkFlags[min+1]
356 gotTargetSdkVersion := linkFlags[target+1]
357
358 if gotMinSdkVersion != test.expectedMinSdkVersion {
359 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
360 test.expectedMinSdkVersion, gotMinSdkVersion)
361 }
362
363 if gotTargetSdkVersion != test.expectedMinSdkVersion {
364 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
365 test.expectedMinSdkVersion, gotTargetSdkVersion)
366 }
367 })
368 }
369 }
370}
Colin Crossa4f08812018-10-02 22:03:40 -0700371
372func TestJNI(t *testing.T) {
373 ctx := testJava(t, `
374 toolchain_library {
375 name: "libcompiler_rt-extras",
376 src: "",
377 }
378
379 toolchain_library {
380 name: "libatomic",
381 src: "",
382 }
383
384 toolchain_library {
385 name: "libgcc",
386 src: "",
387 }
388
389 toolchain_library {
390 name: "libclang_rt.builtins-aarch64-android",
391 src: "",
392 }
393
394 toolchain_library {
395 name: "libclang_rt.builtins-arm-android",
396 src: "",
397 }
398
399 cc_object {
400 name: "crtbegin_so",
401 stl: "none",
402 }
403
404 cc_object {
405 name: "crtend_so",
406 stl: "none",
407 }
408
409 cc_library {
410 name: "libjni",
411 system_shared_libs: [],
412 stl: "none",
413 }
414
415 android_test {
416 name: "test",
417 no_framework_libs: true,
418 jni_libs: ["libjni"],
419 }
420
421 android_test {
422 name: "test_first",
423 no_framework_libs: true,
424 compile_multilib: "first",
425 jni_libs: ["libjni"],
426 }
427
428 android_test {
429 name: "test_both",
430 no_framework_libs: true,
431 compile_multilib: "both",
432 jni_libs: ["libjni"],
433 }
434
435 android_test {
436 name: "test_32",
437 no_framework_libs: true,
438 compile_multilib: "32",
439 jni_libs: ["libjni"],
440 }
441
442 android_test {
443 name: "test_64",
444 no_framework_libs: true,
445 compile_multilib: "64",
446 jni_libs: ["libjni"],
447 }
448 `)
449
450 // check the existence of the internal modules
451 ctx.ModuleForTests("test", "android_common")
452 ctx.ModuleForTests("test_first", "android_common")
453 ctx.ModuleForTests("test_both", "android_common")
454 ctx.ModuleForTests("test_32", "android_common")
455 ctx.ModuleForTests("test_64", "android_common")
456
457 testCases := []struct {
458 name string
459 abis []string
460 }{
461 {"test", []string{"arm64-v8a"}},
462 {"test_first", []string{"arm64-v8a"}},
463 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
464 {"test_32", []string{"armeabi-v7a"}},
465 {"test_64", []string{"arm64-v8a"}},
466 }
467
468 for _, test := range testCases {
469 t.Run(test.name, func(t *testing.T) {
470 app := ctx.ModuleForTests(test.name, "android_common")
471 jniLibZip := app.Output("jnilibs.zip")
472 var abis []string
473 args := strings.Fields(jniLibZip.Args["jarArgs"])
474 for i := 0; i < len(args); i++ {
475 if args[i] == "-P" {
476 abis = append(abis, filepath.Base(args[i+1]))
477 i++
478 }
479 }
480 if !reflect.DeepEqual(abis, test.abis) {
481 t.Errorf("want abis %v, got %v", test.abis, abis)
482 }
483 })
484 }
485}
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800486
487func TestCertificates(t *testing.T) {
488 testCases := []struct {
489 name string
490 bp string
491 certificateOverride string
492 expected string
493 }{
494 {
495 name: "default",
496 bp: `
497 android_app {
498 name: "foo",
499 srcs: ["a.java"],
500 }
501 `,
502 certificateOverride: "",
503 expected: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
504 },
505 {
506 name: "module certificate property",
507 bp: `
508 android_app {
509 name: "foo",
510 srcs: ["a.java"],
511 certificate: ":new_certificate"
512 }
513
514 android_app_certificate {
515 name: "new_certificate",
516 certificate: "cert/new_cert",
517 }
518 `,
519 certificateOverride: "",
520 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
521 },
522 {
523 name: "path certificate property",
524 bp: `
525 android_app {
526 name: "foo",
527 srcs: ["a.java"],
528 certificate: "expiredkey"
529 }
530 `,
531 certificateOverride: "",
532 expected: "build/target/product/security/expiredkey.x509.pem build/target/product/security/expiredkey.pk8",
533 },
534 {
535 name: "certificate overrides",
536 bp: `
537 android_app {
538 name: "foo",
539 srcs: ["a.java"],
540 certificate: "expiredkey"
541 }
542
543 android_app_certificate {
544 name: "new_certificate",
545 certificate: "cert/new_cert",
546 }
547 `,
548 certificateOverride: "foo:new_certificate",
549 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
550 },
551 }
552
553 for _, test := range testCases {
554 t.Run(test.name, func(t *testing.T) {
555 config := testConfig(nil)
556 if test.certificateOverride != "" {
557 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
558 }
559 ctx := testAppContext(config, test.bp, nil)
560
561 run(t, ctx, config)
562 foo := ctx.ModuleForTests("foo", "android_common")
563
564 signapk := foo.Output("foo.apk")
565 signFlags := signapk.Args["certificates"]
566 if test.expected != signFlags {
567 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
568 }
569 })
570 }
571}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800572
573func TestPackageNameOverride(t *testing.T) {
574 testCases := []struct {
575 name string
576 bp string
577 packageNameOverride string
578 expected []string
579 }{
580 {
581 name: "default",
582 bp: `
583 android_app {
584 name: "foo",
585 srcs: ["a.java"],
586 }
587 `,
588 packageNameOverride: "",
589 expected: []string{
590 buildDir + "/.intermediates/foo/android_common/foo.apk",
591 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
592 },
593 },
594 {
595 name: "overridden",
596 bp: `
597 android_app {
598 name: "foo",
599 srcs: ["a.java"],
600 }
601 `,
602 packageNameOverride: "foo:bar",
603 expected: []string{
604 // The package apk should be still be the original name for test dependencies.
605 buildDir + "/.intermediates/foo/android_common/foo.apk",
606 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
607 },
608 },
609 }
610
611 for _, test := range testCases {
612 t.Run(test.name, func(t *testing.T) {
613 config := testConfig(nil)
614 if test.packageNameOverride != "" {
615 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
616 }
617 ctx := testAppContext(config, test.bp, nil)
618
619 run(t, ctx, config)
620 foo := ctx.ModuleForTests("foo", "android_common")
621
622 outputs := foo.AllOutputs()
623 outputMap := make(map[string]bool)
624 for _, o := range outputs {
625 outputMap[o] = true
626 }
627 for _, e := range test.expected {
628 if _, exist := outputMap[e]; !exist {
629 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
630 }
631 }
632 })
633 }
634}