xref: /aosp_15_r20/build/soong/cc/cc_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// 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 cc
16
17import (
18	"fmt"
19	"os"
20	"reflect"
21	"regexp"
22	"runtime"
23	"slices"
24	"strings"
25	"testing"
26
27	"android/soong/aidl_library"
28	"android/soong/android"
29
30	"github.com/google/blueprint"
31)
32
33func init() {
34	registerTestMutators(android.InitRegistrationContext)
35}
36
37func TestMain(m *testing.M) {
38	os.Exit(m.Run())
39}
40
41var prepareForCcTest = android.GroupFixturePreparers(
42	PrepareForIntegrationTestWithCc,
43)
44
45var apexVariationName = "apex28"
46var apexVersion = "28"
47
48func registerTestMutators(ctx android.RegistrationContext) {
49	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
50		ctx.Transition("apex", &testApexTransitionMutator{})
51	})
52}
53
54type testApexTransitionMutator struct{}
55
56func (t *testApexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
57	return []string{apexVariationName}
58}
59
60func (t *testApexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
61	return sourceVariation
62}
63
64func (t *testApexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
65	return incomingVariation
66}
67
68func (t *testApexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
69	apexInfo := android.ApexInfo{
70		ApexVariationName: apexVariationName,
71		MinSdkVersion:     android.ApiLevelForTest(apexVersion),
72	}
73	android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
74}
75
76// testCcWithConfig runs tests using the prepareForCcTest
77//
78// See testCc for an explanation as to how to stop using this deprecated method.
79//
80// deprecated
81func testCcWithConfig(t *testing.T, config android.Config) *android.TestContext {
82	t.Helper()
83	result := prepareForCcTest.RunTestWithConfig(t, config)
84	return result.TestContext
85}
86
87// testCc runs tests using the prepareForCcTest
88//
89// Do not add any new usages of this, instead use the prepareForCcTest directly as it makes it much
90// easier to customize the test behavior.
91//
92// If it is necessary to customize the behavior of an existing test that uses this then please first
93// convert the test to using prepareForCcTest first and then in a following change add the
94// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
95// that it did not change the test behavior unexpectedly.
96//
97// deprecated
98func testCc(t *testing.T, bp string) *android.TestContext {
99	t.Helper()
100	result := prepareForCcTest.RunTestWithBp(t, bp)
101	return result.TestContext
102}
103
104// testCcErrorWithConfig runs tests using the prepareForCcTest
105//
106// See testCc for an explanation as to how to stop using this deprecated method.
107//
108// deprecated
109func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
110	t.Helper()
111
112	prepareForCcTest.
113		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
114		RunTestWithConfig(t, config)
115}
116
117// testCcError runs tests using the prepareForCcTest
118//
119// See testCc for an explanation as to how to stop using this deprecated method.
120//
121// deprecated
122func testCcError(t *testing.T, pattern string, bp string) {
123	t.Helper()
124	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
125	testCcErrorWithConfig(t, pattern, config)
126	return
127}
128
129const (
130	coreVariant     = "android_arm64_armv8-a_shared"
131	vendorVariant   = "android_vendor_arm64_armv8-a_shared"
132	productVariant  = "android_product_arm64_armv8-a_shared"
133	recoveryVariant = "android_recovery_arm64_armv8-a_shared"
134)
135
136// Test that the PrepareForTestWithCcDefaultModules provides all the files that it uses by
137// running it in a fixture that requires all source files to exist.
138func TestPrepareForTestWithCcDefaultModules(t *testing.T) {
139	android.GroupFixturePreparers(
140		PrepareForTestWithCcDefaultModules,
141		android.PrepareForTestDisallowNonExistentPaths,
142	).RunTest(t)
143}
144
145func TestVendorSrc(t *testing.T) {
146	t.Parallel()
147	ctx := testCc(t, `
148		cc_library {
149			name: "libTest",
150			srcs: ["foo.c"],
151			no_libcrt: true,
152			nocrt: true,
153			system_shared_libs: [],
154			vendor_available: true,
155			target: {
156				vendor: {
157					srcs: ["bar.c"],
158				},
159			},
160		}
161	`)
162
163	ld := ctx.ModuleForTests("libTest", vendorVariant).Rule("ld")
164	var objs []string
165	for _, o := range ld.Inputs {
166		objs = append(objs, o.Base())
167	}
168	if len(objs) != 2 || objs[0] != "foo.o" || objs[1] != "bar.o" {
169		t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
170	}
171}
172
173func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
174	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
175	partitionDefined := false
176	checkPartition := func(specific bool, partition string) {
177		if specific {
178			if expected != partition && !partitionDefined {
179				// The variant is installed to the 'partition'
180				t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition)
181			}
182			partitionDefined = true
183		} else {
184			// The variant is not installed to the 'partition'
185			if expected == partition {
186				t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition)
187			}
188		}
189	}
190	socSpecific := func(m *Module) bool {
191		return m.SocSpecific() || m.InstallInVendor()
192	}
193	deviceSpecific := func(m *Module) bool {
194		return m.DeviceSpecific() || m.InstallInOdm()
195	}
196	productSpecific := func(m *Module) bool {
197		return m.ProductSpecific() || m.InstallInProduct()
198	}
199	systemExtSpecific := func(m *Module) bool {
200		return m.SystemExtSpecific()
201	}
202	checkPartition(socSpecific(mod), "vendor")
203	checkPartition(deviceSpecific(mod), "odm")
204	checkPartition(productSpecific(mod), "product")
205	checkPartition(systemExtSpecific(mod), "system_ext")
206	if !partitionDefined && expected != "system" {
207		t.Errorf("%s variant of %q is expected to be installed to %s partition,"+
208			" but installed to system partition", variant, name, expected)
209	}
210}
211
212func TestInstallPartition(t *testing.T) {
213	t.Parallel()
214	t.Helper()
215	ctx := prepareForCcTest.RunTestWithBp(t, `
216		cc_library {
217			name: "libsystem",
218		}
219		cc_library {
220			name: "libsystem_ext",
221			system_ext_specific: true,
222		}
223		cc_library {
224			name: "libproduct",
225			product_specific: true,
226		}
227		cc_library {
228			name: "libvendor",
229			vendor: true,
230		}
231		cc_library {
232			name: "libodm",
233			device_specific: true,
234		}
235		cc_library {
236			name: "liball_available",
237			vendor_available: true,
238			product_available: true,
239		}
240		cc_library {
241			name: "libsystem_ext_all_available",
242			system_ext_specific: true,
243			vendor_available: true,
244			product_available: true,
245		}
246		cc_library {
247			name: "liball_available_odm",
248			odm_available: true,
249			product_available: true,
250		}
251		cc_library {
252			name: "libproduct_vendoravailable",
253			product_specific: true,
254			vendor_available: true,
255		}
256		cc_library {
257			name: "libproduct_odmavailable",
258			product_specific: true,
259			odm_available: true,
260		}
261	`).TestContext
262
263	checkInstallPartition(t, ctx, "libsystem", coreVariant, "system")
264	checkInstallPartition(t, ctx, "libsystem_ext", coreVariant, "system_ext")
265	checkInstallPartition(t, ctx, "libproduct", productVariant, "product")
266	checkInstallPartition(t, ctx, "libvendor", vendorVariant, "vendor")
267	checkInstallPartition(t, ctx, "libodm", vendorVariant, "odm")
268
269	checkInstallPartition(t, ctx, "liball_available", coreVariant, "system")
270	checkInstallPartition(t, ctx, "liball_available", productVariant, "product")
271	checkInstallPartition(t, ctx, "liball_available", vendorVariant, "vendor")
272
273	checkInstallPartition(t, ctx, "libsystem_ext_all_available", coreVariant, "system_ext")
274	checkInstallPartition(t, ctx, "libsystem_ext_all_available", productVariant, "product")
275	checkInstallPartition(t, ctx, "libsystem_ext_all_available", vendorVariant, "vendor")
276
277	checkInstallPartition(t, ctx, "liball_available_odm", coreVariant, "system")
278	checkInstallPartition(t, ctx, "liball_available_odm", productVariant, "product")
279	checkInstallPartition(t, ctx, "liball_available_odm", vendorVariant, "odm")
280
281	checkInstallPartition(t, ctx, "libproduct_vendoravailable", productVariant, "product")
282	checkInstallPartition(t, ctx, "libproduct_vendoravailable", vendorVariant, "vendor")
283
284	checkInstallPartition(t, ctx, "libproduct_odmavailable", productVariant, "product")
285	checkInstallPartition(t, ctx, "libproduct_odmavailable", vendorVariant, "odm")
286}
287
288func checkWriteFileOutput(t *testing.T, ctx *android.TestContext, params android.TestingBuildParams, expected []string) {
289	t.Helper()
290	content := android.ContentFromFileRuleForTests(t, ctx, params)
291	actual := strings.FieldsFunc(content, func(r rune) bool { return r == '\n' })
292	assertArrayString(t, actual, expected)
293}
294
295func TestDataLibs(t *testing.T) {
296	t.Parallel()
297	bp := `
298		cc_test_library {
299			name: "test_lib",
300			srcs: ["test_lib.cpp"],
301			gtest: false,
302		}
303
304		cc_test {
305			name: "main_test",
306			data_libs: ["test_lib"],
307			gtest: false,
308		}
309 `
310
311	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
312
313	ctx := testCcWithConfig(t, config)
314	testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
315	testBinary := testingModule.Module().(*Module).linker.(*testBinary)
316	outputFiles := testingModule.OutputFiles(ctx, t, "")
317	if len(outputFiles) != 1 {
318		t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
319		return
320	}
321	if len(testBinary.dataPaths()) != 1 {
322		t.Errorf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
323		return
324	}
325
326	outputPath := outputFiles[0].String()
327	testBinaryPath := testBinary.dataPaths()[0].SrcPath.String()
328
329	if !strings.HasSuffix(outputPath, "/main_test") {
330		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
331		return
332	}
333	if !strings.HasSuffix(testBinaryPath, "/test_lib.so") {
334		t.Errorf("expected test data file to be 'test_lib.so', but was '%s'", testBinaryPath)
335		return
336	}
337}
338
339func TestDataLibsRelativeInstallPath(t *testing.T) {
340	t.Parallel()
341	bp := `
342		cc_test_library {
343			name: "test_lib",
344			srcs: ["test_lib.cpp"],
345			relative_install_path: "foo/bar/baz",
346			gtest: false,
347		}
348
349		cc_binary {
350			name: "test_bin",
351			relative_install_path: "foo/bar/baz",
352			compile_multilib: "both",
353		}
354
355		cc_test {
356			name: "main_test",
357			data_libs: ["test_lib"],
358			data_bins: ["test_bin"],
359			gtest: false,
360		}
361 `
362
363	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
364
365	ctx := testCcWithConfig(t, config)
366	testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
367	module := testingModule.Module()
368	testBinary := module.(*Module).linker.(*testBinary)
369	outputFiles := testingModule.OutputFiles(ctx, t, "")
370	if len(outputFiles) != 1 {
371		t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
372	}
373	if len(testBinary.dataPaths()) != 2 {
374		t.Fatalf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
375	}
376
377	outputPath := outputFiles[0].String()
378
379	if !strings.HasSuffix(outputPath, "/main_test") {
380		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
381	}
382	entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
383	if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
384		t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
385			" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
386	}
387	if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][1], ":test_bin:foo/bar/baz") {
388		t.Errorf("expected LOCAL_TEST_DATA to end with `:test_bin:foo/bar/baz`,"+
389			" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][1])
390	}
391}
392
393func TestTestBinaryTestSuites(t *testing.T) {
394	t.Parallel()
395	bp := `
396		cc_test {
397			name: "main_test",
398			srcs: ["main_test.cpp"],
399			test_suites: [
400				"suite_1",
401				"suite_2",
402			],
403			gtest: false,
404		}
405	`
406
407	ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
408	module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
409
410	entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
411	compatEntries := entries.EntryMap["LOCAL_COMPATIBILITY_SUITE"]
412	if len(compatEntries) != 2 {
413		t.Errorf("expected two elements in LOCAL_COMPATIBILITY_SUITE. got %d", len(compatEntries))
414	}
415	if compatEntries[0] != "suite_1" {
416		t.Errorf("expected LOCAL_COMPATIBILITY_SUITE to be`suite_1`,"+
417			" but was '%s'", compatEntries[0])
418	}
419	if compatEntries[1] != "suite_2" {
420		t.Errorf("expected LOCAL_COMPATIBILITY_SUITE to be`suite_2`,"+
421			" but was '%s'", compatEntries[1])
422	}
423}
424
425func TestTestLibraryTestSuites(t *testing.T) {
426	t.Parallel()
427	bp := `
428		cc_test_library {
429			name: "main_test_lib",
430			srcs: ["main_test_lib.cpp"],
431			test_suites: [
432				"suite_1",
433				"suite_2",
434			],
435			gtest: false,
436		}
437	`
438
439	ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
440	module := ctx.ModuleForTests("main_test_lib", "android_arm_armv7-a-neon_shared").Module()
441
442	entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
443	compatEntries := entries.EntryMap["LOCAL_COMPATIBILITY_SUITE"]
444	if len(compatEntries) != 2 {
445		t.Errorf("expected two elements in LOCAL_COMPATIBILITY_SUITE. got %d", len(compatEntries))
446	}
447	if compatEntries[0] != "suite_1" {
448		t.Errorf("expected LOCAL_COMPATIBILITY_SUITE to be`suite_1`,"+
449			" but was '%s'", compatEntries[0])
450	}
451	if compatEntries[1] != "suite_2" {
452		t.Errorf("expected LOCAL_COMPATIBILITY_SUITE to be`suite_2`,"+
453			" but was '%s'", compatEntries[1])
454	}
455}
456
457func TestDoubleLoadbleDep(t *testing.T) {
458	t.Parallel()
459	// okay to link : LLNDK -> double_loadable
460	testCc(t, `
461		cc_library {
462			name: "libllndk",
463			shared_libs: ["libdoubleloadable"],
464			llndk: {
465				symbol_file: "libllndk.map.txt",
466			}
467		}
468
469		cc_library {
470			name: "libdoubleloadable",
471			vendor_available: true,
472			product_available: true,
473			double_loadable: true,
474		}
475	`)
476	// okay to link : double_loadable -> double_loadable
477	testCc(t, `
478		cc_library {
479			name: "libdoubleloadable1",
480			shared_libs: ["libdoubleloadable2"],
481			vendor_available: true,
482			double_loadable: true,
483		}
484
485		cc_library {
486			name: "libdoubleloadable2",
487			vendor_available: true,
488			double_loadable: true,
489		}
490	`)
491	// okay to link : double_loadable -> double_loadable
492	testCc(t, `
493		cc_library {
494			name: "libdoubleloadable",
495			vendor_available: true,
496			product_available: true,
497			double_loadable: true,
498			shared_libs: ["libnondoubleloadable"],
499		}
500
501		cc_library {
502			name: "libnondoubleloadable",
503			vendor_available: true,
504			product_available: true,
505			double_loadable: true,
506		}
507	`)
508	// okay to link : LLNDK -> core-only -> vendor_available & double_loadable
509	testCc(t, `
510		cc_library {
511			name: "libllndk",
512			shared_libs: ["libcoreonly"],
513			llndk: {
514				symbol_file: "libllndk.map.txt",
515			}
516		}
517
518		cc_library {
519			name: "libcoreonly",
520			shared_libs: ["libvendoravailable"],
521		}
522
523		// indirect dependency of LLNDK
524		cc_library {
525			name: "libvendoravailable",
526			vendor_available: true,
527			double_loadable: true,
528		}
529	`)
530}
531
532func TestDoubleLoadableDepError(t *testing.T) {
533	t.Parallel()
534	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable lib.
535	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
536		cc_library {
537			name: "libllndk",
538			shared_libs: ["libnondoubleloadable"],
539			llndk: {
540				symbol_file: "libllndk.map.txt",
541			}
542		}
543
544		cc_library {
545			name: "libnondoubleloadable",
546			vendor_available: true,
547			product_available: true,
548		}
549	`)
550
551	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable vendor_available lib.
552	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
553		cc_library {
554			name: "libllndk",
555			no_libcrt: true,
556			shared_libs: ["libnondoubleloadable"],
557			llndk: {
558				symbol_file: "libllndk.map.txt",
559			}
560		}
561
562		cc_library {
563			name: "libnondoubleloadable",
564			vendor_available: true,
565		}
566	`)
567
568	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable indirectly.
569	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
570		cc_library {
571			name: "libllndk",
572			shared_libs: ["libcoreonly"],
573			llndk: {
574				symbol_file: "libllndk.map.txt",
575			}
576		}
577
578		cc_library {
579			name: "libcoreonly",
580			shared_libs: ["libvendoravailable"],
581		}
582
583		// indirect dependency of LLNDK
584		cc_library {
585			name: "libvendoravailable",
586			vendor_available: true,
587		}
588	`)
589
590	// The error is not from 'client' but from 'libllndk'
591	testCcError(t, "module \"libllndk\".* links a library \"libnondoubleloadable\".*double_loadable", `
592		cc_library {
593			name: "client",
594			vendor_available: true,
595			double_loadable: true,
596			shared_libs: ["libllndk"],
597		}
598		cc_library {
599			name: "libllndk",
600			shared_libs: ["libnondoubleloadable"],
601			llndk: {
602				symbol_file: "libllndk.map.txt",
603			}
604		}
605		cc_library {
606			name: "libnondoubleloadable",
607			vendor_available: true,
608		}
609	`)
610}
611
612func TestMakeLinkType(t *testing.T) {
613	t.Parallel()
614	bp := `
615		cc_library {
616			name: "libvendor",
617			vendor: true,
618		}
619		vndk_prebuilt_shared {
620			name: "prevndk",
621			version: "27",
622			target_arch: "arm",
623			binder32bit: true,
624			vendor_available: true,
625			product_available: true,
626			vndk: {
627				enabled: true,
628			},
629			arch: {
630				arm: {
631					srcs: ["liba.so"],
632				},
633			},
634		}
635		cc_library {
636			name: "libllndk",
637			llndk: {
638				symbol_file: "libllndk.map.txt",
639			}
640		}
641		cc_library {
642			name: "libllndkprivate",
643			llndk: {
644				symbol_file: "libllndkprivate.map.txt",
645				private: true,
646			}
647		}
648		llndk_libraries_txt {
649			name: "llndk.libraries.txt",
650		}
651	`
652
653	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
654	// native:vndk
655	ctx := testCcWithConfig(t, config)
656
657	vendorVariant27 := "android_vendor.27_arm64_armv8-a_shared"
658
659	tests := []struct {
660		variant  string
661		name     string
662		expected string
663	}{
664		{vendorVariant, "libvendor", "native:vendor"},
665		{vendorVariant, "libllndk", "native:vndk"},
666		{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vendor"},
667		{coreVariant, "libllndk", "native:platform"},
668	}
669	for _, test := range tests {
670		t.Run(test.name, func(t *testing.T) {
671			module := ctx.ModuleForTests(test.name, test.variant).Module().(*Module)
672			assertString(t, module.makeLinkType, test.expected)
673		})
674	}
675}
676
677var staticLinkDepOrderTestCases = []struct {
678	// This is a string representation of a map[moduleName][]moduleDependency .
679	// It models the dependencies declared in an Android.bp file.
680	inStatic string
681
682	// This is a string representation of a map[moduleName][]moduleDependency .
683	// It models the dependencies declared in an Android.bp file.
684	inShared string
685
686	// allOrdered is a string representation of a map[moduleName][]moduleDependency .
687	// The keys of allOrdered specify which modules we would like to check.
688	// The values of allOrdered specify the expected result (of the transitive closure of all
689	// dependencies) for each module to test
690	allOrdered string
691
692	// outOrdered is a string representation of a map[moduleName][]moduleDependency .
693	// The keys of outOrdered specify which modules we would like to check.
694	// The values of outOrdered specify the expected result (of the ordered linker command line)
695	// for each module to test.
696	outOrdered string
697}{
698	// Simple tests
699	{
700		inStatic:   "",
701		outOrdered: "",
702	},
703	{
704		inStatic:   "a:",
705		outOrdered: "a:",
706	},
707	{
708		inStatic:   "a:b; b:",
709		outOrdered: "a:b; b:",
710	},
711	// Tests of reordering
712	{
713		// diamond example
714		inStatic:   "a:d,b,c; b:d; c:d; d:",
715		outOrdered: "a:b,c,d; b:d; c:d; d:",
716	},
717	{
718		// somewhat real example
719		inStatic:   "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
720		outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
721	},
722	{
723		// multiple reorderings
724		inStatic:   "a:b,c,d,e; d:b; e:c",
725		outOrdered: "a:d,b,e,c; d:b; e:c",
726	},
727	{
728		// should reorder without adding new transitive dependencies
729		inStatic:   "bin:lib2,lib1;             lib1:lib2,liboptional",
730		allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
731		outOrdered: "bin:lib1,lib2;             lib1:lib2,liboptional",
732	},
733	{
734		// multiple levels of dependencies
735		inStatic:   "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
736		allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
737		outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
738	},
739	// shared dependencies
740	{
741		// Note that this test doesn't recurse, to minimize the amount of logic it tests.
742		// So, we don't actually have to check that a shared dependency of c will change the order
743		// of a library that depends statically on b and on c.  We only need to check that if c has
744		// a shared dependency on b, that that shows up in allOrdered.
745		inShared:   "c:b",
746		allOrdered: "c:b",
747		outOrdered: "c:",
748	},
749	{
750		// This test doesn't actually include any shared dependencies but it's a reminder of what
751		// the second phase of the above test would look like
752		inStatic:   "a:b,c; c:b",
753		allOrdered: "a:c,b; c:b",
754		outOrdered: "a:c,b; c:b",
755	},
756	// tiebreakers for when two modules specifying different orderings and there is no dependency
757	// to dictate an order
758	{
759		// if the tie is between two modules at the end of a's deps, then a's order wins
760		inStatic:   "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
761		outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
762	},
763	{
764		// if the tie is between two modules at the start of a's deps, then c's order is used
765		inStatic:   "a1:d,e,b1,c1; b1:d,e; c1:e,d;   a2:d,e,b2,c2; b2:d,e; c2:d,e",
766		outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d;   a2:b2,c2,d,e; b2:d,e; c2:d,e",
767	},
768	// Tests involving duplicate dependencies
769	{
770		// simple duplicate
771		inStatic:   "a:b,c,c,b",
772		outOrdered: "a:c,b",
773	},
774	{
775		// duplicates with reordering
776		inStatic:   "a:b,c,d,c; c:b",
777		outOrdered: "a:d,c,b",
778	},
779	// Tests to confirm the nonexistence of infinite loops.
780	// These cases should never happen, so as long as the test terminates and the
781	// result is deterministic then that should be fine.
782	{
783		inStatic:   "a:a",
784		outOrdered: "a:a",
785	},
786	{
787		inStatic:   "a:b;   b:c;   c:a",
788		allOrdered: "a:b,c; b:c,a; c:a,b",
789		outOrdered: "a:b;   b:c;   c:a",
790	},
791	{
792		inStatic:   "a:b,c;   b:c,a;   c:a,b",
793		allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
794		outOrdered: "a:c,b;   b:a,c;   c:b,a",
795	},
796}
797
798// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
799func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
800	// convert from "a:b,c; d:e" to "a:b,c;d:e"
801	strippedText := strings.Replace(text, " ", "", -1)
802	if len(strippedText) < 1 {
803		return []android.Path{}, make(map[android.Path][]android.Path, 0)
804	}
805	allDeps = make(map[android.Path][]android.Path, 0)
806
807	// convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
808	moduleTexts := strings.Split(strippedText, ";")
809
810	outputForModuleName := func(moduleName string) android.Path {
811		return android.PathForTesting(moduleName)
812	}
813
814	for _, moduleText := range moduleTexts {
815		// convert from "a:b,c" to ["a", "b,c"]
816		components := strings.Split(moduleText, ":")
817		if len(components) != 2 {
818			panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
819		}
820		moduleName := components[0]
821		moduleOutput := outputForModuleName(moduleName)
822		modulesInOrder = append(modulesInOrder, moduleOutput)
823
824		depString := components[1]
825		// convert from "b,c" to ["b", "c"]
826		depNames := strings.Split(depString, ",")
827		if len(depString) < 1 {
828			depNames = []string{}
829		}
830		var deps []android.Path
831		for _, depName := range depNames {
832			deps = append(deps, outputForModuleName(depName))
833		}
834		allDeps[moduleOutput] = deps
835	}
836	return modulesInOrder, allDeps
837}
838
839func TestStaticLibDepReordering(t *testing.T) {
840	t.Parallel()
841	ctx := testCc(t, `
842	cc_library {
843		name: "a",
844		static_libs: ["b", "c", "d"],
845		stl: "none",
846	}
847	cc_library {
848		name: "b",
849		stl: "none",
850	}
851	cc_library {
852		name: "c",
853		static_libs: ["b"],
854		stl: "none",
855	}
856	cc_library {
857		name: "d",
858		stl: "none",
859	}
860
861	`)
862
863	variant := "android_arm64_armv8-a_static"
864	moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
865	staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
866	actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
867	expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
868
869	if !reflect.DeepEqual(actual, expected) {
870		t.Errorf("staticDeps orderings were not propagated correctly"+
871			"\nactual:   %v"+
872			"\nexpected: %v",
873			actual,
874			expected,
875		)
876	}
877}
878
879func TestStaticLibDepReorderingWithShared(t *testing.T) {
880	t.Parallel()
881	ctx := testCc(t, `
882	cc_library {
883		name: "a",
884		static_libs: ["b", "c"],
885		stl: "none",
886	}
887	cc_library {
888		name: "b",
889		stl: "none",
890	}
891	cc_library {
892		name: "c",
893		shared_libs: ["b"],
894		stl: "none",
895	}
896
897	`)
898
899	variant := "android_arm64_armv8-a_static"
900	moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
901	staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
902	actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
903	expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b"})
904
905	if !reflect.DeepEqual(actual, expected) {
906		t.Errorf("staticDeps orderings did not account for shared libs"+
907			"\nactual:   %v"+
908			"\nexpected: %v",
909			actual,
910			expected,
911		)
912	}
913}
914
915func checkEquals(t *testing.T, message string, expected, actual interface{}) {
916	t.Helper()
917	if !reflect.DeepEqual(actual, expected) {
918		t.Errorf(message+
919			"\nactual:   %v"+
920			"\nexpected: %v",
921			actual,
922			expected,
923		)
924	}
925}
926
927func TestLlndkLibrary(t *testing.T) {
928	t.Parallel()
929	result := prepareForCcTest.RunTestWithBp(t, `
930	cc_library {
931		name: "libllndk",
932		stubs: { versions: ["1", "2"] },
933		llndk: {
934			symbol_file: "libllndk.map.txt",
935		},
936		export_include_dirs: ["include"],
937	}
938
939	cc_prebuilt_library_shared {
940		name: "libllndkprebuilt",
941		stubs: { versions: ["1", "2"] , symbol_file: "libllndkprebuilt.map.txt" },
942		llndk: {
943			symbol_file: "libllndkprebuilt.map.txt",
944		},
945	}
946
947	cc_library {
948		name: "libllndk_with_external_headers",
949		stubs: { versions: ["1", "2"] },
950		llndk: {
951			symbol_file: "libllndk.map.txt",
952			export_llndk_headers: ["libexternal_llndk_headers"],
953		},
954		header_libs: ["libexternal_headers"],
955		export_header_lib_headers: ["libexternal_headers"],
956	}
957	cc_library_headers {
958		name: "libexternal_headers",
959		export_include_dirs: ["include"],
960		vendor_available: true,
961		product_available: true,
962	}
963	cc_library_headers {
964		name: "libexternal_llndk_headers",
965		export_include_dirs: ["include_llndk"],
966		export_system_include_dirs: ["include_system_llndk"],
967		llndk: {
968			symbol_file: "libllndk.map.txt",
969		},
970		vendor_available: true,
971	}
972
973	cc_library {
974		name: "libllndk_with_override_headers",
975		stubs: { versions: ["1", "2"] },
976		llndk: {
977			symbol_file: "libllndk.map.txt",
978			override_export_include_dirs: ["include_llndk"],
979		},
980		export_include_dirs: ["include"],
981	}
982
983	cc_library {
984		name: "libllndk_with_system_headers",
985		llndk: {
986			symbol_file: "libllndk.map.txt",
987			export_llndk_headers: ["libexternal_llndk_headers"],
988			export_headers_as_system: true,
989		},
990		export_include_dirs: ["include"],
991		export_system_include_dirs: ["include_system"],
992	}
993	`)
994	actual := result.ModuleVariantsForTests("libllndk")
995	for i := 0; i < len(actual); i++ {
996		if !strings.HasPrefix(actual[i], "android_vendor_") {
997			actual = append(actual[:i], actual[i+1:]...)
998			i--
999		}
1000	}
1001	expected := []string{
1002		"android_vendor_arm64_armv8-a_shared",
1003		"android_vendor_arm_armv7-a-neon_shared",
1004	}
1005	android.AssertArrayString(t, "variants for llndk stubs", expected, actual)
1006
1007	params := result.ModuleForTests("libllndk", "android_vendor_arm_armv7-a-neon_shared").Description("generate stub")
1008	android.AssertSame(t, "use Vendor API level for default stubs", "35", params.Args["apiLevel"])
1009
1010	checkExportedIncludeDirs := func(module, variant string, expectedSystemDirs []string, expectedDirs ...string) {
1011		t.Helper()
1012		m := result.ModuleForTests(module, variant).Module()
1013		f, _ := android.OtherModuleProvider(result, m, FlagExporterInfoProvider)
1014		android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
1015			expectedDirs, f.IncludeDirs)
1016		android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
1017			expectedSystemDirs, f.SystemIncludeDirs)
1018	}
1019
1020	checkExportedIncludeDirs("libllndk", coreVariant, nil, "include")
1021	checkExportedIncludeDirs("libllndk", vendorVariant, nil, "include")
1022	checkExportedIncludeDirs("libllndk_with_external_headers", coreVariant, nil, "include")
1023	checkExportedIncludeDirs("libllndk_with_external_headers", vendorVariant,
1024		[]string{"include_system_llndk"}, "include_llndk")
1025	checkExportedIncludeDirs("libllndk_with_override_headers", coreVariant, nil, "include")
1026	checkExportedIncludeDirs("libllndk_with_override_headers", vendorVariant, nil, "include_llndk")
1027	checkExportedIncludeDirs("libllndk_with_system_headers", coreVariant, []string{"include_system"}, "include")
1028	checkExportedIncludeDirs("libllndk_with_system_headers", vendorVariant,
1029		[]string{"include_system", "include", "include_system_llndk"}, "include_llndk")
1030
1031	checkAbiLinkerIncludeDirs := func(module string) {
1032		t.Helper()
1033		coreModule := result.ModuleForTests(module, coreVariant)
1034		abiCheckFlags := ""
1035		for _, output := range coreModule.AllOutputs() {
1036			if strings.HasSuffix(output, ".so.llndk.lsdump") {
1037				abiCheckFlags = coreModule.Output(output).Args["exportedHeaderFlags"]
1038			}
1039		}
1040		vendorModule := result.ModuleForTests(module, vendorVariant).Module()
1041		vendorInfo, _ := android.OtherModuleProvider(result, vendorModule, FlagExporterInfoProvider)
1042		vendorDirs := android.Concat(vendorInfo.IncludeDirs, vendorInfo.SystemIncludeDirs)
1043		android.AssertStringEquals(t, module+" has different exported include dirs for vendor variant and ABI check",
1044			android.JoinPathsWithPrefix(vendorDirs, "-I"), abiCheckFlags)
1045	}
1046	checkAbiLinkerIncludeDirs("libllndk")
1047	checkAbiLinkerIncludeDirs("libllndk_with_override_headers")
1048	checkAbiLinkerIncludeDirs("libllndk_with_external_headers")
1049	checkAbiLinkerIncludeDirs("libllndk_with_system_headers")
1050}
1051
1052func TestLlndkHeaders(t *testing.T) {
1053	t.Parallel()
1054	ctx := testCc(t, `
1055	cc_library_headers {
1056		name: "libllndk_headers",
1057		export_include_dirs: ["my_include"],
1058		llndk: {
1059			llndk_headers: true,
1060		},
1061	}
1062	cc_library {
1063		name: "libllndk",
1064		llndk: {
1065			symbol_file: "libllndk.map.txt",
1066			export_llndk_headers: ["libllndk_headers"],
1067		}
1068	}
1069
1070	cc_library {
1071		name: "libvendor",
1072		shared_libs: ["libllndk"],
1073		vendor: true,
1074		srcs: ["foo.c"],
1075		no_libcrt: true,
1076		nocrt: true,
1077	}
1078	`)
1079
1080	// _static variant is used since _shared reuses *.o from the static variant
1081	cc := ctx.ModuleForTests("libvendor", "android_vendor_arm_armv7-a-neon_static").Rule("cc")
1082	cflags := cc.Args["cFlags"]
1083	if !strings.Contains(cflags, "-Imy_include") {
1084		t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
1085	}
1086}
1087
1088func checkRuntimeLibs(t *testing.T, expected []string, module *Module) {
1089	actual := module.Properties.AndroidMkRuntimeLibs
1090	if !reflect.DeepEqual(actual, expected) {
1091		t.Errorf("incorrect runtime_libs for shared libs"+
1092			"\nactual:   %v"+
1093			"\nexpected: %v",
1094			actual,
1095			expected,
1096		)
1097	}
1098}
1099
1100const runtimeLibAndroidBp = `
1101	cc_library {
1102		name: "liball_available",
1103		vendor_available: true,
1104		product_available: true,
1105		no_libcrt : true,
1106		nocrt : true,
1107		system_shared_libs : [],
1108	}
1109	cc_library {
1110		name: "libvendor_available1",
1111		vendor_available: true,
1112		runtime_libs: ["liball_available"],
1113		no_libcrt : true,
1114		nocrt : true,
1115		system_shared_libs : [],
1116	}
1117	cc_library {
1118		name: "libvendor_available2",
1119		vendor_available: true,
1120		runtime_libs: ["liball_available"],
1121		target: {
1122			vendor: {
1123				exclude_runtime_libs: ["liball_available"],
1124			}
1125		},
1126		no_libcrt : true,
1127		nocrt : true,
1128		system_shared_libs : [],
1129	}
1130	cc_library {
1131		name: "libproduct_vendor",
1132		product_specific: true,
1133		vendor_available: true,
1134		no_libcrt : true,
1135		nocrt : true,
1136		system_shared_libs : [],
1137	}
1138	cc_library {
1139		name: "libcore",
1140		runtime_libs: ["liball_available"],
1141		no_libcrt : true,
1142		nocrt : true,
1143		system_shared_libs : [],
1144	}
1145	cc_library {
1146		name: "libvendor1",
1147		vendor: true,
1148		no_libcrt : true,
1149		nocrt : true,
1150		system_shared_libs : [],
1151	}
1152	cc_library {
1153		name: "libvendor2",
1154		vendor: true,
1155		runtime_libs: ["liball_available", "libvendor1", "libproduct_vendor"],
1156		no_libcrt : true,
1157		nocrt : true,
1158		system_shared_libs : [],
1159	}
1160	cc_library {
1161		name: "libproduct_available1",
1162		product_available: true,
1163		runtime_libs: ["liball_available"],
1164		no_libcrt : true,
1165		nocrt : true,
1166		system_shared_libs : [],
1167	}
1168	cc_library {
1169		name: "libproduct1",
1170		product_specific: true,
1171		no_libcrt : true,
1172		nocrt : true,
1173		system_shared_libs : [],
1174	}
1175	cc_library {
1176		name: "libproduct2",
1177		product_specific: true,
1178		runtime_libs: ["liball_available", "libproduct1", "libproduct_vendor"],
1179		no_libcrt : true,
1180		nocrt : true,
1181		system_shared_libs : [],
1182	}
1183`
1184
1185func TestRuntimeLibs(t *testing.T) {
1186	t.Parallel()
1187	ctx := testCc(t, runtimeLibAndroidBp)
1188
1189	// runtime_libs for core variants use the module names without suffixes.
1190	variant := "android_arm64_armv8-a_shared"
1191
1192	module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
1193	checkRuntimeLibs(t, []string{"liball_available"}, module)
1194
1195	module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
1196	checkRuntimeLibs(t, []string{"liball_available"}, module)
1197
1198	module = ctx.ModuleForTests("libcore", variant).Module().(*Module)
1199	checkRuntimeLibs(t, []string{"liball_available"}, module)
1200
1201	// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
1202	// and vendor variants.
1203	variant = "android_vendor_arm64_armv8-a_shared"
1204
1205	module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
1206	checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
1207
1208	module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
1209	checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1", "libproduct_vendor.vendor"}, module)
1210
1211	// runtime_libs for product variants have '.product' suffixes if the modules have both core
1212	// and product variants.
1213	variant = "android_product_arm64_armv8-a_shared"
1214
1215	module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
1216	checkRuntimeLibs(t, []string{"liball_available.product"}, module)
1217
1218	module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
1219	checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1", "libproduct_vendor"}, module)
1220}
1221
1222func TestExcludeRuntimeLibs(t *testing.T) {
1223	t.Parallel()
1224	ctx := testCc(t, runtimeLibAndroidBp)
1225
1226	variant := "android_arm64_armv8-a_shared"
1227	module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
1228	checkRuntimeLibs(t, []string{"liball_available"}, module)
1229
1230	variant = "android_vendor_arm64_armv8-a_shared"
1231	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
1232	checkRuntimeLibs(t, nil, module)
1233}
1234
1235func checkStaticLibs(t *testing.T, expected []string, module *Module) {
1236	t.Helper()
1237	actual := module.Properties.AndroidMkStaticLibs
1238	if !reflect.DeepEqual(actual, expected) {
1239		t.Errorf("incorrect static_libs"+
1240			"\nactual:   %v"+
1241			"\nexpected: %v",
1242			actual,
1243			expected,
1244		)
1245	}
1246}
1247
1248const staticLibAndroidBp = `
1249	cc_library {
1250		name: "lib1",
1251	}
1252	cc_library {
1253		name: "lib2",
1254		static_libs: ["lib1"],
1255	}
1256`
1257
1258func TestStaticLibDepExport(t *testing.T) {
1259	t.Parallel()
1260	ctx := testCc(t, staticLibAndroidBp)
1261
1262	// Check the shared version of lib2.
1263	variant := "android_arm64_armv8-a_shared"
1264	module := ctx.ModuleForTests("lib2", variant).Module().(*Module)
1265	checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins"}, module)
1266
1267	// Check the static version of lib2.
1268	variant = "android_arm64_armv8-a_static"
1269	module = ctx.ModuleForTests("lib2", variant).Module().(*Module)
1270	// libc++_static is linked additionally.
1271	checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins"}, module)
1272}
1273
1274var compilerFlagsTestCases = []struct {
1275	in  string
1276	out bool
1277}{
1278	{
1279		in:  "a",
1280		out: false,
1281	},
1282	{
1283		in:  "-a",
1284		out: true,
1285	},
1286	{
1287		in:  "-Ipath/to/something",
1288		out: false,
1289	},
1290	{
1291		in:  "-isystempath/to/something",
1292		out: false,
1293	},
1294	{
1295		in:  "--coverage",
1296		out: false,
1297	},
1298	{
1299		in:  "-include a/b",
1300		out: true,
1301	},
1302	{
1303		in:  "-include a/b c/d",
1304		out: false,
1305	},
1306	{
1307		in:  "-DMACRO",
1308		out: true,
1309	},
1310	{
1311		in:  "-DMAC RO",
1312		out: false,
1313	},
1314	{
1315		in:  "-a -b",
1316		out: false,
1317	},
1318	{
1319		in:  "-DMACRO=definition",
1320		out: true,
1321	},
1322	{
1323		in:  "-DMACRO=defi nition",
1324		out: true, // TODO(jiyong): this should be false
1325	},
1326	{
1327		in:  "-DMACRO(x)=x + 1",
1328		out: true,
1329	},
1330	{
1331		in:  "-DMACRO=\"defi nition\"",
1332		out: true,
1333	},
1334}
1335
1336type mockContext struct {
1337	BaseModuleContext
1338	result bool
1339}
1340
1341func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
1342	// CheckBadCompilerFlags calls this function when the flag should be rejected
1343	ctx.result = false
1344}
1345
1346func TestCompilerFlags(t *testing.T) {
1347	t.Parallel()
1348	for _, testCase := range compilerFlagsTestCases {
1349		ctx := &mockContext{result: true}
1350		CheckBadCompilerFlags(ctx, "", []string{testCase.in})
1351		if ctx.result != testCase.out {
1352			t.Errorf("incorrect output:")
1353			t.Errorf("     input: %#v", testCase.in)
1354			t.Errorf("  expected: %#v", testCase.out)
1355			t.Errorf("       got: %#v", ctx.result)
1356		}
1357	}
1358}
1359
1360func TestRecovery(t *testing.T) {
1361	t.Parallel()
1362	ctx := testCc(t, `
1363		cc_library_shared {
1364			name: "librecovery",
1365			recovery: true,
1366		}
1367		cc_library_shared {
1368			name: "librecovery32",
1369			recovery: true,
1370			compile_multilib:"32",
1371		}
1372		cc_library_shared {
1373			name: "libHalInRecovery",
1374			recovery_available: true,
1375			vendor: true,
1376		}
1377	`)
1378
1379	variants := ctx.ModuleVariantsForTests("librecovery")
1380	const arm64 = "android_recovery_arm64_armv8-a_shared"
1381	if len(variants) != 1 || !android.InList(arm64, variants) {
1382		t.Errorf("variants of librecovery must be \"%s\" only, but was %#v", arm64, variants)
1383	}
1384
1385	variants = ctx.ModuleVariantsForTests("librecovery32")
1386	if android.InList(arm64, variants) {
1387		t.Errorf("multilib was set to 32 for librecovery32, but its variants has %s.", arm64)
1388	}
1389
1390	recoveryModule := ctx.ModuleForTests("libHalInRecovery", recoveryVariant).Module().(*Module)
1391	if !recoveryModule.Platform() {
1392		t.Errorf("recovery variant of libHalInRecovery must not specific to device, soc, or product")
1393	}
1394}
1395
1396func TestDataLibsPrebuiltSharedTestLibrary(t *testing.T) {
1397	t.Parallel()
1398	bp := `
1399		cc_prebuilt_test_library_shared {
1400			name: "test_lib",
1401			relative_install_path: "foo/bar/baz",
1402			srcs: ["srcpath/dontusethispath/baz.so"],
1403		}
1404
1405		cc_test {
1406			name: "main_test",
1407			data_libs: ["test_lib"],
1408			gtest: false,
1409		}
1410 `
1411
1412	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
1413
1414	ctx := testCcWithConfig(t, config)
1415	testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
1416	module := testingModule.Module()
1417	testBinary := module.(*Module).linker.(*testBinary)
1418	outputFiles := testingModule.OutputFiles(ctx, t, "")
1419	if len(outputFiles) != 1 {
1420		t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
1421	}
1422	if len(testBinary.dataPaths()) != 1 {
1423		t.Errorf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
1424	}
1425
1426	outputPath := outputFiles[0].String()
1427
1428	if !strings.HasSuffix(outputPath, "/main_test") {
1429		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
1430	}
1431	entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
1432	if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
1433		t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
1434			" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
1435	}
1436}
1437
1438func TestVersionedStubs(t *testing.T) {
1439	t.Parallel()
1440	ctx := testCc(t, `
1441		cc_library_shared {
1442			name: "libFoo",
1443			srcs: ["foo.c"],
1444			stubs: {
1445				symbol_file: "foo.map.txt",
1446				versions: ["1", "2", "3"],
1447			},
1448		}
1449
1450		cc_library_shared {
1451			name: "libBar",
1452			srcs: ["bar.c"],
1453			shared_libs: ["libFoo#1"],
1454		}`)
1455
1456	variants := ctx.ModuleVariantsForTests("libFoo")
1457	expectedVariants := []string{
1458		"android_arm64_armv8-a_shared",
1459		"android_arm64_armv8-a_shared_1",
1460		"android_arm64_armv8-a_shared_2",
1461		"android_arm64_armv8-a_shared_3",
1462		"android_arm64_armv8-a_shared_current",
1463		"android_arm_armv7-a-neon_shared",
1464		"android_arm_armv7-a-neon_shared_1",
1465		"android_arm_armv7-a-neon_shared_2",
1466		"android_arm_armv7-a-neon_shared_3",
1467		"android_arm_armv7-a-neon_shared_current",
1468	}
1469	variantsMismatch := false
1470	if len(variants) != len(expectedVariants) {
1471		variantsMismatch = true
1472	} else {
1473		for _, v := range expectedVariants {
1474			if !inList(v, variants) {
1475				variantsMismatch = false
1476			}
1477		}
1478	}
1479	if variantsMismatch {
1480		t.Errorf("variants of libFoo expected:\n")
1481		for _, v := range expectedVariants {
1482			t.Errorf("%q\n", v)
1483		}
1484		t.Errorf(", but got:\n")
1485		for _, v := range variants {
1486			t.Errorf("%q\n", v)
1487		}
1488	}
1489
1490	libBarLinkRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_shared").Rule("ld")
1491	libFlags := libBarLinkRule.Args["libFlags"]
1492	libFoo1StubPath := "libFoo/android_arm64_armv8-a_shared_1/libFoo.so"
1493	if !strings.Contains(libFlags, libFoo1StubPath) {
1494		t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
1495	}
1496
1497	libBarCompileRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_shared").Rule("cc")
1498	cFlags := libBarCompileRule.Args["cFlags"]
1499	libFoo1VersioningMacro := "-D__LIBFOO_API__=1"
1500	if !strings.Contains(cFlags, libFoo1VersioningMacro) {
1501		t.Errorf("%q is not found in %q", libFoo1VersioningMacro, cFlags)
1502	}
1503}
1504
1505func TestVersioningMacro(t *testing.T) {
1506	t.Parallel()
1507	for _, tc := range []struct{ moduleName, expected string }{
1508		{"libc", "__LIBC_API__"},
1509		{"libfoo", "__LIBFOO_API__"},
1510		{"libfoo@1", "__LIBFOO_1_API__"},
1511		{"libfoo-v1", "__LIBFOO_V1_API__"},
1512		{"libfoo.v1", "__LIBFOO_V1_API__"},
1513	} {
1514		checkEquals(t, tc.moduleName, tc.expected, versioningMacroName(tc.moduleName))
1515	}
1516}
1517
1518func pathsToBase(paths android.Paths) []string {
1519	var ret []string
1520	for _, p := range paths {
1521		ret = append(ret, p.Base())
1522	}
1523	return ret
1524}
1525
1526func TestStaticLibArchiveArgs(t *testing.T) {
1527	t.Parallel()
1528	ctx := testCc(t, `
1529		cc_library_static {
1530			name: "foo",
1531			srcs: ["foo.c"],
1532		}
1533
1534		cc_library_static {
1535			name: "bar",
1536			srcs: ["bar.c"],
1537		}
1538
1539		cc_library_shared {
1540			name: "qux",
1541			srcs: ["qux.c"],
1542		}
1543
1544		cc_library_static {
1545			name: "baz",
1546			srcs: ["baz.c"],
1547			static_libs: ["foo"],
1548			shared_libs: ["qux"],
1549			whole_static_libs: ["bar"],
1550		}`)
1551
1552	variant := "android_arm64_armv8-a_static"
1553	arRule := ctx.ModuleForTests("baz", variant).Rule("ar")
1554
1555	// For static libraries, the object files of a whole static dep are included in the archive
1556	// directly
1557	if g, w := pathsToBase(arRule.Inputs), []string{"bar.o", "baz.o"}; !reflect.DeepEqual(w, g) {
1558		t.Errorf("Expected input objects %q, got %q", w, g)
1559	}
1560
1561	// non whole static dependencies are not linked into the archive
1562	if len(arRule.Implicits) > 0 {
1563		t.Errorf("Expected 0 additional deps, got %q", arRule.Implicits)
1564	}
1565}
1566
1567func TestSharedLibLinkingArgs(t *testing.T) {
1568	t.Parallel()
1569	ctx := testCc(t, `
1570		cc_library_static {
1571			name: "foo",
1572			srcs: ["foo.c"],
1573		}
1574
1575		cc_library_static {
1576			name: "bar",
1577			srcs: ["bar.c"],
1578		}
1579
1580		cc_library_shared {
1581			name: "qux",
1582			srcs: ["qux.c"],
1583		}
1584
1585		cc_library_shared {
1586			name: "baz",
1587			srcs: ["baz.c"],
1588			static_libs: ["foo"],
1589			shared_libs: ["qux"],
1590			whole_static_libs: ["bar"],
1591		}`)
1592
1593	variant := "android_arm64_armv8-a_shared"
1594	linkRule := ctx.ModuleForTests("baz", variant).Rule("ld")
1595	libFlags := linkRule.Args["libFlags"]
1596	// When dynamically linking, we expect static dependencies to be found on the command line
1597	if expected := "foo.a"; !strings.Contains(libFlags, expected) {
1598		t.Errorf("Static lib %q was not found in %q", expected, libFlags)
1599	}
1600	// When dynamically linking, we expect whole static dependencies to be found on the command line
1601	if expected := "bar.a"; !strings.Contains(libFlags, expected) {
1602		t.Errorf("Static lib %q was not found in %q", expected, libFlags)
1603	}
1604
1605	// When dynamically linking, we expect shared dependencies to be found on the command line
1606	if expected := "qux.so"; !strings.Contains(libFlags, expected) {
1607		t.Errorf("Shared lib %q was not found in %q", expected, libFlags)
1608	}
1609
1610	// We should only have the objects from the shared library srcs, not the whole static dependencies
1611	if g, w := pathsToBase(linkRule.Inputs), []string{"baz.o"}; !reflect.DeepEqual(w, g) {
1612		t.Errorf("Expected input objects %q, got %q", w, g)
1613	}
1614}
1615
1616func TestStaticExecutable(t *testing.T) {
1617	t.Parallel()
1618	ctx := testCc(t, `
1619		cc_binary {
1620			name: "static_test",
1621			srcs: ["foo.c", "baz.o"],
1622			static_executable: true,
1623		}`)
1624
1625	variant := "android_arm64_armv8-a"
1626	binModuleRule := ctx.ModuleForTests("static_test", variant).Rule("ld")
1627	libFlags := binModuleRule.Args["libFlags"]
1628	systemStaticLibs := []string{"libc.a", "libm.a"}
1629	for _, lib := range systemStaticLibs {
1630		if !strings.Contains(libFlags, lib) {
1631			t.Errorf("Static lib %q was not found in %q", lib, libFlags)
1632		}
1633	}
1634	systemSharedLibs := []string{"libc.so", "libm.so", "libdl.so"}
1635	for _, lib := range systemSharedLibs {
1636		if strings.Contains(libFlags, lib) {
1637			t.Errorf("Shared lib %q was found in %q", lib, libFlags)
1638		}
1639	}
1640}
1641
1642func TestStaticDepsOrderWithStubs(t *testing.T) {
1643	t.Parallel()
1644	ctx := testCc(t, `
1645		cc_binary {
1646			name: "mybin",
1647			srcs: ["foo.c"],
1648			static_libs: ["libfooC", "libfooB"],
1649			static_executable: true,
1650			stl: "none",
1651		}
1652
1653		cc_library {
1654			name: "libfooB",
1655			srcs: ["foo.c"],
1656			shared_libs: ["libfooC"],
1657			stl: "none",
1658		}
1659
1660		cc_library {
1661			name: "libfooC",
1662			srcs: ["foo.c"],
1663			stl: "none",
1664			stubs: {
1665				versions: ["1"],
1666			},
1667		}`)
1668
1669	mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld")
1670	actual := mybin.Implicits[:2]
1671	expected := GetOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
1672
1673	if !reflect.DeepEqual(actual, expected) {
1674		t.Errorf("staticDeps orderings were not propagated correctly"+
1675			"\nactual:   %v"+
1676			"\nexpected: %v",
1677			actual,
1678			expected,
1679		)
1680	}
1681}
1682
1683func TestErrorsIfAModuleDependsOnDisabled(t *testing.T) {
1684	t.Parallel()
1685	testCcError(t, `module "libA" .* depends on disabled module "libB"`, `
1686		cc_library {
1687			name: "libA",
1688			srcs: ["foo.c"],
1689			shared_libs: ["libB"],
1690			stl: "none",
1691		}
1692
1693		cc_library {
1694			name: "libB",
1695			srcs: ["foo.c"],
1696			enabled: false,
1697			stl: "none",
1698		}
1699	`)
1700}
1701
1702func VerifyAFLFuzzTargetVariant(t *testing.T, variant string) {
1703	bp := `
1704		cc_fuzz {
1705			name: "test_afl_fuzz_target",
1706			srcs: ["foo.c"],
1707			host_supported: true,
1708			static_libs: [
1709				"afl_fuzz_static_lib",
1710			],
1711			shared_libs: [
1712				"afl_fuzz_shared_lib",
1713			],
1714			fuzzing_frameworks: {
1715				afl: true,
1716				libfuzzer: false,
1717			},
1718		}
1719		cc_library {
1720			name: "afl_fuzz_static_lib",
1721			host_supported: true,
1722			srcs: ["static_file.c"],
1723		}
1724		cc_library {
1725			name: "libfuzzer_only_static_lib",
1726			host_supported: true,
1727			srcs: ["static_file.c"],
1728		}
1729		cc_library {
1730			name: "afl_fuzz_shared_lib",
1731			host_supported: true,
1732			srcs: ["shared_file.c"],
1733			static_libs: [
1734				"second_static_lib",
1735			],
1736		}
1737		cc_library_headers {
1738			name: "libafl_headers",
1739			vendor_available: true,
1740			host_supported: true,
1741			export_include_dirs: [
1742				"include",
1743				"instrumentation",
1744			],
1745		}
1746		cc_object {
1747			name: "afl-compiler-rt",
1748			vendor_available: true,
1749			host_supported: true,
1750			cflags: [
1751				"-fPIC",
1752			],
1753			srcs: [
1754				"instrumentation/afl-compiler-rt.o.c",
1755			],
1756		}
1757		cc_library {
1758			name: "second_static_lib",
1759			host_supported: true,
1760			srcs: ["second_file.c"],
1761		}
1762		cc_object {
1763			name: "aflpp_driver",
1764			host_supported: true,
1765			srcs: [
1766				"aflpp_driver.c",
1767			],
1768		}`
1769
1770	testEnv := map[string]string{
1771		"FUZZ_FRAMEWORK": "AFL",
1772	}
1773
1774	ctx := android.GroupFixturePreparers(prepareForCcTest, android.FixtureMergeEnv(testEnv)).RunTestWithBp(t, bp)
1775
1776	checkPcGuardFlag := func(
1777		modName string, variantName string, shouldHave bool) {
1778		cc := ctx.ModuleForTests(modName, variantName).Rule("cc")
1779
1780		cFlags, ok := cc.Args["cFlags"]
1781		if !ok {
1782			t.Errorf("Could not find cFlags for module %s and variant %s",
1783				modName, variantName)
1784		}
1785
1786		if strings.Contains(
1787			cFlags, "-fsanitize-coverage=trace-pc-guard") != shouldHave {
1788			t.Errorf("Flag was found: %t. Expected to find flag:  %t. "+
1789				"Test failed for module %s and variant %s",
1790				!shouldHave, shouldHave, modName, variantName)
1791		}
1792	}
1793
1794	moduleName := "test_afl_fuzz_target"
1795	checkPcGuardFlag(moduleName, variant+"_fuzzer", true)
1796
1797	moduleName = "afl_fuzz_static_lib"
1798	checkPcGuardFlag(moduleName, variant+"_static", false)
1799	checkPcGuardFlag(moduleName, variant+"_static_fuzzer_afl", true)
1800
1801	moduleName = "second_static_lib"
1802	checkPcGuardFlag(moduleName, variant+"_static", false)
1803	checkPcGuardFlag(moduleName, variant+"_static_fuzzer_afl", true)
1804
1805	ctx.ModuleForTests("afl_fuzz_shared_lib",
1806		"android_arm64_armv8-a_shared").Rule("cc")
1807	ctx.ModuleForTests("afl_fuzz_shared_lib",
1808		"android_arm64_armv8-a_shared_fuzzer").Rule("cc")
1809}
1810
1811func TestAFLFuzzTargetForDevice(t *testing.T) {
1812	t.Parallel()
1813	VerifyAFLFuzzTargetVariant(t, "android_arm64_armv8-a")
1814}
1815
1816func TestAFLFuzzTargetForLinuxHost(t *testing.T) {
1817	t.Parallel()
1818	if runtime.GOOS != "linux" {
1819		t.Skip("requires linux")
1820	}
1821
1822	VerifyAFLFuzzTargetVariant(t, "linux_glibc_x86_64")
1823}
1824
1825// Simple smoke test for the cc_fuzz target that ensures the rule compiles
1826// correctly.
1827func TestFuzzTarget(t *testing.T) {
1828	t.Parallel()
1829	ctx := testCc(t, `
1830		cc_fuzz {
1831			name: "fuzz_smoke_test",
1832			srcs: ["foo.c"],
1833		}`)
1834
1835	variant := "android_arm64_armv8-a_fuzzer"
1836	ctx.ModuleForTests("fuzz_smoke_test", variant).Rule("cc")
1837}
1838
1839func assertString(t *testing.T, got, expected string) {
1840	t.Helper()
1841	if got != expected {
1842		t.Errorf("expected %q got %q", expected, got)
1843	}
1844}
1845
1846func assertArrayString(t *testing.T, got, expected []string) {
1847	t.Helper()
1848	if len(got) != len(expected) {
1849		t.Errorf("expected %d (%q) got (%d) %q", len(expected), expected, len(got), got)
1850		return
1851	}
1852	for i := range got {
1853		if got[i] != expected[i] {
1854			t.Errorf("expected %d-th %q (%q) got %q (%q)",
1855				i, expected[i], expected, got[i], got)
1856			return
1857		}
1858	}
1859}
1860
1861func assertMapKeys(t *testing.T, m map[string]string, expected []string) {
1862	t.Helper()
1863	assertArrayString(t, android.SortedKeys(m), expected)
1864}
1865
1866func TestDefaults(t *testing.T) {
1867	t.Parallel()
1868	ctx := testCc(t, `
1869		cc_defaults {
1870			name: "defaults",
1871			srcs: ["foo.c"],
1872			static: {
1873				srcs: ["bar.c"],
1874			},
1875			shared: {
1876				srcs: ["baz.c"],
1877			},
1878		}
1879
1880		cc_library_static {
1881			name: "libstatic",
1882			defaults: ["defaults"],
1883		}
1884
1885		cc_library_shared {
1886			name: "libshared",
1887			defaults: ["defaults"],
1888		}
1889
1890		cc_library {
1891			name: "libboth",
1892			defaults: ["defaults"],
1893		}
1894
1895		cc_binary {
1896			name: "binary",
1897			defaults: ["defaults"],
1898		}`)
1899
1900	shared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Rule("ld")
1901	if g, w := pathsToBase(shared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
1902		t.Errorf("libshared ld rule wanted %q, got %q", w, g)
1903	}
1904	bothShared := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_shared").Rule("ld")
1905	if g, w := pathsToBase(bothShared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
1906		t.Errorf("libboth ld rule wanted %q, got %q", w, g)
1907	}
1908	binary := ctx.ModuleForTests("binary", "android_arm64_armv8-a").Rule("ld")
1909	if g, w := pathsToBase(binary.Inputs), []string{"foo.o"}; !reflect.DeepEqual(w, g) {
1910		t.Errorf("binary ld rule wanted %q, got %q", w, g)
1911	}
1912
1913	static := ctx.ModuleForTests("libstatic", "android_arm64_armv8-a_static").Rule("ar")
1914	if g, w := pathsToBase(static.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
1915		t.Errorf("libstatic ar rule wanted %q, got %q", w, g)
1916	}
1917	bothStatic := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_static").Rule("ar")
1918	if g, w := pathsToBase(bothStatic.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
1919		t.Errorf("libboth ar rule wanted %q, got %q", w, g)
1920	}
1921}
1922
1923func TestProductVariableDefaults(t *testing.T) {
1924	t.Parallel()
1925	bp := `
1926		cc_defaults {
1927			name: "libfoo_defaults",
1928			srcs: ["foo.c"],
1929			cppflags: ["-DFOO"],
1930			product_variables: {
1931				debuggable: {
1932					cppflags: ["-DBAR"],
1933				},
1934			},
1935		}
1936
1937		cc_library {
1938			name: "libfoo",
1939			defaults: ["libfoo_defaults"],
1940		}
1941	`
1942
1943	result := android.GroupFixturePreparers(
1944		prepareForCcTest,
1945		android.PrepareForTestWithVariables,
1946
1947		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1948			variables.Debuggable = BoolPtr(true)
1949		}),
1950	).RunTestWithBp(t, bp)
1951
1952	libfoo := result.Module("libfoo", "android_arm64_armv8-a_static").(*Module)
1953	android.AssertStringListContains(t, "cppflags", libfoo.flags.Local.CppFlags, "-DBAR")
1954}
1955
1956func TestEmptyWholeStaticLibsAllowMissingDependencies(t *testing.T) {
1957	t.Parallel()
1958	bp := `
1959		cc_library_static {
1960			name: "libfoo",
1961			srcs: ["foo.c"],
1962			whole_static_libs: ["libbar"],
1963		}
1964
1965		cc_library_static {
1966			name: "libbar",
1967			whole_static_libs: ["libmissing"],
1968		}
1969	`
1970
1971	result := android.GroupFixturePreparers(
1972		prepareForCcTest,
1973		android.PrepareForTestWithAllowMissingDependencies,
1974	).RunTestWithBp(t, bp)
1975
1976	libbar := result.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a")
1977	android.AssertDeepEquals(t, "libbar rule", android.ErrorRule, libbar.Rule)
1978
1979	android.AssertStringDoesContain(t, "libbar error", libbar.Args["error"], "missing dependencies: libmissing")
1980
1981	libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
1982	android.AssertStringListContains(t, "libfoo.a dependencies", libfoo.Inputs.Strings(), libbar.Output.String())
1983}
1984
1985func TestInstallSharedLibs(t *testing.T) {
1986	t.Parallel()
1987	bp := `
1988		cc_binary {
1989			name: "bin",
1990			host_supported: true,
1991			shared_libs: ["libshared"],
1992			runtime_libs: ["libruntime"],
1993			srcs: [":gen"],
1994		}
1995
1996		cc_library_shared {
1997			name: "libshared",
1998			host_supported: true,
1999			shared_libs: ["libtransitive"],
2000		}
2001
2002		cc_library_shared {
2003			name: "libtransitive",
2004			host_supported: true,
2005		}
2006
2007		cc_library_shared {
2008			name: "libruntime",
2009			host_supported: true,
2010		}
2011
2012		cc_binary_host {
2013			name: "tool",
2014			srcs: ["foo.cpp"],
2015		}
2016
2017		genrule {
2018			name: "gen",
2019			tools: ["tool"],
2020			out: ["gen.cpp"],
2021			cmd: "$(location tool) $(out)",
2022		}
2023	`
2024
2025	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
2026	ctx := testCcWithConfig(t, config)
2027
2028	hostBin := ctx.ModuleForTests("bin", config.BuildOSTarget.String()).Description("install")
2029	hostShared := ctx.ModuleForTests("libshared", config.BuildOSTarget.String()+"_shared").Description("install")
2030	hostRuntime := ctx.ModuleForTests("libruntime", config.BuildOSTarget.String()+"_shared").Description("install")
2031	hostTransitive := ctx.ModuleForTests("libtransitive", config.BuildOSTarget.String()+"_shared").Description("install")
2032	hostTool := ctx.ModuleForTests("tool", config.BuildOSTarget.String()).Description("install")
2033
2034	if g, w := hostBin.Implicits.Strings(), hostShared.Output.String(); !android.InList(w, g) {
2035		t.Errorf("expected host bin dependency %q, got %q", w, g)
2036	}
2037
2038	if g, w := hostBin.Implicits.Strings(), hostTransitive.Output.String(); !android.InList(w, g) {
2039		t.Errorf("expected host bin dependency %q, got %q", w, g)
2040	}
2041
2042	if g, w := hostShared.Implicits.Strings(), hostTransitive.Output.String(); !android.InList(w, g) {
2043		t.Errorf("expected host bin dependency %q, got %q", w, g)
2044	}
2045
2046	if g, w := hostBin.Implicits.Strings(), hostRuntime.Output.String(); !android.InList(w, g) {
2047		t.Errorf("expected host bin dependency %q, got %q", w, g)
2048	}
2049
2050	if g, w := hostBin.Implicits.Strings(), hostTool.Output.String(); android.InList(w, g) {
2051		t.Errorf("expected no host bin dependency %q, got %q", w, g)
2052	}
2053
2054	deviceBin := ctx.ModuleForTests("bin", "android_arm64_armv8-a").Description("install")
2055	deviceShared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Description("install")
2056	deviceTransitive := ctx.ModuleForTests("libtransitive", "android_arm64_armv8-a_shared").Description("install")
2057	deviceRuntime := ctx.ModuleForTests("libruntime", "android_arm64_armv8-a_shared").Description("install")
2058
2059	if g, w := deviceBin.OrderOnly.Strings(), deviceShared.Output.String(); !android.InList(w, g) {
2060		t.Errorf("expected device bin dependency %q, got %q", w, g)
2061	}
2062
2063	if g, w := deviceBin.OrderOnly.Strings(), deviceTransitive.Output.String(); !android.InList(w, g) {
2064		t.Errorf("expected device bin dependency %q, got %q", w, g)
2065	}
2066
2067	if g, w := deviceShared.OrderOnly.Strings(), deviceTransitive.Output.String(); !android.InList(w, g) {
2068		t.Errorf("expected device bin dependency %q, got %q", w, g)
2069	}
2070
2071	if g, w := deviceBin.OrderOnly.Strings(), deviceRuntime.Output.String(); !android.InList(w, g) {
2072		t.Errorf("expected device bin dependency %q, got %q", w, g)
2073	}
2074
2075	if g, w := deviceBin.OrderOnly.Strings(), hostTool.Output.String(); android.InList(w, g) {
2076		t.Errorf("expected no device bin dependency %q, got %q", w, g)
2077	}
2078
2079}
2080
2081func TestStubsLibReexportsHeaders(t *testing.T) {
2082	t.Parallel()
2083	ctx := testCc(t, `
2084		cc_library_shared {
2085			name: "libclient",
2086			srcs: ["foo.c"],
2087			shared_libs: ["libfoo#1"],
2088		}
2089
2090		cc_library_shared {
2091			name: "libfoo",
2092			srcs: ["foo.c"],
2093			shared_libs: ["libbar"],
2094			export_shared_lib_headers: ["libbar"],
2095			stubs: {
2096				symbol_file: "foo.map.txt",
2097				versions: ["1", "2", "3"],
2098			},
2099		}
2100
2101		cc_library_shared {
2102			name: "libbar",
2103			export_include_dirs: ["include/libbar"],
2104			srcs: ["foo.c"],
2105		}`)
2106
2107	cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
2108
2109	if !strings.Contains(cFlags, "-Iinclude/libbar") {
2110		t.Errorf("expected %q in cflags, got %q", "-Iinclude/libbar", cFlags)
2111	}
2112}
2113
2114func TestAidlLibraryWithHeaders(t *testing.T) {
2115	t.Parallel()
2116	ctx := android.GroupFixturePreparers(
2117		prepareForCcTest,
2118		aidl_library.PrepareForTestWithAidlLibrary,
2119		android.MockFS{
2120			"package_bar/Android.bp": []byte(`
2121			aidl_library {
2122				name: "bar",
2123				srcs: ["x/y/Bar.aidl"],
2124				hdrs: ["x/HeaderBar.aidl"],
2125				strip_import_prefix: "x",
2126			}
2127			`)}.AddToFixture(),
2128		android.MockFS{
2129			"package_foo/Android.bp": []byte(`
2130			aidl_library {
2131				name: "foo",
2132				srcs: ["a/b/Foo.aidl"],
2133				hdrs: ["a/HeaderFoo.aidl"],
2134				strip_import_prefix: "a",
2135				deps: ["bar"],
2136			}
2137			cc_library {
2138				name: "libfoo",
2139				aidl: {
2140					libs: ["foo"],
2141				}
2142			}
2143			`),
2144		}.AddToFixture(),
2145	).RunTest(t).TestContext
2146
2147	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
2148
2149	android.AssertPathsRelativeToTopEquals(
2150		t,
2151		"aidl headers",
2152		[]string{
2153			"package_bar/x/HeaderBar.aidl",
2154			"package_foo/a/HeaderFoo.aidl",
2155			"package_foo/a/b/Foo.aidl",
2156			"out/soong/.intermediates/package_foo/libfoo/android_arm64_armv8-a_static/gen/aidl_library.sbox.textproto",
2157		},
2158		libfoo.Rule("aidl_library").Implicits,
2159	)
2160
2161	manifest := android.RuleBuilderSboxProtoForTests(t, ctx, libfoo.Output("aidl_library.sbox.textproto"))
2162	aidlCommand := manifest.Commands[0].GetCommand()
2163
2164	expectedAidlFlags := "-Ipackage_foo/a -Ipackage_bar/x"
2165	if !strings.Contains(aidlCommand, expectedAidlFlags) {
2166		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlags)
2167	}
2168
2169	outputs := strings.Join(libfoo.AllOutputs(), " ")
2170
2171	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/BpFoo.h")
2172	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/BnFoo.h")
2173	android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl_library/b/Foo.h")
2174	android.AssertStringDoesContain(t, "aidl-generated cpp", outputs, "b/Foo.cpp")
2175	// Confirm that the aidl header doesn't get compiled to cpp and h files
2176	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/BpBar.h")
2177	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/BnBar.h")
2178	android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl_library/y/Bar.h")
2179	android.AssertStringDoesNotContain(t, "aidl-generated cpp", outputs, "y/Bar.cpp")
2180}
2181
2182func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
2183	t.Parallel()
2184	ctx := android.GroupFixturePreparers(
2185		prepareForCcTest,
2186		aidl_library.PrepareForTestWithAidlLibrary,
2187	).RunTestWithBp(t, `
2188		cc_library {
2189			name: "libfoo",
2190			srcs: ["a/Foo.aidl"],
2191			aidl: { flags: ["-Werror"], },
2192		}
2193	`)
2194
2195	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
2196	manifest := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, libfoo.Output("aidl.sbox.textproto"))
2197	aidlCommand := manifest.Commands[0].GetCommand()
2198	expectedAidlFlag := "-Werror"
2199	if !strings.Contains(aidlCommand, expectedAidlFlag) {
2200		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
2201	}
2202}
2203
2204func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
2205	t.Parallel()
2206	for _, tc := range []struct {
2207		name       string
2208		sdkVersion string
2209		variant    string
2210		expected   string
2211	}{
2212		{
2213			name:       "default is current",
2214			sdkVersion: "",
2215			variant:    "android_arm64_armv8-a_static",
2216			expected:   "platform_apis",
2217		},
2218		{
2219			name:       "use sdk_version",
2220			sdkVersion: `sdk_version: "29"`,
2221			variant:    "android_arm64_armv8-a_static",
2222			expected:   "platform_apis",
2223		},
2224		{
2225			name:       "use sdk_version(sdk variant)",
2226			sdkVersion: `sdk_version: "29"`,
2227			variant:    "android_arm64_armv8-a_sdk_static",
2228			expected:   "29",
2229		},
2230		{
2231			name:       "use min_sdk_version",
2232			sdkVersion: `min_sdk_version: "29"`,
2233			variant:    "android_arm64_armv8-a_static",
2234			expected:   "29",
2235		},
2236	} {
2237		t.Run(tc.name, func(t *testing.T) {
2238			ctx := testCc(t, `
2239				cc_library {
2240					name: "libfoo",
2241					stl: "none",
2242					srcs: ["a/Foo.aidl"],
2243					`+tc.sdkVersion+`
2244				}
2245			`)
2246			libfoo := ctx.ModuleForTests("libfoo", tc.variant)
2247			manifest := android.RuleBuilderSboxProtoForTests(t, ctx, libfoo.Output("aidl.sbox.textproto"))
2248			aidlCommand := manifest.Commands[0].GetCommand()
2249			expectedAidlFlag := "--min_sdk_version=" + tc.expected
2250			if !strings.Contains(aidlCommand, expectedAidlFlag) {
2251				t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
2252			}
2253		})
2254	}
2255}
2256
2257func TestInvalidAidlProp(t *testing.T) {
2258	t.Parallel()
2259
2260	testCases := []struct {
2261		description string
2262		bp          string
2263	}{
2264		{
2265			description: "Invalid use of aidl.libs and aidl.include_dirs",
2266			bp: `
2267			cc_library {
2268				name: "foo",
2269				aidl: {
2270					libs: ["foo_aidl"],
2271					include_dirs: ["bar/include"],
2272				}
2273			}
2274			`,
2275		},
2276		{
2277			description: "Invalid use of aidl.libs and aidl.local_include_dirs",
2278			bp: `
2279			cc_library {
2280				name: "foo",
2281				aidl: {
2282					libs: ["foo_aidl"],
2283					local_include_dirs: ["include"],
2284				}
2285			}
2286			`,
2287		},
2288	}
2289
2290	for _, testCase := range testCases {
2291		t.Run(testCase.description, func(t *testing.T) {
2292			bp := `
2293			aidl_library {
2294				name: "foo_aidl",
2295				srcs: ["Foo.aidl"],
2296			} ` + testCase.bp
2297			android.GroupFixturePreparers(
2298				prepareForCcTest,
2299				aidl_library.PrepareForTestWithAidlLibrary.
2300					ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("For aidl headers, please only use aidl.libs prop")),
2301			).RunTestWithBp(t, bp)
2302		})
2303	}
2304}
2305
2306func TestMinSdkVersionInClangTriple(t *testing.T) {
2307	t.Parallel()
2308	ctx := testCc(t, `
2309		cc_library_shared {
2310			name: "libfoo",
2311			srcs: ["foo.c"],
2312			min_sdk_version: "29",
2313		}`)
2314
2315	cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
2316	android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
2317}
2318
2319func TestNonDigitMinSdkVersionInClangTriple(t *testing.T) {
2320	t.Parallel()
2321	bp := `
2322		cc_library_shared {
2323			name: "libfoo",
2324			srcs: ["foo.c"],
2325			min_sdk_version: "S",
2326		}
2327	`
2328	result := android.GroupFixturePreparers(
2329		prepareForCcTest,
2330		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2331			variables.Platform_version_active_codenames = []string{"UpsideDownCake", "Tiramisu"}
2332		}),
2333	).RunTestWithBp(t, bp)
2334	ctx := result.TestContext
2335	cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
2336	android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android31")
2337}
2338
2339func TestIncludeDirsExporting(t *testing.T) {
2340	t.Parallel()
2341
2342	// Trim spaces from the beginning, end and immediately after any newline characters. Leaves
2343	// embedded newline characters alone.
2344	trimIndentingSpaces := func(s string) string {
2345		return strings.TrimSpace(regexp.MustCompile("(^|\n)\\s+").ReplaceAllString(s, "$1"))
2346	}
2347
2348	checkPaths := func(t *testing.T, message string, expected string, paths android.Paths) {
2349		t.Helper()
2350		expected = trimIndentingSpaces(expected)
2351		actual := trimIndentingSpaces(strings.Join(android.FirstUniqueStrings(android.NormalizePathsForTesting(paths)), "\n"))
2352		if expected != actual {
2353			t.Errorf("%s: expected:\n%s\n actual:\n%s\n", message, expected, actual)
2354		}
2355	}
2356
2357	type exportedChecker func(t *testing.T, name string, exported FlagExporterInfo)
2358
2359	checkIncludeDirs := func(t *testing.T, ctx *android.TestContext, module android.Module, checkers ...exportedChecker) {
2360		t.Helper()
2361		exported, _ := android.OtherModuleProvider(ctx, module, FlagExporterInfoProvider)
2362		name := module.Name()
2363
2364		for _, checker := range checkers {
2365			checker(t, name, exported)
2366		}
2367	}
2368
2369	expectedIncludeDirs := func(expectedPaths string) exportedChecker {
2370		return func(t *testing.T, name string, exported FlagExporterInfo) {
2371			t.Helper()
2372			checkPaths(t, fmt.Sprintf("%s: include dirs", name), expectedPaths, exported.IncludeDirs)
2373		}
2374	}
2375
2376	expectedSystemIncludeDirs := func(expectedPaths string) exportedChecker {
2377		return func(t *testing.T, name string, exported FlagExporterInfo) {
2378			t.Helper()
2379			checkPaths(t, fmt.Sprintf("%s: system include dirs", name), expectedPaths, exported.SystemIncludeDirs)
2380		}
2381	}
2382
2383	expectedGeneratedHeaders := func(expectedPaths string) exportedChecker {
2384		return func(t *testing.T, name string, exported FlagExporterInfo) {
2385			t.Helper()
2386			checkPaths(t, fmt.Sprintf("%s: generated headers", name), expectedPaths, exported.GeneratedHeaders)
2387		}
2388	}
2389
2390	expectedOrderOnlyDeps := func(expectedPaths string) exportedChecker {
2391		return func(t *testing.T, name string, exported FlagExporterInfo) {
2392			t.Helper()
2393			checkPaths(t, fmt.Sprintf("%s: order only deps", name), expectedPaths, exported.Deps)
2394		}
2395	}
2396
2397	genRuleModules := `
2398		genrule {
2399			name: "genrule_foo",
2400			cmd: "generate-foo",
2401			out: [
2402				"generated_headers/foo/generated_header.h",
2403			],
2404			export_include_dirs: [
2405				"generated_headers",
2406			],
2407		}
2408
2409		genrule {
2410			name: "genrule_bar",
2411			cmd: "generate-bar",
2412			out: [
2413				"generated_headers/bar/generated_header.h",
2414			],
2415			export_include_dirs: [
2416				"generated_headers",
2417			],
2418		}
2419	`
2420
2421	t.Run("ensure exported include dirs are not automatically re-exported from shared_libs", func(t *testing.T) {
2422		ctx := testCc(t, genRuleModules+`
2423		cc_library {
2424			name: "libfoo",
2425			srcs: ["foo.c"],
2426			export_include_dirs: ["foo/standard"],
2427			export_system_include_dirs: ["foo/system"],
2428			generated_headers: ["genrule_foo"],
2429			export_generated_headers: ["genrule_foo"],
2430		}
2431
2432		cc_library {
2433			name: "libbar",
2434			srcs: ["bar.c"],
2435			shared_libs: ["libfoo"],
2436			export_include_dirs: ["bar/standard"],
2437			export_system_include_dirs: ["bar/system"],
2438			generated_headers: ["genrule_bar"],
2439			export_generated_headers: ["genrule_bar"],
2440		}
2441		`)
2442		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
2443		checkIncludeDirs(t, ctx, foo,
2444			expectedIncludeDirs(`
2445				foo/standard
2446				.intermediates/genrule_foo/gen/generated_headers
2447			`),
2448			expectedSystemIncludeDirs(`foo/system`),
2449			expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
2450			expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
2451		)
2452
2453		bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
2454		checkIncludeDirs(t, ctx, bar,
2455			expectedIncludeDirs(`
2456				bar/standard
2457				.intermediates/genrule_bar/gen/generated_headers
2458			`),
2459			expectedSystemIncludeDirs(`bar/system`),
2460			expectedGeneratedHeaders(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
2461			expectedOrderOnlyDeps(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
2462		)
2463	})
2464
2465	t.Run("ensure exported include dirs are automatically re-exported from whole_static_libs", func(t *testing.T) {
2466		ctx := testCc(t, genRuleModules+`
2467		cc_library {
2468			name: "libfoo",
2469			srcs: ["foo.c"],
2470			export_include_dirs: ["foo/standard"],
2471			export_system_include_dirs: ["foo/system"],
2472			generated_headers: ["genrule_foo"],
2473			export_generated_headers: ["genrule_foo"],
2474		}
2475
2476		cc_library {
2477			name: "libbar",
2478			srcs: ["bar.c"],
2479			whole_static_libs: ["libfoo"],
2480			export_include_dirs: ["bar/standard"],
2481			export_system_include_dirs: ["bar/system"],
2482			generated_headers: ["genrule_bar"],
2483			export_generated_headers: ["genrule_bar"],
2484		}
2485		`)
2486		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
2487		checkIncludeDirs(t, ctx, foo,
2488			expectedIncludeDirs(`
2489				foo/standard
2490				.intermediates/genrule_foo/gen/generated_headers
2491			`),
2492			expectedSystemIncludeDirs(`foo/system`),
2493			expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
2494			expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
2495		)
2496
2497		bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
2498		checkIncludeDirs(t, ctx, bar,
2499			expectedIncludeDirs(`
2500				bar/standard
2501				foo/standard
2502				.intermediates/genrule_foo/gen/generated_headers
2503				.intermediates/genrule_bar/gen/generated_headers
2504			`),
2505			expectedSystemIncludeDirs(`
2506				bar/system
2507				foo/system
2508			`),
2509			expectedGeneratedHeaders(`
2510				.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
2511				.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
2512			`),
2513			expectedOrderOnlyDeps(`
2514				.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
2515				.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
2516			`),
2517		)
2518	})
2519
2520	t.Run("ensure only aidl headers are exported", func(t *testing.T) {
2521		ctx := android.GroupFixturePreparers(
2522			prepareForCcTest,
2523			aidl_library.PrepareForTestWithAidlLibrary,
2524		).RunTestWithBp(t, `
2525		aidl_library {
2526			name: "libfoo_aidl",
2527			srcs: ["x/y/Bar.aidl"],
2528			strip_import_prefix: "x",
2529		}
2530		cc_library_shared {
2531			name: "libfoo",
2532			srcs: [
2533				"foo.c",
2534				"b.aidl",
2535				"a.proto",
2536			],
2537			aidl: {
2538				libs: ["libfoo_aidl"],
2539				export_aidl_headers: true,
2540			}
2541		}
2542		`).TestContext
2543		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
2544		checkIncludeDirs(t, ctx, foo,
2545			expectedIncludeDirs(`
2546				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl
2547				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library
2548			`),
2549			expectedSystemIncludeDirs(``),
2550			expectedGeneratedHeaders(`
2551				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
2552				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
2553				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
2554				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/Bar.h
2555				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BnBar.h
2556				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BpBar.h
2557			`),
2558			expectedOrderOnlyDeps(`
2559				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
2560				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
2561				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
2562				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/Bar.h
2563				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BnBar.h
2564				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl_library/y/BpBar.h
2565			`),
2566		)
2567	})
2568
2569	t.Run("ensure only proto headers are exported", func(t *testing.T) {
2570		ctx := testCc(t, genRuleModules+`
2571		cc_library_shared {
2572			name: "libfoo",
2573			srcs: [
2574				"foo.c",
2575				"b.aidl",
2576				"a.proto",
2577			],
2578			proto: {
2579				export_proto_headers: true,
2580			}
2581		}
2582		`)
2583		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
2584		checkIncludeDirs(t, ctx, foo,
2585			expectedIncludeDirs(`
2586				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto
2587			`),
2588			expectedSystemIncludeDirs(``),
2589			expectedGeneratedHeaders(`
2590				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
2591			`),
2592			expectedOrderOnlyDeps(`
2593				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
2594			`),
2595		)
2596	})
2597
2598	t.Run("ensure only sysprop headers are exported", func(t *testing.T) {
2599		ctx := testCc(t, genRuleModules+`
2600		cc_library_shared {
2601			name: "libfoo",
2602			srcs: [
2603				"foo.c",
2604				"path/to/a.sysprop",
2605				"b.aidl",
2606				"a.proto",
2607			],
2608		}
2609		`)
2610		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
2611		checkIncludeDirs(t, ctx, foo,
2612			expectedIncludeDirs(`
2613				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include
2614			`),
2615			expectedSystemIncludeDirs(``),
2616			expectedGeneratedHeaders(`
2617				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/path/to/a.sysprop.h
2618			`),
2619			expectedOrderOnlyDeps(`
2620				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/path/to/a.sysprop.h
2621				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/public/include/path/to/a.sysprop.h
2622			`),
2623		)
2624	})
2625}
2626
2627func TestIncludeDirectoryOrdering(t *testing.T) {
2628	t.Parallel()
2629
2630	expectedPlatformFlags := []string{
2631		"-nostdlibinc",
2632	}
2633
2634	baseExpectedFlags := []string{
2635		"${config.ArmThumbCflags}",
2636		"${config.ArmCflags}",
2637		"${config.CommonGlobalCflags}",
2638		"${config.DeviceGlobalCflags}",
2639		"${config.ExternalCflags}",
2640		"${config.ArmToolchainCflags}",
2641		"${config.ArmArmv7ANeonCflags}",
2642		"${config.ArmGenericCflags}",
2643	}
2644
2645	expectedTargetNDKFlags := []string{
2646		"-target",
2647		"armv7a-linux-androideabi21",
2648	}
2649
2650	expectedTargetPlatformFlags := []string{
2651		"-target",
2652		"armv7a-linux-androideabi10000",
2653	}
2654
2655	expectedIncludes := []string{
2656		"external/foo/android_arm_export_include_dirs",
2657		"external/foo/lib32_export_include_dirs",
2658		"external/foo/arm_export_include_dirs",
2659		"external/foo/android_export_include_dirs",
2660		"external/foo/linux_export_include_dirs",
2661		"external/foo/export_include_dirs",
2662		"external/foo/android_arm_local_include_dirs",
2663		"external/foo/lib32_local_include_dirs",
2664		"external/foo/arm_local_include_dirs",
2665		"external/foo/android_local_include_dirs",
2666		"external/foo/linux_local_include_dirs",
2667		"external/foo/local_include_dirs",
2668		"external/foo",
2669		"external/foo/libheader1",
2670		"external/foo/libheader2",
2671		"external/foo/libwhole1",
2672		"external/foo/libwhole2",
2673		"external/foo/libstatic1",
2674		"external/foo/libstatic2",
2675		"external/foo/libshared1",
2676		"external/foo/libshared2",
2677		"external/foo/liblinux",
2678		"external/foo/libandroid",
2679		"external/foo/libarm",
2680		"external/foo/lib32",
2681		"external/foo/libandroid_arm",
2682	}
2683
2684	expectedNDKSTLIncludes := []string{
2685		"defaults/cc/common/ndk_libc++_shared_include_dirs",
2686	}
2687
2688	conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"}
2689	cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
2690
2691	cflags := []string{"-Werror", "-std=candcpp"}
2692	cstd := []string{"-std=gnu17", "-std=conly"}
2693	cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"}
2694
2695	lastNDKFlags := []string{
2696		"--sysroot",
2697		"out/soong/ndk/sysroot",
2698	}
2699
2700	lastPlatformIncludes := []string{
2701		"${config.CommonGlobalIncludes}",
2702	}
2703
2704	testCases := []struct {
2705		name             string
2706		src              string
2707		expectedNDK      []string
2708		expectedPlatform []string
2709	}{
2710		{
2711			name: "c",
2712			src:  "foo.c",
2713			expectedNDK: slices.Concat(
2714				baseExpectedFlags,
2715				expectedTargetNDKFlags,
2716				conly,
2717				expectedIncludes,
2718				expectedNDKSTLIncludes,
2719				cflags,
2720				cstd,
2721				lastNDKFlags,
2722				[]string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
2723			),
2724			expectedPlatform: slices.Concat(
2725				expectedPlatformFlags,
2726				baseExpectedFlags,
2727				expectedTargetPlatformFlags,
2728				conly,
2729				expectedIncludes,
2730				cflags,
2731				cstd,
2732				lastPlatformIncludes,
2733				[]string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
2734			),
2735		},
2736		{
2737			name: "cc",
2738			src:  "foo.cc",
2739			expectedNDK: slices.Concat(
2740				baseExpectedFlags,
2741				expectedTargetNDKFlags,
2742				cppOnly,
2743				expectedIncludes,
2744				expectedNDKSTLIncludes,
2745				cflags,
2746				cppstd,
2747				lastNDKFlags,
2748				[]string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
2749			),
2750			expectedPlatform: slices.Concat(
2751				expectedPlatformFlags,
2752				baseExpectedFlags,
2753				expectedTargetPlatformFlags,
2754				cppOnly,
2755				expectedIncludes,
2756				cflags,
2757				cppstd,
2758				lastPlatformIncludes,
2759				[]string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
2760			),
2761		},
2762		{
2763			name: "assemble",
2764			src:  "foo.s",
2765			expectedNDK: slices.Concat(
2766				baseExpectedFlags,
2767				expectedTargetNDKFlags,
2768				[]string{"${config.CommonGlobalAsflags}"},
2769				expectedIncludes,
2770				expectedNDKSTLIncludes,
2771				lastNDKFlags,
2772			),
2773			expectedPlatform: slices.Concat(
2774				expectedPlatformFlags,
2775				baseExpectedFlags,
2776				expectedTargetPlatformFlags,
2777				[]string{"${config.CommonGlobalAsflags}"},
2778				expectedIncludes,
2779				lastPlatformIncludes,
2780			),
2781		},
2782	}
2783
2784	for _, tc := range testCases {
2785		t.Run(tc.name, func(t *testing.T) {
2786			bp := fmt.Sprintf(`
2787		cc_library {
2788			name: "libfoo",
2789			srcs: ["%s"],
2790			cflags: ["-std=candcpp"],
2791			conlyflags: ["-std=conly"],
2792			cppflags: ["-std=cpp"],
2793			local_include_dirs: ["local_include_dirs"],
2794			export_include_dirs: ["export_include_dirs"],
2795			export_system_include_dirs: ["export_system_include_dirs"],
2796			static_libs: ["libstatic1", "libstatic2"],
2797			whole_static_libs: ["libwhole1", "libwhole2"],
2798			shared_libs: ["libshared1", "libshared2"],
2799			header_libs: ["libheader1", "libheader2"],
2800			target: {
2801				android: {
2802					shared_libs: ["libandroid"],
2803					local_include_dirs: ["android_local_include_dirs"],
2804					export_include_dirs: ["android_export_include_dirs"],
2805				},
2806				android_arm: {
2807					shared_libs: ["libandroid_arm"],
2808					local_include_dirs: ["android_arm_local_include_dirs"],
2809					export_include_dirs: ["android_arm_export_include_dirs"],
2810				},
2811				linux: {
2812					shared_libs: ["liblinux"],
2813					local_include_dirs: ["linux_local_include_dirs"],
2814					export_include_dirs: ["linux_export_include_dirs"],
2815				},
2816			},
2817			multilib: {
2818				lib32: {
2819					shared_libs: ["lib32"],
2820					local_include_dirs: ["lib32_local_include_dirs"],
2821					export_include_dirs: ["lib32_export_include_dirs"],
2822				},
2823			},
2824			arch: {
2825				arm: {
2826					shared_libs: ["libarm"],
2827					local_include_dirs: ["arm_local_include_dirs"],
2828					export_include_dirs: ["arm_export_include_dirs"],
2829				},
2830			},
2831			stl: "libc++",
2832			sdk_version: "minimum",
2833		}
2834
2835		cc_library_headers {
2836			name: "libheader1",
2837			export_include_dirs: ["libheader1"],
2838			sdk_version: "minimum",
2839			stl: "none",
2840		}
2841
2842		cc_library_headers {
2843			name: "libheader2",
2844			export_include_dirs: ["libheader2"],
2845			sdk_version: "minimum",
2846			stl: "none",
2847		}
2848	`, tc.src)
2849
2850			libs := []string{
2851				"libstatic1",
2852				"libstatic2",
2853				"libwhole1",
2854				"libwhole2",
2855				"libshared1",
2856				"libshared2",
2857				"libandroid",
2858				"libandroid_arm",
2859				"liblinux",
2860				"lib32",
2861				"libarm",
2862			}
2863
2864			for _, lib := range libs {
2865				bp += fmt.Sprintf(`
2866			cc_library {
2867				name: "%s",
2868				export_include_dirs: ["%s"],
2869				sdk_version: "minimum",
2870				stl: "none",
2871			}
2872		`, lib, lib)
2873			}
2874
2875			runTest := func(t *testing.T, variant string, expected []string) {
2876				ctx := android.GroupFixturePreparers(
2877					PrepareForIntegrationTestWithCc,
2878					android.FixtureAddTextFile("external/foo/Android.bp", bp),
2879				).RunTest(t)
2880				cflags := ctx.ModuleForTests("libfoo", variant).Output("obj/external/foo/foo.o").Args["cFlags"]
2881
2882				var includes []string
2883				flags := strings.Split(cflags, " ")
2884				for _, flag := range flags {
2885					if strings.HasPrefix(flag, "-I") {
2886						includes = append(includes, strings.TrimPrefix(flag, "-I"))
2887					} else if flag == "-isystem" {
2888						// skip isystem, include next
2889					} else if len(flag) > 0 {
2890						includes = append(includes, flag)
2891					}
2892				}
2893
2894				android.AssertArrayString(t, "includes", expected, includes)
2895			}
2896
2897			t.Run("platform", func(t *testing.T) {
2898				runTest(t, "android_arm_armv7-a-neon_static", tc.expectedPlatform)
2899			})
2900			t.Run("ndk", func(t *testing.T) {
2901				runTest(t, "android_arm_armv7-a-neon_sdk_static", tc.expectedNDK)
2902			})
2903		})
2904	}
2905
2906}
2907
2908func TestAddnoOverride64GlobalCflags(t *testing.T) {
2909	t.Parallel()
2910	ctx := testCc(t, `
2911		cc_library_shared {
2912			name: "libclient",
2913			srcs: ["foo.c"],
2914			shared_libs: ["libfoo#1"],
2915		}
2916
2917		cc_library_shared {
2918			name: "libfoo",
2919			srcs: ["foo.c"],
2920			shared_libs: ["libbar"],
2921			export_shared_lib_headers: ["libbar"],
2922			stubs: {
2923				symbol_file: "foo.map.txt",
2924				versions: ["1", "2", "3"],
2925			},
2926		}
2927
2928		cc_library_shared {
2929			name: "libbar",
2930			export_include_dirs: ["include/libbar"],
2931			srcs: ["foo.c"],
2932		}`)
2933
2934	cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
2935
2936	if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") {
2937		t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags)
2938	}
2939}
2940
2941func TestCcBuildBrokenClangProperty(t *testing.T) {
2942	t.Parallel()
2943	tests := []struct {
2944		name                     string
2945		clang                    bool
2946		BuildBrokenClangProperty bool
2947		err                      string
2948	}{
2949		{
2950			name:  "error when clang is set to false",
2951			clang: false,
2952			err:   "is no longer supported",
2953		},
2954		{
2955			name:  "error when clang is set to true",
2956			clang: true,
2957			err:   "property is deprecated, see Changes.md",
2958		},
2959		{
2960			name:                     "no error when BuildBrokenClangProperty is explicitly set to true",
2961			clang:                    true,
2962			BuildBrokenClangProperty: true,
2963		},
2964	}
2965
2966	for _, test := range tests {
2967		t.Run(test.name, func(t *testing.T) {
2968			bp := fmt.Sprintf(`
2969			cc_library {
2970			   name: "foo",
2971			   clang: %t,
2972			}`, test.clang)
2973
2974			if test.err == "" {
2975				android.GroupFixturePreparers(
2976					prepareForCcTest,
2977					android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2978						if test.BuildBrokenClangProperty {
2979							variables.BuildBrokenClangProperty = test.BuildBrokenClangProperty
2980						}
2981					}),
2982				).RunTestWithBp(t, bp)
2983			} else {
2984				prepareForCcTest.
2985					ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
2986					RunTestWithBp(t, bp)
2987			}
2988		})
2989	}
2990}
2991
2992func TestCcBuildBrokenClangAsFlags(t *testing.T) {
2993	t.Parallel()
2994	tests := []struct {
2995		name                    string
2996		clangAsFlags            []string
2997		BuildBrokenClangAsFlags bool
2998		err                     string
2999	}{
3000		{
3001			name:         "error when clang_asflags is set",
3002			clangAsFlags: []string{"-a", "-b"},
3003			err:          "clang_asflags: property is deprecated",
3004		},
3005		{
3006			name:                    "no error when BuildBrokenClangAsFlags is explicitly set to true",
3007			clangAsFlags:            []string{"-a", "-b"},
3008			BuildBrokenClangAsFlags: true,
3009		},
3010	}
3011
3012	for _, test := range tests {
3013		t.Run(test.name, func(t *testing.T) {
3014			bp := fmt.Sprintf(`
3015			cc_library {
3016			   name: "foo",
3017			   clang_asflags: %s,
3018			}`, `["`+strings.Join(test.clangAsFlags, `","`)+`"]`)
3019
3020			if test.err == "" {
3021				android.GroupFixturePreparers(
3022					prepareForCcTest,
3023					android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3024						if test.BuildBrokenClangAsFlags {
3025							variables.BuildBrokenClangAsFlags = test.BuildBrokenClangAsFlags
3026						}
3027					}),
3028				).RunTestWithBp(t, bp)
3029			} else {
3030				prepareForCcTest.
3031					ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
3032					RunTestWithBp(t, bp)
3033			}
3034		})
3035	}
3036}
3037
3038func TestCcBuildBrokenClangCFlags(t *testing.T) {
3039	t.Parallel()
3040	tests := []struct {
3041		name                   string
3042		clangCFlags            []string
3043		BuildBrokenClangCFlags bool
3044		err                    string
3045	}{
3046		{
3047			name:        "error when clang_cflags is set",
3048			clangCFlags: []string{"-a", "-b"},
3049			err:         "clang_cflags: property is deprecated",
3050		},
3051		{
3052			name:                   "no error when BuildBrokenClangCFlags is explicitly set to true",
3053			clangCFlags:            []string{"-a", "-b"},
3054			BuildBrokenClangCFlags: true,
3055		},
3056	}
3057
3058	for _, test := range tests {
3059		t.Run(test.name, func(t *testing.T) {
3060			bp := fmt.Sprintf(`
3061			cc_library {
3062			   name: "foo",
3063			   clang_cflags: %s,
3064			}`, `["`+strings.Join(test.clangCFlags, `","`)+`"]`)
3065
3066			if test.err == "" {
3067				android.GroupFixturePreparers(
3068					prepareForCcTest,
3069					android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3070						if test.BuildBrokenClangCFlags {
3071							variables.BuildBrokenClangCFlags = test.BuildBrokenClangCFlags
3072						}
3073					}),
3074				).RunTestWithBp(t, bp)
3075			} else {
3076				prepareForCcTest.
3077					ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
3078					RunTestWithBp(t, bp)
3079			}
3080		})
3081	}
3082}
3083
3084func TestStrippedAllOutputFile(t *testing.T) {
3085	t.Parallel()
3086	bp := `
3087		cc_library {
3088			name: "test_lib",
3089			srcs: ["test_lib.cpp"],
3090			dist: {
3091				targets: [ "dist_target" ],
3092				tag: "stripped_all",
3093			}
3094		}
3095 `
3096	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
3097	ctx := testCcWithConfig(t, config)
3098	testingModule := ctx.ModuleForTests("test_lib", "android_arm_armv7-a-neon_shared")
3099	outputFile := testingModule.OutputFiles(ctx, t, "stripped_all")
3100	if !strings.HasSuffix(outputFile.Strings()[0], "/stripped_all/test_lib.so") {
3101		t.Errorf("Unexpected output file: %s", outputFile.Strings()[0])
3102		return
3103	}
3104}
3105
3106func TestImageVariants(t *testing.T) {
3107	t.Parallel()
3108
3109	bp := `
3110	cc_binary {
3111		name: "binfoo",
3112		srcs: ["binfoo.cc"],
3113		vendor_available: true,
3114		product_available: true,
3115		shared_libs: ["libbar"]
3116	}
3117	cc_library {
3118		name: "libbar",
3119		srcs: ["libbar.cc"],
3120		vendor_available: true,
3121		product_available: true,
3122	}
3123	`
3124
3125	ctx := prepareForCcTest.RunTestWithBp(t, bp)
3126
3127	hasDep := func(m android.Module, wantDep android.Module) bool {
3128		t.Helper()
3129		var found bool
3130		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
3131			if dep == wantDep {
3132				found = true
3133			}
3134		})
3135		return found
3136	}
3137
3138	testDepWithVariant := func(imageVariant string) {
3139		imageVariantStr := ""
3140		if imageVariant != "core" {
3141			imageVariantStr = "_" + imageVariant
3142		}
3143		binFooModule := ctx.ModuleForTests("binfoo", "android"+imageVariantStr+"_arm64_armv8-a").Module()
3144		libBarModule := ctx.ModuleForTests("libbar", "android"+imageVariantStr+"_arm64_armv8-a_shared").Module()
3145		android.AssertBoolEquals(t, "binfoo should have dependency on libbar with image variant "+imageVariant, true, hasDep(binFooModule, libBarModule))
3146	}
3147
3148	testDepWithVariant("core")
3149	testDepWithVariant("vendor")
3150	testDepWithVariant("product")
3151}
3152
3153func TestVendorOrProductVariantUsesPlatformSdkVersionAsDefault(t *testing.T) {
3154	t.Parallel()
3155
3156	bp := `
3157		cc_library {
3158			name: "libfoo",
3159			srcs: ["libfoo.cc"],
3160			vendor_available: true,
3161			product_available: true,
3162		}
3163
3164		cc_library {
3165			name: "libbar",
3166			srcs: ["libbar.cc"],
3167			vendor_available: true,
3168			product_available: true,
3169			min_sdk_version: "29",
3170		}
3171	`
3172
3173	ctx := prepareForCcTest.RunTestWithBp(t, bp)
3174	testSdkVersionFlag := func(module, variant, version string) {
3175		flags := ctx.ModuleForTests(module, "android_"+variant+"_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3176		android.AssertStringDoesContain(t, "target SDK version", flags, "-target aarch64-linux-android"+version)
3177	}
3178
3179	testSdkVersionFlag("libfoo", "vendor", "30")
3180	testSdkVersionFlag("libfoo", "product", "30")
3181	// target SDK version can be set explicitly with min_sdk_version
3182	testSdkVersionFlag("libbar", "vendor", "29")
3183	testSdkVersionFlag("libbar", "product", "29")
3184}
3185
3186func TestClangVerify(t *testing.T) {
3187	t.Parallel()
3188
3189	ctx := testCc(t, `
3190		cc_library {
3191			name: "lib_no_clang_verify",
3192			srcs: ["libnocv.cc"],
3193		}
3194
3195		cc_library {
3196			name: "lib_clang_verify",
3197			srcs: ["libcv.cc"],
3198			clang_verify: true,
3199		}
3200	`)
3201
3202	module := ctx.ModuleForTests("lib_no_clang_verify", "android_arm64_armv8-a_shared")
3203
3204	cFlags_no_cv := module.Rule("cc").Args["cFlags"]
3205	if strings.Contains(cFlags_no_cv, "-Xclang") || strings.Contains(cFlags_no_cv, "-verify") {
3206		t.Errorf("expected %q not in cflags, got %q", "-Xclang -verify", cFlags_no_cv)
3207	}
3208
3209	cFlags_cv := ctx.ModuleForTests("lib_clang_verify", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
3210	if strings.Contains(cFlags_cv, "-Xclang") && strings.Contains(cFlags_cv, "-verify") {
3211		t.Errorf("expected %q in cflags, got %q", "-Xclang -verify", cFlags_cv)
3212	}
3213}
3214
3215func TestCheckConflictingExplicitVersions(t *testing.T) {
3216	PrepareForIntegrationTestWithCc.
3217		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
3218			`shared_libs: duplicate shared libraries with different explicit versions: "libbar" and "libbar#impl"`,
3219		)).
3220		RunTestWithBp(t, `
3221			cc_library {
3222				name: "libfoo",
3223				shared_libs: ["libbar", "libbar#impl"],
3224			}
3225
3226			cc_library {
3227				name: "libbar",
3228			}
3229		`)
3230}
3231