• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18	"android/soong/android"
19	"fmt"
20	"path/filepath"
21	"reflect"
22	"strings"
23	"testing"
24)
25
26func checkJsonContents(t *testing.T, ctx android.TestingSingleton, jsonPath string, key string, value string) {
27	jsonOut := ctx.MaybeOutput(jsonPath)
28	if jsonOut.Rule == nil {
29		t.Errorf("%q expected but not found", jsonPath)
30		return
31	}
32	if !strings.Contains(jsonOut.Args["content"], fmt.Sprintf("%q:%q", key, value)) {
33		t.Errorf("%q must include %q:%q but it only has %v", jsonPath, key, value, jsonOut.Args["content"])
34	}
35}
36
37func TestVendorSnapshotCapture(t *testing.T) {
38	bp := `
39	cc_library {
40		name: "libvndk",
41		vendor_available: true,
42		product_available: true,
43		vndk: {
44			enabled: true,
45		},
46		nocrt: true,
47	}
48
49	cc_library {
50		name: "libvendor",
51		vendor: true,
52		nocrt: true,
53	}
54
55	cc_library {
56		name: "libvendor_override",
57		vendor: true,
58		nocrt: true,
59		overrides: ["libvendor"],
60	}
61
62	cc_library {
63		name: "libvendor_available",
64		vendor_available: true,
65		nocrt: true,
66		min_sdk_version: "29",
67	}
68
69	cc_library_headers {
70		name: "libvendor_headers",
71		vendor_available: true,
72		nocrt: true,
73	}
74
75	cc_binary {
76		name: "vendor_bin",
77		vendor: true,
78		nocrt: true,
79	}
80
81	cc_binary {
82		name: "vendor_available_bin",
83		vendor_available: true,
84		nocrt: true,
85	}
86
87	cc_binary {
88		name: "vendor_bin_override",
89		vendor: true,
90		nocrt: true,
91		overrides: ["vendor_bin"],
92	}
93
94	cc_prebuilt_library_static {
95		name: "libb",
96		vendor_available: true,
97		srcs: ["libb.a"],
98		nocrt: true,
99		no_libcrt: true,
100		stl: "none",
101	}
102
103	cc_object {
104		name: "obj",
105		vendor_available: true,
106	}
107
108	cc_library {
109		name: "libllndk",
110		llndk: {
111			symbol_file: "libllndk.map.txt",
112		},
113	}
114`
115
116	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
117	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
118	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
119	ctx := testCcWithConfig(t, config)
120
121	// Check Vendor snapshot output.
122
123	snapshotDir := "vendor-snapshot"
124	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
125	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
126
127	var jsonFiles []string
128
129	for _, arch := range [][]string{
130		[]string{"arm64", "armv8-a"},
131		[]string{"arm", "armv7-a-neon"},
132	} {
133		archType := arch[0]
134		archVariant := arch[1]
135		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
136
137		// For shared libraries, only non-VNDK vendor_available modules are captured
138		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
139		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
140		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
141		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
142		jsonFiles = append(jsonFiles,
143			filepath.Join(sharedDir, "libvendor.so.json"),
144			filepath.Join(sharedDir, "libvendor_available.so.json"))
145
146		// LLNDK modules are not captured
147		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
148
149		// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
150		// Also cfi variants are captured, except for prebuilts like toolchain_library
151		staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
152		staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant)
153		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
154		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
155		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
156		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
157		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
158		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
159		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
160		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
161		jsonFiles = append(jsonFiles,
162			filepath.Join(staticDir, "libb.a.json"),
163			filepath.Join(staticDir, "libvndk.a.json"),
164			filepath.Join(staticDir, "libvndk.cfi.a.json"),
165			filepath.Join(staticDir, "libvendor.a.json"),
166			filepath.Join(staticDir, "libvendor.cfi.a.json"),
167			filepath.Join(staticDir, "libvendor_available.a.json"),
168			filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
169
170		checkJsonContents(t, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit")
171		checkJsonContents(t, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29")
172
173		// For binary executables, all vendor:true and vendor_available modules are captured.
174		if archType == "arm64" {
175			binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
176			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
177			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
178			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
179			jsonFiles = append(jsonFiles,
180				filepath.Join(binaryDir, "vendor_bin.json"),
181				filepath.Join(binaryDir, "vendor_available_bin.json"))
182
183			checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"})
184		}
185
186		// For header libraries, all vendor:true and vendor_available modules are captured.
187		headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
188		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
189
190		// For object modules, all vendor:true and vendor_available modules are captured.
191		objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
192		objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
193		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
194		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
195
196		checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"})
197	}
198
199	for _, jsonFile := range jsonFiles {
200		// verify all json files exist
201		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
202			t.Errorf("%q expected but not found", jsonFile)
203		}
204	}
205
206	// fake snapshot should have all outputs in the normal snapshot.
207	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
208	for _, output := range snapshotSingleton.AllOutputs() {
209		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
210		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
211			t.Errorf("%q expected but not found", fakeOutput)
212		}
213	}
214}
215
216func TestVendorSnapshotDirected(t *testing.T) {
217	bp := `
218	cc_library_shared {
219		name: "libvendor",
220		vendor: true,
221		nocrt: true,
222	}
223
224	cc_library_shared {
225		name: "libvendor_available",
226		vendor_available: true,
227		nocrt: true,
228	}
229
230	genrule {
231		name: "libfoo_gen",
232		cmd: "",
233		out: ["libfoo.so"],
234	}
235
236	cc_prebuilt_library_shared {
237		name: "libfoo",
238		vendor: true,
239		prefer: true,
240		srcs: [":libfoo_gen"],
241	}
242
243	cc_library_shared {
244		name: "libfoo",
245		vendor: true,
246		nocrt: true,
247	}
248`
249	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
250	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
251	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
252	config.TestProductVariables.DirectedVendorSnapshot = true
253	config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
254	config.TestProductVariables.VendorSnapshotModules["libvendor"] = true
255	config.TestProductVariables.VendorSnapshotModules["libfoo"] = true
256	ctx := testCcWithConfig(t, config)
257
258	// Check Vendor snapshot output.
259
260	snapshotDir := "vendor-snapshot"
261	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
262	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
263
264	var includeJsonFiles []string
265
266	for _, arch := range [][]string{
267		[]string{"arm64", "armv8-a"},
268		[]string{"arm", "armv7-a-neon"},
269	} {
270		archType := arch[0]
271		archVariant := arch[1]
272		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
273
274		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
275		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
276
277		// Included modules
278		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
279		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
280		// Check that snapshot captures "prefer: true" prebuilt
281		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
282		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
283
284		// Excluded modules. Modules not included in the directed vendor snapshot
285		// are still include as fake modules.
286		CheckSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
287		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
288	}
289
290	// Verify that each json file for an included module has a rule.
291	for _, jsonFile := range includeJsonFiles {
292		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
293			t.Errorf("include json file %q not found", jsonFile)
294		}
295	}
296}
297
298func TestVendorSnapshotUse(t *testing.T) {
299	frameworkBp := `
300	cc_library {
301		name: "libvndk",
302		vendor_available: true,
303		product_available: true,
304		vndk: {
305			enabled: true,
306		},
307		nocrt: true,
308	}
309
310	cc_library {
311		name: "libvendor",
312		vendor: true,
313		nocrt: true,
314		no_libcrt: true,
315		stl: "none",
316		system_shared_libs: [],
317	}
318
319	cc_library {
320		name: "libvendor_available",
321		vendor_available: true,
322		nocrt: true,
323		no_libcrt: true,
324		stl: "none",
325		system_shared_libs: [],
326	}
327
328	cc_library {
329		name: "lib32",
330		vendor: true,
331		nocrt: true,
332		no_libcrt: true,
333		stl: "none",
334		system_shared_libs: [],
335		compile_multilib: "32",
336	}
337
338	cc_library {
339		name: "lib64",
340		vendor: true,
341		nocrt: true,
342		no_libcrt: true,
343		stl: "none",
344		system_shared_libs: [],
345		compile_multilib: "64",
346	}
347
348	cc_library {
349		name: "libllndk",
350		llndk: {
351			symbol_file: "libllndk.map.txt",
352		},
353	}
354
355	cc_binary {
356		name: "bin",
357		vendor: true,
358		nocrt: true,
359		no_libcrt: true,
360		stl: "none",
361		system_shared_libs: [],
362	}
363
364	cc_binary {
365		name: "bin32",
366		vendor: true,
367		nocrt: true,
368		no_libcrt: true,
369		stl: "none",
370		system_shared_libs: [],
371		compile_multilib: "32",
372	}
373`
374
375	vndkBp := `
376	vndk_prebuilt_shared {
377		name: "libvndk",
378		version: "31",
379		target_arch: "arm64",
380		vendor_available: true,
381		product_available: true,
382		vndk: {
383			enabled: true,
384		},
385		arch: {
386			arm64: {
387				srcs: ["libvndk.so"],
388				export_include_dirs: ["include/libvndk"],
389			},
390			arm: {
391				srcs: ["libvndk.so"],
392				export_include_dirs: ["include/libvndk"],
393			},
394		},
395	}
396
397	// old snapshot module which has to be ignored
398	vndk_prebuilt_shared {
399		name: "libvndk",
400		version: "26",
401		target_arch: "arm64",
402		vendor_available: true,
403		product_available: true,
404		vndk: {
405			enabled: true,
406		},
407		arch: {
408			arm64: {
409				srcs: ["libvndk.so"],
410				export_include_dirs: ["include/libvndk"],
411			},
412			arm: {
413				srcs: ["libvndk.so"],
414				export_include_dirs: ["include/libvndk"],
415			},
416		},
417	}
418
419	// different arch snapshot which has to be ignored
420	vndk_prebuilt_shared {
421		name: "libvndk",
422		version: "31",
423		target_arch: "arm",
424		vendor_available: true,
425		product_available: true,
426		vndk: {
427			enabled: true,
428		},
429		arch: {
430			arm: {
431				srcs: ["libvndk.so"],
432				export_include_dirs: ["include/libvndk"],
433			},
434		},
435	}
436
437	vndk_prebuilt_shared {
438		name: "libllndk",
439		version: "31",
440		target_arch: "arm64",
441		vendor_available: true,
442		product_available: true,
443		arch: {
444			arm64: {
445				srcs: ["libllndk.so"],
446			},
447			arm: {
448				srcs: ["libllndk.so"],
449			},
450		},
451	}
452`
453
454	vendorProprietaryBp := `
455	cc_library {
456		name: "libvendor_without_snapshot",
457		vendor: true,
458		nocrt: true,
459		no_libcrt: true,
460		stl: "none",
461		system_shared_libs: [],
462	}
463
464	cc_library_shared {
465		name: "libclient",
466		vendor: true,
467		nocrt: true,
468		no_libcrt: true,
469		stl: "none",
470		system_shared_libs: [],
471		shared_libs: ["libvndk", "libvendor_available", "libllndk"],
472		static_libs: ["libvendor", "libvendor_without_snapshot"],
473		arch: {
474			arm64: {
475				shared_libs: ["lib64"],
476			},
477			arm: {
478				shared_libs: ["lib32"],
479			},
480		},
481		srcs: ["client.cpp"],
482	}
483
484	cc_library_shared {
485		name: "libclient_cfi",
486		vendor: true,
487		nocrt: true,
488		no_libcrt: true,
489		stl: "none",
490		system_shared_libs: [],
491		static_libs: ["libvendor"],
492		sanitize: {
493			cfi: true,
494		},
495		srcs: ["client.cpp"],
496	}
497
498	cc_library_shared {
499		name: "libvndkext",
500		vendor: true,
501		nocrt: true,
502		no_libcrt: true,
503		stl: "none",
504		system_shared_libs: [],
505		vndk: {
506			extends: "libvndk",
507			enabled: true,
508		}
509	}
510
511	cc_binary {
512		name: "bin_without_snapshot",
513		vendor: true,
514		nocrt: true,
515		no_libcrt: true,
516		stl: "libc++_static",
517		system_shared_libs: [],
518		static_libs: ["libvndk"],
519		srcs: ["bin.cpp"],
520	}
521
522	vendor_snapshot {
523		name: "vendor_snapshot",
524		version: "31",
525		arch: {
526			arm64: {
527				vndk_libs: [
528					"libvndk",
529					"libllndk",
530				],
531				static_libs: [
532					"libc++_static",
533					"libc++demangle",
534					"libunwind",
535					"libvendor",
536					"libvendor_available",
537					"libvndk",
538					"lib64",
539				],
540				shared_libs: [
541					"libvendor",
542					"libvendor_override",
543					"libvendor_available",
544					"lib64",
545				],
546				binaries: [
547					"bin",
548					"bin_override",
549				],
550			},
551			arm: {
552				vndk_libs: [
553					"libvndk",
554					"libllndk",
555				],
556				static_libs: [
557					"libvendor",
558					"libvendor_available",
559					"libvndk",
560					"lib32",
561				],
562				shared_libs: [
563					"libvendor",
564					"libvendor_override",
565					"libvendor_available",
566					"lib32",
567				],
568				binaries: [
569					"bin32",
570				],
571			},
572		}
573	}
574
575	vendor_snapshot_static {
576		name: "libvndk",
577		version: "31",
578		target_arch: "arm64",
579		compile_multilib: "both",
580		vendor: true,
581		arch: {
582			arm64: {
583				src: "libvndk.a",
584			},
585			arm: {
586				src: "libvndk.a",
587			},
588		},
589		shared_libs: ["libvndk"],
590		export_shared_lib_headers: ["libvndk"],
591	}
592
593	vendor_snapshot_shared {
594		name: "libvendor",
595		version: "31",
596		target_arch: "arm64",
597		compile_multilib: "both",
598		vendor: true,
599		shared_libs: [
600			"libvendor_without_snapshot",
601			"libvendor_available",
602			"libvndk",
603		],
604		arch: {
605			arm64: {
606				src: "libvendor.so",
607				export_include_dirs: ["include/libvendor"],
608			},
609			arm: {
610				src: "libvendor.so",
611				export_include_dirs: ["include/libvendor"],
612			},
613		},
614	}
615
616	vendor_snapshot_shared {
617		name: "libvendor_override",
618		version: "31",
619		target_arch: "arm64",
620		compile_multilib: "both",
621		vendor: true,
622		overrides: ["libvendor"],
623		shared_libs: [
624			"libvendor_without_snapshot",
625			"libvendor_available",
626			"libvndk",
627		],
628		arch: {
629			arm64: {
630				src: "override/libvendor.so",
631				export_include_dirs: ["include/libvendor"],
632			},
633			arm: {
634				src: "override/libvendor.so",
635				export_include_dirs: ["include/libvendor"],
636			},
637		},
638	}
639
640	vendor_snapshot_static {
641		name: "lib32",
642		version: "31",
643		target_arch: "arm64",
644		compile_multilib: "32",
645		vendor: true,
646		arch: {
647			arm: {
648				src: "lib32.a",
649			},
650		},
651	}
652
653	vendor_snapshot_shared {
654		name: "lib32",
655		version: "31",
656		target_arch: "arm64",
657		compile_multilib: "32",
658		vendor: true,
659		arch: {
660			arm: {
661				src: "lib32.so",
662			},
663		},
664	}
665
666	vendor_snapshot_static {
667		name: "lib64",
668		version: "31",
669		target_arch: "arm64",
670		compile_multilib: "64",
671		vendor: true,
672		arch: {
673			arm64: {
674				src: "lib64.a",
675			},
676		},
677	}
678
679	vendor_snapshot_shared {
680		name: "lib64",
681		version: "31",
682		target_arch: "arm64",
683		compile_multilib: "64",
684		vendor: true,
685		arch: {
686			arm64: {
687				src: "lib64.so",
688			},
689		},
690	}
691
692	vendor_snapshot_static {
693		name: "libvendor",
694		version: "31",
695		target_arch: "arm64",
696		compile_multilib: "both",
697		vendor: true,
698		arch: {
699			arm64: {
700				cfi: {
701					src: "libvendor.cfi.a",
702					export_include_dirs: ["include/libvendor_cfi"],
703				},
704				src: "libvendor.a",
705				export_include_dirs: ["include/libvendor"],
706			},
707			arm: {
708				cfi: {
709					src: "libvendor.cfi.a",
710					export_include_dirs: ["include/libvendor_cfi"],
711				},
712				src: "libvendor.a",
713				export_include_dirs: ["include/libvendor"],
714			},
715		},
716	}
717
718	vendor_snapshot_shared {
719		name: "libvendor_available",
720		version: "31",
721		target_arch: "arm64",
722		compile_multilib: "both",
723		vendor: true,
724		arch: {
725			arm64: {
726				src: "libvendor_available.so",
727				export_include_dirs: ["include/libvendor"],
728			},
729			arm: {
730				src: "libvendor_available.so",
731				export_include_dirs: ["include/libvendor"],
732			},
733		},
734	}
735
736	vendor_snapshot_static {
737		name: "libvendor_available",
738		version: "31",
739		target_arch: "arm64",
740		compile_multilib: "both",
741		vendor: true,
742		arch: {
743			arm64: {
744				src: "libvendor_available.a",
745				export_include_dirs: ["include/libvendor"],
746			},
747			arm: {
748				src: "libvendor_available.so",
749				export_include_dirs: ["include/libvendor"],
750			},
751		},
752	}
753
754	vendor_snapshot_static {
755		name: "libc++_static",
756		version: "31",
757		target_arch: "arm64",
758		compile_multilib: "64",
759		vendor: true,
760		arch: {
761			arm64: {
762				src: "libc++_static.a",
763			},
764		},
765	}
766
767	vendor_snapshot_static {
768		name: "libc++demangle",
769		version: "31",
770		target_arch: "arm64",
771		compile_multilib: "64",
772		vendor: true,
773		arch: {
774			arm64: {
775				src: "libc++demangle.a",
776			},
777		},
778	}
779
780	vendor_snapshot_static {
781		name: "libunwind",
782		version: "31",
783		target_arch: "arm64",
784		compile_multilib: "64",
785		vendor: true,
786		arch: {
787			arm64: {
788				src: "libunwind.a",
789			},
790		},
791	}
792
793	vendor_snapshot_binary {
794		name: "bin",
795		version: "31",
796		target_arch: "arm64",
797		compile_multilib: "64",
798		vendor: true,
799		arch: {
800			arm64: {
801				src: "bin",
802			},
803		},
804		symlinks: ["binfoo", "binbar"],
805	}
806
807	vendor_snapshot_binary {
808		name: "bin_override",
809		version: "31",
810		target_arch: "arm64",
811		compile_multilib: "64",
812		vendor: true,
813		overrides: ["bin"],
814		arch: {
815			arm64: {
816				src: "override/bin",
817			},
818		},
819		symlinks: ["binfoo", "binbar"],
820	}
821
822	vendor_snapshot_binary {
823		name: "bin32",
824		version: "31",
825		target_arch: "arm64",
826		compile_multilib: "32",
827		vendor: true,
828		arch: {
829			arm: {
830				src: "bin32",
831			},
832		},
833	}
834
835	// old snapshot module which has to be ignored
836	vendor_snapshot_binary {
837		name: "bin",
838		version: "26",
839		target_arch: "arm64",
840		compile_multilib: "first",
841		vendor: true,
842		arch: {
843			arm64: {
844				src: "bin",
845			},
846		},
847	}
848
849	// different arch snapshot which has to be ignored
850	vendor_snapshot_binary {
851		name: "bin",
852		version: "31",
853		target_arch: "arm",
854		compile_multilib: "first",
855		vendor: true,
856		arch: {
857			arm64: {
858				src: "bin",
859			},
860		},
861	}
862`
863	depsBp := GatherRequiredDepsForTest(android.Android)
864
865	mockFS := map[string][]byte{
866		"deps/Android.bp":                  []byte(depsBp),
867		"framework/Android.bp":             []byte(frameworkBp),
868		"framework/symbol.txt":             nil,
869		"vendor/Android.bp":                []byte(vendorProprietaryBp),
870		"vendor/bin":                       nil,
871		"vendor/override/bin":              nil,
872		"vendor/bin32":                     nil,
873		"vendor/bin.cpp":                   nil,
874		"vendor/client.cpp":                nil,
875		"vendor/include/libvndk/a.h":       nil,
876		"vendor/include/libvendor/b.h":     nil,
877		"vendor/include/libvendor_cfi/c.h": nil,
878		"vendor/libc++_static.a":           nil,
879		"vendor/libc++demangle.a":          nil,
880		"vendor/libunwind.a":               nil,
881		"vendor/libvndk.a":                 nil,
882		"vendor/libvendor.a":               nil,
883		"vendor/libvendor.cfi.a":           nil,
884		"vendor/libvendor.so":              nil,
885		"vendor/override/libvendor.so":     nil,
886		"vendor/lib32.a":                   nil,
887		"vendor/lib32.so":                  nil,
888		"vendor/lib64.a":                   nil,
889		"vendor/lib64.so":                  nil,
890		"vndk/Android.bp":                  []byte(vndkBp),
891		"vndk/include/libvndk/a.h":         nil,
892		"vndk/libvndk.so":                  nil,
893		"vndk/libllndk.so":                 nil,
894	}
895
896	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
897	config.TestProductVariables.DeviceVndkVersion = StringPtr("31")
898	config.TestProductVariables.Platform_vndk_version = StringPtr("32")
899	ctx := CreateTestContext(config)
900	ctx.Register()
901
902	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
903	android.FailIfErrored(t, errs)
904	_, errs = ctx.PrepareBuildActions(config)
905	android.FailIfErrored(t, errs)
906
907	sharedVariant := "android_vendor.31_arm64_armv8-a_shared"
908	staticVariant := "android_vendor.31_arm64_armv8-a_static"
909	binaryVariant := "android_vendor.31_arm64_armv8-a"
910
911	sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi"
912	staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi"
913
914	shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared"
915	binary32Variant := "android_vendor.31_arm_armv7-a-neon"
916
917	// libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot
918	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
919	for _, includeFlags := range []string{
920		"-Ivndk/include/libvndk",     // libvndk
921		"-Ivendor/include/libvendor", // libvendor
922	} {
923		if !strings.Contains(libclientCcFlags, includeFlags) {
924			t.Errorf("flags for libclient must contain %#v, but was %#v.",
925				includeFlags, libclientCcFlags)
926		}
927	}
928
929	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
930	for _, input := range [][]string{
931		[]string{sharedVariant, "libvndk.vndk.31.arm64"},
932		[]string{sharedVariant, "libllndk.vndk.31.arm64"},
933		[]string{staticVariant, "libvendor.vendor_static.31.arm64"},
934		[]string{staticVariant, "libvendor_without_snapshot"},
935	} {
936		outputPaths := GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
937		if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
938			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
939		}
940
941	}
942
943	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
944	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
945		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
946	}
947
948	libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
949	if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) {
950		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
951	}
952
953	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
954	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
955		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
956	}
957
958	// libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant
959	libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"]
960	if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") {
961		t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.",
962			"-Ivendor/include/libvendor_cfi", libclientCfiCcFlags)
963	}
964
965	libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
966	libvendorCfiOutputPaths := GetOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
967	if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
968		t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
969	}
970
971	// bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers)
972	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
973	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") {
974		t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
975			"-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
976	}
977
978	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
979	libVndkStaticOutputPaths := GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
980	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
981		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
982			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
983	}
984
985	// libvendor.so is installed by libvendor.vendor_shared.31.arm64
986	ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so")
987
988	// lib64.so is installed by lib64.vendor_shared.31.arm64
989	ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so")
990
991	// lib32.so is installed by lib32.vendor_shared.31.arm64
992	ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so")
993
994	// libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64
995	ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so")
996
997	// libvendor_without_snapshot.so is installed by libvendor_without_snapshot
998	ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
999
1000	// bin is installed by bin.vendor_binary.31.arm64
1001	bin64Module := ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant)
1002	bin64Module.Output("bin")
1003
1004	// also test symlinks
1005	bin64MkEntries := android.AndroidMkEntriesForTest(t, ctx, bin64Module.Module())
1006	bin64KatiSymlinks := bin64MkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
1007
1008	// Either AndroidMk entries contain symlinks, or symlinks should be installed by Soong
1009	for _, symlink := range []string{"binfoo", "binbar"} {
1010		if inList(symlink, bin64KatiSymlinks) {
1011			continue
1012		}
1013
1014		bin64Module.Output(symlink)
1015	}
1016
1017	// bin32 is installed by bin32.vendor_binary.31.arm64
1018	ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32")
1019
1020	// bin_without_snapshot is installed by bin_without_snapshot
1021	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
1022
1023	// libvendor, libvendor_available and bin don't have vendor.31 variant
1024	libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
1025	if inList(sharedVariant, libvendorVariants) {
1026		t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
1027	}
1028
1029	libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
1030	if inList(sharedVariant, libvendorAvailableVariants) {
1031		t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
1032	}
1033
1034	binVariants := ctx.ModuleVariantsForTests("bin")
1035	if inList(binaryVariant, binVariants) {
1036		t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
1037	}
1038
1039	// test overrides property
1040	binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant)
1041	binOverrideModule.Output("bin")
1042	binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module())
1043	binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
1044	if !inList("bin", binOverrideEntry) {
1045		t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry)
1046	}
1047
1048	libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant)
1049	libvendorOverrideModule.Output("libvendor.so")
1050	libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module())
1051	libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
1052	if !inList("libvendor", libvendorOverrideEntry) {
1053		t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry)
1054	}
1055}
1056
1057func TestVendorSnapshotSanitizer(t *testing.T) {
1058	bp := `
1059	vendor_snapshot {
1060		name: "vendor_snapshot",
1061		version: "28",
1062		arch: {
1063			arm64: {
1064				static_libs: [
1065					"libsnapshot",
1066					"note_memtag_heap_sync",
1067				],
1068				objects: [
1069					"snapshot_object",
1070				],
1071				vndk_libs: [
1072					"libclang_rt.hwasan",
1073				],
1074			},
1075		},
1076	}
1077
1078	vendor_snapshot_static {
1079		name: "libsnapshot",
1080		vendor: true,
1081		target_arch: "arm64",
1082		version: "28",
1083		arch: {
1084			arm64: {
1085				src: "libsnapshot.a",
1086				cfi: {
1087					src: "libsnapshot.cfi.a",
1088				},
1089				hwasan: {
1090					src: "libsnapshot.hwasan.a",
1091				},
1092			},
1093		},
1094	}
1095
1096	vendor_snapshot_static {
1097		name: "note_memtag_heap_sync",
1098		vendor: true,
1099		target_arch: "arm64",
1100		version: "28",
1101		arch: {
1102			arm64: {
1103				src: "note_memtag_heap_sync.a",
1104			},
1105		},
1106	}
1107
1108	vndk_prebuilt_shared {
1109		name: "libclang_rt.hwasan",
1110		version: "28",
1111		target_arch: "arm64",
1112		vendor_available: true,
1113		product_available: true,
1114		vndk: {
1115			enabled: true,
1116		},
1117		arch: {
1118			arm64: {
1119				srcs: ["libclang_rt.hwasan.so"],
1120			},
1121		},
1122	}
1123
1124	vendor_snapshot_object {
1125		name: "snapshot_object",
1126		vendor: true,
1127		target_arch: "arm64",
1128		version: "28",
1129		arch: {
1130			arm64: {
1131				src: "snapshot_object.o",
1132			},
1133		},
1134		stl: "none",
1135	}
1136
1137	cc_test {
1138		name: "vstest",
1139		gtest: false,
1140		vendor: true,
1141		compile_multilib: "64",
1142		nocrt: true,
1143		no_libcrt: true,
1144		stl: "none",
1145		static_libs: ["libsnapshot"],
1146		system_shared_libs: [],
1147	}
1148`
1149
1150	mockFS := map[string][]byte{
1151		"vendor/Android.bp":              []byte(bp),
1152		"vendor/libc++demangle.a":        nil,
1153		"vendor/libclang_rt.hwasan.so":   nil,
1154		"vendor/libsnapshot.a":           nil,
1155		"vendor/libsnapshot.cfi.a":       nil,
1156		"vendor/libsnapshot.hwasan.a":    nil,
1157		"vendor/note_memtag_heap_sync.a": nil,
1158		"vendor/snapshot_object.o":       nil,
1159	}
1160
1161	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
1162	config.TestProductVariables.DeviceVndkVersion = StringPtr("28")
1163	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1164	config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
1165	ctx := testCcWithConfig(t, config)
1166
1167	// Check non-cfi, cfi and hwasan variant.
1168	staticVariant := "android_vendor.28_arm64_armv8-a_static"
1169	staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi"
1170	staticHwasanVariant := "android_vendor.28_arm64_armv8-a_static_hwasan"
1171	staticHwasanCfiVariant := "android_vendor.28_arm64_armv8-a_static_hwasan_cfi"
1172
1173	staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module)
1174	assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
1175
1176	staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module)
1177	assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
1178
1179	staticHwasanModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanVariant).Module().(*Module)
1180	assertString(t, staticHwasanModule.outputFile.Path().Base(), "libsnapshot.hwasan.a")
1181
1182	staticHwasanCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanCfiVariant).Module().(*Module)
1183	if !staticHwasanCfiModule.HiddenFromMake() || !staticHwasanCfiModule.PreventInstall() {
1184		t.Errorf("Hwasan and Cfi cannot enabled at the same time.")
1185	}
1186
1187	snapshotObjModule := ctx.ModuleForTests("snapshot_object.vendor_object.28.arm64", "android_vendor.28_arm64_armv8-a").Module()
1188	snapshotObjMkEntries := android.AndroidMkEntriesForTest(t, ctx, snapshotObjModule)
1189	// snapshot object must not add ".hwasan" suffix
1190	assertString(t, snapshotObjMkEntries[0].EntryMap["LOCAL_MODULE"][0], "snapshot_object")
1191}
1192
1193func TestVendorSnapshotExclude(t *testing.T) {
1194
1195	// This test verifies that the exclude_from_vendor_snapshot property
1196	// makes its way from the Android.bp source file into the module data
1197	// structure. It also verifies that modules are correctly included or
1198	// excluded in the vendor snapshot based on their path (framework or
1199	// vendor) and the exclude_from_vendor_snapshot property.
1200
1201	frameworkBp := `
1202		cc_library_shared {
1203			name: "libinclude",
1204			srcs: ["src/include.cpp"],
1205			vendor_available: true,
1206		}
1207		cc_library_shared {
1208			name: "libexclude",
1209			srcs: ["src/exclude.cpp"],
1210			vendor: true,
1211			exclude_from_vendor_snapshot: true,
1212		}
1213		cc_library_shared {
1214			name: "libavailable_exclude",
1215			srcs: ["src/exclude.cpp"],
1216			vendor_available: true,
1217			exclude_from_vendor_snapshot: true,
1218		}
1219	`
1220
1221	vendorProprietaryBp := `
1222		cc_library_shared {
1223			name: "libvendor",
1224			srcs: ["vendor.cpp"],
1225			vendor: true,
1226		}
1227	`
1228
1229	depsBp := GatherRequiredDepsForTest(android.Android)
1230
1231	mockFS := map[string][]byte{
1232		"deps/Android.bp":       []byte(depsBp),
1233		"framework/Android.bp":  []byte(frameworkBp),
1234		"framework/include.cpp": nil,
1235		"framework/exclude.cpp": nil,
1236		"device/Android.bp":     []byte(vendorProprietaryBp),
1237		"device/vendor.cpp":     nil,
1238	}
1239
1240	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
1241	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
1242	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1243	ctx := CreateTestContext(config)
1244	ctx.Register()
1245
1246	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
1247	android.FailIfErrored(t, errs)
1248	_, errs = ctx.PrepareBuildActions(config)
1249	android.FailIfErrored(t, errs)
1250
1251	// Test an include and exclude framework module.
1252	AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant)
1253	AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant)
1254	AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant)
1255
1256	// A vendor module is excluded, but by its path, not the
1257	// exclude_from_vendor_snapshot property.
1258	AssertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false, vendorVariant)
1259
1260	// Verify the content of the vendor snapshot.
1261
1262	snapshotDir := "vendor-snapshot"
1263	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
1264	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
1265
1266	var includeJsonFiles []string
1267	var excludeJsonFiles []string
1268
1269	for _, arch := range [][]string{
1270		[]string{"arm64", "armv8-a"},
1271		[]string{"arm", "armv7-a-neon"},
1272	} {
1273		archType := arch[0]
1274		archVariant := arch[1]
1275		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
1276
1277		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
1278		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
1279
1280		// Included modules
1281		CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
1282		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
1283
1284		// Excluded modules
1285		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
1286		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
1287		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
1288		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
1289		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
1290		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
1291	}
1292
1293	// Verify that each json file for an included module has a rule.
1294	for _, jsonFile := range includeJsonFiles {
1295		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
1296			t.Errorf("include json file %q not found", jsonFile)
1297		}
1298	}
1299
1300	// Verify that each json file for an excluded module has no rule.
1301	for _, jsonFile := range excludeJsonFiles {
1302		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
1303			t.Errorf("exclude json file %q found", jsonFile)
1304		}
1305	}
1306}
1307
1308func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
1309
1310	// This test verifies that using the exclude_from_vendor_snapshot
1311	// property on a module in a vendor proprietary path generates an
1312	// error. These modules are already excluded, so we prohibit using the
1313	// property in this way, which could add to confusion.
1314
1315	vendorProprietaryBp := `
1316		cc_library_shared {
1317			name: "libvendor",
1318			srcs: ["vendor.cpp"],
1319			vendor: true,
1320			exclude_from_vendor_snapshot: true,
1321		}
1322	`
1323
1324	depsBp := GatherRequiredDepsForTest(android.Android)
1325
1326	mockFS := map[string][]byte{
1327		"deps/Android.bp":   []byte(depsBp),
1328		"device/Android.bp": []byte(vendorProprietaryBp),
1329		"device/vendor.cpp": nil,
1330	}
1331
1332	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
1333	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
1334	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1335	ctx := CreateTestContext(config)
1336	ctx.Register()
1337
1338	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
1339	android.FailIfErrored(t, errs)
1340
1341	_, errs = ctx.PrepareBuildActions(config)
1342	android.CheckErrorsAgainstExpectations(t, errs, []string{
1343		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1344		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1345		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1346		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1347		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1348		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
1349	})
1350}
1351
1352func TestRecoverySnapshotCapture(t *testing.T) {
1353	bp := `
1354	cc_library {
1355		name: "libvndk",
1356		vendor_available: true,
1357		recovery_available: true,
1358		product_available: true,
1359		vndk: {
1360			enabled: true,
1361		},
1362		nocrt: true,
1363	}
1364
1365	cc_library {
1366		name: "librecovery",
1367		recovery: true,
1368		nocrt: true,
1369	}
1370
1371	cc_library {
1372		name: "librecovery_available",
1373		recovery_available: true,
1374		nocrt: true,
1375	}
1376
1377	cc_library_headers {
1378		name: "librecovery_headers",
1379		recovery_available: true,
1380		nocrt: true,
1381	}
1382
1383	cc_binary {
1384		name: "recovery_bin",
1385		recovery: true,
1386		nocrt: true,
1387	}
1388
1389	cc_binary {
1390		name: "recovery_available_bin",
1391		recovery_available: true,
1392		nocrt: true,
1393	}
1394
1395	cc_prebuilt_library_static {
1396		name: "libb",
1397		recovery_available: true,
1398		srcs: ["libb.a"],
1399		nocrt: true,
1400		no_libcrt: true,
1401		stl: "none",
1402	}
1403
1404	cc_object {
1405		name: "obj",
1406		recovery_available: true,
1407	}
1408`
1409	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
1410	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
1411	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1412	ctx := testCcWithConfig(t, config)
1413
1414	// Check Recovery snapshot output.
1415
1416	snapshotDir := "recovery-snapshot"
1417	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
1418	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
1419
1420	var jsonFiles []string
1421
1422	for _, arch := range [][]string{
1423		[]string{"arm64", "armv8-a"},
1424	} {
1425		archType := arch[0]
1426		archVariant := arch[1]
1427		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
1428
1429		// For shared libraries, only recovery_available modules are captured.
1430		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
1431		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
1432		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
1433		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
1434		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
1435		jsonFiles = append(jsonFiles,
1436			filepath.Join(sharedDir, "libvndk.so.json"),
1437			filepath.Join(sharedDir, "librecovery.so.json"),
1438			filepath.Join(sharedDir, "librecovery_available.so.json"))
1439
1440		// For static libraries, all recovery:true and recovery_available modules are captured.
1441		staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
1442		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
1443		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
1444		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
1445		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
1446		jsonFiles = append(jsonFiles,
1447			filepath.Join(staticDir, "libb.a.json"),
1448			filepath.Join(staticDir, "librecovery.a.json"),
1449			filepath.Join(staticDir, "librecovery_available.a.json"))
1450
1451		// For binary executables, all recovery:true and recovery_available modules are captured.
1452		if archType == "arm64" {
1453			binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
1454			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
1455			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
1456			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
1457			jsonFiles = append(jsonFiles,
1458				filepath.Join(binaryDir, "recovery_bin.json"),
1459				filepath.Join(binaryDir, "recovery_available_bin.json"))
1460		}
1461
1462		// For header libraries, all vendor:true and vendor_available modules are captured.
1463		headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
1464		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json"))
1465
1466		// For object modules, all vendor:true and vendor_available modules are captured.
1467		objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
1468		objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
1469		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
1470		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
1471	}
1472
1473	for _, jsonFile := range jsonFiles {
1474		// verify all json files exist
1475		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
1476			t.Errorf("%q expected but not found", jsonFile)
1477		}
1478	}
1479}
1480
1481func TestRecoverySnapshotExclude(t *testing.T) {
1482	// This test verifies that the exclude_from_recovery_snapshot property
1483	// makes its way from the Android.bp source file into the module data
1484	// structure. It also verifies that modules are correctly included or
1485	// excluded in the recovery snapshot based on their path (framework or
1486	// vendor) and the exclude_from_recovery_snapshot property.
1487
1488	frameworkBp := `
1489		cc_library_shared {
1490			name: "libinclude",
1491			srcs: ["src/include.cpp"],
1492			recovery_available: true,
1493		}
1494		cc_library_shared {
1495			name: "libexclude",
1496			srcs: ["src/exclude.cpp"],
1497			recovery: true,
1498			exclude_from_recovery_snapshot: true,
1499		}
1500		cc_library_shared {
1501			name: "libavailable_exclude",
1502			srcs: ["src/exclude.cpp"],
1503			recovery_available: true,
1504			exclude_from_recovery_snapshot: true,
1505		}
1506	`
1507
1508	vendorProprietaryBp := `
1509		cc_library_shared {
1510			name: "librecovery",
1511			srcs: ["recovery.cpp"],
1512			recovery: true,
1513		}
1514	`
1515
1516	depsBp := GatherRequiredDepsForTest(android.Android)
1517
1518	mockFS := map[string][]byte{
1519		"deps/Android.bp":       []byte(depsBp),
1520		"framework/Android.bp":  []byte(frameworkBp),
1521		"framework/include.cpp": nil,
1522		"framework/exclude.cpp": nil,
1523		"device/Android.bp":     []byte(vendorProprietaryBp),
1524		"device/recovery.cpp":   nil,
1525	}
1526
1527	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
1528	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
1529	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1530	ctx := CreateTestContext(config)
1531	ctx.Register()
1532
1533	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
1534	android.FailIfErrored(t, errs)
1535	_, errs = ctx.PrepareBuildActions(config)
1536	android.FailIfErrored(t, errs)
1537
1538	// Test an include and exclude framework module.
1539	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, recoveryVariant)
1540	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, recoveryVariant)
1541	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, recoveryVariant)
1542
1543	// A recovery module is excluded, but by its path, not the
1544	// exclude_from_recovery_snapshot property.
1545	AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, recoveryVariant)
1546
1547	// Verify the content of the recovery snapshot.
1548
1549	snapshotDir := "recovery-snapshot"
1550	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
1551	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
1552
1553	var includeJsonFiles []string
1554	var excludeJsonFiles []string
1555
1556	for _, arch := range [][]string{
1557		[]string{"arm64", "armv8-a"},
1558	} {
1559		archType := arch[0]
1560		archVariant := arch[1]
1561		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
1562
1563		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
1564		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
1565
1566		// Included modules
1567		CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
1568		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
1569
1570		// Excluded modules
1571		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
1572		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
1573		CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
1574		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
1575		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
1576		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
1577	}
1578
1579	// Verify that each json file for an included module has a rule.
1580	for _, jsonFile := range includeJsonFiles {
1581		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
1582			t.Errorf("include json file %q not found", jsonFile)
1583		}
1584	}
1585
1586	// Verify that each json file for an excluded module has no rule.
1587	for _, jsonFile := range excludeJsonFiles {
1588		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
1589			t.Errorf("exclude json file %q found", jsonFile)
1590		}
1591	}
1592}
1593
1594func TestRecoverySnapshotDirected(t *testing.T) {
1595	bp := `
1596	cc_library_shared {
1597		name: "librecovery",
1598		recovery: true,
1599		nocrt: true,
1600	}
1601
1602	cc_library_shared {
1603		name: "librecovery_available",
1604		recovery_available: true,
1605		nocrt: true,
1606	}
1607
1608	genrule {
1609		name: "libfoo_gen",
1610		cmd: "",
1611		out: ["libfoo.so"],
1612	}
1613
1614	cc_prebuilt_library_shared {
1615		name: "libfoo",
1616		recovery: true,
1617		prefer: true,
1618		srcs: [":libfoo_gen"],
1619	}
1620
1621	cc_library_shared {
1622		name: "libfoo",
1623		recovery: true,
1624		nocrt: true,
1625	}
1626`
1627	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
1628	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
1629	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
1630	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1631	config.TestProductVariables.DirectedRecoverySnapshot = true
1632	config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
1633	config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true
1634	config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true
1635	ctx := testCcWithConfig(t, config)
1636
1637	// Check recovery snapshot output.
1638
1639	snapshotDir := "recovery-snapshot"
1640	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
1641	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
1642
1643	var includeJsonFiles []string
1644
1645	for _, arch := range [][]string{
1646		[]string{"arm64", "armv8-a"},
1647	} {
1648		archType := arch[0]
1649		archVariant := arch[1]
1650		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
1651
1652		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
1653		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
1654
1655		// Included modules
1656		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
1657		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
1658		// Check that snapshot captures "prefer: true" prebuilt
1659		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
1660		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
1661
1662		// Excluded modules. Modules not included in the directed recovery snapshot
1663		// are still include as fake modules.
1664		CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
1665		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
1666	}
1667
1668	// Verify that each json file for an included module has a rule.
1669	for _, jsonFile := range includeJsonFiles {
1670		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
1671			t.Errorf("include json file %q not found", jsonFile)
1672		}
1673	}
1674}
1675
1676func TestSnapshotInRelativeInstallPath(t *testing.T) {
1677	bp := `
1678	cc_library {
1679		name: "libvendor_available",
1680		vendor_available: true,
1681		nocrt: true,
1682	}
1683
1684	cc_library {
1685		name: "libvendor_available_var",
1686		vendor_available: true,
1687		stem: "libvendor_available",
1688		relative_install_path: "var",
1689		nocrt: true,
1690	}
1691`
1692
1693	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
1694	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
1695	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
1696	ctx := testCcWithConfig(t, config)
1697
1698	// Check Vendor snapshot output.
1699
1700	snapshotDir := "vendor-snapshot"
1701	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
1702	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
1703
1704	var jsonFiles []string
1705
1706	for _, arch := range [][]string{
1707		[]string{"arm64", "armv8-a"},
1708		[]string{"arm", "armv7-a-neon"},
1709	} {
1710		archType := arch[0]
1711		archVariant := arch[1]
1712		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
1713
1714		// For shared libraries, only non-VNDK vendor_available modules are captured
1715		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
1716		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
1717		sharedDirVar := filepath.Join(sharedDir, "var")
1718		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
1719		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available_var", "libvendor_available.so", sharedDirVar, sharedVariant)
1720		jsonFiles = append(jsonFiles,
1721			filepath.Join(sharedDir, "libvendor_available.so.json"),
1722			filepath.Join(sharedDirVar, "libvendor_available.so.json"))
1723	}
1724
1725	for _, jsonFile := range jsonFiles {
1726		// verify all json files exist
1727		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
1728			t.Errorf("%q expected but not found", jsonFile)
1729		}
1730	}
1731
1732	// fake snapshot should have all outputs in the normal snapshot.
1733	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
1734	for _, output := range snapshotSingleton.AllOutputs() {
1735		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
1736		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
1737			t.Errorf("%q expected but not found", fakeOutput)
1738		}
1739	}
1740}
1741