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