xref: /aosp_15_r20/build/soong/cc/prebuilt_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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			prefer: true,
54		}
55
56		cc_library {
57			name: "libb",
58		}
59
60		cc_prebuilt_library_static {
61			name: "libb",
62			srcs: ["libb.a"],
63			prefer: true,
64		}
65
66		cc_library_shared {
67			name: "libd",
68		}
69
70		cc_prebuilt_library_shared {
71			name: "libd",
72			srcs: ["libd.so"],
73		}
74
75		cc_library_static {
76			name: "libe",
77		}
78
79		cc_prebuilt_library_static {
80			name: "libe",
81			srcs: ["libe.a"],
82		}
83
84		cc_library {
85			name: "libf",
86		}
87
88		cc_prebuilt_library {
89			name: "libf",
90			static: {
91				srcs: ["libf.a"],
92			},
93			shared: {
94				srcs: ["libf.so"],
95			},
96		}
97
98		cc_object {
99			name: "crtx",
100		}
101
102		cc_prebuilt_object {
103			name: "crtx",
104			srcs: ["crtx.o"],
105		}
106	`
107
108	ctx := testPrebuilt(t, bp, map[string][]byte{
109		"liba.so": nil,
110		"libb.a":  nil,
111		"libd.so": nil,
112		"libe.a":  nil,
113		"libf.a":  nil,
114		"libf.so": nil,
115		"crtx.o":  nil,
116	})
117
118	// Verify that all the modules exist and that their dependencies were connected correctly
119	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
120	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
121	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
122	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
123	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
124	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
125	crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
126
127	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
128	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
129	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
130	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
131	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
132	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
133	prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
134
135	hasDep := func(m android.Module, wantDep android.Module) bool {
136		t.Helper()
137		var found bool
138		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
139			if dep == wantDep {
140				found = true
141			}
142		})
143		return found
144	}
145
146	if !hasDep(liba, prebuiltLiba) {
147		t.Errorf("liba missing dependency on prebuilt_liba")
148	}
149
150	if !hasDep(libb, prebuiltLibb) {
151		t.Errorf("libb missing dependency on prebuilt_libb")
152	}
153
154	if !hasDep(libd, prebuiltLibd) {
155		t.Errorf("libd missing dependency on prebuilt_libd")
156	}
157
158	if !hasDep(libe, prebuiltLibe) {
159		t.Errorf("libe missing dependency on prebuilt_libe")
160	}
161
162	if !hasDep(libfStatic, prebuiltLibfStatic) {
163		t.Errorf("libf static missing dependency on prebuilt_libf")
164	}
165
166	if !hasDep(libfShared, prebuiltLibfShared) {
167		t.Errorf("libf shared missing dependency on prebuilt_libf")
168	}
169
170	if !hasDep(crtx, prebuiltCrtx) {
171		t.Errorf("crtx missing dependency on prebuilt_crtx")
172	}
173
174	entries := android.AndroidMkInfoForTest(t, ctx, prebuiltLiba).PrimaryInfo
175	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_shared", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
176	entries = android.AndroidMkInfoForTest(t, ctx, prebuiltLibb).PrimaryInfo
177	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_static", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
178}
179
180func TestPrebuiltLibraryShared(t *testing.T) {
181	ctx := testPrebuilt(t, `
182	cc_prebuilt_library_shared {
183		name: "libtest",
184		srcs: ["libf.so"],
185    strip: {
186        none: true,
187    },
188	}
189	`, map[string][]byte{
190		"libf.so": nil,
191	})
192
193	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
194	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
195}
196
197func TestPrebuiltLibraryStatic(t *testing.T) {
198	ctx := testPrebuilt(t, `
199	cc_prebuilt_library_static {
200		name: "libtest",
201		srcs: ["libf.a"],
202	}
203	`, map[string][]byte{
204		"libf.a": nil,
205	})
206
207	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
208	assertString(t, static.OutputFile().Path().Base(), "libf.a")
209}
210
211func TestPrebuiltLibrary(t *testing.T) {
212	ctx := testPrebuilt(t, `
213	cc_prebuilt_library {
214		name: "libtest",
215		static: {
216			srcs: ["libf.a"],
217		},
218		shared: {
219			srcs: ["libf.so"],
220		},
221    strip: {
222        none: true,
223    },
224	}
225	`, map[string][]byte{
226		"libf.a":  nil,
227		"libf.so": nil,
228	})
229
230	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
231	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
232
233	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
234	assertString(t, static.OutputFile().Path().Base(), "libf.a")
235}
236
237func TestPrebuiltLibraryStem(t *testing.T) {
238	ctx := testPrebuilt(t, `
239	cc_prebuilt_library {
240		name: "libfoo",
241		stem: "libbar",
242		static: {
243			srcs: ["libfoo.a"],
244		},
245		shared: {
246			srcs: ["libfoo.so"],
247		},
248		strip: {
249			none: true,
250		},
251	}
252	`, map[string][]byte{
253		"libfoo.a":  nil,
254		"libfoo.so": nil,
255	})
256
257	static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
258	assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
259
260	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
261	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
262}
263
264func TestPrebuiltLibrarySharedStem(t *testing.T) {
265	ctx := testPrebuilt(t, `
266	cc_prebuilt_library_shared {
267		name: "libfoo",
268		stem: "libbar",
269		srcs: ["libfoo.so"],
270		strip: {
271			none: true,
272		},
273	}
274	`, map[string][]byte{
275		"libfoo.so": nil,
276	})
277
278	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
279	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
280}
281
282func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
283	if runtime.GOOS != "linux" {
284		t.Skipf("Skipping host prebuilt testing that is only supported on linux not %s", runtime.GOOS)
285	}
286
287	ctx := testPrebuilt(t, `
288	cc_prebuilt_library_shared {
289		name: "libfoo",
290		device_supported: false,
291		host_supported: true,
292		target: {
293			linux_glibc_x86_64: {
294				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
295			},
296		},
297	}
298
299	cc_prebuilt_binary {
300		name: "foo",
301		device_supported: false,
302		host_supported: true,
303		shared_libs: ["libfoo"],
304		target: {
305			linux_glibc_x86_64: {
306				srcs: ["linux_glibc_x86_64/bin/foo"],
307			},
308		},
309	}
310	`, map[string][]byte{
311		"libfoo.so": nil,
312		"foo":       nil,
313	})
314
315	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
316	assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
317	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
318
319	var libfooDep android.Path
320	for _, dep := range fooRule.Implicits {
321		if dep.Base() == "libfoo.so" {
322			libfooDep = dep
323			break
324		}
325	}
326	assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
327}
328
329func TestPrebuiltLibrarySanitized(t *testing.T) {
330	bp := `cc_prebuilt_library {
331	name: "libtest",
332		static: {
333                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
334		},
335		shared: {
336                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
337		},
338	}
339	cc_prebuilt_library_static {
340		name: "libtest_static",
341                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
342	}
343	cc_prebuilt_library_shared {
344		name: "libtest_shared",
345                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
346	}`
347
348	fs := map[string][]byte{
349		"libf.a":         nil,
350		"libf.hwasan.a":  nil,
351		"libf.so":        nil,
352		"hwasan/libf.so": nil,
353	}
354
355	// Without SANITIZE_TARGET.
356	ctx := testPrebuilt(t, bp, fs)
357
358	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
359	assertString(t, shared_rule.Input.String(), "libf.so")
360
361	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
362	assertString(t, static.OutputFile().Path().Base(), "libf.a")
363
364	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
365	assertString(t, shared_rule2.Input.String(), "libf.so")
366
367	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
368	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
369
370	// With SANITIZE_TARGET=hwaddress
371	ctx = testPrebuilt(t, bp, fs,
372		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
373			variables.SanitizeDevice = []string{"hwaddress"}
374		}),
375	)
376
377	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
378	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
379
380	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
381	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
382
383	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
384	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
385
386	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
387	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
388}
389
390func TestPrebuiltBinaryNoSrcsNoError(t *testing.T) {
391	const bp = `
392cc_prebuilt_binary {
393	name: "bintest",
394	srcs: [],
395}`
396	ctx := testPrebuilt(t, bp, map[string][]byte{})
397	mod := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
398	android.AssertBoolEquals(t, `expected no srcs to yield no output file`, false, mod.OutputFile().Valid())
399}
400
401func TestPrebuiltBinaryMultipleSrcs(t *testing.T) {
402	const bp = `
403cc_prebuilt_binary {
404	name: "bintest",
405	srcs: ["foo", "bar"],
406}`
407	testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
408}
409
410func TestMultiplePrebuilts(t *testing.T) {
411	bp := `
412		// an rdep
413		cc_library {
414			name: "libfoo",
415			shared_libs: ["libbar"],
416		}
417
418		// multiple variations of dep
419		// source
420		cc_library {
421			name: "libbar",
422		}
423		// prebuilt "v1"
424		cc_prebuilt_library_shared {
425			name: "libbar",
426			srcs: ["libbar.so"],
427		}
428		// prebuilt "v2"
429		cc_prebuilt_library_shared {
430			name: "libbar.v2",
431			stem: "libbar",
432			source_module_name: "libbar",
433			srcs: ["libbar.so"],
434		}
435
436		// selectors
437		apex_contributions {
438			name: "myapex_contributions",
439			contents: ["%v"],
440		}
441		all_apex_contributions {name: "all_apex_contributions"}
442	`
443	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
444		t.Helper()
445		var found bool
446		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
447			if dep == wantDep {
448				found = true
449			}
450		})
451		return found
452	}
453
454	testCases := []struct {
455		desc                   string
456		selectedDependencyName string
457		expectedDependencyName string
458	}{
459		{
460			desc:                   "Source library is selected using apex_contributions",
461			selectedDependencyName: "libbar",
462			expectedDependencyName: "libbar",
463		},
464		{
465			desc:                   "Prebuilt library v1 is selected using apex_contributions",
466			selectedDependencyName: "prebuilt_libbar",
467			expectedDependencyName: "prebuilt_libbar",
468		},
469		{
470			desc:                   "Prebuilt library v2 is selected using apex_contributions",
471			selectedDependencyName: "prebuilt_libbar.v2",
472			expectedDependencyName: "prebuilt_libbar.v2",
473		},
474	}
475
476	for _, tc := range testCases {
477		preparer := android.GroupFixturePreparers(
478			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
479				android.RegisterApexContributionsBuildComponents(ctx)
480			}),
481			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
482		)
483		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
484			"libbar.so": nil,
485			"crtx.o":    nil,
486		}, preparer)
487		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
488		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
489		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
490		// check that LOCAL_SHARED_LIBRARIES contains libbar and not libbar.v<N>
491		entries := android.AndroidMkInfoForTest(t, ctx, libfoo).PrimaryInfo
492		android.AssertStringListContains(t, "Version should not be present in LOCAL_SHARED_LIBRARIES", entries.EntryMap["LOCAL_SHARED_LIBRARIES"], "libbar")
493
494		// check installation rules
495		// the selected soong module should be exported to make
496		libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
497		android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())
498
499		// check LOCAL_MODULE of the selected module name
500		// the prebuilt should have the same LOCAL_MODULE when exported to make
501		entries = android.AndroidMkInfoForTest(t, ctx, libbar).PrimaryInfo
502		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
503	}
504}
505
506// Setting prefer on multiple prebuilts is an error, unless one of them is also listed in apex_contributions
507func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
508	bp := `
509		// an rdep
510		cc_library {
511			name: "libfoo",
512			shared_libs: ["libbar"],
513		}
514
515		// multiple variations of dep
516		// source
517		cc_library {
518			name: "libbar",
519		}
520		// prebuilt "v1"
521		cc_prebuilt_library_shared {
522			name: "libbar",
523			srcs: ["libbar.so"],
524			prefer: true,
525		}
526		// prebuilt "v2"
527		cc_prebuilt_library_shared {
528			name: "libbar.v2",
529			stem: "libbar",
530			source_module_name: "libbar",
531			srcs: ["libbar.so"],
532			prefer: true,
533		}
534
535		// selectors
536		apex_contributions {
537			name: "myapex_contributions",
538			contents: [%v],
539		}
540		all_apex_contributions {name: "all_apex_contributions"}
541	`
542	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
543		t.Helper()
544		var found bool
545		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
546			if dep == wantDep {
547				found = true
548			}
549		})
550		return found
551	}
552
553	testCases := []struct {
554		desc                   string
555		selectedDependencyName string
556		expectedDependencyName string
557		expectedErr            string
558	}{
559		{
560			desc:        "Multiple prebuilts have prefer: true",
561			expectedErr: "Multiple prebuilt modules prebuilt_libbar and prebuilt_libbar.v2 have been marked as preferred for this source module",
562		},
563		{
564			desc:                   "Multiple prebuilts have prefer: true. The prebuilt listed in apex_contributions wins.",
565			selectedDependencyName: `"prebuilt_libbar"`,
566			expectedDependencyName: "prebuilt_libbar",
567		},
568	}
569
570	for _, tc := range testCases {
571		preparer := android.GroupFixturePreparers(
572			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
573				android.RegisterApexContributionsBuildComponents(ctx)
574			}),
575			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
576		)
577		if tc.expectedErr != "" {
578			preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedErr))
579		}
580
581		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
582			"libbar.so": nil,
583			"crtx.o":    nil,
584		}, preparer)
585		if tc.expectedErr != "" {
586			return // the fixture will assert that the excepted err has been raised
587		}
588		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
589		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
590		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
591	}
592}
593
594// If module sdk cannot provide a cc module variant (e.g. static), then the module variant from source should be used
595func TestMissingVariantInModuleSdk(t *testing.T) {
596	bp := `
597		// an rdep
598		cc_library {
599			name: "libfoo",
600			static_libs: ["libbar"],
601		}
602
603		// source
604		cc_library {
605			name: "libbar",
606		}
607		// prebuilt
608		// libbar only exists as a shared library
609		cc_prebuilt_library_shared {
610			name: "libbar",
611			srcs: ["libbar.so"],
612		}
613		// selectors
614		apex_contributions {
615			name: "myapex_contributions",
616			contents: ["prebuilt_libbar"],
617		}
618		all_apex_contributions {name: "all_apex_contributions"}
619	`
620	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
621		t.Helper()
622		var found bool
623		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
624			if dep == wantDep {
625				found = true
626			}
627		})
628		return found
629	}
630
631	preparer := android.GroupFixturePreparers(
632		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
633			android.RegisterApexContributionsBuildComponents(ctx)
634		}),
635		android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
636	)
637	ctx := testPrebuilt(t, bp, map[string][]byte{
638		"libbar.so": nil,
639		"crtx.o":    nil,
640	}, preparer)
641	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
642	sourceLibBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module()
643	// Even though the prebuilt is listed in apex_contributions, the prebuilt does not have a static variant.
644	// Therefore source of libbar should be used.
645	android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true, hasDep(ctx, libfoo, sourceLibBar))
646}
647