• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 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	"fmt"
19	"runtime"
20	"testing"
21
22	"android/soong/android"
23	"github.com/google/blueprint"
24)
25
26var prepareForPrebuiltTest = android.GroupFixturePreparers(
27	prepareForCcTest,
28	android.PrepareForTestWithAndroidMk,
29)
30
31func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
32	t.Helper()
33	result := android.GroupFixturePreparers(
34		prepareForPrebuiltTest,
35		fs.AddToFixture(),
36		android.GroupFixturePreparers(handlers...),
37	).RunTestWithBp(t, bp)
38
39	return result.TestContext
40}
41
42type configCustomizer func(config android.Config)
43
44func TestPrebuilt(t *testing.T) {
45	bp := `
46		cc_library {
47			name: "liba",
48		}
49
50		cc_prebuilt_library_shared {
51			name: "liba",
52			srcs: ["liba.so"],
53		}
54
55		cc_library {
56			name: "libb",
57		}
58
59		cc_prebuilt_library_static {
60			name: "libb",
61			srcs: ["libb.a"],
62		}
63
64		cc_library_shared {
65			name: "libd",
66		}
67
68		cc_prebuilt_library_shared {
69			name: "libd",
70			srcs: ["libd.so"],
71		}
72
73		cc_library_static {
74			name: "libe",
75		}
76
77		cc_prebuilt_library_static {
78			name: "libe",
79			srcs: ["libe.a"],
80		}
81
82		cc_library {
83			name: "libf",
84		}
85
86		cc_prebuilt_library {
87			name: "libf",
88			static: {
89				srcs: ["libf.a"],
90			},
91			shared: {
92				srcs: ["libf.so"],
93			},
94		}
95
96		cc_object {
97			name: "crtx",
98		}
99
100		cc_prebuilt_object {
101			name: "crtx",
102			srcs: ["crtx.o"],
103		}
104	`
105
106	ctx := testPrebuilt(t, bp, map[string][]byte{
107		"liba.so": nil,
108		"libb.a":  nil,
109		"libd.so": nil,
110		"libe.a":  nil,
111		"libf.a":  nil,
112		"libf.so": nil,
113		"crtx.o":  nil,
114	})
115
116	// Verify that all the modules exist and that their dependencies were connected correctly
117	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
118	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
119	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
120	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
121	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
122	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
123	crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
124
125	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
126	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
127	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
128	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
129	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
130	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
131	prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
132
133	hasDep := func(m android.Module, wantDep android.Module) bool {
134		t.Helper()
135		var found bool
136		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
137			if dep == wantDep {
138				found = true
139			}
140		})
141		return found
142	}
143
144	if !hasDep(liba, prebuiltLiba) {
145		t.Errorf("liba missing dependency on prebuilt_liba")
146	}
147
148	if !hasDep(libb, prebuiltLibb) {
149		t.Errorf("libb missing dependency on prebuilt_libb")
150	}
151
152	if !hasDep(libd, prebuiltLibd) {
153		t.Errorf("libd missing dependency on prebuilt_libd")
154	}
155
156	if !hasDep(libe, prebuiltLibe) {
157		t.Errorf("libe missing dependency on prebuilt_libe")
158	}
159
160	if !hasDep(libfStatic, prebuiltLibfStatic) {
161		t.Errorf("libf static missing dependency on prebuilt_libf")
162	}
163
164	if !hasDep(libfShared, prebuiltLibfShared) {
165		t.Errorf("libf shared missing dependency on prebuilt_libf")
166	}
167
168	if !hasDep(crtx, prebuiltCrtx) {
169		t.Errorf("crtx missing dependency on prebuilt_crtx")
170	}
171
172	entries := android.AndroidMkEntriesForTest(t, ctx, prebuiltLiba)[0]
173	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_shared", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
174	entries = android.AndroidMkEntriesForTest(t, ctx, prebuiltLibb)[0]
175	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_static", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
176}
177
178func TestPrebuiltLibraryShared(t *testing.T) {
179	ctx := testPrebuilt(t, `
180	cc_prebuilt_library_shared {
181		name: "libtest",
182		srcs: ["libf.so"],
183    strip: {
184        none: true,
185    },
186	}
187	`, map[string][]byte{
188		"libf.so": nil,
189	})
190
191	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
192	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
193}
194
195func TestPrebuiltLibraryStatic(t *testing.T) {
196	ctx := testPrebuilt(t, `
197	cc_prebuilt_library_static {
198		name: "libtest",
199		srcs: ["libf.a"],
200	}
201	`, map[string][]byte{
202		"libf.a": nil,
203	})
204
205	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
206	assertString(t, static.OutputFile().Path().Base(), "libf.a")
207}
208
209func TestPrebuiltLibrary(t *testing.T) {
210	ctx := testPrebuilt(t, `
211	cc_prebuilt_library {
212		name: "libtest",
213		static: {
214			srcs: ["libf.a"],
215		},
216		shared: {
217			srcs: ["libf.so"],
218		},
219    strip: {
220        none: true,
221    },
222	}
223	`, map[string][]byte{
224		"libf.a":  nil,
225		"libf.so": nil,
226	})
227
228	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
229	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
230
231	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
232	assertString(t, static.OutputFile().Path().Base(), "libf.a")
233}
234
235func TestPrebuiltLibraryStem(t *testing.T) {
236	ctx := testPrebuilt(t, `
237	cc_prebuilt_library {
238		name: "libfoo",
239		stem: "libbar",
240		static: {
241			srcs: ["libfoo.a"],
242		},
243		shared: {
244			srcs: ["libfoo.so"],
245		},
246		strip: {
247			none: true,
248		},
249	}
250	`, map[string][]byte{
251		"libfoo.a":  nil,
252		"libfoo.so": nil,
253	})
254
255	static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
256	assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
257
258	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
259	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
260}
261
262func TestPrebuiltLibrarySharedStem(t *testing.T) {
263	ctx := testPrebuilt(t, `
264	cc_prebuilt_library_shared {
265		name: "libfoo",
266		stem: "libbar",
267		srcs: ["libfoo.so"],
268		strip: {
269			none: true,
270		},
271	}
272	`, map[string][]byte{
273		"libfoo.so": nil,
274	})
275
276	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
277	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
278}
279
280func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
281	if runtime.GOOS != "linux" {
282		t.Skipf("Skipping host prebuilt testing that is only supported on linux not %s", runtime.GOOS)
283	}
284
285	ctx := testPrebuilt(t, `
286	cc_prebuilt_library_shared {
287		name: "libfoo",
288		device_supported: false,
289		host_supported: true,
290		target: {
291			linux_glibc_x86_64: {
292				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
293			},
294		},
295	}
296
297	cc_prebuilt_binary {
298		name: "foo",
299		device_supported: false,
300		host_supported: true,
301		shared_libs: ["libfoo"],
302		target: {
303			linux_glibc_x86_64: {
304				srcs: ["linux_glibc_x86_64/bin/foo"],
305			},
306		},
307	}
308	`, map[string][]byte{
309		"libfoo.so": nil,
310		"foo":       nil,
311	})
312
313	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
314	assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
315	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
316
317	var libfooDep android.Path
318	for _, dep := range fooRule.Implicits {
319		if dep.Base() == "libfoo.so" {
320			libfooDep = dep
321			break
322		}
323	}
324	assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
325}
326
327func TestPrebuiltLibrarySanitized(t *testing.T) {
328	bp := `cc_prebuilt_library {
329	name: "libtest",
330		static: {
331                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
332		},
333		shared: {
334                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
335		},
336	}
337	cc_prebuilt_library_static {
338		name: "libtest_static",
339                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
340	}
341	cc_prebuilt_library_shared {
342		name: "libtest_shared",
343                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
344	}`
345
346	fs := map[string][]byte{
347		"libf.a":         nil,
348		"libf.hwasan.a":  nil,
349		"libf.so":        nil,
350		"hwasan/libf.so": nil,
351	}
352
353	// Without SANITIZE_TARGET.
354	ctx := testPrebuilt(t, bp, fs)
355
356	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
357	assertString(t, shared_rule.Input.String(), "libf.so")
358
359	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
360	assertString(t, static.OutputFile().Path().Base(), "libf.a")
361
362	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
363	assertString(t, shared_rule2.Input.String(), "libf.so")
364
365	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
366	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
367
368	// With SANITIZE_TARGET=hwaddress
369	ctx = testPrebuilt(t, bp, fs,
370		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
371			variables.SanitizeDevice = []string{"hwaddress"}
372		}),
373	)
374
375	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
376	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
377
378	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
379	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
380
381	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
382	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
383
384	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
385	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
386}
387
388func TestPrebuiltStubNoinstall(t *testing.T) {
389	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
390		result := android.GroupFixturePreparers(
391			prepareForPrebuiltTest,
392			android.PrepareForTestWithMakevars,
393			android.FixtureMergeMockFs(fs),
394		).RunTest(t)
395
396		ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
397		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
398
399		installRules := result.InstallMakeRulesForTesting(t)
400		var installedlibRule *android.InstallMakeRule
401		for i, rule := range installRules {
402			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
403				if installedlibRule != nil {
404					t.Errorf("Duplicate install rules for %s", rule.Target)
405				}
406				installedlibRule = &installRules[i]
407			}
408		}
409		if installedlibRule == nil {
410			t.Errorf("No install rule found for installedlib")
411			return
412		}
413
414		if expectLibfooOnSystemLib {
415			android.AssertStringListContains(t,
416				"installedlib doesn't have install dependency on libfoo impl",
417				installedlibRule.OrderOnlyDeps,
418				"out/target/product/test_device/system/lib/libfoo.so")
419		} else {
420			android.AssertStringListDoesNotContain(t,
421				"installedlib has install dependency on libfoo stub",
422				installedlibRule.Deps,
423				"out/target/product/test_device/system/lib/libfoo.so")
424			android.AssertStringListDoesNotContain(t,
425				"installedlib has order-only install dependency on libfoo stub",
426				installedlibRule.OrderOnlyDeps,
427				"out/target/product/test_device/system/lib/libfoo.so")
428		}
429	}
430
431	prebuiltLibfooBp := []byte(`
432		cc_prebuilt_library {
433			name: "libfoo",
434			prefer: true,
435			srcs: ["libfoo.so"],
436			stubs: {
437				versions: ["1"],
438			},
439		}
440	`)
441
442	installedlibBp := []byte(`
443		cc_library {
444			name: "installedlib",
445			shared_libs: ["libfoo"],
446		}
447	`)
448
449	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
450		testFunc(
451			t,
452			/*expectLibfooOnSystemLib=*/ false,
453			android.MockFS{
454				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
455				"Android.bp": installedlibBp,
456			},
457		)
458	})
459
460	disabledSourceLibfooBp := []byte(`
461		cc_library {
462			name: "libfoo",
463			enabled: false,
464			stubs: {
465				versions: ["1"],
466			},
467		}
468	`)
469
470	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
471		testFunc(
472			t,
473			/*expectLibfooOnSystemLib=*/ false,
474			android.MockFS{
475				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
476				"impl/Android.bp": disabledSourceLibfooBp,
477				"Android.bp":      installedlibBp,
478			},
479		)
480	})
481
482	t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
483		testFunc(
484			t,
485			/*expectLibfooOnSystemLib=*/ true,
486			android.MockFS{
487				"impl/Android.bp": prebuiltLibfooBp,
488				"Android.bp":      installedlibBp,
489			},
490		)
491	})
492}
493
494func TestPrebuiltBinaryNoSrcsNoError(t *testing.T) {
495	const bp = `
496cc_prebuilt_binary {
497	name: "bintest",
498	srcs: [],
499}`
500	ctx := testPrebuilt(t, bp, map[string][]byte{})
501	mod := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
502	android.AssertBoolEquals(t, `expected no srcs to yield no output file`, false, mod.OutputFile().Valid())
503}
504
505func TestPrebuiltBinaryMultipleSrcs(t *testing.T) {
506	const bp = `
507cc_prebuilt_binary {
508	name: "bintest",
509	srcs: ["foo", "bar"],
510}`
511	testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
512}
513
514func TestMultiplePrebuilts(t *testing.T) {
515	bp := `
516		// an rdep
517		cc_library {
518			name: "libfoo",
519			shared_libs: ["libbar"],
520		}
521
522		// multiple variations of dep
523		// source
524		cc_library {
525			name: "libbar",
526		}
527		// prebuilt "v1"
528		cc_prebuilt_library_shared {
529			name: "libbar",
530			srcs: ["libbar.so"],
531		}
532		// prebuilt "v2"
533		cc_prebuilt_library_shared {
534			name: "libbar.v2",
535			stem: "libbar",
536			source_module_name: "libbar",
537			srcs: ["libbar.so"],
538		}
539
540		// selectors
541		apex_contributions {
542			name: "myapex_contributions",
543			contents: ["%v"],
544		}
545		all_apex_contributions {name: "all_apex_contributions"}
546	`
547	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
548		t.Helper()
549		var found bool
550		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
551			if dep == wantDep {
552				found = true
553			}
554		})
555		return found
556	}
557
558	testCases := []struct {
559		desc                   string
560		selectedDependencyName string
561		expectedDependencyName string
562	}{
563		{
564			desc:                   "Source library is selected using apex_contributions",
565			selectedDependencyName: "libbar",
566			expectedDependencyName: "libbar",
567		},
568		{
569			desc:                   "Prebuilt library v1 is selected using apex_contributions",
570			selectedDependencyName: "prebuilt_libbar",
571			expectedDependencyName: "prebuilt_libbar",
572		},
573		{
574			desc:                   "Prebuilt library v2 is selected using apex_contributions",
575			selectedDependencyName: "prebuilt_libbar.v2",
576			expectedDependencyName: "prebuilt_libbar.v2",
577		},
578	}
579
580	for _, tc := range testCases {
581		preparer := android.GroupFixturePreparers(
582			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
583				android.RegisterApexContributionsBuildComponents(ctx)
584			}),
585			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
586				variables.BuildFlags = map[string]string{
587					"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
588				}
589			}),
590		)
591		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
592			"libbar.so": nil,
593			"crtx.o":    nil,
594		}, preparer)
595		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
596		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
597		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
598		// check that LOCAL_SHARED_LIBRARIES contains libbar and not libbar.v<N>
599		entries := android.AndroidMkEntriesForTest(t, ctx, libfoo)[0]
600		android.AssertStringListContains(t, "Version should not be present in LOCAL_SHARED_LIBRARIES", entries.EntryMap["LOCAL_SHARED_LIBRARIES"], "libbar")
601
602		// check installation rules
603		// the selected soong module should be exported to make
604		libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
605		android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())
606
607		// check LOCAL_MODULE of the selected module name
608		// the prebuilt should have the same LOCAL_MODULE when exported to make
609		entries = android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
610		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
611	}
612}
613
614// Setting prefer on multiple prebuilts is an error, unless one of them is also listed in apex_contributions
615func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
616	bp := `
617		// an rdep
618		cc_library {
619			name: "libfoo",
620			shared_libs: ["libbar"],
621		}
622
623		// multiple variations of dep
624		// source
625		cc_library {
626			name: "libbar",
627		}
628		// prebuilt "v1"
629		cc_prebuilt_library_shared {
630			name: "libbar",
631			srcs: ["libbar.so"],
632			prefer: true,
633		}
634		// prebuilt "v2"
635		cc_prebuilt_library_shared {
636			name: "libbar.v2",
637			stem: "libbar",
638			source_module_name: "libbar",
639			srcs: ["libbar.so"],
640			prefer: true,
641		}
642
643		// selectors
644		apex_contributions {
645			name: "myapex_contributions",
646			contents: [%v],
647		}
648		all_apex_contributions {name: "all_apex_contributions"}
649	`
650	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
651		t.Helper()
652		var found bool
653		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
654			if dep == wantDep {
655				found = true
656			}
657		})
658		return found
659	}
660
661	testCases := []struct {
662		desc                   string
663		selectedDependencyName string
664		expectedDependencyName string
665		expectedErr            string
666	}{
667		{
668			desc:        "Multiple prebuilts have prefer: true",
669			expectedErr: "Multiple prebuilt modules prebuilt_libbar and prebuilt_libbar.v2 have been marked as preferred for this source module",
670		},
671		{
672			desc:                   "Multiple prebuilts have prefer: true. The prebuilt listed in apex_contributions wins.",
673			selectedDependencyName: `"prebuilt_libbar"`,
674			expectedDependencyName: "prebuilt_libbar",
675		},
676	}
677
678	for _, tc := range testCases {
679		preparer := android.GroupFixturePreparers(
680			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
681				android.RegisterApexContributionsBuildComponents(ctx)
682			}),
683			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
684				variables.BuildFlags = map[string]string{
685					"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
686				}
687			}),
688		)
689		if tc.expectedErr != "" {
690			preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedErr))
691		}
692
693		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
694			"libbar.so": nil,
695			"crtx.o":    nil,
696		}, preparer)
697		if tc.expectedErr != "" {
698			return // the fixture will assert that the excepted err has been raised
699		}
700		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
701		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
702		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
703	}
704}
705
706// If module sdk cannot provide a cc module variant (e.g. static), then the module variant from source should be used
707func TestMissingVariantInModuleSdk(t *testing.T) {
708	bp := `
709		// an rdep
710		cc_library {
711			name: "libfoo",
712			static_libs: ["libbar"],
713		}
714
715		// source
716		cc_library {
717			name: "libbar",
718		}
719		// prebuilt
720		// libbar only exists as a shared library
721		cc_prebuilt_library_shared {
722			name: "libbar",
723			srcs: ["libbar.so"],
724		}
725		// selectors
726		apex_contributions {
727			name: "myapex_contributions",
728			contents: ["prebuilt_libbar"],
729		}
730		all_apex_contributions {name: "all_apex_contributions"}
731	`
732	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
733		t.Helper()
734		var found bool
735		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
736			if dep == wantDep {
737				found = true
738			}
739		})
740		return found
741	}
742
743	preparer := android.GroupFixturePreparers(
744		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
745			android.RegisterApexContributionsBuildComponents(ctx)
746		}),
747		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
748			variables.BuildFlags = map[string]string{
749				"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
750			}
751		}),
752	)
753	ctx := testPrebuilt(t, bp, map[string][]byte{
754		"libbar.so": nil,
755		"crtx.o":    nil,
756	}, preparer)
757	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
758	sourceLibBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module()
759	// Even though the prebuilt is listed in apex_contributions, the prebuilt does not have a static variant.
760	// Therefore source of libbar should be used.
761	android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true, hasDep(ctx, libfoo, sourceLibBar))
762}
763