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