xref: /aosp_15_r20/build/soong/cc/testing.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright (C) 2019 The Android Open Source Project
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	"path/filepath"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/genrule"
23)
24
25func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
26	RegisterPrebuiltBuildComponents(ctx)
27	RegisterCCBuildComponents(ctx)
28	RegisterBinaryBuildComponents(ctx)
29	RegisterLibraryBuildComponents(ctx)
30	RegisterLibraryHeadersBuildComponents(ctx)
31
32	ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
33	ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
34	ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
35	ctx.RegisterModuleType("cc_object", ObjectFactory)
36	ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
37	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
38	ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
39}
40
41func GatherRequiredDepsForTest(oses ...android.OsType) string {
42	ret := commonDefaultModules()
43
44	supportLinuxBionic := false
45	for _, os := range oses {
46		if os == android.Windows {
47			ret += withWindowsModules()
48		}
49		if os == android.LinuxBionic {
50			supportLinuxBionic = true
51			ret += withLinuxBionic()
52		}
53	}
54
55	if !supportLinuxBionic {
56		ret += withoutLinuxBionic()
57	}
58
59	return ret
60}
61
62func commonDefaultModules() string {
63	return `
64		cc_defaults {
65			name: "toolchain_libs_defaults",
66			host_supported: true,
67			vendor_available: true,
68			product_available: true,
69			recovery_available: true,
70			no_libcrt: true,
71			sdk_version: "minimum",
72			nocrt: true,
73			no_crt_pad_segment: true,
74			system_shared_libs: [],
75			stl: "none",
76			check_elf_files: false,
77			sanitize: {
78				never: true,
79			},
80			apex_available: [
81				"//apex_available:anyapex",
82				"//apex_available:platform",
83			],
84		}
85
86		cc_prebuilt_library_static {
87			name: "libcompiler_rt-extras",
88			defaults: ["toolchain_libs_defaults"],
89			vendor_ramdisk_available: true,
90			srcs: [""],
91		}
92
93		cc_prebuilt_library_static {
94			name: "libclang_rt.builtins",
95			defaults: ["toolchain_libs_defaults"],
96			host_supported: true,
97	        vendor_available: true,
98			vendor_ramdisk_available: true,
99			native_bridge_supported: true,
100			srcs: [""],
101		}
102
103		cc_prebuilt_library_shared {
104			name: "libclang_rt.hwasan",
105			defaults: ["toolchain_libs_defaults"],
106			srcs: [""],
107		}
108
109		cc_prebuilt_library_static {
110			name: "libunwind",
111			defaults: [
112				"linux_bionic_supported",
113				"toolchain_libs_defaults",
114			],
115			vendor_ramdisk_available: true,
116			native_bridge_supported: true,
117			srcs: [""],
118		}
119
120		cc_prebuilt_library_static {
121			name: "libclang_rt.fuzzer",
122			defaults: [
123				"linux_bionic_supported",
124				"toolchain_libs_defaults",
125			],
126			srcs: [""],
127		}
128
129		// Needed for sanitizer
130		cc_prebuilt_library_shared {
131			name: "libclang_rt.ubsan_standalone",
132			defaults: ["toolchain_libs_defaults"],
133			srcs: [""],
134		}
135
136		cc_prebuilt_library_static {
137			name: "libclang_rt.ubsan_standalone.static",
138			defaults: ["toolchain_libs_defaults"],
139			srcs: [""],
140		}
141
142		cc_prebuilt_library_static {
143			name: "libclang_rt.ubsan_minimal",
144			defaults: ["toolchain_libs_defaults"],
145			host_supported: true,
146			target: {
147				android_arm64: {
148					srcs: ["libclang_rt.ubsan_minimal.android_arm64.a"],
149				},
150				android_arm: {
151					srcs: ["libclang_rt.ubsan_minimal.android_arm.a"],
152				},
153				linux_glibc_x86_64: {
154					srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
155				},
156				linux_glibc_x86: {
157					srcs: ["libclang_rt.ubsan_minimal.x86.a"],
158				},
159				linux_musl_x86_64: {
160					srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
161				},
162				linux_musl_x86: {
163					srcs: ["libclang_rt.ubsan_minimal.x86.a"],
164				},
165			},
166		}
167
168		cc_library {
169			name: "libc",
170			defaults: ["linux_bionic_supported"],
171			no_libcrt: true,
172			nocrt: true,
173			stl: "none",
174			system_shared_libs: [],
175			recovery_available: true,
176			stubs: {
177				versions: ["27", "28", "29"],
178			},
179			llndk: {
180				symbol_file: "libc.map.txt",
181			},
182		}
183		cc_library {
184			name: "libm",
185			defaults: ["linux_bionic_supported"],
186			no_libcrt: true,
187			nocrt: true,
188			stl: "none",
189			system_shared_libs: [],
190			recovery_available: true,
191			stubs: {
192				versions: ["27", "28", "29"],
193			},
194			apex_available: [
195				"//apex_available:platform",
196				"myapex"
197			],
198			llndk: {
199				symbol_file: "libm.map.txt",
200			},
201		}
202
203		// Coverage libraries
204		cc_library {
205			name: "libprofile-extras",
206			vendor_available: true,
207			vendor_ramdisk_available: true,
208			product_available: true,
209			recovery_available: true,
210			native_coverage: false,
211			system_shared_libs: [],
212			stl: "none",
213		}
214		cc_library {
215			name: "libprofile-clang-extras",
216			vendor_available: true,
217			vendor_ramdisk_available: true,
218			product_available: true,
219			recovery_available: true,
220			native_coverage: false,
221			system_shared_libs: [],
222			stl: "none",
223		}
224		cc_library {
225			name: "libprofile-extras_ndk",
226			vendor_available: true,
227			product_available: true,
228			native_coverage: false,
229			system_shared_libs: [],
230			stl: "none",
231			sdk_version: "current",
232		}
233		cc_library {
234			name: "libprofile-clang-extras_ndk",
235			vendor_available: true,
236			product_available: true,
237			native_coverage: false,
238			system_shared_libs: [],
239			stl: "none",
240			sdk_version: "current",
241		}
242
243		cc_library {
244			name: "libdl",
245			defaults: ["linux_bionic_supported"],
246			no_libcrt: true,
247			nocrt: true,
248			stl: "none",
249			system_shared_libs: [],
250			recovery_available: true,
251			stubs: {
252				versions: ["27", "28", "29"],
253			},
254			apex_available: [
255				"//apex_available:platform",
256				"myapex"
257			],
258			llndk: {
259				symbol_file: "libdl.map.txt",
260			},
261		}
262		cc_library {
263			name: "libft2",
264			no_libcrt: true,
265			nocrt: true,
266			system_shared_libs: [],
267			recovery_available: true,
268			llndk: {
269				symbol_file: "libft2.map.txt",
270				private: true,
271			}
272		}
273		cc_library {
274			name: "libc++_static",
275			no_libcrt: true,
276			nocrt: true,
277			system_shared_libs: [],
278			stl: "none",
279			vendor_available: true,
280			vendor_ramdisk_available: true,
281			product_available: true,
282			recovery_available: true,
283			host_supported: true,
284			min_sdk_version: "29",
285			apex_available: [
286				"//apex_available:platform",
287				"//apex_available:anyapex",
288			],
289		}
290		cc_library {
291			name: "libc++",
292			no_libcrt: true,
293			nocrt: true,
294			system_shared_libs: [],
295			stl: "none",
296			vendor_available: true,
297			vendor_ramdisk_available: true,
298			product_available: true,
299			recovery_available: true,
300			host_supported: true,
301			min_sdk_version: "29",
302			double_loadable: true,
303			apex_available: [
304				"//apex_available:platform",
305				"//apex_available:anyapex",
306			],
307		}
308		cc_library {
309			name: "ndk_libc++_shared",
310			export_include_dirs: ["ndk_libc++_shared_include_dirs"],
311			no_libcrt: true,
312			nocrt: true,
313			system_shared_libs: [],
314			stl: "none",
315			vendor_available: true,
316			vendor_ramdisk_available: true,
317			product_available: true,
318			recovery_available: true,
319			host_supported: false,
320			sdk_version: "minimum",
321			double_loadable: true,
322			apex_available: [
323				"//apex_available:platform",
324				"//apex_available:anyapex",
325			],
326		}
327		cc_library {
328			name: "libc++demangle",
329			no_libcrt: true,
330			nocrt: true,
331			system_shared_libs: [],
332			stl: "none",
333			host_supported: false,
334			vendor_available: true,
335			vendor_ramdisk_available: true,
336			product_available: true,
337			recovery_available: true,
338			min_sdk_version: "29",
339			apex_available: [
340				"//apex_available:platform",
341				"//apex_available:anyapex",
342			],
343		}
344
345		cc_defaults {
346			name: "crt_defaults",
347			defaults: ["linux_bionic_supported"],
348			recovery_available: true,
349			vendor_available: true,
350			vendor_ramdisk_available: true,
351			product_available: true,
352			native_bridge_supported: true,
353			stl: "none",
354			min_sdk_version: "16",
355			crt: true,
356			system_shared_libs: [],
357			apex_available: [
358				"//apex_available:platform",
359				"//apex_available:anyapex",
360			],
361		}
362
363		cc_object {
364			name: "crtbegin_so",
365			defaults: ["crt_defaults"],
366			srcs: ["crtbegin_so.c"],
367			objs: ["crtbrand"],
368		}
369
370		cc_object {
371			name: "crtbegin_dynamic",
372			defaults: ["crt_defaults"],
373			srcs: ["crtbegin.c"],
374			objs: ["crtbrand"],
375		}
376
377		cc_object {
378			name: "crtbegin_static",
379			defaults: ["crt_defaults"],
380			srcs: ["crtbegin.c"],
381			objs: ["crtbrand"],
382		}
383
384		cc_object {
385			name: "crtend_so",
386			defaults: ["crt_defaults"],
387			srcs: ["crtend_so.c"],
388			objs: ["crtbrand"],
389		}
390
391		cc_object {
392			name: "crtend_android",
393			defaults: ["crt_defaults"],
394			srcs: ["crtend.c"],
395			objs: ["crtbrand"],
396		}
397
398		cc_object {
399			name: "crt_pad_segment",
400			defaults: ["crt_defaults"],
401		}
402
403		cc_object {
404			name: "crtbrand",
405			defaults: ["crt_defaults"],
406			srcs: ["crtbrand.c"],
407		}
408
409		cc_library {
410			name: "libprotobuf-cpp-lite",
411		}
412
413		ndk_library {
414			name: "libc",
415			first_version: "minimum",
416			symbol_file: "libc.map.txt",
417		}
418
419		ndk_library {
420			name: "libm",
421			first_version: "minimum",
422			symbol_file: "libm.map.txt",
423		}
424
425		ndk_library {
426			name: "libdl",
427			first_version: "minimum",
428			symbol_file: "libdl.map.txt",
429		}
430
431		cc_library_static {
432			name: "libgoogle-benchmark",
433			sdk_version: "current",
434			stl: "none",
435			system_shared_libs: [],
436		}
437
438		cc_library_static {
439			name: "note_memtag_heap_async",
440		}
441
442		cc_library_static {
443			name: "note_memtag_heap_sync",
444		}
445
446		cc_library {
447			name: "libc_musl",
448			host_supported: true,
449			no_libcrt: true,
450			nocrt: true,
451			system_shared_libs: [],
452			stl: "none",
453		}
454	`
455}
456
457func withWindowsModules() string {
458	return `
459		cc_prebuilt_library_static {
460			name: "libwinpthread",
461			host_supported: true,
462			enabled: false,
463			target: {
464				windows: {
465					enabled: true,
466				},
467			},
468			stl: "none",
469			srcs:[""],
470		}
471		`
472}
473
474func withLinuxBionic() string {
475	return `
476				cc_binary {
477					name: "linker",
478					defaults: ["linux_bionic_supported"],
479					recovery_available: true,
480					stl: "none",
481					nocrt: true,
482					static_executable: true,
483					native_coverage: false,
484					system_shared_libs: [],
485				}
486
487				cc_genrule {
488					name: "host_bionic_linker_script",
489					host_supported: true,
490					device_supported: false,
491					target: {
492						host: {
493							enabled: false,
494						},
495						linux_bionic: {
496							enabled: true,
497						},
498					},
499					out: ["linker.script"],
500				}
501
502				cc_defaults {
503					name: "linux_bionic_supported",
504					host_supported: true,
505					target: {
506						host: {
507							enabled: false,
508						},
509						linux_bionic: {
510							enabled: true,
511						},
512					},
513				}
514			`
515}
516
517func withoutLinuxBionic() string {
518	return `
519			cc_defaults {
520				name: "linux_bionic_supported",
521			}
522		`
523}
524
525func GatherRequiredFilesForTest(fs map[string][]byte) {
526}
527
528// The directory in which cc linux bionic default modules will be defined.
529//
530// Placing them here ensures that their location does not conflict with default test modules
531// defined by other packages.
532const linuxBionicDefaultsPath = "defaults/cc/linux-bionic/Android.bp"
533
534// The directory in which the default cc common test modules will be defined.
535//
536// Placing them here ensures that their location does not conflict with default test modules
537// defined by other packages.
538const DefaultCcCommonTestModulesDir = "defaults/cc/common/"
539
540// Test fixture preparer that will register most cc build components.
541//
542// Singletons and mutators should only be added here if they are needed for a majority of cc
543// module types, otherwise they should be added under a separate preparer to allow them to be
544// selected only when needed to reduce test execution time.
545//
546// Module types do not have much of an overhead unless they are used so this should include as many
547// module types as possible. The exceptions are those module types that require mutators and/or
548// singletons in order to function in which case they should be kept together in a separate
549// preparer.
550var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers(
551	android.PrepareForTestWithAndroidBuildComponents,
552	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
553	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
554		ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
555		ctx.RegisterModuleType("cc_test", TestFactory)
556		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
557		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
558
559		RegisterLlndkLibraryTxtType(ctx)
560	}),
561)
562
563// Preparer that will define default cc modules, e.g. standard prebuilt modules.
564var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
565	PrepareForTestWithCcBuildComponents,
566
567	// Additional files needed in tests that disallow non-existent source.
568	android.MockFS{
569		"defaults/cc/common/libc.map.txt":                   nil,
570		"defaults/cc/common/libdl.map.txt":                  nil,
571		"defaults/cc/common/libft2.map.txt":                 nil,
572		"defaults/cc/common/libm.map.txt":                   nil,
573		"defaults/cc/common/ndk_libc++_shared_include_dirs": nil,
574		"defaults/cc/common/crtbegin_so.c":                  nil,
575		"defaults/cc/common/crtbegin.c":                     nil,
576		"defaults/cc/common/crtend_so.c":                    nil,
577		"defaults/cc/common/crtend.c":                       nil,
578		"defaults/cc/common/crtbrand.c":                     nil,
579		"external/compiler-rt/lib/cfi/cfi_blocklist.txt":    nil,
580
581		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
582		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a":   nil,
583		"defaults/cc/common/libclang_rt.ubsan_minimal.x86_64.a":        nil,
584		"defaults/cc/common/libclang_rt.ubsan_minimal.x86.a":           nil,
585	}.AddToFixture(),
586
587	// Place the default cc test modules that are common to all platforms in a location that will not
588	// conflict with default test modules defined by other packages.
589	android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()),
590	// Disable linux bionic by default.
591	android.FixtureAddTextFile(linuxBionicDefaultsPath, withoutLinuxBionic()),
592)
593
594// Prepare a fixture to use all cc module types, mutators and singletons fully.
595//
596// This should only be used by tests that want to run with as much of the build enabled as possible.
597var PrepareForIntegrationTestWithCc = android.GroupFixturePreparers(
598	android.PrepareForIntegrationTestWithAndroid,
599	genrule.PrepareForIntegrationTestWithGenrule,
600	PrepareForTestWithCcDefaultModules,
601)
602
603// The preparer to include if running a cc related test for windows.
604var PrepareForTestOnWindows = android.GroupFixturePreparers(
605	// Place the default cc test modules for windows platforms in a location that will not conflict
606	// with default test modules defined by other packages.
607	android.FixtureAddTextFile("defaults/cc/windows/Android.bp", withWindowsModules()),
608)
609
610// The preparer to include if running a cc related test for linux bionic.
611var PrepareForTestOnLinuxBionic = android.GroupFixturePreparers(
612	// Enable linux bionic
613	//
614	// Can be used after PrepareForTestWithCcDefaultModules to override its default behavior of
615	// disabling linux bionic, hence why this uses FixtureOverrideTextFile.
616	android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
617)
618
619// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc.  It also disables the test
620// on mac, which doesn't support musl libc, and adds musl modules.
621var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
622	android.FixtureModifyConfig(android.ModifyTestConfigForMusl),
623	android.PrepareForSkipTestOnMac,
624	android.FixtureAddTextFile("external/musl/Android.bp", `
625		cc_defaults {
626			name: "libc_musl_crt_defaults",
627			host_supported: true,
628			device_supported: false,
629		}
630
631		cc_object {
632			name: "libc_musl_crtbegin_so",
633			defaults: ["libc_musl_crt_defaults"],
634		}
635
636		cc_object {
637			name: "libc_musl_crtend_so",
638			defaults: ["libc_musl_crt_defaults"],
639		}
640
641		cc_object {
642			name: "libc_musl_crtbegin_dynamic",
643			defaults: ["libc_musl_crt_defaults"],
644		}
645
646		cc_object {
647			name: "libc_musl_crtbegin_static",
648			defaults: ["libc_musl_crt_defaults"],
649		}
650
651		cc_object {
652			name: "libc_musl_crtend",
653			defaults: ["libc_musl_crt_defaults"],
654		}
655	`),
656)
657
658// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
659var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
660	ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
661	ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
662})
663
664// TestConfig is the legacy way of creating a test Config for testing cc modules.
665//
666// See testCc for an explanation as to how to stop using this deprecated method.
667//
668// deprecated
669func TestConfig(buildDir string, os android.OsType, env map[string]string,
670	bp string, fs map[string][]byte) android.Config {
671
672	// add some modules that are required by the compiler and/or linker
673	bp = bp + GatherRequiredDepsForTest(os)
674
675	mockFS := map[string][]byte{}
676
677	GatherRequiredFilesForTest(mockFS)
678
679	for k, v := range fs {
680		mockFS[k] = v
681	}
682
683	return android.TestArchConfig(buildDir, env, bp, mockFS)
684}
685
686// CreateTestContext is the legacy way of creating a TestContext for testing cc modules.
687//
688// See testCc for an explanation as to how to stop using this deprecated method.
689//
690// deprecated
691func CreateTestContext(config android.Config) *android.TestContext {
692	ctx := android.NewTestArchContext(config)
693	genrule.RegisterGenruleBuildComponents(ctx)
694	ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
695	ctx.RegisterModuleType("cc_test", TestFactory)
696	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
697	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
698	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
699
700	RegisterLlndkLibraryTxtType(ctx)
701
702	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
703	android.RegisterPrebuiltMutators(ctx)
704	RegisterRequiredBuildComponentsForTest(ctx)
705
706	return ctx
707}
708
709func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
710	t.Helper()
711	mod := ctx.ModuleForTests(moduleName, variant)
712	outputFiles := mod.OutputFiles(ctx, t, "")
713	if len(outputFiles) != 1 {
714		t.Errorf("%q must have single output\n", moduleName)
715		return
716	}
717	snapshotPath := filepath.Join(subDir, snapshotFilename)
718
719	if include {
720		out := singleton.Output(snapshotPath)
721		if fake {
722			if out.Rule == nil {
723				t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
724			}
725		} else {
726			if out.Input.String() != outputFiles[0].String() {
727				t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
728			}
729		}
730	} else {
731		out := singleton.MaybeOutput(snapshotPath)
732		if out.Rule != nil {
733			t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
734		}
735	}
736}
737
738func CheckSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
739	t.Helper()
740	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
741}
742
743func CheckSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
744	t.Helper()
745	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
746}
747
748func CheckSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
749	t.Helper()
750	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
751}
752
753func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
754	for _, moduleName := range moduleNames {
755		module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
756		output := module.outputFile.Path().RelativeToTop()
757		paths = append(paths, output)
758	}
759	return paths
760}
761