| // Copyright 2021 Google Inc. All rights reserved. | 
 | // | 
 | // 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 ( | 
 | 	"android/soong/android" | 
 | 	"fmt" | 
 | 	"path/filepath" | 
 | 	"reflect" | 
 | 	"strings" | 
 | 	"testing" | 
 | ) | 
 |  | 
 | func checkJsonContents(t *testing.T, ctx *android.TestContext, snapshotSingleton android.TestingSingleton, jsonPath string, key string, value string) { | 
 | 	jsonOut := snapshotSingleton.MaybeOutput(jsonPath) | 
 | 	if jsonOut.Rule == nil { | 
 | 		t.Errorf("%q expected but not found", jsonPath) | 
 | 		return | 
 | 	} | 
 | 	content := android.ContentFromFileRuleForTests(t, ctx, jsonOut) | 
 | 	if !strings.Contains(content, fmt.Sprintf("%q:%q", key, value)) { | 
 | 		t.Errorf("%q must include %q:%q but it only has %v", jsonPath, key, value, jsonOut.Args["content"]) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVendorSnapshotCapture(t *testing.T) { | 
 | 	bp := ` | 
 | 	cc_library { | 
 | 		name: "libvndk", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor_override", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		overrides: ["libvendor"], | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor_available", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 		min_sdk_version: "29", | 
 | 	} | 
 |  | 
 | 	cc_library_headers { | 
 | 		name: "libvendor_headers", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "vendor_bin", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "vendor_available_bin", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "vendor_bin_override", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		overrides: ["vendor_bin"], | 
 | 	} | 
 |  | 
 | 	cc_prebuilt_library_static { | 
 | 		name: "libb", | 
 | 		vendor_available: true, | 
 | 		srcs: ["libb.a"], | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 	} | 
 |  | 
 | 	cc_object { | 
 | 		name: "obj", | 
 | 		vendor_available: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libllndk", | 
 | 		llndk: { | 
 | 			symbol_file: "libllndk.map.txt", | 
 | 		}, | 
 | 	} | 
 | ` | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check Vendor snapshot output. | 
 |  | 
 | 	snapshotDir := "vendor-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") | 
 |  | 
 | 	var jsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 		[]string{"arm", "armv7-a-neon"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		// For shared libraries, only non-VNDK vendor_available modules are captured | 
 | 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant) | 
 | 		jsonFiles = append(jsonFiles, | 
 | 			filepath.Join(sharedDir, "libvendor.so.json"), | 
 | 			filepath.Join(sharedDir, "libvendor_available.so.json")) | 
 |  | 
 | 		// LLNDK modules are not captured | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant) | 
 |  | 
 | 		// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured. | 
 | 		// Also cfi variants are captured, except for prebuilts like toolchain_library | 
 | 		staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant) | 
 | 		staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant) | 
 | 		staticDir := filepath.Join(snapshotVariantPath, archDir, "static") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant) | 
 | 		jsonFiles = append(jsonFiles, | 
 | 			filepath.Join(staticDir, "libb.a.json"), | 
 | 			filepath.Join(staticDir, "libvndk.a.json"), | 
 | 			filepath.Join(staticDir, "libvndk.cfi.a.json"), | 
 | 			filepath.Join(staticDir, "libvendor.a.json"), | 
 | 			filepath.Join(staticDir, "libvendor.cfi.a.json"), | 
 | 			filepath.Join(staticDir, "libvendor_available.a.json"), | 
 | 			filepath.Join(staticDir, "libvendor_available.cfi.a.json")) | 
 |  | 
 | 		checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit") | 
 | 		checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29") | 
 |  | 
 | 		// For binary executables, all vendor:true and vendor_available modules are captured. | 
 | 		if archType == "arm64" { | 
 | 			binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant) | 
 | 			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary") | 
 | 			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant) | 
 | 			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant) | 
 | 			jsonFiles = append(jsonFiles, | 
 | 				filepath.Join(binaryDir, "vendor_bin.json"), | 
 | 				filepath.Join(binaryDir, "vendor_available_bin.json")) | 
 |  | 
 | 			checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"}) | 
 | 		} | 
 |  | 
 | 		// For header libraries, all vendor:true and vendor_available modules are captured. | 
 | 		headerDir := filepath.Join(snapshotVariantPath, archDir, "header") | 
 | 		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json")) | 
 |  | 
 | 		// For object modules, all vendor:true and vendor_available modules are captured. | 
 | 		objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant) | 
 | 		objectDir := filepath.Join(snapshotVariantPath, archDir, "object") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant) | 
 | 		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json")) | 
 |  | 
 | 		checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"}) | 
 | 	} | 
 |  | 
 | 	for _, jsonFile := range jsonFiles { | 
 | 		// verify all json files exist | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("%q expected but not found", jsonFile) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// fake snapshot should have all outputs in the normal snapshot. | 
 | 	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot") | 
 | 	for _, output := range snapshotSingleton.AllOutputs() { | 
 | 		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1) | 
 | 		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil { | 
 | 			t.Errorf("%q expected but not found", fakeOutput) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestVendorSnapshotDirected(t *testing.T) { | 
 | 	bp := ` | 
 | 	cc_library_shared { | 
 | 		name: "libvendor", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libvendor_available", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	genrule { | 
 | 		name: "libfoo_gen", | 
 | 		cmd: "", | 
 | 		out: ["libfoo.so"], | 
 | 	} | 
 |  | 
 | 	cc_prebuilt_library_shared { | 
 | 		name: "libfoo", | 
 | 		vendor: true, | 
 | 		prefer: true, | 
 | 		srcs: [":libfoo_gen"], | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libfoo", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 	} | 
 | ` | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	config.TestProductVariables.DirectedVendorSnapshot = true | 
 | 	config.TestProductVariables.VendorSnapshotModules = make(map[string]bool) | 
 | 	config.TestProductVariables.VendorSnapshotModules["libvendor"] = true | 
 | 	config.TestProductVariables.VendorSnapshotModules["libfoo"] = true | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check Vendor snapshot output. | 
 |  | 
 | 	snapshotDir := "vendor-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") | 
 |  | 
 | 	var includeJsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 		[]string{"arm", "armv7-a-neon"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 |  | 
 | 		// Included modules | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json")) | 
 | 		// Check that snapshot captures "prefer: true" prebuilt | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json")) | 
 |  | 
 | 		// Excluded modules. Modules not included in the directed vendor snapshot | 
 | 		// are still include as fake modules. | 
 | 		CheckSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json")) | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an included module has a rule. | 
 | 	for _, jsonFile := range includeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("include json file %q not found", jsonFile) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestVendorSnapshotUse(t *testing.T) { | 
 | 	frameworkBp := ` | 
 | 	cc_library { | 
 | 		name: "libvndk", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor_available", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "lib32", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		compile_multilib: "32", | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "lib64", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		compile_multilib: "64", | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libllndk", | 
 | 		llndk: { | 
 | 			symbol_file: "libllndk.map.txt", | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "bin", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "bin32", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		compile_multilib: "32", | 
 | 	} | 
 | ` | 
 |  | 
 | 	vndkBp := ` | 
 | 	vndk_prebuilt_shared { | 
 | 		name: "libvndk", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				srcs: ["libvndk.so"], | 
 | 				export_include_dirs: ["include/libvndk"], | 
 | 			}, | 
 | 			arm: { | 
 | 				srcs: ["libvndk.so"], | 
 | 				export_include_dirs: ["include/libvndk"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	// old snapshot module which has to be ignored | 
 | 	vndk_prebuilt_shared { | 
 | 		name: "libvndk", | 
 | 		version: "26", | 
 | 		target_arch: "arm64", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				srcs: ["libvndk.so"], | 
 | 				export_include_dirs: ["include/libvndk"], | 
 | 			}, | 
 | 			arm: { | 
 | 				srcs: ["libvndk.so"], | 
 | 				export_include_dirs: ["include/libvndk"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	// different arch snapshot which has to be ignored | 
 | 	vndk_prebuilt_shared { | 
 | 		name: "libvndk", | 
 | 		version: "31", | 
 | 		target_arch: "arm", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		arch: { | 
 | 			arm: { | 
 | 				srcs: ["libvndk.so"], | 
 | 				export_include_dirs: ["include/libvndk"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vndk_prebuilt_shared { | 
 | 		name: "libllndk", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				srcs: ["libllndk.so"], | 
 | 			}, | 
 | 			arm: { | 
 | 				srcs: ["libllndk.so"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 | ` | 
 |  | 
 | 	vendorProprietaryBp := ` | 
 | 	cc_library { | 
 | 		name: "libvendor_without_snapshot", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libclient", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		shared_libs: ["libvndk", "libvendor_available", "libllndk"], | 
 | 		static_libs: ["libvendor", "libvendor_without_snapshot"], | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				shared_libs: ["lib64"], | 
 | 			}, | 
 | 			arm: { | 
 | 				shared_libs: ["lib32"], | 
 | 			}, | 
 | 		}, | 
 | 		srcs: ["client.cpp"], | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libclient_cfi", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		static_libs: ["libvendor"], | 
 | 		sanitize: { | 
 | 			cfi: true, | 
 | 		}, | 
 | 		srcs: ["client.cpp"], | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libvndkext", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		system_shared_libs: [], | 
 | 		vndk: { | 
 | 			extends: "libvndk", | 
 | 			enabled: true, | 
 | 		} | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "bin_without_snapshot", | 
 | 		vendor: true, | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "libc++_static", | 
 | 		system_shared_libs: [], | 
 | 		static_libs: ["libvndk"], | 
 | 		srcs: ["bin.cpp"], | 
 | 	} | 
 |  | 
 | 	vendor_snapshot { | 
 | 		name: "vendor_snapshot", | 
 | 		version: "31", | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				vndk_libs: [ | 
 | 					"libvndk", | 
 | 					"libllndk", | 
 | 				], | 
 | 				static_libs: [ | 
 | 					"libc++_static", | 
 | 					"libc++demangle", | 
 | 					"libunwind", | 
 | 					"libvendor", | 
 | 					"libvendor_available", | 
 | 					"libvndk", | 
 | 					"lib64", | 
 | 				], | 
 | 				shared_libs: [ | 
 | 					"libvendor", | 
 | 					"libvendor_override", | 
 | 					"libvendor_available", | 
 | 					"lib64", | 
 | 				], | 
 | 				binaries: [ | 
 | 					"bin", | 
 | 					"bin_override", | 
 | 				], | 
 | 			}, | 
 | 			arm: { | 
 | 				vndk_libs: [ | 
 | 					"libvndk", | 
 | 					"libllndk", | 
 | 				], | 
 | 				static_libs: [ | 
 | 					"libvendor", | 
 | 					"libvendor_available", | 
 | 					"libvndk", | 
 | 					"lib32", | 
 | 				], | 
 | 				shared_libs: [ | 
 | 					"libvendor", | 
 | 					"libvendor_override", | 
 | 					"libvendor_available", | 
 | 					"lib32", | 
 | 				], | 
 | 				binaries: [ | 
 | 					"bin32", | 
 | 				], | 
 | 			}, | 
 | 		} | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libvndk", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libvndk.a", | 
 | 			}, | 
 | 			arm: { | 
 | 				src: "libvndk.a", | 
 | 			}, | 
 | 		}, | 
 | 		shared_libs: ["libvndk"], | 
 | 		export_shared_lib_headers: ["libvndk"], | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_shared { | 
 | 		name: "libvendor", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		shared_libs: [ | 
 | 			"libvendor_without_snapshot", | 
 | 			"libvendor_available", | 
 | 			"libvndk", | 
 | 		], | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libvendor.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 			arm: { | 
 | 				src: "libvendor.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_shared { | 
 | 		name: "libvendor_override", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		overrides: ["libvendor"], | 
 | 		shared_libs: [ | 
 | 			"libvendor_without_snapshot", | 
 | 			"libvendor_available", | 
 | 			"libvndk", | 
 | 		], | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "override/libvendor.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 			arm: { | 
 | 				src: "override/libvendor.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "lib32", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "32", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm: { | 
 | 				src: "lib32.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_shared { | 
 | 		name: "lib32", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "32", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm: { | 
 | 				src: "lib32.so", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "lib64", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "lib64.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_shared { | 
 | 		name: "lib64", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "lib64.so", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libvendor", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				cfi: { | 
 | 					src: "libvendor.cfi.a", | 
 | 					export_include_dirs: ["include/libvendor_cfi"], | 
 | 				}, | 
 | 				src: "libvendor.a", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 			arm: { | 
 | 				cfi: { | 
 | 					src: "libvendor.cfi.a", | 
 | 					export_include_dirs: ["include/libvendor_cfi"], | 
 | 				}, | 
 | 				src: "libvendor.a", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_shared { | 
 | 		name: "libvendor_available", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libvendor_available.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 			arm: { | 
 | 				src: "libvendor_available.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libvendor_available", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "both", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libvendor_available.a", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 			arm: { | 
 | 				src: "libvendor_available.so", | 
 | 				export_include_dirs: ["include/libvendor"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libc++_static", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libc++_static.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libc++demangle", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libc++demangle.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libunwind", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libunwind.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_binary { | 
 | 		name: "bin", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "bin", | 
 | 			}, | 
 | 		}, | 
 | 		symlinks: ["binfoo", "binbar"], | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_binary { | 
 | 		name: "bin_override", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "64", | 
 | 		vendor: true, | 
 | 		overrides: ["bin"], | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "override/bin", | 
 | 			}, | 
 | 		}, | 
 | 		symlinks: ["binfoo", "binbar"], | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_binary { | 
 | 		name: "bin32", | 
 | 		version: "31", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "32", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm: { | 
 | 				src: "bin32", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	// old snapshot module which has to be ignored | 
 | 	vendor_snapshot_binary { | 
 | 		name: "bin", | 
 | 		version: "26", | 
 | 		target_arch: "arm64", | 
 | 		compile_multilib: "first", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "bin", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	// different arch snapshot which has to be ignored | 
 | 	vendor_snapshot_binary { | 
 | 		name: "bin", | 
 | 		version: "31", | 
 | 		target_arch: "arm", | 
 | 		compile_multilib: "first", | 
 | 		vendor: true, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "bin", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 | ` | 
 | 	depsBp := GatherRequiredDepsForTest(android.Android) | 
 |  | 
 | 	mockFS := map[string][]byte{ | 
 | 		"deps/Android.bp":                  []byte(depsBp), | 
 | 		"framework/Android.bp":             []byte(frameworkBp), | 
 | 		"framework/symbol.txt":             nil, | 
 | 		"vendor/Android.bp":                []byte(vendorProprietaryBp), | 
 | 		"vendor/bin":                       nil, | 
 | 		"vendor/override/bin":              nil, | 
 | 		"vendor/bin32":                     nil, | 
 | 		"vendor/bin.cpp":                   nil, | 
 | 		"vendor/client.cpp":                nil, | 
 | 		"vendor/include/libvndk/a.h":       nil, | 
 | 		"vendor/include/libvendor/b.h":     nil, | 
 | 		"vendor/include/libvendor_cfi/c.h": nil, | 
 | 		"vendor/libc++_static.a":           nil, | 
 | 		"vendor/libc++demangle.a":          nil, | 
 | 		"vendor/libunwind.a":               nil, | 
 | 		"vendor/libvndk.a":                 nil, | 
 | 		"vendor/libvendor.a":               nil, | 
 | 		"vendor/libvendor.cfi.a":           nil, | 
 | 		"vendor/libvendor.so":              nil, | 
 | 		"vendor/override/libvendor.so":     nil, | 
 | 		"vendor/lib32.a":                   nil, | 
 | 		"vendor/lib32.so":                  nil, | 
 | 		"vendor/lib64.a":                   nil, | 
 | 		"vendor/lib64.so":                  nil, | 
 | 		"vndk/Android.bp":                  []byte(vndkBp), | 
 | 		"vndk/include/libvndk/a.h":         nil, | 
 | 		"vndk/libvndk.so":                  nil, | 
 | 		"vndk/libllndk.so":                 nil, | 
 | 	} | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("31") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("32") | 
 | 	ctx := CreateTestContext(config) | 
 | 	ctx.Register() | 
 |  | 
 | 	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"}) | 
 | 	android.FailIfErrored(t, errs) | 
 | 	_, errs = ctx.PrepareBuildActions(config) | 
 | 	android.FailIfErrored(t, errs) | 
 |  | 
 | 	sharedVariant := "android_vendor.31_arm64_armv8-a_shared" | 
 | 	staticVariant := "android_vendor.31_arm64_armv8-a_static" | 
 | 	binaryVariant := "android_vendor.31_arm64_armv8-a" | 
 |  | 
 | 	sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi" | 
 | 	staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi" | 
 |  | 
 | 	shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared" | 
 | 	binary32Variant := "android_vendor.31_arm_armv7-a-neon" | 
 |  | 
 | 	// libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot | 
 | 	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"] | 
 | 	for _, includeFlags := range []string{ | 
 | 		"-Ivndk/include/libvndk",     // libvndk | 
 | 		"-Ivendor/include/libvendor", // libvendor | 
 | 	} { | 
 | 		if !strings.Contains(libclientCcFlags, includeFlags) { | 
 | 			t.Errorf("flags for libclient must contain %#v, but was %#v.", | 
 | 				includeFlags, libclientCcFlags) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"] | 
 | 	for _, input := range [][]string{ | 
 | 		[]string{sharedVariant, "libvndk.vndk.31.arm64"}, | 
 | 		[]string{sharedVariant, "libllndk.vndk.31.arm64"}, | 
 | 		[]string{staticVariant, "libvendor.vendor_static.31.arm64"}, | 
 | 		[]string{staticVariant, "libvendor_without_snapshot"}, | 
 | 	} { | 
 | 		outputPaths := GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */) | 
 | 		if !strings.Contains(libclientLdFlags, outputPaths[0].String()) { | 
 | 			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags) | 
 | 		} | 
 |  | 
 | 	} | 
 |  | 
 | 	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs | 
 | 	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) { | 
 | 		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g) | 
 | 	} | 
 |  | 
 | 	libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs | 
 | 	if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) { | 
 | 		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g) | 
 | 	} | 
 |  | 
 | 	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs | 
 | 	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) { | 
 | 		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g) | 
 | 	} | 
 |  | 
 | 	// libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant | 
 | 	libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"] | 
 | 	if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") { | 
 | 		t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.", | 
 | 			"-Ivendor/include/libvendor_cfi", libclientCfiCcFlags) | 
 | 	} | 
 |  | 
 | 	libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"] | 
 | 	libvendorCfiOutputPaths := GetOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"}) | 
 | 	if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) { | 
 | 		t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags) | 
 | 	} | 
 |  | 
 | 	// bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers) | 
 | 	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"] | 
 | 	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") { | 
 | 		t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.", | 
 | 			"-Ivendor/include/libvndk", binWithoutSnapshotCcFlags) | 
 | 	} | 
 |  | 
 | 	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"] | 
 | 	libVndkStaticOutputPaths := GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"}) | 
 | 	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) { | 
 | 		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v", | 
 | 			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags) | 
 | 	} | 
 |  | 
 | 	// libvendor.so is installed by libvendor.vendor_shared.31.arm64 | 
 | 	ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so") | 
 |  | 
 | 	// lib64.so is installed by lib64.vendor_shared.31.arm64 | 
 | 	ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so") | 
 |  | 
 | 	// lib32.so is installed by lib32.vendor_shared.31.arm64 | 
 | 	ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so") | 
 |  | 
 | 	// libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64 | 
 | 	ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so") | 
 |  | 
 | 	// libvendor_without_snapshot.so is installed by libvendor_without_snapshot | 
 | 	ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so") | 
 |  | 
 | 	// bin is installed by bin.vendor_binary.31.arm64 | 
 | 	bin64Module := ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant) | 
 | 	bin64Module.Output("bin") | 
 |  | 
 | 	// also test symlinks | 
 | 	bin64MkEntries := android.AndroidMkEntriesForTest(t, ctx, bin64Module.Module()) | 
 | 	bin64KatiSymlinks := bin64MkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"] | 
 |  | 
 | 	// Either AndroidMk entries contain symlinks, or symlinks should be installed by Soong | 
 | 	for _, symlink := range []string{"binfoo", "binbar"} { | 
 | 		if inList(symlink, bin64KatiSymlinks) { | 
 | 			continue | 
 | 		} | 
 |  | 
 | 		bin64Module.Output(symlink) | 
 | 	} | 
 |  | 
 | 	// bin32 is installed by bin32.vendor_binary.31.arm64 | 
 | 	ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32") | 
 |  | 
 | 	// bin_without_snapshot is installed by bin_without_snapshot | 
 | 	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot") | 
 |  | 
 | 	// libvendor, libvendor_available and bin don't have vendor.31 variant | 
 | 	libvendorVariants := ctx.ModuleVariantsForTests("libvendor") | 
 | 	if inList(sharedVariant, libvendorVariants) { | 
 | 		t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant) | 
 | 	} | 
 |  | 
 | 	libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available") | 
 | 	if inList(sharedVariant, libvendorAvailableVariants) { | 
 | 		t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant) | 
 | 	} | 
 |  | 
 | 	binVariants := ctx.ModuleVariantsForTests("bin") | 
 | 	if inList(binaryVariant, binVariants) { | 
 | 		t.Errorf("bin must not have variant %#v, but it does", sharedVariant) | 
 | 	} | 
 |  | 
 | 	// test overrides property | 
 | 	binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant) | 
 | 	binOverrideModule.Output("bin") | 
 | 	binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module()) | 
 | 	binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"] | 
 | 	if !inList("bin", binOverrideEntry) { | 
 | 		t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry) | 
 | 	} | 
 |  | 
 | 	libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant) | 
 | 	libvendorOverrideModule.Output("libvendor.so") | 
 | 	libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module()) | 
 | 	libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"] | 
 | 	if !inList("libvendor", libvendorOverrideEntry) { | 
 | 		t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVendorSnapshotSanitizer(t *testing.T) { | 
 | 	bp := ` | 
 | 	vendor_snapshot { | 
 | 		name: "vendor_snapshot", | 
 | 		version: "28", | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				static_libs: [ | 
 | 					"libsnapshot", | 
 | 					"note_memtag_heap_sync", | 
 | 				], | 
 | 				objects: [ | 
 | 					"snapshot_object", | 
 | 				], | 
 | 				vndk_libs: [ | 
 | 					"libclang_rt.hwasan", | 
 | 				], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "libsnapshot", | 
 | 		vendor: true, | 
 | 		target_arch: "arm64", | 
 | 		version: "28", | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "libsnapshot.a", | 
 | 				cfi: { | 
 | 					src: "libsnapshot.cfi.a", | 
 | 				}, | 
 | 				hwasan: { | 
 | 					src: "libsnapshot.hwasan.a", | 
 | 				}, | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_static { | 
 | 		name: "note_memtag_heap_sync", | 
 | 		vendor: true, | 
 | 		target_arch: "arm64", | 
 | 		version: "28", | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "note_memtag_heap_sync.a", | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vndk_prebuilt_shared { | 
 | 		name: "libclang_rt.hwasan", | 
 | 		version: "28", | 
 | 		target_arch: "arm64", | 
 | 		vendor_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				srcs: ["libclang_rt.hwasan.so"], | 
 | 			}, | 
 | 		}, | 
 | 	} | 
 |  | 
 | 	vendor_snapshot_object { | 
 | 		name: "snapshot_object", | 
 | 		vendor: true, | 
 | 		target_arch: "arm64", | 
 | 		version: "28", | 
 | 		arch: { | 
 | 			arm64: { | 
 | 				src: "snapshot_object.o", | 
 | 			}, | 
 | 		}, | 
 | 		stl: "none", | 
 | 	} | 
 |  | 
 | 	cc_test { | 
 | 		name: "vstest", | 
 | 		gtest: false, | 
 | 		vendor: true, | 
 | 		compile_multilib: "64", | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 		static_libs: ["libsnapshot"], | 
 | 		system_shared_libs: [], | 
 | 	} | 
 | ` | 
 |  | 
 | 	mockFS := map[string][]byte{ | 
 | 		"vendor/Android.bp":              []byte(bp), | 
 | 		"vendor/libc++demangle.a":        nil, | 
 | 		"vendor/libclang_rt.hwasan.so":   nil, | 
 | 		"vendor/libsnapshot.a":           nil, | 
 | 		"vendor/libsnapshot.cfi.a":       nil, | 
 | 		"vendor/libsnapshot.hwasan.a":    nil, | 
 | 		"vendor/note_memtag_heap_sync.a": nil, | 
 | 		"vendor/snapshot_object.o":       nil, | 
 | 	} | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("28") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	config.TestProductVariables.SanitizeDevice = []string{"hwaddress"} | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check non-cfi, cfi and hwasan variant. | 
 | 	staticVariant := "android_vendor.28_arm64_armv8-a_static" | 
 | 	staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi" | 
 | 	staticHwasanVariant := "android_vendor.28_arm64_armv8-a_static_hwasan" | 
 | 	staticHwasanCfiVariant := "android_vendor.28_arm64_armv8-a_static_hwasan_cfi" | 
 |  | 
 | 	staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module) | 
 | 	assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a") | 
 |  | 
 | 	staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module) | 
 | 	assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a") | 
 |  | 
 | 	staticHwasanModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanVariant).Module().(*Module) | 
 | 	assertString(t, staticHwasanModule.outputFile.Path().Base(), "libsnapshot.hwasan.a") | 
 |  | 
 | 	staticHwasanCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanCfiVariant).Module().(*Module) | 
 | 	if !staticHwasanCfiModule.HiddenFromMake() || !staticHwasanCfiModule.PreventInstall() { | 
 | 		t.Errorf("Hwasan and Cfi cannot enabled at the same time.") | 
 | 	} | 
 |  | 
 | 	snapshotObjModule := ctx.ModuleForTests("snapshot_object.vendor_object.28.arm64", "android_vendor.28_arm64_armv8-a").Module() | 
 | 	snapshotObjMkEntries := android.AndroidMkEntriesForTest(t, ctx, snapshotObjModule) | 
 | 	// snapshot object must not add ".hwasan" suffix | 
 | 	assertString(t, snapshotObjMkEntries[0].EntryMap["LOCAL_MODULE"][0], "snapshot_object") | 
 | } | 
 |  | 
 | func TestVendorSnapshotExclude(t *testing.T) { | 
 |  | 
 | 	// This test verifies that the exclude_from_vendor_snapshot property | 
 | 	// makes its way from the Android.bp source file into the module data | 
 | 	// structure. It also verifies that modules are correctly included or | 
 | 	// excluded in the vendor snapshot based on their path (framework or | 
 | 	// vendor) and the exclude_from_vendor_snapshot property. | 
 |  | 
 | 	frameworkBp := ` | 
 | 		cc_library_shared { | 
 | 			name: "libinclude", | 
 | 			srcs: ["src/include.cpp"], | 
 | 			vendor_available: true, | 
 | 		} | 
 | 		cc_library_shared { | 
 | 			name: "libexclude", | 
 | 			srcs: ["src/exclude.cpp"], | 
 | 			vendor: true, | 
 | 			exclude_from_vendor_snapshot: true, | 
 | 		} | 
 | 		cc_library_shared { | 
 | 			name: "libavailable_exclude", | 
 | 			srcs: ["src/exclude.cpp"], | 
 | 			vendor_available: true, | 
 | 			exclude_from_vendor_snapshot: true, | 
 | 		} | 
 | 	` | 
 |  | 
 | 	vendorProprietaryBp := ` | 
 | 		cc_library_shared { | 
 | 			name: "libvendor", | 
 | 			srcs: ["vendor.cpp"], | 
 | 			vendor: true, | 
 | 		} | 
 | 	` | 
 |  | 
 | 	depsBp := GatherRequiredDepsForTest(android.Android) | 
 |  | 
 | 	mockFS := map[string][]byte{ | 
 | 		"deps/Android.bp":       []byte(depsBp), | 
 | 		"framework/Android.bp":  []byte(frameworkBp), | 
 | 		"framework/include.cpp": nil, | 
 | 		"framework/exclude.cpp": nil, | 
 | 		"device/Android.bp":     []byte(vendorProprietaryBp), | 
 | 		"device/vendor.cpp":     nil, | 
 | 	} | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := CreateTestContext(config) | 
 | 	ctx.Register() | 
 |  | 
 | 	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"}) | 
 | 	android.FailIfErrored(t, errs) | 
 | 	_, errs = ctx.PrepareBuildActions(config) | 
 | 	android.FailIfErrored(t, errs) | 
 |  | 
 | 	// Test an include and exclude framework module. | 
 | 	AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant) | 
 | 	AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant) | 
 | 	AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant) | 
 |  | 
 | 	// A vendor module is excluded, but by its path, not the | 
 | 	// exclude_from_vendor_snapshot property. | 
 | 	AssertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false, vendorVariant) | 
 |  | 
 | 	// Verify the content of the vendor snapshot. | 
 |  | 
 | 	snapshotDir := "vendor-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") | 
 |  | 
 | 	var includeJsonFiles []string | 
 | 	var excludeJsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 		[]string{"arm", "armv7-a-neon"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 |  | 
 | 		// Included modules | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json")) | 
 |  | 
 | 		// Excluded modules | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json")) | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json")) | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json")) | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an included module has a rule. | 
 | 	for _, jsonFile := range includeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("include json file %q not found", jsonFile) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an excluded module has no rule. | 
 | 	for _, jsonFile := range excludeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil { | 
 | 			t.Errorf("exclude json file %q found", jsonFile) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) { | 
 |  | 
 | 	// This test verifies that using the exclude_from_vendor_snapshot | 
 | 	// property on a module in a vendor proprietary path generates an | 
 | 	// error. These modules are already excluded, so we prohibit using the | 
 | 	// property in this way, which could add to confusion. | 
 |  | 
 | 	vendorProprietaryBp := ` | 
 | 		cc_library_shared { | 
 | 			name: "libvendor", | 
 | 			srcs: ["vendor.cpp"], | 
 | 			vendor: true, | 
 | 			exclude_from_vendor_snapshot: true, | 
 | 		} | 
 | 	` | 
 |  | 
 | 	depsBp := GatherRequiredDepsForTest(android.Android) | 
 |  | 
 | 	mockFS := map[string][]byte{ | 
 | 		"deps/Android.bp":   []byte(depsBp), | 
 | 		"device/Android.bp": []byte(vendorProprietaryBp), | 
 | 		"device/vendor.cpp": nil, | 
 | 	} | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := CreateTestContext(config) | 
 | 	ctx.Register() | 
 |  | 
 | 	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"}) | 
 | 	android.FailIfErrored(t, errs) | 
 |  | 
 | 	_, errs = ctx.PrepareBuildActions(config) | 
 | 	android.CheckErrorsAgainstExpectations(t, errs, []string{ | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, | 
 | 	}) | 
 | } | 
 |  | 
 | func TestRecoverySnapshotCapture(t *testing.T) { | 
 | 	bp := ` | 
 | 	cc_library { | 
 | 		name: "libvndk", | 
 | 		vendor_available: true, | 
 | 		recovery_available: true, | 
 | 		product_available: true, | 
 | 		vndk: { | 
 | 			enabled: true, | 
 | 		}, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "librecovery", | 
 | 		recovery: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "librecovery_available", | 
 | 		recovery_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library_headers { | 
 | 		name: "librecovery_headers", | 
 | 		recovery_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "recovery_bin", | 
 | 		recovery: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_binary { | 
 | 		name: "recovery_available_bin", | 
 | 		recovery_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_prebuilt_library_static { | 
 | 		name: "libb", | 
 | 		recovery_available: true, | 
 | 		srcs: ["libb.a"], | 
 | 		nocrt: true, | 
 | 		no_libcrt: true, | 
 | 		stl: "none", | 
 | 	} | 
 |  | 
 | 	cc_object { | 
 | 		name: "obj", | 
 | 		recovery_available: true, | 
 | 	} | 
 | ` | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) | 
 | 	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check Recovery snapshot output. | 
 |  | 
 | 	snapshotDir := "recovery-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot") | 
 |  | 
 | 	var jsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		// For shared libraries, only recovery_available modules are captured. | 
 | 		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant) | 
 | 		jsonFiles = append(jsonFiles, | 
 | 			filepath.Join(sharedDir, "libvndk.so.json"), | 
 | 			filepath.Join(sharedDir, "librecovery.so.json"), | 
 | 			filepath.Join(sharedDir, "librecovery_available.so.json")) | 
 |  | 
 | 		// For static libraries, all recovery:true and recovery_available modules are captured. | 
 | 		staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant) | 
 | 		staticDir := filepath.Join(snapshotVariantPath, archDir, "static") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant) | 
 | 		jsonFiles = append(jsonFiles, | 
 | 			filepath.Join(staticDir, "libb.a.json"), | 
 | 			filepath.Join(staticDir, "librecovery.a.json"), | 
 | 			filepath.Join(staticDir, "librecovery_available.a.json")) | 
 |  | 
 | 		// For binary executables, all recovery:true and recovery_available modules are captured. | 
 | 		if archType == "arm64" { | 
 | 			binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant) | 
 | 			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary") | 
 | 			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant) | 
 | 			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant) | 
 | 			jsonFiles = append(jsonFiles, | 
 | 				filepath.Join(binaryDir, "recovery_bin.json"), | 
 | 				filepath.Join(binaryDir, "recovery_available_bin.json")) | 
 | 		} | 
 |  | 
 | 		// For header libraries, all vendor:true and vendor_available modules are captured. | 
 | 		headerDir := filepath.Join(snapshotVariantPath, archDir, "header") | 
 | 		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json")) | 
 |  | 
 | 		// For object modules, all vendor:true and vendor_available modules are captured. | 
 | 		objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant) | 
 | 		objectDir := filepath.Join(snapshotVariantPath, archDir, "object") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant) | 
 | 		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json")) | 
 | 	} | 
 |  | 
 | 	for _, jsonFile := range jsonFiles { | 
 | 		// verify all json files exist | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("%q expected but not found", jsonFile) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestRecoverySnapshotExclude(t *testing.T) { | 
 | 	// This test verifies that the exclude_from_recovery_snapshot property | 
 | 	// makes its way from the Android.bp source file into the module data | 
 | 	// structure. It also verifies that modules are correctly included or | 
 | 	// excluded in the recovery snapshot based on their path (framework or | 
 | 	// vendor) and the exclude_from_recovery_snapshot property. | 
 |  | 
 | 	frameworkBp := ` | 
 | 		cc_library_shared { | 
 | 			name: "libinclude", | 
 | 			srcs: ["src/include.cpp"], | 
 | 			recovery_available: true, | 
 | 		} | 
 | 		cc_library_shared { | 
 | 			name: "libexclude", | 
 | 			srcs: ["src/exclude.cpp"], | 
 | 			recovery: true, | 
 | 			exclude_from_recovery_snapshot: true, | 
 | 		} | 
 | 		cc_library_shared { | 
 | 			name: "libavailable_exclude", | 
 | 			srcs: ["src/exclude.cpp"], | 
 | 			recovery_available: true, | 
 | 			exclude_from_recovery_snapshot: true, | 
 | 		} | 
 | 	` | 
 |  | 
 | 	vendorProprietaryBp := ` | 
 | 		cc_library_shared { | 
 | 			name: "librecovery", | 
 | 			srcs: ["recovery.cpp"], | 
 | 			recovery: true, | 
 | 		} | 
 | 	` | 
 |  | 
 | 	depsBp := GatherRequiredDepsForTest(android.Android) | 
 |  | 
 | 	mockFS := map[string][]byte{ | 
 | 		"deps/Android.bp":       []byte(depsBp), | 
 | 		"framework/Android.bp":  []byte(frameworkBp), | 
 | 		"framework/include.cpp": nil, | 
 | 		"framework/exclude.cpp": nil, | 
 | 		"device/Android.bp":     []byte(vendorProprietaryBp), | 
 | 		"device/recovery.cpp":   nil, | 
 | 	} | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS) | 
 | 	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := CreateTestContext(config) | 
 | 	ctx.Register() | 
 |  | 
 | 	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"}) | 
 | 	android.FailIfErrored(t, errs) | 
 | 	_, errs = ctx.PrepareBuildActions(config) | 
 | 	android.FailIfErrored(t, errs) | 
 |  | 
 | 	// Test an include and exclude framework module. | 
 | 	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, recoveryVariant) | 
 | 	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, recoveryVariant) | 
 | 	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, recoveryVariant) | 
 |  | 
 | 	// A recovery module is excluded, but by its path, not the | 
 | 	// exclude_from_recovery_snapshot property. | 
 | 	AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, recoveryVariant) | 
 |  | 
 | 	// Verify the content of the recovery snapshot. | 
 |  | 
 | 	snapshotDir := "recovery-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot") | 
 |  | 
 | 	var includeJsonFiles []string | 
 | 	var excludeJsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 |  | 
 | 		// Included modules | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json")) | 
 |  | 
 | 		// Excluded modules | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json")) | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json")) | 
 | 		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant) | 
 | 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json")) | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an included module has a rule. | 
 | 	for _, jsonFile := range includeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("include json file %q not found", jsonFile) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an excluded module has no rule. | 
 | 	for _, jsonFile := range excludeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil { | 
 | 			t.Errorf("exclude json file %q found", jsonFile) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestRecoverySnapshotDirected(t *testing.T) { | 
 | 	bp := ` | 
 | 	cc_library_shared { | 
 | 		name: "librecovery", | 
 | 		recovery: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "librecovery_available", | 
 | 		recovery_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	genrule { | 
 | 		name: "libfoo_gen", | 
 | 		cmd: "", | 
 | 		out: ["libfoo.so"], | 
 | 	} | 
 |  | 
 | 	cc_prebuilt_library_shared { | 
 | 		name: "libfoo", | 
 | 		recovery: true, | 
 | 		prefer: true, | 
 | 		srcs: [":libfoo_gen"], | 
 | 	} | 
 |  | 
 | 	cc_library_shared { | 
 | 		name: "libfoo", | 
 | 		recovery: true, | 
 | 		nocrt: true, | 
 | 	} | 
 | ` | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	config.TestProductVariables.DirectedRecoverySnapshot = true | 
 | 	config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool) | 
 | 	config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true | 
 | 	config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check recovery snapshot output. | 
 |  | 
 | 	snapshotDir := "recovery-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot") | 
 |  | 
 | 	var includeJsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 |  | 
 | 		// Included modules | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json")) | 
 | 		// Check that snapshot captures "prefer: true" prebuilt | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json")) | 
 |  | 
 | 		// Excluded modules. Modules not included in the directed recovery snapshot | 
 | 		// are still include as fake modules. | 
 | 		CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant) | 
 | 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json")) | 
 | 	} | 
 |  | 
 | 	// Verify that each json file for an included module has a rule. | 
 | 	for _, jsonFile := range includeJsonFiles { | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("include json file %q not found", jsonFile) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestSnapshotInRelativeInstallPath(t *testing.T) { | 
 | 	bp := ` | 
 | 	cc_library { | 
 | 		name: "libvendor_available", | 
 | 		vendor_available: true, | 
 | 		nocrt: true, | 
 | 	} | 
 |  | 
 | 	cc_library { | 
 | 		name: "libvendor_available_var", | 
 | 		vendor_available: true, | 
 | 		stem: "libvendor_available", | 
 | 		relative_install_path: "var", | 
 | 		nocrt: true, | 
 | 	} | 
 | ` | 
 |  | 
 | 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) | 
 | 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current") | 
 | 	config.TestProductVariables.Platform_vndk_version = StringPtr("29") | 
 | 	ctx := testCcWithConfig(t, config) | 
 |  | 
 | 	// Check Vendor snapshot output. | 
 |  | 
 | 	snapshotDir := "vendor-snapshot" | 
 | 	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") | 
 | 	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") | 
 |  | 
 | 	var jsonFiles []string | 
 |  | 
 | 	for _, arch := range [][]string{ | 
 | 		[]string{"arm64", "armv8-a"}, | 
 | 		[]string{"arm", "armv7-a-neon"}, | 
 | 	} { | 
 | 		archType := arch[0] | 
 | 		archVariant := arch[1] | 
 | 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) | 
 |  | 
 | 		// For shared libraries, only non-VNDK vendor_available modules are captured | 
 | 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) | 
 | 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") | 
 | 		sharedDirVar := filepath.Join(sharedDir, "var") | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant) | 
 | 		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available_var", "libvendor_available.so", sharedDirVar, sharedVariant) | 
 | 		jsonFiles = append(jsonFiles, | 
 | 			filepath.Join(sharedDir, "libvendor_available.so.json"), | 
 | 			filepath.Join(sharedDirVar, "libvendor_available.so.json")) | 
 | 	} | 
 |  | 
 | 	for _, jsonFile := range jsonFiles { | 
 | 		// verify all json files exist | 
 | 		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { | 
 | 			t.Errorf("%q expected but not found", jsonFile) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// fake snapshot should have all outputs in the normal snapshot. | 
 | 	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot") | 
 | 	for _, output := range snapshotSingleton.AllOutputs() { | 
 | 		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1) | 
 | 		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil { | 
 | 			t.Errorf("%q expected but not found", fakeOutput) | 
 | 		} | 
 | 	} | 
 | } |