• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 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	"fmt"
19	"runtime"
20	"strings"
21	"testing"
22
23	"android/soong/android"
24	"android/soong/cc"
25	"android/soong/dexpreopt"
26)
27
28func init() {
29	RegisterFakeRuntimeApexMutator()
30}
31
32func TestDexpreoptEnabled(t *testing.T) {
33	tests := []struct {
34		name        string
35		bp          string
36		moduleName  string
37		apexVariant bool
38		enabled     bool
39	}{
40		{
41			name: "app",
42			bp: `
43				android_app {
44					name: "foo",
45					srcs: ["a.java"],
46					sdk_version: "current",
47				}`,
48			enabled: true,
49		},
50		{
51			name: "installable java library",
52			bp: `
53				java_library {
54					name: "foo",
55					installable: true,
56					srcs: ["a.java"],
57				}`,
58			enabled: true,
59		},
60		{
61			name: "java binary",
62			bp: `
63				java_binary {
64					name: "foo",
65					srcs: ["a.java"],
66					main_class: "foo.bar.jb",
67				}`,
68			enabled: true,
69		},
70		{
71			name: "app without sources",
72			bp: `
73				android_app {
74					name: "foo",
75					sdk_version: "current",
76				}`,
77			enabled: false,
78		},
79		{
80			name: "app with libraries",
81			bp: `
82				android_app {
83					name: "foo",
84					static_libs: ["lib"],
85					sdk_version: "current",
86				}
87
88				java_library {
89					name: "lib",
90					srcs: ["a.java"],
91					sdk_version: "current",
92				}`,
93			enabled: true,
94		},
95		{
96			name: "installable java library without sources",
97			bp: `
98				java_library {
99					name: "foo",
100					installable: true,
101				}`,
102			enabled: false,
103		},
104		{
105			name: "static java library",
106			bp: `
107				java_library {
108					name: "foo",
109					srcs: ["a.java"],
110				}`,
111			enabled: false,
112		},
113		{
114			name: "java test",
115			bp: `
116				java_test {
117					name: "foo",
118					srcs: ["a.java"],
119				}`,
120			enabled: false,
121		},
122		{
123			name: "android test",
124			bp: `
125				android_test {
126					name: "foo",
127					srcs: ["a.java"],
128				}`,
129			enabled: false,
130		},
131		{
132			name: "android test helper app",
133			bp: `
134				android_test_helper_app {
135					name: "foo",
136					srcs: ["a.java"],
137				}`,
138			enabled: false,
139		},
140		{
141			name: "compile_dex",
142			bp: `
143				java_library {
144					name: "foo",
145					srcs: ["a.java"],
146					compile_dex: true,
147				}`,
148			enabled: false,
149		},
150		{
151			name: "dex_import",
152			bp: `
153				dex_import {
154					name: "foo",
155					jars: ["a.jar"],
156				}`,
157			enabled: true,
158		},
159		{
160			name: "apex variant",
161			bp: `
162				java_library {
163					name: "foo",
164					installable: true,
165					srcs: ["a.java"],
166					apex_available: ["com.android.apex1"],
167				}`,
168			apexVariant: true,
169			enabled:     false,
170		},
171		{
172			name: "apex variant of apex system server jar",
173			bp: `
174				java_library {
175					name: "service-foo",
176					installable: true,
177					srcs: ["a.java"],
178					apex_available: ["com.android.apex1"],
179				}`,
180			moduleName:  "service-foo",
181			apexVariant: true,
182			enabled:     true,
183		},
184		{
185			name: "apex variant of prebuilt apex system server jar",
186			bp: `
187				java_library {
188					name: "prebuilt_service-foo",
189					installable: true,
190					srcs: ["a.java"],
191					apex_available: ["com.android.apex1"],
192				}`,
193			moduleName:  "prebuilt_service-foo",
194			apexVariant: true,
195			enabled:     true,
196		},
197		{
198			name: "platform variant of apex system server jar",
199			bp: `
200				java_library {
201					name: "service-foo",
202					installable: true,
203					srcs: ["a.java"],
204					apex_available: ["com.android.apex1"],
205				}`,
206			moduleName:  "service-foo",
207			apexVariant: false,
208			enabled:     false,
209		},
210	}
211
212	for _, test := range tests {
213		t.Run(test.name, func(t *testing.T) {
214			preparers := android.GroupFixturePreparers(
215				PrepareForTestWithDexpreopt,
216				PrepareForTestWithFakeApexMutator,
217				dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
218			)
219
220			result := preparers.RunTestWithBp(t, test.bp)
221			ctx := result.TestContext
222
223			moduleName := "foo"
224			if test.moduleName != "" {
225				moduleName = test.moduleName
226			}
227
228			variant := "android_common"
229			if test.apexVariant {
230				variant += "_apex1000"
231			}
232
233			dexpreopt := ctx.ModuleForTests(moduleName, variant).MaybeRule("dexpreopt")
234			enabled := dexpreopt.Rule != nil
235
236			if enabled != test.enabled {
237				t.Fatalf("want dexpreopt %s, got %s", enabledString(test.enabled), enabledString(enabled))
238			}
239		})
240
241	}
242}
243
244func enabledString(enabled bool) string {
245	if enabled {
246		return "enabled"
247	} else {
248		return "disabled"
249	}
250}
251
252func TestDex2oatToolDeps(t *testing.T) {
253	if runtime.GOOS != "linux" {
254		// The host binary paths checked below are build OS dependent.
255		t.Skipf("Unsupported build OS %s", runtime.GOOS)
256	}
257
258	preparers := android.GroupFixturePreparers(
259		cc.PrepareForTestWithCcDefaultModules,
260		PrepareForTestWithDexpreoptWithoutFakeDex2oatd,
261		dexpreopt.PrepareForTestByEnablingDexpreopt)
262
263	testDex2oatToolDep := func(sourceEnabled, prebuiltEnabled, prebuiltPreferred bool,
264		expectedDex2oatPath string) {
265		name := fmt.Sprintf("sourceEnabled:%t,prebuiltEnabled:%t,prebuiltPreferred:%t",
266			sourceEnabled, prebuiltEnabled, prebuiltPreferred)
267		t.Run(name, func(t *testing.T) {
268			result := preparers.RunTestWithBp(t, fmt.Sprintf(`
269					cc_binary {
270						name: "dex2oatd",
271						enabled: %t,
272						host_supported: true,
273					}
274					cc_prebuilt_binary {
275						name: "dex2oatd",
276						enabled: %t,
277						prefer: %t,
278						host_supported: true,
279						srcs: ["x86_64/bin/dex2oatd"],
280					}
281					java_library {
282						name: "myjavalib",
283					}
284				`, sourceEnabled, prebuiltEnabled, prebuiltPreferred))
285			pathContext := android.PathContextForTesting(result.Config)
286			dex2oatPath := dexpreopt.GetCachedGlobalSoongConfig(pathContext).Dex2oat
287			android.AssertStringEquals(t, "Testing "+name, expectedDex2oatPath, android.NormalizePathForTesting(dex2oatPath))
288		})
289	}
290
291	sourceDex2oatPath := "host/linux-x86/bin/dex2oatd"
292	prebuiltDex2oatPath := ".intermediates/prebuilt_dex2oatd/linux_glibc_x86_64/dex2oatd"
293
294	testDex2oatToolDep(true, false, false, sourceDex2oatPath)
295	testDex2oatToolDep(true, true, false, sourceDex2oatPath)
296	testDex2oatToolDep(true, true, true, prebuiltDex2oatPath)
297	testDex2oatToolDep(false, true, false, prebuiltDex2oatPath)
298}
299
300func TestDexpreoptBuiltInstalledForApex(t *testing.T) {
301	preparers := android.GroupFixturePreparers(
302		PrepareForTestWithDexpreopt,
303		PrepareForTestWithFakeApexMutator,
304		dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
305	)
306
307	// An APEX system server jar.
308	result := preparers.RunTestWithBp(t, `
309		java_library {
310			name: "service-foo",
311			installable: true,
312			srcs: ["a.java"],
313			apex_available: ["com.android.apex1"],
314		}`)
315	ctx := result.TestContext
316	module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
317	library := module.Module().(*Library)
318
319	installs := library.dexpreopter.DexpreoptBuiltInstalledForApex()
320
321	android.AssertIntEquals(t, "install count", 2, len(installs))
322
323	android.AssertStringEquals(t, "installs[0] FullModuleName",
324		"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
325		installs[0].FullModuleName())
326
327	android.AssertStringEquals(t, "installs[0] SubModuleName",
328		"-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
329		installs[0].SubModuleName())
330
331	android.AssertStringEquals(t, "installs[1] FullModuleName",
332		"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
333		installs[1].FullModuleName())
334
335	android.AssertStringEquals(t, "installs[1] SubModuleName",
336		"-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
337		installs[1].SubModuleName())
338
339	// Not an APEX system server jar.
340	result = preparers.RunTestWithBp(t, `
341		java_library {
342			name: "foo",
343			installable: true,
344			srcs: ["a.java"],
345		}`)
346	ctx = result.TestContext
347	module = ctx.ModuleForTests("foo", "android_common")
348	library = module.Module().(*Library)
349
350	installs = library.dexpreopter.DexpreoptBuiltInstalledForApex()
351
352	android.AssertIntEquals(t, "install count", 0, len(installs))
353}
354
355func filterDexpreoptEntriesList(entriesList []android.AndroidMkEntries) []android.AndroidMkEntries {
356	var results []android.AndroidMkEntries
357	for _, entries := range entriesList {
358		if strings.Contains(entries.EntryMap["LOCAL_MODULE"][0], "-dexpreopt-") {
359			results = append(results, entries)
360		}
361	}
362	return results
363}
364
365func verifyEntries(t *testing.T, message string, expectedModule string,
366	expectedPrebuiltModuleFile string, expectedModulePath string, expectedInstalledModuleStem string,
367	entries android.AndroidMkEntries) {
368	android.AssertStringEquals(t, message+" LOCAL_MODULE", expectedModule,
369		entries.EntryMap["LOCAL_MODULE"][0])
370
371	android.AssertStringEquals(t, message+" LOCAL_MODULE_CLASS", "ETC",
372		entries.EntryMap["LOCAL_MODULE_CLASS"][0])
373
374	android.AssertStringDoesContain(t, message+" LOCAL_PREBUILT_MODULE_FILE",
375		entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"][0], expectedPrebuiltModuleFile)
376
377	android.AssertStringDoesContain(t, message+" LOCAL_MODULE_PATH",
378		entries.EntryMap["LOCAL_MODULE_PATH"][0], expectedModulePath)
379
380	android.AssertStringEquals(t, message+" LOCAL_INSTALLED_MODULE_STEM",
381		expectedInstalledModuleStem, entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
382
383	android.AssertStringEquals(t, message+" LOCAL_NOT_AVAILABLE_FOR_PLATFORM",
384		"false", entries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"][0])
385}
386
387func TestAndroidMkEntriesForApex(t *testing.T) {
388	preparers := android.GroupFixturePreparers(
389		PrepareForTestWithDexpreopt,
390		PrepareForTestWithFakeApexMutator,
391		dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
392	)
393
394	// An APEX system server jar.
395	result := preparers.RunTestWithBp(t, `
396		java_library {
397			name: "service-foo",
398			installable: true,
399			srcs: ["a.java"],
400			apex_available: ["com.android.apex1"],
401		}`)
402	ctx := result.TestContext
403	module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
404
405	entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module())
406	entriesList = filterDexpreoptEntriesList(entriesList)
407
408	android.AssertIntEquals(t, "entries count", 2, len(entriesList))
409
410	verifyEntries(t,
411		"entriesList[0]",
412		"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
413		"/dexpreopt/oat/arm64/javalib.odex",
414		"/system/framework/oat/arm64",
415		"apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
416		entriesList[0])
417
418	verifyEntries(t,
419		"entriesList[1]",
420		"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
421		"/dexpreopt/oat/arm64/javalib.vdex",
422		"/system/framework/oat/arm64",
423		"apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
424		entriesList[1])
425
426	// Not an APEX system server jar.
427	result = preparers.RunTestWithBp(t, `
428		java_library {
429			name: "foo",
430			installable: true,
431			srcs: ["a.java"],
432		}`)
433	ctx = result.TestContext
434	module = ctx.ModuleForTests("foo", "android_common")
435
436	entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module())
437	entriesList = filterDexpreoptEntriesList(entriesList)
438
439	android.AssertIntEquals(t, "entries count", 0, len(entriesList))
440}
441
442func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) {
443	preparers := android.GroupFixturePreparers(
444		PrepareForTestWithJavaDefaultModules,
445		PrepareForTestWithFakeApexMutator,
446		dexpreopt.FixtureDisableDexpreopt(true),
447	)
448
449	result := preparers.RunTestWithBp(t, `
450		java_library {
451			name: "foo",
452			installable: true,
453			dex_preopt: {
454				profile: "art-profile",
455			},
456			srcs: ["a.java"],
457		}`)
458
459	ctx := result.TestContext
460	dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
461
462	expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/profile.prof"}
463
464	android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs())
465}
466