| // Copyright (C) 2019 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package cc |
| |
| import ( |
| "path/filepath" |
| "testing" |
| |
| "android/soong/android" |
| "android/soong/genrule" |
| "android/soong/snapshot" |
| ) |
| |
| func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { |
| RegisterPrebuiltBuildComponents(ctx) |
| RegisterCCBuildComponents(ctx) |
| RegisterBinaryBuildComponents(ctx) |
| RegisterLibraryBuildComponents(ctx) |
| RegisterLibraryHeadersBuildComponents(ctx) |
| |
| ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory) |
| ctx.RegisterModuleType("cc_object", ObjectFactory) |
| ctx.RegisterModuleType("cc_genrule", GenRuleFactory) |
| ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory) |
| ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory) |
| ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory) |
| ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) |
| } |
| |
| func GatherRequiredDepsForTest(oses ...android.OsType) string { |
| ret := commonDefaultModules() |
| |
| supportLinuxBionic := false |
| for _, os := range oses { |
| if os == android.Windows { |
| ret += withWindowsModules() |
| } |
| if os == android.LinuxBionic { |
| supportLinuxBionic = true |
| ret += withLinuxBionic() |
| } |
| } |
| |
| if !supportLinuxBionic { |
| ret += withoutLinuxBionic() |
| } |
| |
| return ret |
| } |
| |
| func commonDefaultModules() string { |
| return ` |
| cc_defaults { |
| name: "toolchain_libs_defaults", |
| vendor_available: true, |
| product_available: true, |
| recovery_available: true, |
| no_libcrt: true, |
| sdk_version: "minimum", |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| srcs: [""], |
| check_elf_files: false, |
| sanitize: { |
| never: true, |
| }, |
| } |
| |
| cc_prebuilt_library_static { |
| name: "libcompiler_rt-extras", |
| defaults: ["toolchain_libs_defaults"], |
| vendor_ramdisk_available: true, |
| } |
| |
| cc_prebuilt_library_static { |
| name: "libclang_rt.builtins", |
| defaults: ["toolchain_libs_defaults"], |
| host_supported: true, |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| native_bridge_supported: true, |
| } |
| |
| cc_prebuilt_library_shared { |
| name: "libclang_rt.hwasan", |
| defaults: ["toolchain_libs_defaults"], |
| } |
| |
| cc_prebuilt_library_static { |
| name: "libunwind", |
| defaults: [ |
| "linux_bionic_supported", |
| "toolchain_libs_defaults", |
| ], |
| vendor_ramdisk_available: true, |
| native_bridge_supported: true, |
| } |
| |
| cc_prebuilt_library_static { |
| name: "libclang_rt.fuzzer", |
| defaults: [ |
| "linux_bionic_supported", |
| "toolchain_libs_defaults", |
| ], |
| } |
| |
| // Needed for sanitizer |
| cc_prebuilt_library_shared { |
| name: "libclang_rt.ubsan_standalone", |
| defaults: ["toolchain_libs_defaults"], |
| } |
| |
| cc_prebuilt_library_static { |
| name: "libclang_rt.ubsan_minimal", |
| defaults: ["toolchain_libs_defaults"], |
| } |
| |
| cc_library { |
| name: "libc", |
| defaults: ["linux_bionic_supported"], |
| no_libcrt: true, |
| nocrt: true, |
| stl: "none", |
| system_shared_libs: [], |
| recovery_available: true, |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| llndk: { |
| symbol_file: "libc.map.txt", |
| }, |
| } |
| cc_library { |
| name: "libm", |
| defaults: ["linux_bionic_supported"], |
| no_libcrt: true, |
| nocrt: true, |
| stl: "none", |
| system_shared_libs: [], |
| recovery_available: true, |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| apex_available: [ |
| "//apex_available:platform", |
| "myapex" |
| ], |
| llndk: { |
| symbol_file: "libm.map.txt", |
| }, |
| } |
| |
| // Coverage libraries |
| cc_library { |
| name: "libprofile-extras", |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| product_available: true, |
| recovery_available: true, |
| native_coverage: false, |
| system_shared_libs: [], |
| stl: "none", |
| notice: "custom_notice", |
| } |
| cc_library { |
| name: "libprofile-clang-extras", |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| product_available: true, |
| recovery_available: true, |
| native_coverage: false, |
| system_shared_libs: [], |
| stl: "none", |
| notice: "custom_notice", |
| } |
| cc_library { |
| name: "libprofile-extras_ndk", |
| vendor_available: true, |
| product_available: true, |
| native_coverage: false, |
| system_shared_libs: [], |
| stl: "none", |
| notice: "custom_notice", |
| sdk_version: "current", |
| } |
| cc_library { |
| name: "libprofile-clang-extras_ndk", |
| vendor_available: true, |
| product_available: true, |
| native_coverage: false, |
| system_shared_libs: [], |
| stl: "none", |
| notice: "custom_notice", |
| sdk_version: "current", |
| } |
| |
| cc_library { |
| name: "libdl", |
| defaults: ["linux_bionic_supported"], |
| no_libcrt: true, |
| nocrt: true, |
| stl: "none", |
| system_shared_libs: [], |
| recovery_available: true, |
| stubs: { |
| versions: ["27", "28", "29"], |
| }, |
| apex_available: [ |
| "//apex_available:platform", |
| "myapex" |
| ], |
| llndk: { |
| symbol_file: "libdl.map.txt", |
| }, |
| } |
| cc_library { |
| name: "libft2", |
| no_libcrt: true, |
| nocrt: true, |
| system_shared_libs: [], |
| recovery_available: true, |
| llndk: { |
| symbol_file: "libft2.map.txt", |
| private: true, |
| } |
| } |
| cc_library { |
| name: "libc++_static", |
| no_libcrt: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| product_available: true, |
| recovery_available: true, |
| host_supported: true, |
| min_sdk_version: "29", |
| apex_available: [ |
| "//apex_available:platform", |
| "//apex_available:anyapex", |
| ], |
| } |
| cc_library { |
| name: "libc++", |
| no_libcrt: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| vendor_available: true, |
| product_available: true, |
| recovery_available: true, |
| host_supported: true, |
| min_sdk_version: "29", |
| vndk: { |
| enabled: true, |
| support_system_process: true, |
| }, |
| apex_available: [ |
| "//apex_available:platform", |
| "//apex_available:anyapex", |
| ], |
| } |
| cc_library { |
| name: "libc++demangle", |
| no_libcrt: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| host_supported: false, |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| product_available: true, |
| recovery_available: true, |
| min_sdk_version: "29", |
| apex_available: [ |
| "//apex_available:platform", |
| "//apex_available:anyapex", |
| ], |
| } |
| |
| cc_defaults { |
| name: "crt_defaults", |
| defaults: ["linux_bionic_supported"], |
| recovery_available: true, |
| vendor_available: true, |
| vendor_ramdisk_available: true, |
| product_available: true, |
| native_bridge_supported: true, |
| stl: "none", |
| min_sdk_version: "16", |
| crt: true, |
| system_shared_libs: [], |
| apex_available: [ |
| "//apex_available:platform", |
| "//apex_available:anyapex", |
| ], |
| } |
| |
| cc_object { |
| name: "crtbegin_so", |
| defaults: ["crt_defaults"], |
| srcs: ["crtbegin_so.c"], |
| objs: ["crtbrand"], |
| } |
| |
| cc_object { |
| name: "crtbegin_dynamic", |
| defaults: ["crt_defaults"], |
| srcs: ["crtbegin.c"], |
| objs: ["crtbrand"], |
| } |
| |
| cc_object { |
| name: "crtbegin_static", |
| defaults: ["crt_defaults"], |
| srcs: ["crtbegin.c"], |
| objs: ["crtbrand"], |
| } |
| |
| cc_object { |
| name: "crtend_so", |
| defaults: ["crt_defaults"], |
| srcs: ["crtend_so.c"], |
| objs: ["crtbrand"], |
| } |
| |
| cc_object { |
| name: "crtend_android", |
| defaults: ["crt_defaults"], |
| srcs: ["crtend.c"], |
| objs: ["crtbrand"], |
| } |
| |
| cc_object { |
| name: "crtbrand", |
| defaults: ["crt_defaults"], |
| srcs: ["crtbrand.c"], |
| } |
| |
| cc_library { |
| name: "libprotobuf-cpp-lite", |
| } |
| |
| cc_library { |
| name: "ndk_libunwind", |
| sdk_version: "minimum", |
| stl: "none", |
| system_shared_libs: [], |
| } |
| |
| ndk_library { |
| name: "libc", |
| first_version: "minimum", |
| symbol_file: "libc.map.txt", |
| } |
| |
| ndk_library { |
| name: "libm", |
| first_version: "minimum", |
| symbol_file: "libm.map.txt", |
| } |
| |
| ndk_library { |
| name: "libdl", |
| first_version: "minimum", |
| symbol_file: "libdl.map.txt", |
| } |
| |
| ndk_prebuilt_shared_stl { |
| name: "ndk_libc++_shared", |
| export_include_dirs: ["ndk_libc++_shared"], |
| } |
| |
| ndk_prebuilt_static_stl { |
| name: "ndk_libandroid_support", |
| export_include_dirs: ["ndk_libandroid_support"], |
| } |
| |
| cc_library_static { |
| name: "libgoogle-benchmark", |
| sdk_version: "current", |
| stl: "none", |
| system_shared_libs: [], |
| } |
| |
| cc_library_static { |
| name: "note_memtag_heap_async", |
| } |
| |
| cc_library_static { |
| name: "note_memtag_heap_sync", |
| } |
| |
| cc_library { |
| name: "libc_musl", |
| host_supported: true, |
| no_libcrt: true, |
| nocrt: true, |
| system_shared_libs: [], |
| stl: "none", |
| } |
| ` |
| } |
| |
| func withWindowsModules() string { |
| return ` |
| cc_prebuilt_library_static { |
| name: "libwinpthread", |
| host_supported: true, |
| enabled: false, |
| target: { |
| windows: { |
| enabled: true, |
| }, |
| }, |
| stl: "none", |
| srcs:[""], |
| } |
| ` |
| } |
| |
| func withLinuxBionic() string { |
| return ` |
| cc_binary { |
| name: "linker", |
| defaults: ["linux_bionic_supported"], |
| recovery_available: true, |
| stl: "none", |
| nocrt: true, |
| static_executable: true, |
| native_coverage: false, |
| system_shared_libs: [], |
| } |
| |
| cc_genrule { |
| name: "host_bionic_linker_script", |
| host_supported: true, |
| device_supported: false, |
| target: { |
| host: { |
| enabled: false, |
| }, |
| linux_bionic: { |
| enabled: true, |
| }, |
| }, |
| out: ["linker.script"], |
| } |
| |
| cc_defaults { |
| name: "linux_bionic_supported", |
| host_supported: true, |
| target: { |
| host: { |
| enabled: false, |
| }, |
| linux_bionic: { |
| enabled: true, |
| }, |
| }, |
| } |
| ` |
| } |
| |
| func withoutLinuxBionic() string { |
| return ` |
| cc_defaults { |
| name: "linux_bionic_supported", |
| } |
| ` |
| } |
| |
| func GatherRequiredFilesForTest(fs map[string][]byte) { |
| } |
| |
| // The directory in which cc linux bionic default modules will be defined. |
| // |
| // Placing them here ensures that their location does not conflict with default test modules |
| // defined by other packages. |
| const linuxBionicDefaultsPath = "defaults/cc/linux-bionic/Android.bp" |
| |
| // The directory in which the default cc common test modules will be defined. |
| // |
| // Placing them here ensures that their location does not conflict with default test modules |
| // defined by other packages. |
| const DefaultCcCommonTestModulesDir = "defaults/cc/common/" |
| |
| // Test fixture preparer that will register most cc build components. |
| // |
| // Singletons and mutators should only be added here if they are needed for a majority of cc |
| // module types, otherwise they should be added under a separate preparer to allow them to be |
| // selected only when needed to reduce test execution time. |
| // |
| // Module types do not have much of an overhead unless they are used so this should include as many |
| // module types as possible. The exceptions are those module types that require mutators and/or |
| // singletons in order to function in which case they should be kept together in a separate |
| // preparer. |
| var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( |
| android.PrepareForTestWithAndroidBuildComponents, |
| android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest), |
| android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { |
| ctx.RegisterModuleType("cc_fuzz", FuzzFactory) |
| ctx.RegisterModuleType("cc_test", TestFactory) |
| ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) |
| ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) |
| |
| RegisterVndkLibraryTxtTypes(ctx) |
| }), |
| |
| // Additional files needed in tests that disallow non-existent source files. |
| // This includes files that are needed by all, or at least most, instances of a cc module type. |
| android.MockFS{ |
| // Needed for ndk_prebuilt_(shared|static)_stl. |
| "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs": nil, |
| }.AddToFixture(), |
| ) |
| |
| // Preparer that will define default cc modules, e.g. standard prebuilt modules. |
| var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers( |
| PrepareForTestWithCcBuildComponents, |
| |
| // Additional files needed in tests that disallow non-existent source. |
| android.MockFS{ |
| "defaults/cc/common/libc.map.txt": nil, |
| "defaults/cc/common/libdl.map.txt": nil, |
| "defaults/cc/common/libm.map.txt": nil, |
| "defaults/cc/common/ndk_libandroid_support": nil, |
| "defaults/cc/common/ndk_libc++_shared": nil, |
| "defaults/cc/common/crtbegin_so.c": nil, |
| "defaults/cc/common/crtbegin.c": nil, |
| "defaults/cc/common/crtend_so.c": nil, |
| "defaults/cc/common/crtend.c": nil, |
| "defaults/cc/common/crtbrand.c": nil, |
| }.AddToFixture(), |
| |
| // Place the default cc test modules that are common to all platforms in a location that will not |
| // conflict with default test modules defined by other packages. |
| android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()), |
| // Disable linux bionic by default. |
| android.FixtureAddTextFile(linuxBionicDefaultsPath, withoutLinuxBionic()), |
| ) |
| |
| // Prepare a fixture to use all cc module types, mutators and singletons fully. |
| // |
| // This should only be used by tests that want to run with as much of the build enabled as possible. |
| var PrepareForIntegrationTestWithCc = android.GroupFixturePreparers( |
| android.PrepareForIntegrationTestWithAndroid, |
| genrule.PrepareForIntegrationTestWithGenrule, |
| PrepareForTestWithCcDefaultModules, |
| ) |
| |
| // The preparer to include if running a cc related test for windows. |
| var PrepareForTestOnWindows = android.GroupFixturePreparers( |
| // Place the default cc test modules for windows platforms in a location that will not conflict |
| // with default test modules defined by other packages. |
| android.FixtureAddTextFile("defaults/cc/windows/Android.bp", withWindowsModules()), |
| ) |
| |
| // The preparer to include if running a cc related test for linux bionic. |
| var PrepareForTestOnLinuxBionic = android.GroupFixturePreparers( |
| // Enable linux bionic |
| // |
| // Can be used after PrepareForTestWithCcDefaultModules to override its default behavior of |
| // disabling linux bionic, hence why this uses FixtureOverrideTextFile. |
| android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()), |
| ) |
| |
| // This adds some additional modules and singletons which might negatively impact the performance |
| // of tests so they are not included in the PrepareForIntegrationTestWithCc. |
| var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers( |
| PrepareForIntegrationTestWithCc, |
| android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { |
| snapshot.VendorSnapshotImageSingleton.Init(ctx) |
| snapshot.RecoverySnapshotImageSingleton.Init(ctx) |
| RegisterVendorSnapshotModules(ctx) |
| RegisterRecoverySnapshotModules(ctx) |
| ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) |
| }), |
| ) |
| |
| // TestConfig is the legacy way of creating a test Config for testing cc modules. |
| // |
| // See testCc for an explanation as to how to stop using this deprecated method. |
| // |
| // deprecated |
| func TestConfig(buildDir string, os android.OsType, env map[string]string, |
| bp string, fs map[string][]byte) android.Config { |
| |
| // add some modules that are required by the compiler and/or linker |
| bp = bp + GatherRequiredDepsForTest(os) |
| |
| mockFS := map[string][]byte{} |
| |
| GatherRequiredFilesForTest(mockFS) |
| |
| for k, v := range fs { |
| mockFS[k] = v |
| } |
| |
| return android.TestArchConfig(buildDir, env, bp, mockFS) |
| } |
| |
| // CreateTestContext is the legacy way of creating a TestContext for testing cc modules. |
| // |
| // See testCc for an explanation as to how to stop using this deprecated method. |
| // |
| // deprecated |
| func CreateTestContext(config android.Config) *android.TestContext { |
| ctx := android.NewTestArchContext(config) |
| genrule.RegisterGenruleBuildComponents(ctx) |
| ctx.RegisterModuleType("cc_fuzz", FuzzFactory) |
| ctx.RegisterModuleType("cc_test", TestFactory) |
| ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) |
| ctx.RegisterModuleType("filegroup", android.FileGroupFactory) |
| ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) |
| |
| snapshot.VendorSnapshotImageSingleton.Init(ctx) |
| snapshot.RecoverySnapshotImageSingleton.Init(ctx) |
| RegisterVendorSnapshotModules(ctx) |
| RegisterRecoverySnapshotModules(ctx) |
| ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) |
| RegisterVndkLibraryTxtTypes(ctx) |
| |
| ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) |
| android.RegisterPrebuiltMutators(ctx) |
| RegisterRequiredBuildComponentsForTest(ctx) |
| |
| return ctx |
| } |
| |
| func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) { |
| t.Helper() |
| mod := ctx.ModuleForTests(moduleName, variant) |
| outputFiles := mod.OutputFiles(t, "") |
| if len(outputFiles) != 1 { |
| t.Errorf("%q must have single output\n", moduleName) |
| return |
| } |
| snapshotPath := filepath.Join(subDir, snapshotFilename) |
| |
| if include { |
| out := singleton.Output(snapshotPath) |
| if fake { |
| if out.Rule == nil { |
| t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0]) |
| } |
| } else { |
| if out.Input.String() != outputFiles[0].String() { |
| t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0]) |
| } |
| } |
| } else { |
| out := singleton.MaybeOutput(snapshotPath) |
| if out.Rule != nil { |
| t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0]) |
| } |
| } |
| } |
| |
| func CheckSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { |
| t.Helper() |
| checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false) |
| } |
| |
| func CheckSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { |
| t.Helper() |
| checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false) |
| } |
| |
| func CheckSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { |
| t.Helper() |
| checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true) |
| } |
| |
| func AssertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) { |
| t.Helper() |
| m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface) |
| if m.ExcludeFromVendorSnapshot() != expected { |
| t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected) |
| } |
| } |
| |
| func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) { |
| for _, moduleName := range moduleNames { |
| module := ctx.ModuleForTests(moduleName, variant).Module().(*Module) |
| output := module.outputFile.Path().RelativeToTop() |
| paths = append(paths, output) |
| } |
| return paths |
| } |
| |
| func AssertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) { |
| t.Helper() |
| m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface) |
| if m.ExcludeFromRecoverySnapshot() != expected { |
| t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected) |
| } |
| } |