• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 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	"strconv"
20	"testing"
21
22	"android/soong/android"
23
24	"github.com/google/blueprint/proptools"
25)
26
27func TestR8(t *testing.T) {
28	t.Parallel()
29	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
30		android_app {
31			name: "app",
32			srcs: ["foo.java"],
33			libs: ["lib"],
34			static_libs: ["static_lib"],
35			platform_apis: true,
36		}
37
38		android_app {
39			name: "stable_app",
40			srcs: ["foo.java"],
41			sdk_version: "current",
42			min_sdk_version: "31",
43		}
44
45		android_app {
46			name: "core_platform_app",
47			srcs: ["foo.java"],
48			sdk_version: "core_platform",
49			min_sdk_version: "31",
50		}
51
52		java_library {
53			name: "lib",
54			srcs: ["foo.java"],
55		}
56
57		java_library {
58			name: "static_lib",
59			srcs: ["foo.java"],
60		}
61	`)
62
63	app := result.ModuleForTests(t, "app", "android_common")
64	stableApp := result.ModuleForTests(t, "stable_app", "android_common")
65	corePlatformApp := result.ModuleForTests(t, "core_platform_app", "android_common")
66	lib := result.ModuleForTests(t, "lib", "android_common")
67	staticLib := result.ModuleForTests(t, "static_lib", "android_common")
68
69	appJavac := app.Rule("javac")
70	appR8 := app.Rule("r8")
71	stableAppR8 := stableApp.Rule("r8")
72	corePlatformAppR8 := corePlatformApp.Rule("r8")
73	libHeader := lib.Output("turbine/lib.jar").Output
74	libCombinedHeader := lib.Output("turbine-combined/lib.jar").Output
75	staticLibHeader := staticLib.Output("turbine/static_lib.jar").Output
76
77	android.AssertStringDoesContain(t, "expected lib header jar in app javac classpath",
78		appJavac.Args["classpath"], libHeader.String())
79	android.AssertStringDoesContain(t, "expected static_lib header jar in app javac classpath",
80		appJavac.Args["classpath"], staticLibHeader.String())
81
82	android.AssertStringDoesContain(t, "expected lib combined header jar in app r8 classpath",
83		appR8.Args["r8Flags"], libCombinedHeader.String())
84	android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
85		appR8.Args["r8Flags"], staticLibHeader.String())
86	android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
87		appR8.Args["r8Flags"], "-ignorewarnings")
88	android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
89		appR8.Args["r8Flags"], "--android-platform-build")
90	android.AssertStringDoesNotContain(t, "expected no --android-platform-build in stable_app r8 flags",
91		stableAppR8.Args["r8Flags"], "--android-platform-build")
92	android.AssertStringDoesContain(t, "expected --android-platform-build in core_platform_app r8 flags",
93		corePlatformAppR8.Args["r8Flags"], "--android-platform-build")
94}
95
96func TestR8TransitiveDeps(t *testing.T) {
97	t.Parallel()
98	bp := `
99		override_android_app {
100			name: "override_app",
101			base: "app",
102		}
103
104		android_app {
105			name: "app",
106			srcs: ["foo.java"],
107			libs: [
108				"lib",
109				"uses_libs_dep_import",
110			],
111			static_libs: [
112				"static_lib",
113				"repeated_dep",
114			],
115			platform_apis: true,
116		}
117
118		java_library {
119			name: "static_lib",
120			srcs: ["foo.java"],
121		}
122
123		java_library {
124			name: "lib",
125			libs: [
126				"transitive_lib",
127				"repeated_dep",
128				"prebuilt_lib",
129			],
130			static_libs: ["transitive_static_lib"],
131			srcs: ["foo.java"],
132		}
133
134		java_library {
135			name: "repeated_dep",
136			srcs: ["foo.java"],
137		}
138
139		java_library {
140			name: "transitive_static_lib",
141			srcs: ["foo.java"],
142		}
143
144		java_library {
145			name: "transitive_lib",
146			srcs: ["foo.java"],
147			libs: ["transitive_lib_2"],
148		}
149
150		java_library {
151			name: "transitive_lib_2",
152			srcs: ["foo.java"],
153		}
154
155		java_import {
156			name: "lib",
157			jars: ["lib.jar"],
158		}
159
160		java_library {
161			name: "uses_lib",
162			srcs: ["foo.java"],
163		}
164
165		java_library {
166			name: "optional_uses_lib",
167			srcs: ["foo.java"],
168		}
169
170		android_library {
171			name: "uses_libs_dep",
172			uses_libs: ["uses_lib"],
173			optional_uses_libs: ["optional_uses_lib"],
174		}
175
176		android_library_import {
177			name: "uses_libs_dep_import",
178			aars: ["aar.aar"],
179			static_libs: ["uses_libs_dep"],
180		}
181	`
182
183	testcases := []struct {
184		name      string
185		unbundled bool
186	}{
187		{
188			name:      "non-unbundled build",
189			unbundled: false,
190		},
191		{
192			name:      "unbundled build",
193			unbundled: true,
194		},
195	}
196
197	for _, tc := range testcases {
198		t.Run(tc.name, func(t *testing.T) {
199			t.Parallel()
200			fixturePreparer := PrepareForTestWithJavaDefaultModules
201			if tc.unbundled {
202				fixturePreparer = android.GroupFixturePreparers(
203					fixturePreparer,
204					android.FixtureModifyProductVariables(
205						func(variables android.FixtureProductVariables) {
206							variables.Unbundled_build = proptools.BoolPtr(true)
207						},
208					),
209				)
210			}
211			result := fixturePreparer.RunTestWithBp(t, bp)
212
213			getHeaderJar := func(name string) android.Path {
214				mod := result.ModuleForTests(t, name, "android_common")
215				return mod.Output("turbine-combined/" + name + ".jar").Output
216			}
217
218			appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
219			overrideAppR8 := result.ModuleForTests(t, "app", "android_common_override_app").Rule("r8")
220			appHeader := getHeaderJar("app")
221			overrideAppHeader := result.ModuleForTests(t, "app", "android_common_override_app").Output("turbine-combined/app.jar").Output
222			libHeader := getHeaderJar("lib")
223			transitiveLibHeader := getHeaderJar("transitive_lib")
224			transitiveLib2Header := getHeaderJar("transitive_lib_2")
225			staticLibHeader := getHeaderJar("static_lib")
226			transitiveStaticLibHeader := getHeaderJar("transitive_static_lib")
227			repeatedDepHeader := getHeaderJar("repeated_dep")
228			usesLibHeader := getHeaderJar("uses_lib")
229			optionalUsesLibHeader := getHeaderJar("optional_uses_lib")
230			prebuiltLibHeader := result.ModuleForTests(t, "prebuilt_lib", "android_common").Output("combined/lib.jar").Output
231
232			for _, rule := range []android.TestingBuildParams{appR8, overrideAppR8} {
233				android.AssertStringDoesNotContain(t, "expected no app header jar in app r8 classpath",
234					rule.Args["r8Flags"], appHeader.String())
235				android.AssertStringDoesNotContain(t, "expected no override_app header jar in app r8 classpath",
236					rule.Args["r8Flags"], overrideAppHeader.String())
237				android.AssertStringDoesContain(t, "expected transitive lib header jar in app r8 classpath",
238					rule.Args["r8Flags"], transitiveLibHeader.String())
239				android.AssertStringDoesContain(t, "expected transitive lib ^2 header jar in app r8 classpath",
240					rule.Args["r8Flags"], transitiveLib2Header.String())
241				android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
242					rule.Args["r8Flags"], libHeader.String())
243				android.AssertStringDoesContain(t, "expected uses_lib header jar in app r8 classpath",
244					rule.Args["r8Flags"], usesLibHeader.String())
245				android.AssertStringDoesContain(t, "expected optional_uses_lib header jar in app r8 classpath",
246					rule.Args["r8Flags"], optionalUsesLibHeader.String())
247				android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
248					rule.Args["r8Flags"], staticLibHeader.String())
249				android.AssertStringDoesNotContain(t, "expected no transitive static_lib header jar in app r8 classpath",
250					rule.Args["r8Flags"], transitiveStaticLibHeader.String())
251				// we shouldn't list this dep because it is already included as static_libs in the app
252				android.AssertStringDoesNotContain(t, "expected no repeated_dep header jar in app r8 classpath",
253					rule.Args["r8Flags"], repeatedDepHeader.String())
254				// skip a prebuilt transitive dep if the source is also a transitive dep
255				android.AssertStringDoesNotContain(t, "expected no prebuilt header jar in app r8 classpath",
256					rule.Args["r8Flags"], prebuiltLibHeader.String())
257				android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
258					rule.Args["r8Flags"], "-ignorewarnings")
259				android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
260					rule.Args["r8Flags"], "--android-platform-build")
261			}
262		})
263	}
264}
265
266func TestR8Flags(t *testing.T) {
267	t.Parallel()
268	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
269		android_app {
270			name: "app",
271			srcs: ["foo.java"],
272			platform_apis: true,
273			optimize: {
274				shrink: false,
275				optimize: false,
276				obfuscate: false,
277				ignore_warnings: false,
278			},
279		}
280	`)
281
282	app := result.ModuleForTests(t, "app", "android_common")
283	appR8 := app.Rule("r8")
284	android.AssertStringDoesContain(t, "expected -dontshrink in app r8 flags",
285		appR8.Args["r8Flags"], "-dontshrink")
286	android.AssertStringDoesContain(t, "expected -dontoptimize in app r8 flags",
287		appR8.Args["r8Flags"], "-dontoptimize")
288	android.AssertStringDoesContain(t, "expected -dontobfuscate in app r8 flags",
289		appR8.Args["r8Flags"], "-dontobfuscate")
290	android.AssertStringDoesNotContain(t, "expected no -ignorewarnings in app r8 flags",
291		appR8.Args["r8Flags"], "-ignorewarnings")
292	android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
293		appR8.Args["r8Flags"], "--android-platform-build")
294}
295
296func TestD8(t *testing.T) {
297	t.Parallel()
298	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
299		java_library {
300			name: "foo",
301			srcs: ["foo.java"],
302			libs: ["lib"],
303			static_libs: ["static_lib"],
304			installable: true,
305		}
306
307		java_library {
308			name: "lib",
309			srcs: ["foo.java"],
310		}
311
312		java_library {
313			name: "static_lib",
314			srcs: ["foo.java"],
315		}
316
317		android_app {
318			name: "app",
319			srcs: ["foo.java"],
320			platform_apis: true,
321			optimize: {
322				enabled: false,
323			},
324		}
325	`)
326
327	foo := result.ModuleForTests(t, "foo", "android_common")
328	lib := result.ModuleForTests(t, "lib", "android_common")
329	app := result.ModuleForTests(t, "app", "android_common")
330	staticLib := result.ModuleForTests(t, "static_lib", "android_common")
331
332	fooJavac := foo.Rule("javac")
333	fooD8 := foo.Rule("d8")
334	appD8 := app.Rule("d8")
335	libHeader := lib.Output("turbine/lib.jar").Output
336	libCombinedHeader := lib.Output("turbine-combined/lib.jar").Output
337	staticLibHeader := staticLib.Output("turbine/static_lib.jar").Output
338
339	android.AssertStringDoesContain(t, "expected lib header jar in foo javac classpath",
340		fooJavac.Args["classpath"], libHeader.String())
341	android.AssertStringDoesContain(t, "expected static_lib header jar in foo javac classpath",
342		fooJavac.Args["classpath"], staticLibHeader.String())
343
344	android.AssertStringDoesContain(t, "expected lib combined header jar in foo d8 classpath",
345		fooD8.Args["d8Flags"], libCombinedHeader.String())
346	android.AssertStringDoesNotContain(t, "expected no  static_lib header jar in foo javac classpath",
347		fooD8.Args["d8Flags"], staticLibHeader.String())
348
349	// A --release flag is added only for targets that opt out of default R8 behavior (e.g., apps).
350	// For library targets that don't use R8 by default, no --debug or --release flag should be
351	// added, instead relying on default D8 behavior (--debug).
352	android.AssertStringDoesContain(t, "expected --release in app d8 flags",
353		appD8.Args["d8Flags"], "--release")
354	android.AssertStringDoesNotContain(t, "expected no --release flag in lib d8 flags",
355		fooD8.Args["d8Flags"], "--release")
356	android.AssertStringDoesNotContain(t, "expected no --debug flag in lib d8 flags",
357		fooD8.Args["d8Flags"], "--debug")
358}
359
360func TestProguardFlagsInheritanceStatic(t *testing.T) {
361	t.Parallel()
362	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
363		android_app {
364			name: "app",
365			static_libs: [
366				"primary_android_lib",
367				"primary_lib",
368			],
369			platform_apis: true,
370		}
371
372		java_library {
373			name: "primary_lib",
374			optimize: {
375				proguard_flags_files: ["primary.flags"],
376			},
377		}
378
379		android_library {
380			name: "primary_android_lib",
381			static_libs: ["secondary_lib"],
382			optimize: {
383				proguard_flags_files: ["primary_android.flags"],
384			},
385		}
386
387		java_library {
388			name: "secondary_lib",
389			static_libs: ["tertiary_lib"],
390			optimize: {
391				proguard_flags_files: ["secondary.flags"],
392			},
393		}
394
395		java_library {
396			name: "tertiary_lib",
397			optimize: {
398				proguard_flags_files: ["tertiary.flags"],
399			},
400		}
401	`)
402
403	app := result.ModuleForTests(t, "app", "android_common")
404	appR8 := app.Rule("r8")
405	android.AssertStringDoesContain(t, "expected primary_lib's proguard flags from direct dep",
406		appR8.Args["r8Flags"], "primary.flags")
407	android.AssertStringDoesContain(t, "expected primary_android_lib's proguard flags from direct dep",
408		appR8.Args["r8Flags"], "primary_android.flags")
409	android.AssertStringDoesContain(t, "expected secondary_lib's proguard flags from inherited dep",
410		appR8.Args["r8Flags"], "secondary.flags")
411	android.AssertStringDoesContain(t, "expected tertiary_lib's proguard flags from inherited dep",
412		appR8.Args["r8Flags"], "tertiary.flags")
413}
414
415func TestProguardFlagsInheritance(t *testing.T) {
416	t.Parallel()
417	directDepFlagsFileName := "direct_dep.flags"
418	transitiveDepFlagsFileName := "transitive_dep.flags"
419
420	topLevelModules := []struct {
421		name       string
422		definition string
423	}{
424		{
425			name: "android_app",
426			definition: `
427				android_app {
428					name: "app",
429					static_libs: ["androidlib"], // this must be static_libs to initate dexing
430					platform_apis: true,
431				}
432			`,
433		},
434		{
435			name: "android_library",
436			definition: `
437				android_library {
438					name: "app",
439					static_libs: ["androidlib"], // this must be static_libs to initate dexing
440					installable: true,
441					optimize: {
442						enabled: true,
443						shrink: true,
444					},
445				}
446			`,
447		},
448		{
449			name: "java_library",
450			definition: `
451				java_library {
452					name: "app",
453					static_libs: ["androidlib"], // this must be static_libs to initate dexing
454					srcs: ["Foo.java"],
455					installable: true,
456					optimize: {
457						enabled: true,
458						shrink: true,
459					},
460				}
461			`,
462		},
463	}
464
465	bp := `
466		android_library {
467			name: "androidlib",
468			static_libs: ["app_dep"],
469		}
470
471		java_library {
472			name: "app_dep",
473			%s: ["dep"],
474		}
475
476		java_library {
477			name: "dep",
478			%s: ["transitive_dep"],
479			optimize: {
480				proguard_flags_files: ["direct_dep.flags"],
481				export_proguard_flags_files: %v,
482			},
483		}
484
485		java_library {
486			name: "transitive_dep",
487			optimize: {
488				proguard_flags_files: ["transitive_dep.flags"],
489				export_proguard_flags_files: %v,
490			},
491		}
492	`
493
494	testcases := []struct {
495		name                           string
496		depType                        string
497		depExportsFlagsFiles           bool
498		transitiveDepType              string
499		transitiveDepExportsFlagsFiles bool
500		expectedFlagsFiles             []string
501	}{
502		{
503			name:                           "libs_export_libs_export",
504			depType:                        "libs",
505			depExportsFlagsFiles:           true,
506			transitiveDepType:              "libs",
507			transitiveDepExportsFlagsFiles: true,
508			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
509		},
510		{
511			name:                           "static_export_libs_export",
512			depType:                        "static_libs",
513			depExportsFlagsFiles:           true,
514			transitiveDepType:              "libs",
515			transitiveDepExportsFlagsFiles: true,
516			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
517		},
518		{
519			name:                           "libs_no-export_static_export",
520			depType:                        "libs",
521			depExportsFlagsFiles:           false,
522			transitiveDepType:              "static_libs",
523			transitiveDepExportsFlagsFiles: true,
524			expectedFlagsFiles:             []string{transitiveDepFlagsFileName},
525		},
526		{
527			name:                           "static_no-export_static_export",
528			depType:                        "static_libs",
529			depExportsFlagsFiles:           false,
530			transitiveDepType:              "static_libs",
531			transitiveDepExportsFlagsFiles: true,
532			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
533		},
534		{
535			name:                           "libs_export_libs_no-export",
536			depType:                        "libs",
537			depExportsFlagsFiles:           true,
538			transitiveDepType:              "libs",
539			transitiveDepExportsFlagsFiles: false,
540			expectedFlagsFiles:             []string{directDepFlagsFileName},
541		},
542		{
543			name:                           "static_export_libs_no-export",
544			depType:                        "static_libs",
545			depExportsFlagsFiles:           true,
546			transitiveDepType:              "libs",
547			transitiveDepExportsFlagsFiles: false,
548			expectedFlagsFiles:             []string{directDepFlagsFileName},
549		},
550		{
551			name:                           "libs_no-export_static_no-export",
552			depType:                        "libs",
553			depExportsFlagsFiles:           false,
554			transitiveDepType:              "static_libs",
555			transitiveDepExportsFlagsFiles: false,
556			expectedFlagsFiles:             []string{},
557		},
558		{
559			name:                           "static_no-export_static_no-export",
560			depType:                        "static_libs",
561			depExportsFlagsFiles:           false,
562			transitiveDepType:              "static_libs",
563			transitiveDepExportsFlagsFiles: false,
564			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
565		},
566		{
567			name:                           "libs_no-export_libs_export",
568			depType:                        "libs",
569			depExportsFlagsFiles:           false,
570			transitiveDepType:              "libs",
571			transitiveDepExportsFlagsFiles: true,
572			expectedFlagsFiles:             []string{transitiveDepFlagsFileName},
573		},
574		{
575			name:                           "static_no-export_libs_export",
576			depType:                        "static_libs",
577			depExportsFlagsFiles:           false,
578			transitiveDepType:              "libs",
579			transitiveDepExportsFlagsFiles: true,
580			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
581		},
582		{
583			name:                           "libs_export_static_export",
584			depType:                        "libs",
585			depExportsFlagsFiles:           true,
586			transitiveDepType:              "static_libs",
587			transitiveDepExportsFlagsFiles: true,
588			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
589		},
590		{
591			name:                           "static_export_static_export",
592			depType:                        "static_libs",
593			depExportsFlagsFiles:           true,
594			transitiveDepType:              "static_libs",
595			transitiveDepExportsFlagsFiles: true,
596			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
597		},
598		{
599			name:                           "libs_no-export_libs_no-export",
600			depType:                        "libs",
601			depExportsFlagsFiles:           false,
602			transitiveDepType:              "libs",
603			transitiveDepExportsFlagsFiles: false,
604			expectedFlagsFiles:             []string{},
605		},
606		{
607			name:                           "static_no-export_libs_no-export",
608			depType:                        "static_libs",
609			depExportsFlagsFiles:           false,
610			transitiveDepType:              "libs",
611			transitiveDepExportsFlagsFiles: false,
612			expectedFlagsFiles:             []string{directDepFlagsFileName},
613		},
614		{
615			name:                           "libs_export_static_no-export",
616			depType:                        "libs",
617			depExportsFlagsFiles:           true,
618			transitiveDepType:              "static_libs",
619			transitiveDepExportsFlagsFiles: false,
620			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
621		},
622		{
623			name:                           "static_export_static_no-export",
624			depType:                        "static_libs",
625			depExportsFlagsFiles:           true,
626			transitiveDepType:              "static_libs",
627			transitiveDepExportsFlagsFiles: false,
628			expectedFlagsFiles:             []string{directDepFlagsFileName, transitiveDepFlagsFileName},
629		},
630	}
631
632	for _, topLevelModuleDef := range topLevelModules {
633		for _, tc := range testcases {
634			t.Run(topLevelModuleDef.name+"-"+tc.name, func(t *testing.T) {
635				t.Parallel()
636				result := android.GroupFixturePreparers(
637					PrepareForTestWithJavaDefaultModules,
638					android.FixtureMergeMockFs(android.MockFS{
639						directDepFlagsFileName:     nil,
640						transitiveDepFlagsFileName: nil,
641					}),
642				).RunTestWithBp(t,
643					topLevelModuleDef.definition+
644						fmt.Sprintf(
645							bp,
646							tc.depType,
647							tc.transitiveDepType,
648							tc.depExportsFlagsFiles,
649							tc.transitiveDepExportsFlagsFiles,
650						),
651				)
652				appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
653
654				shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles)
655				if shouldHaveDepFlags {
656					android.AssertStringDoesContain(t, "expected deps's proguard flags",
657						appR8.Args["r8Flags"], directDepFlagsFileName)
658				} else {
659					android.AssertStringDoesNotContain(t, "app did not expect deps's proguard flags",
660						appR8.Args["r8Flags"], directDepFlagsFileName)
661				}
662
663				shouldHaveTransitiveDepFlags := android.InList(transitiveDepFlagsFileName, tc.expectedFlagsFiles)
664				if shouldHaveTransitiveDepFlags {
665					android.AssertStringDoesContain(t, "expected transitive deps's proguard flags",
666						appR8.Args["r8Flags"], transitiveDepFlagsFileName)
667				} else {
668					android.AssertStringDoesNotContain(t, "app did not expect transitive deps's proguard flags",
669						appR8.Args["r8Flags"], transitiveDepFlagsFileName)
670				}
671			})
672		}
673	}
674}
675
676func TestProguardFlagsInheritanceAppImport(t *testing.T) {
677	t.Parallel()
678	bp := `
679		android_app {
680			name: "app",
681			static_libs: ["aarimport"], // this must be static_libs to initate dexing
682			platform_apis: true,
683		}
684
685		android_library_import {
686			name: "aarimport",
687			aars: ["import.aar"],
688		}
689	`
690	result := android.GroupFixturePreparers(
691		PrepareForTestWithJavaDefaultModules,
692	).RunTestWithBp(t, bp)
693
694	appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
695	android.AssertStringDoesContain(t, "expected aarimports's proguard flags",
696		appR8.Args["r8Flags"], "proguard.txt")
697}
698
699func TestR8FlagsArtProfile(t *testing.T) {
700	t.Parallel()
701	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
702		android_app {
703			name: "app",
704			srcs: ["foo.java"],
705			platform_apis: true,
706			dex_preopt: {
707				profile_guided: true,
708				profile: "profile.txt.prof",
709				enable_profile_rewriting: true,
710			},
711		}
712	`)
713
714	app := result.ModuleForTests(t, "app", "android_common")
715	appR8 := app.Rule("r8")
716	android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags",
717		appR8.Args["r8Flags"], "--art-profile")
718
719	appDexpreopt := app.Rule("dexpreopt")
720	android.AssertStringDoesContain(t,
721		"expected --art-profile output to be used to create .prof binary",
722		appDexpreopt.RuleParams.Command,
723		"--create-profile-from=out/soong/.intermediates/app/android_common/profile.prof.txt --output-profile-type=app",
724	)
725}
726
727// This test checks that users explicitly set `enable_profile_rewriting` to true when the following are true
728// 1. optimize or obfuscate is enabled AND
729// 2. dex_preopt.profile_guided is enabled
730//
731// The rewritten profile should be used since the dex signatures in the checked-in profile will not match the optimized binary.
732func TestEnableProfileRewritingIsRequiredForOptimizedApps(t *testing.T) {
733	t.Parallel()
734	testJavaError(t,
735		"Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on",
736		`
737android_app {
738	name: "app",
739	srcs: ["foo.java"],
740	platform_apis: true,
741	dex_preopt: {
742		profile_guided: true,
743		profile: "profile.txt.prof",
744		// enable_profile_rewriting is not set, this is an error
745	},
746	optimize: {
747		optimize: true,
748	}
749}`)
750}
751
752func TestDebugReleaseFlags(t *testing.T) {
753	t.Parallel()
754	bp := `
755		android_app {
756			name: "app",
757			srcs: ["foo.java"],
758			platform_apis: true,
759			optimize: {
760				enabled: %s,
761			},
762			dxflags: ["%s"]
763		}
764	`
765
766	testcases := []struct {
767		name          string
768		envVar        string
769		isEng         bool
770		useD8         bool
771		dxFlags       string
772		expectedFlags string
773	}{
774		{
775			name:          "app_no_optimize_dx",
776			envVar:        "NO_OPTIMIZE_DX",
777			expectedFlags: "--debug",
778		},
779		{
780			name:    "app_release_no_optimize_dx",
781			envVar:  "NO_OPTIMIZE_DX",
782			dxFlags: "--release",
783			// Global env vars override explicit dxflags.
784			expectedFlags: "--debug",
785		},
786		{
787			name:          "app_generate_dex_debug",
788			envVar:        "GENERATE_DEX_DEBUG",
789			expectedFlags: "--debug",
790		},
791		{
792			name:    "app_release_generate_dex_debug",
793			envVar:  "GENERATE_DEX_DEBUG",
794			dxFlags: "--release",
795			// Global env vars override explicit dxflags.
796			expectedFlags: "--debug",
797		},
798		{
799			name:          "app_eng",
800			useD8:         true,
801			isEng:         true,
802			expectedFlags: "--debug",
803		},
804		{
805			name:    "app_release_eng",
806			isEng:   true,
807			useD8:   true,
808			dxFlags: "--release",
809			// Eng mode does *not* override explicit dxflags.
810			expectedFlags: "--release",
811		},
812		{
813			name:  "app_d8",
814			useD8: true,
815			// D8 usage w/ apps should explicitly enable --release mode.
816			expectedFlags: "--release",
817		},
818		{
819			name:    "app_d8_debug",
820			useD8:   true,
821			dxFlags: "--debug",
822			// D8 usage w/ apps respects overriding dxFlags.
823			expectedFlags: "--debug",
824		},
825	}
826
827	for _, tc := range testcases {
828		t.Run(tc.name, func(t *testing.T) {
829			t.Parallel()
830			fixturePreparer := PrepareForTestWithJavaDefaultModules
831			fixturePreparer = android.GroupFixturePreparers(
832				fixturePreparer,
833				android.FixtureModifyProductVariables(
834					func(variables android.FixtureProductVariables) {
835						variables.Eng = proptools.BoolPtr(tc.isEng)
836					},
837				),
838			)
839			if tc.envVar != "" {
840				fixturePreparer = android.GroupFixturePreparers(
841					fixturePreparer,
842					android.FixtureMergeEnv(map[string]string{
843						tc.envVar: "true",
844					}),
845				)
846			}
847			result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, strconv.FormatBool(!tc.useD8), tc.dxFlags))
848
849			dexRuleKey := "r8"
850			if tc.useD8 {
851				dexRuleKey = "d8"
852			}
853			dexFlagsKey := dexRuleKey + "Flags"
854			appDex := result.ModuleForTests(t, "app", "android_common").Rule(dexRuleKey)
855			android.AssertStringDoesContain(t, "expected flag in dex flags",
856				appDex.Args[dexFlagsKey], tc.expectedFlags)
857
858			var unexpectedFlags string
859			if tc.expectedFlags == "--debug" {
860				unexpectedFlags = "--release"
861			} else if tc.expectedFlags == "--release" {
862				unexpectedFlags = "--debug"
863			}
864			if unexpectedFlags != "" {
865				android.AssertStringDoesNotContain(t, "unexpected flag in dex flags",
866					appDex.Args[dexFlagsKey], unexpectedFlags)
867			}
868		})
869	}
870}
871
872func TestTraceReferences(t *testing.T) {
873	t.Parallel()
874	bp := `
875		android_app {
876			name: "app",
877			libs: ["lib.impl"],
878			srcs: ["foo.java"],
879			platform_apis: true,
880		}
881
882		java_library {
883			name: "lib",
884			optimize: {
885				enabled: true,
886				trace_references_from: ["app"],
887			},
888			srcs: ["bar.java"],
889			static_libs: ["lib.impl"],
890			installable: true,
891		}
892
893		java_library {
894			name: "lib.impl",
895			srcs: ["baz.java"],
896		}
897	`
898	result := android.GroupFixturePreparers(
899		PrepareForTestWithJavaDefaultModules,
900	).RunTestWithBp(t, bp)
901
902	appJar := result.ModuleForTests(t, "app", "android_common").Output("combined/app.jar").Output
903	libJar := result.ModuleForTests(t, "lib", "android_common").Output("combined/lib.jar").Output
904	libTraceRefs := result.ModuleForTests(t, "lib", "android_common").Rule("traceReferences")
905	libR8 := result.ModuleForTests(t, "lib", "android_common").Rule("r8")
906
907	android.AssertStringDoesContain(t, "expected trace reference source from app jar",
908		libTraceRefs.Args["sources"], "--source "+appJar.String())
909	android.AssertStringEquals(t, "expected trace reference target into lib jar",
910		libJar.String(), libTraceRefs.Input.String())
911	android.AssertStringDoesContain(t, "expected trace reference proguard flags in lib r8 flags",
912		libR8.Args["r8Flags"], "trace_references.flags")
913}
914