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