1// Copyright (C) 2019 The Android Open Source Project
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 aidl
16
17import (
18	"fmt"
19	"os"
20	"path/filepath"
21	"strings"
22	"testing"
23
24	"github.com/google/blueprint"
25	"github.com/google/blueprint/proptools"
26
27	"android/soong/android"
28	"android/soong/apex"
29	"android/soong/cc"
30	"android/soong/genrule"
31	"android/soong/java"
32	"android/soong/rust"
33)
34
35func TestMain(m *testing.M) {
36	os.Exit(m.Run())
37}
38
39func withFiles(files map[string][]byte) android.FixturePreparer {
40	return android.FixtureMergeMockFs(files)
41}
42
43func intPtr(v int) *int {
44	return &v
45}
46
47func setReleaseEnv() android.FixturePreparer {
48	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
49		// Q is finalized as 29. No codename that is actively being developed.
50		variables.Platform_sdk_version = intPtr(29)
51		variables.Platform_sdk_codename = proptools.StringPtr("REL")
52		variables.Platform_sdk_final = proptools.BoolPtr(true)
53		variables.Platform_version_active_codenames = []string{}
54	})
55}
56
57func _testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) android.FixturePreparer {
58	t.Helper()
59
60	preparers := []android.FixturePreparer{}
61
62	preparers = append(preparers,
63		cc.PrepareForTestWithCcDefaultModules,
64		java.PrepareForTestWithJavaDefaultModules,
65		genrule.PrepareForTestWithGenRuleBuildComponents,
66	)
67
68	bp = bp + `
69		package {
70			default_visibility: ["//visibility:public"],
71		}
72		java_defaults {
73			name: "aidl-java-module-defaults",
74		}
75		cc_defaults {
76			name: "aidl-cpp-module-defaults",
77		}
78		rust_defaults {
79			name: "aidl-rust-module-defaults",
80		}
81		cc_library {
82			name: "libbinder",
83		}
84		cc_library {
85			name: "libutils",
86		}
87		cc_library {
88			name: "libcutils",
89		}
90		cc_library {
91			name: "libbinder_ndk",
92			stubs: {
93				versions: ["29"],
94			}
95		}
96		ndk_library {
97			name: "libbinder_ndk",
98			symbol_file: "libbinder_ndk.map.txt",
99			first_version: "29",
100		}
101		cc_library {
102			name: "liblog",
103			no_libcrt: true,
104			nocrt: true,
105			system_shared_libs: [],
106		}
107		rust_library {
108			name: "libstd",
109			crate_name: "std",
110			srcs: [""],
111			no_stdlibs: true,
112			sysroot: true,
113		}
114		rust_library {
115			name: "libtest",
116			crate_name: "test",
117			srcs: [""],
118			no_stdlibs: true,
119			sysroot: true,
120		}
121		rust_library {
122			name: "liblazy_static",
123			crate_name: "lazy_static",
124			srcs: [""],
125		}
126		rust_library {
127			name: "libbinder_rs",
128			crate_name: "binder",
129			srcs: [""],
130		}
131	`
132
133	preparers = append(preparers, android.FixtureWithRootAndroidBp(bp))
134	preparers = append(preparers, android.FixtureAddTextFile("system/tools/aidl/build/Android.bp", `
135		aidl_interfaces_metadata {
136			name: "aidl_metadata_json",
137			visibility: ["//system/tools/aidl:__subpackages__"],
138		}
139	`))
140
141	preparers = append(preparers, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
142		// To keep tests stable, fix Platform_sdk_codename and Platform_sdk_final
143		// Use setReleaseEnv() to test release version
144		variables.Platform_sdk_version = intPtr(28)
145		variables.Platform_sdk_codename = proptools.StringPtr("Q")
146		variables.Platform_version_active_codenames = []string{"Q"}
147		variables.Platform_sdk_final = proptools.BoolPtr(false)
148	}))
149
150	preparers = append(preparers, customizers...)
151
152	preparers = append(preparers,
153		apex.PrepareForTestWithApexBuildComponents,
154		rust.PrepareForTestWithRustBuildComponents,
155		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
156			ctx.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
157			ctx.RegisterModuleType("aidl_interfaces_metadata", aidlInterfacesMetadataSingletonFactory)
158			ctx.RegisterModuleType("rust_defaults", func() android.Module {
159				return rust.DefaultsFactory()
160			})
161
162			ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
163				ctx.BottomUp("checkImports", checkImports)
164				ctx.TopDown("createAidlInterface", createAidlInterfaceMutator)
165			})
166
167			ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
168				ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
169				ctx.BottomUp("recordVersions", recordVersions).Parallel()
170				ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel()
171			})
172		}),
173	)
174
175	return android.GroupFixturePreparers(preparers...)
176}
177
178func testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) (*android.TestContext, android.Config) {
179	t.Helper()
180	preparer := _testAidl(t, bp, customizers...)
181	result := preparer.RunTest(t)
182	return result.TestContext, result.Config
183}
184
185func testAidlError(t *testing.T, pattern, bp string, customizers ...android.FixturePreparer) {
186	t.Helper()
187	preparer := _testAidl(t, bp, customizers...)
188	preparer.
189		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
190		RunTest(t)
191}
192
193// asserts that there are expected module regardless of variants
194func assertModulesExists(t *testing.T, ctx *android.TestContext, names ...string) {
195	t.Helper()
196	missing := []string{}
197	for _, name := range names {
198		variants := ctx.ModuleVariantsForTests(name)
199		if len(variants) == 0 {
200			missing = append(missing, name)
201		}
202	}
203	if len(missing) > 0 {
204		// find all the modules that do exist
205		allModuleNames := make(map[string]bool)
206		ctx.VisitAllModules(func(m blueprint.Module) {
207			allModuleNames[ctx.ModuleName(m)] = true
208		})
209		t.Errorf("expected modules(%v) not found. all modules: %v", missing, android.SortedStringKeys(allModuleNames))
210	}
211}
212
213func assertContains(t *testing.T, actual, expected string) {
214	t.Helper()
215	if !strings.Contains(actual, expected) {
216		t.Errorf("%q is not found in %q.", expected, actual)
217	}
218}
219
220func assertListContains(t *testing.T, actual []string, expected string) {
221	t.Helper()
222	for _, a := range actual {
223		if strings.Contains(a, expected) {
224			return
225		}
226	}
227	t.Errorf("%q is not found in %v.", expected, actual)
228}
229
230// Vintf module must have versions in release version
231func TestVintfWithoutVersionInRelease(t *testing.T) {
232	vintfWithoutVersionBp := `
233	aidl_interface {
234		name: "foo",
235		stability: "vintf",
236		srcs: [
237			"IFoo.aidl",
238		],
239		backend: {
240			rust: {
241				enabled: true,
242			},
243		},
244	}`
245	expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
246	testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv())
247
248	ctx, _ := testAidl(t, vintfWithoutVersionBp)
249	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
250}
251
252// Check if using unstable version in release cause an error.
253func TestUnstableVersionUsageInRelease(t *testing.T) {
254	unstableVersionUsageInJavaBp := `
255	aidl_interface {
256		name: "foo",
257		versions: [
258			"1",
259		],
260		srcs: [
261			"IFoo.aidl",
262		],
263	}
264	java_library {
265		name: "bar",
266		libs: ["foo-V2-java"],
267	}`
268
269	expectedError := `foo-V2-java is disallowed in release version because it is unstable.`
270	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
271		"aidl_api/foo/1/foo.1.aidl": nil,
272	}))
273
274	testAidl(t, unstableVersionUsageInJavaBp, withFiles(map[string][]byte{
275		"aidl_api/foo/1/foo.1.aidl": nil,
276	}))
277
278	// A stable version can be used in release version
279	stableVersionUsageInJavaBp := `
280	aidl_interface {
281		name: "foo",
282		versions: [
283			"1",
284		],
285		srcs: [
286			"IFoo.aidl",
287		],
288	}
289	java_library {
290		name: "bar",
291		libs: ["foo-V1-java"],
292	}`
293
294	testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
295		"aidl_api/foo/1/foo.1.aidl": nil,
296	}))
297
298	testAidl(t, stableVersionUsageInJavaBp, withFiles(map[string][]byte{
299		"aidl_api/foo/1/foo.1.aidl": nil,
300	}))
301}
302
303// The module which has never been frozen and is not "unstable" is not allowed in release version.
304func TestNonVersionedModuleUsageInRelease(t *testing.T) {
305	nonVersionedModuleUsageInJavaBp := `
306	aidl_interface {
307		name: "foo",
308		srcs: [
309			"IFoo.aidl",
310		],
311	}
312
313	java_library {
314		name: "bar",
315		libs: ["foo-V1-java"],
316	}`
317
318	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
319	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
320	testAidl(t, nonVersionedModuleUsageInJavaBp)
321
322	nonVersionedUnstableModuleUsageInJavaBp := `
323	aidl_interface {
324		name: "foo",
325		srcs: [
326			"IFoo.aidl",
327		],
328		unstable: true,
329	}
330
331	java_library {
332		name: "bar",
333		libs: ["foo-java"],
334	}`
335
336	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv())
337	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp)
338}
339
340func TestImportInRelease(t *testing.T) {
341	importInRelease := `
342	aidl_interface {
343		name: "foo",
344		srcs: [
345			"IFoo.aidl",
346		],
347		imports: ["bar"],
348		versions: ["1"],
349	}
350
351	aidl_interface {
352		name: "bar",
353		srcs: [
354			"IBar.aidl",
355		],
356		versions: ["1"],
357	}
358	`
359
360	testAidl(t, importInRelease, setReleaseEnv(), withFiles(map[string][]byte{
361		"aidl_api/foo/1/foo.1.aidl": nil,
362		"aidl_api/foo/1/.hash":      nil,
363		"aidl_api/bar/1/bar.1.aidl": nil,
364		"aidl_api/bar/1/.hash":      nil,
365	}))
366}
367
368func TestUnstableVersionedModuleUsageInRelease(t *testing.T) {
369	nonVersionedModuleUsageInJavaBp := `
370	aidl_interface {
371		name: "foo",
372		srcs: [
373			"IFoo.aidl",
374		],
375		versions: ["1"],
376	}
377
378	java_library {
379		name: "bar",
380		libs: ["foo-V2-java"],
381	}`
382
383	expectedError := `Android.bp:10:2: module \"bar\" variant \"android_common\": foo-V2-java is disallowed in release version because it is unstable, and its \"owner\" property is missing.`
384	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
385	testAidl(t, nonVersionedModuleUsageInJavaBp, withFiles(map[string][]byte{
386		"aidl_api/foo/1/foo.1.aidl": nil,
387	}))
388}
389
390func TestUnstableModules(t *testing.T) {
391	testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, `
392		aidl_interface {
393			name: "foo",
394			stability: "vintf",
395			unstable: true,
396			srcs: [
397				"IFoo.aidl",
398			],
399			backend: {
400				rust: {
401					enabled: true,
402				},
403			},
404		}
405	`)
406
407	testAidlError(t, `module "foo_interface": versions: cannot have versions for an unstable interface`, `
408		aidl_interface {
409			name: "foo",
410			versions: [
411				"1",
412			],
413			unstable: true,
414			srcs: [
415				"IFoo.aidl",
416			],
417			backend: {
418				rust: {
419					enabled: true,
420				},
421			},
422		}
423	`)
424
425	ctx, _ := testAidl(t, `
426		aidl_interface {
427			name: "foo",
428			unstable: true,
429			srcs: [
430				"IFoo.aidl",
431			],
432			backend: {
433				rust: {
434					enabled: true,
435				},
436			},
437		}
438	`)
439
440	assertModulesExists(t, ctx, "foo-java", "foo-rust", "foo-cpp", "foo-ndk", "foo-ndk_platform")
441}
442
443func TestCreatesModulesWithNoVersions(t *testing.T) {
444	ctx, _ := testAidl(t, `
445		aidl_interface {
446			name: "foo",
447			srcs: [
448				"IFoo.aidl",
449			],
450			backend: {
451				rust: {
452					enabled: true,
453				},
454			},
455		}
456	`)
457
458	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
459}
460
461func TestCreatesModulesWithFrozenVersions(t *testing.T) {
462	// Each version should be under aidl_api/<name>/<ver>
463	testAidlError(t, `aidl_api/foo/1`, `
464		aidl_interface {
465			name: "foo",
466			srcs: [
467				"IFoo.aidl",
468			],
469			versions: [
470				"1",
471			],
472			backend: {
473				rust: {
474					enabled: true,
475				},
476			},
477		}
478	`)
479
480	ctx, _ := testAidl(t, `
481		aidl_interface {
482			name: "foo",
483			srcs: [
484				"IFoo.aidl",
485			],
486			versions: [
487				"1",
488			],
489			backend: {
490				rust: {
491					enabled: true,
492				},
493			},
494		}
495	`, withFiles(map[string][]byte{
496		"aidl_api/foo/1/foo.1.aidl": nil,
497	}))
498
499	// For frozen version "1"
500	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
501
502	// For ToT (current)
503	assertModulesExists(t, ctx, "foo-V2-java", "foo-V2-rust", "foo-V2-cpp", "foo-V2-ndk", "foo-V2-ndk_platform")
504}
505
506func TestErrorsWithUnsortedVersions(t *testing.T) {
507	testAidlError(t, `versions: should be sorted`, `
508		aidl_interface {
509			name: "foo",
510			srcs: [
511				"IFoo.aidl",
512			],
513			versions: [
514				"2",
515				"1",
516			],
517			backend: {
518				rust: {
519					enabled: true,
520				},
521			},
522		}
523	`)
524}
525
526func TestErrorsWithDuplicateVersions(t *testing.T) {
527	testAidlError(t, `versions: duplicate`, `
528		aidl_interface {
529			name: "foo",
530			srcs: [
531				"IFoo.aidl",
532			],
533			versions: [
534				"1",
535				"1",
536			],
537		}
538	`)
539}
540
541func TestErrorsWithNonPositiveVersions(t *testing.T) {
542	testAidlError(t, `versions: should be > 0`, `
543		aidl_interface {
544			name: "foo",
545			srcs: [
546				"IFoo.aidl",
547			],
548			versions: [
549				"-1",
550				"1",
551			],
552		}
553	`)
554}
555
556func TestErrorsWithNonIntegerVersions(t *testing.T) {
557	testAidlError(t, `versions: "first" is not an integer`, `
558		aidl_interface {
559			name: "foo",
560			srcs: [
561				"IFoo.aidl",
562			],
563			versions: [
564				"first",
565			],
566		}
567	`)
568}
569
570const (
571	androidVariant    = "android_common"
572	nativeVariant     = "android_arm_armv7-a-neon_shared"
573	nativeRustVariant = "android_arm_armv7-a-neon_dylib"
574)
575
576func TestNativeOutputIsAlwaysVersioned(t *testing.T) {
577	var ctx *android.TestContext
578	assertOutput := func(moduleName, variant, outputFilename string) {
579		t.Helper()
580		producer, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
581		if !ok {
582			t.Errorf("%s(%s): should be OutputFileProducer.", moduleName, variant)
583		}
584		paths, err := producer.OutputFiles("")
585		if err != nil {
586			t.Errorf("%s(%s): failed to get OutputFiles: %v", moduleName, variant, err)
587		}
588		if len(paths) != 1 || paths[0].Base() != outputFilename {
589			t.Errorf("%s(%s): expected output %q, but got %v", moduleName, variant, outputFilename, paths)
590		}
591	}
592
593	// No versions
594	ctx, _ = testAidl(t, `
595		aidl_interface {
596			name: "foo",
597			srcs: [
598				"IFoo.aidl",
599			],
600			backend: {
601				rust: {
602					enabled: true,
603				},
604			},
605		}
606	`)
607	// Even though there is no version, generated modules have version(V1) unless it isn't an unstable interface.
608	assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar")
609
610	assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so")
611	assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so")
612
613	// With versions: "1", "2"
614	ctx, _ = testAidl(t, `
615		aidl_interface {
616			name: "foo",
617			srcs: [
618				"IFoo.aidl",
619			],
620			versions: [
621				"1", "2",
622			],
623			backend: {
624				rust: {
625					enabled: true,
626				},
627			},
628		}
629	`, withFiles(map[string][]byte{
630		"aidl_api/foo/1/foo.1.aidl": nil,
631		"aidl_api/foo/2/foo.2.aidl": nil,
632	}))
633
634	// alias for the latest frozen version (=2)
635	assertOutput("foo-V2-java", androidVariant, "foo-V2-java.jar")
636	assertOutput("foo-V2-cpp", nativeVariant, "foo-V2-cpp.so")
637	assertOutput("foo-V2-rust", nativeRustVariant, "libfoo_V2.dylib.so")
638
639	// frozen "1"
640	assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar")
641	assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so")
642	assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so")
643
644	// tot
645	assertOutput("foo-V3-java", androidVariant, "foo-V3-java.jar")
646	assertOutput("foo-V3-cpp", nativeVariant, "foo-V3-cpp.so")
647	assertOutput("foo-V3-rust", nativeRustVariant, "libfoo_V3.dylib.so")
648
649	// skip ndk/ndk_platform since they follow the same rule with cpp
650}
651
652func TestImports(t *testing.T) {
653	testAidlError(t, `Import does not exist:`, `
654		aidl_interface {
655			name: "foo",
656			srcs: [
657				"IFoo.aidl",
658			],
659			imports: [
660				"bar",
661			]
662		}
663	`)
664
665	testAidlError(t, `backend.java.enabled: Java backend not enabled in the imported AIDL interface "bar"`, `
666		aidl_interface {
667			name: "foo",
668			srcs: [
669				"IFoo.aidl",
670			],
671			imports: [
672				"bar",
673			]
674		}
675		aidl_interface {
676			name: "bar",
677			srcs: [
678				"IBar.aidl",
679			],
680			backend: {
681				java: {
682					enabled: false,
683				},
684			},
685		}
686	`)
687
688	testAidlError(t, `backend.cpp.enabled: C\+\+ backend not enabled in the imported AIDL interface "bar"`, `
689		aidl_interface {
690			name: "foo",
691			srcs: [
692				"IFoo.aidl",
693			],
694			imports: [
695				"bar",
696			]
697		}
698		aidl_interface {
699			name: "bar",
700			srcs: [
701				"IBar.aidl",
702			],
703			backend: {
704				cpp: {
705					enabled: false,
706				},
707			},
708		}
709	`)
710
711	ctx, _ := testAidl(t, `
712		aidl_interface {
713			name: "foo",
714			srcs: [
715				"IFoo.aidl",
716			],
717			backend: {
718				rust: {
719					enabled: true,
720				},
721			},
722			imports: [
723				"bar.1",
724			]
725		}
726		aidl_interface {
727			name: "bar.1",
728			srcs: [
729				"IBar.aidl",
730			],
731			backend: {
732				rust: {
733					enabled: true,
734				},
735			},
736		}
737	`)
738
739	ldRule := ctx.ModuleForTests("foo-V1-cpp", nativeVariant).Rule("ld")
740	libFlags := ldRule.Args["libFlags"]
741	libBar := filepath.Join("bar.1-V1-cpp", nativeVariant, "bar.1-V1-cpp.so")
742	if !strings.Contains(libFlags, libBar) {
743		t.Errorf("%q is not found in %q", libBar, libFlags)
744	}
745
746	rustcRule := ctx.ModuleForTests("foo-V1-rust", nativeRustVariant).Rule("rustc")
747	libFlags = rustcRule.Args["libFlags"]
748	libBar = filepath.Join("out", "soong", ".intermediates", "bar.1-V1-rust", nativeRustVariant, "libbar_1_V1.dylib.so")
749	libBarFlag := "--extern bar_1=" + libBar
750	if !strings.Contains(libFlags, libBarFlag) {
751		t.Errorf("%q is not found in %q", libBarFlag, libFlags)
752	}
753}
754
755func TestDuplicatedVersions(t *testing.T) {
756	// foo depends on myiface-V2-ndk via direct dep and also on
757	// myiface-V1-ndk via indirect dep. This should be prohibited.
758	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, `
759		aidl_interface {
760			name: "myiface",
761			srcs: ["IFoo.aidl"],
762			versions: ["1", "2"],
763		}
764
765		cc_library {
766			name: "foo",
767			shared_libs: ["myiface-V2-ndk", "bar"],
768		}
769
770		cc_library {
771			name: "bar",
772			shared_libs: ["myiface-V1-ndk"],
773		}
774
775	`, withFiles(map[string][]byte{
776		"aidl_api/myiface/1/myiface.1.aidl": nil,
777		"aidl_api/myiface/1/.hash":          nil,
778		"aidl_api/myiface/2/myiface.2.aidl": nil,
779		"aidl_api/myiface/2/.hash":          nil,
780	}))
781	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, `
782		aidl_interface {
783			name: "myiface",
784			srcs: ["IFoo.aidl"],
785			versions: ["1"],
786		}
787
788		aidl_interface {
789			name: "myiface2",
790			srcs: ["IBar.aidl"],
791			imports: ["myiface"]
792		}
793
794		cc_library {
795			name: "foobar",
796			shared_libs: ["myiface-V1-ndk", "myiface2-V1-ndk"],
797		}
798
799	`, withFiles(map[string][]byte{
800		"aidl_api/myiface/1/myiface.1.aidl": nil,
801		"aidl_api/myiface/1/.hash":          nil,
802	}))
803	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk-source, myiface-V2-ndk`, `
804		aidl_interface {
805			name: "myiface",
806			srcs: ["IFoo.aidl"],
807			versions: ["1"],
808			backend: {
809				ndk: {
810					srcs_available: true,
811				},
812			},
813		}
814
815		aidl_interface {
816			name: "myiface2",
817			srcs: ["IBar.aidl"],
818			imports: ["myiface"]
819		}
820
821		cc_library {
822			name: "foobar",
823			srcs: [":myiface-V1-ndk-source"],
824			shared_libs: ["myiface2-V1-ndk"],
825		}
826
827	`, withFiles(map[string][]byte{
828		"aidl_api/myiface/1/myiface.1.aidl": nil,
829		"aidl_api/myiface/1/.hash":          nil,
830	}))
831	testAidl(t, `
832		aidl_interface {
833			name: "myiface",
834			srcs: ["IFoo.aidl"],
835			versions: ["1"],
836			backend: {
837				ndk: {
838					srcs_available: true,
839				},
840			},
841		}
842
843		aidl_interface {
844			name: "myiface2",
845			srcs: ["IBar.aidl"],
846			imports: ["myiface"]
847		}
848
849		cc_library {
850			name: "foobar",
851			srcs: [":myiface-V2-ndk-source"],
852			shared_libs: ["myiface2-V1-ndk"],
853		}
854
855	`, withFiles(map[string][]byte{
856		"aidl_api/myiface/1/myiface.1.aidl": nil,
857		"aidl_api/myiface/1/.hash":          nil,
858	}))
859	testAidl(t, `
860		aidl_interface {
861			name: "myiface",
862			srcs: ["IFoo.aidl"],
863			versions: ["1"],
864		}
865
866		aidl_interface {
867			name: "myiface2",
868			srcs: ["IBar.aidl"],
869			imports: ["myiface"]
870		}
871
872		cc_library {
873			name: "foobar",
874			shared_libs: ["myiface-V2-ndk", "myiface2-V1-ndk"],
875		}
876
877	`, withFiles(map[string][]byte{
878		"aidl_api/myiface/1/myiface.1.aidl": nil,
879		"aidl_api/myiface/1/.hash":          nil,
880	}))
881}
882
883func TestUnstableVndkModule(t *testing.T) {
884	testAidlError(t, `module "myiface_interface": stability: must be "vintf" if the module is for VNDK.`, `
885		aidl_interface {
886			name: "myiface",
887			srcs: ["IFoo.aidl"],
888			vendor_available: true,
889			product_available: true,
890			unstable: true,
891			vndk: {
892				enabled: true,
893			},
894		}
895	`)
896	testAidlError(t, `module "myiface_interface": stability: must be "vintf" if the module is for VNDK.`, `
897		aidl_interface {
898			name: "myiface",
899			vendor_available: true,
900			product_available: true,
901			srcs: ["IFoo.aidl"],
902			vndk: {
903				enabled: true,
904			},
905		}
906	`)
907	testAidl(t, `
908		aidl_interface {
909			name: "myiface",
910			vendor_available: true,
911			product_available: true,
912			srcs: ["IFoo.aidl"],
913			stability: "vintf",
914			vndk: {
915				enabled: true,
916			},
917		}
918	`)
919}
920
921func TestCcModuleWithApexNameMacro(t *testing.T) {
922	ctx, _ := testAidl(t, `
923		aidl_interface {
924			name: "myiface",
925			srcs: ["IFoo.aidl"],
926			backend: {
927				ndk: {
928					apex_available: ["myapex"],
929				},
930			},
931		}
932		apex {
933			name: "myapex",
934			key: "myapex.key",
935			native_shared_libs: ["myiface-V1-ndk_platform"],
936			updatable: false,
937		}
938		apex_key {
939			name: "myapex.key",
940			public_key: "testkey.avbpubkey",
941			private_key: "testkey.pem",
942		}
943	`, withFiles(map[string][]byte{
944		"system/sepolicy/apex/myapex-file_contexts": nil,
945	}))
946
947	ccRule := ctx.ModuleForTests("myiface-V1-ndk_platform", "android_arm64_armv8-a_static_myapex").Rule("cc")
948	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX__")
949	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_NAME__='\"myapex\"'")
950	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_MYAPEX__")
951}
952
953func TestSrcsAvailable(t *testing.T) {
954	bp := `
955		aidl_interface {
956			name: "myiface",
957			srcs: ["IFoo.aidl"],
958			backend: {
959				java: {
960					srcs_available: %s,
961				},
962				cpp: {
963					srcs_available: %s,
964				},
965			},
966		}
967	`
968	customizer := withFiles(map[string][]byte{
969		"otherpackage/Android.bp": []byte(`
970			java_library {
971				name: "javalib",
972				srcs: [":myiface-V1-java-source"],
973			}
974			cc_library_shared {
975				name: "cclib",
976				srcs: [":myiface-V1-cpp-source"],
977			}
978		`),
979	})
980	ctx, _ := testAidl(t, fmt.Sprintf(bp, "true", "true"), customizer)
981	javaInputs := ctx.ModuleForTests("javalib", "android_common").Rule("javac").Inputs.Strings()
982	assertListContains(t, javaInputs, "myiface-V1-java-source/gen/IFoo.java")
983	ccInput := ctx.ModuleForTests("cclib", "android_arm64_armv8-a_shared").Rule("cc").Input.String()
984	assertContains(t, ccInput, "myiface-V1-cpp-source/gen/IFoo.cpp")
985
986	testAidlError(t, `depends on //.:myiface-V1-java-source which is not visible to this module`,
987		fmt.Sprintf(bp, "false", "true"), customizer)
988	testAidlError(t, `depends on //.:myiface-V1-cpp-source which is not visible to this module`,
989		fmt.Sprintf(bp, "true", "false"), customizer)
990}
991
992func TestRustDuplicateNames(t *testing.T) {
993	testAidl(t, `
994		aidl_interface {
995			name: "myiface",
996			srcs: ["dir/a/Foo.aidl", "dir/b/Foo.aidl"],
997			backend: {
998				rust: {
999					enabled: true,
1000				},
1001			},
1002		}
1003	`)
1004}
1005
1006func TestAidlImportFlagsForIncludeDirs(t *testing.T) {
1007	customizer := withFiles(map[string][]byte{
1008		"foo/Android.bp": []byte(`
1009			aidl_interface {
1010				name: "foo-iface",
1011				local_include_dir: "src",
1012				include_dirs: [
1013						"path1",
1014						"path2/sub",
1015				],
1016				srcs: [
1017						"src/foo/Foo.aidl",
1018				],
1019				imports: [
1020						"bar-iface",
1021				],
1022				versions: ["1", "2"],
1023			}
1024			aidl_interface {
1025				name: "bar-iface",
1026				local_include_dir: "src",
1027				srcs: [
1028						"src/bar/Bar.aidl",
1029				],
1030			}
1031		`),
1032		"foo/src/foo/Foo.aidl":                        nil,
1033		"foo/src/bar/Bar.aidl":                        nil,
1034		"foo/aidl_api/foo-iface/current/foo/Foo.aidl": nil,
1035		"foo/aidl_api/foo-iface/1/foo/Foo.aidl":       nil,
1036		"foo/aidl_api/foo-iface/1/.hash":              nil,
1037		"foo/aidl_api/foo-iface/2/foo/Foo.aidl":       nil,
1038		"foo/aidl_api/foo-iface/2/.hash":              nil,
1039	})
1040	ctx, _ := testAidl(t, ``, customizer)
1041
1042	// compile for older version
1043	{
1044		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp")
1045		imports := strings.Split(rule.Args["imports"], " ")
1046		android.AssertArrayString(t, "should import foo/1(target) and bar/current(imported)", []string{
1047			"-Ifoo/aidl_api/foo-iface/1",
1048			"-Ipath1",
1049			"-Ipath2/sub",
1050			"-Ifoo/aidl_api/bar-iface/current",
1051		}, imports)
1052	}
1053	// compile for tot version
1054	{
1055		rule := ctx.ModuleForTests("foo-iface-V3-cpp-source", "").Output("foo/Foo.cpp")
1056		imports := strings.Split(rule.Args["imports"], " ")
1057		android.AssertArrayString(t, "aidlCompile should import ToT", []string{
1058			"-Ifoo/src",
1059			"-Ipath1",
1060			"-Ipath2/sub",
1061			"-Ifoo/src",
1062		}, imports)
1063	}
1064}
1065
1066func TestSupportsGenruleAndFilegroup(t *testing.T) {
1067	customizer := withFiles(map[string][]byte{
1068		"foo/Android.bp": []byte(`
1069			aidl_interface {
1070				name: "foo-iface",
1071				local_include_dir: "src",
1072				include_dirs: [
1073						"path1",
1074						"path2/sub",
1075				],
1076				srcs: [
1077						"src/foo/Foo.aidl",
1078						":filegroup1",
1079						":gen1",
1080				],
1081				imports: [
1082						"bar-iface",
1083				],
1084				versions: ["1"],
1085			}
1086			filegroup {
1087				name: "filegroup1",
1088				path: "filegroup/sub",
1089				srcs: [
1090						"filegroup/sub/pkg/Bar.aidl",
1091				],
1092			}
1093			genrule {
1094				name: "gen1",
1095				cmd: "generate baz/Baz.aidl",
1096				out: [
1097					"baz/Baz.aidl",
1098				]
1099			}
1100			aidl_interface {
1101				name: "bar-iface",
1102				local_include_dir: "src",
1103				srcs: [
1104						"src/bar/Bar.aidl",
1105				],
1106			}
1107		`),
1108		"foo/aidl_api/foo-iface/1/foo/Foo.aidl": nil,
1109		"foo/aidl_api/foo-iface/1/.hash":        nil,
1110		"foo/filegroup/sub/pkg/Bar.aidl":        nil,
1111		"foo/src/foo/Foo.aidl":                  nil,
1112	})
1113	ctx, _ := testAidl(t, ``, customizer)
1114
1115	// aidlCompile for snapshots (v1)
1116	{
1117		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp")
1118		imports := strings.Split(rule.Args["imports"], " ")
1119		android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{
1120			"-Ifoo/aidl_api/foo-iface/1",
1121			"-Ipath1",
1122			"-Ipath2/sub",
1123			"-Ifoo/aidl_api/bar-iface/current",
1124		}, imports)
1125	}
1126	// aidlCompile for ToT (v2)
1127	{
1128		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("foo/Foo.cpp")
1129		imports := strings.Split(rule.Args["imports"], " ")
1130		android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{
1131			"-Ifoo/src",
1132			"-Ifoo/filegroup/sub",
1133			"-Iout/soong/.intermediates/foo/gen1/gen",
1134			"-Ipath1",
1135			"-Ipath2/sub",
1136			"-Ifoo/src",
1137		}, imports)
1138	}
1139
1140	// dumpapi
1141	{
1142		rule := ctx.ModuleForTests("foo-iface-api", "").Rule("aidlDumpApiRule")
1143		android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump srcs/filegroups/genrules", []string{
1144			"foo/src/foo/Foo.aidl",
1145			"foo/filegroup/sub/pkg/Bar.aidl",
1146			"out/soong/.intermediates/foo/gen1/gen/baz/Baz.aidl",
1147		}, rule.Inputs)
1148
1149		dumpDir := "out/soong/.intermediates/foo/foo-iface-api/dump"
1150		android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump with rel paths", []string{
1151			dumpDir + "/foo/Foo.aidl",
1152			dumpDir + "/pkg/Bar.aidl",
1153			dumpDir + "/baz/Baz.aidl",
1154			dumpDir + "/.hash",
1155		}, rule.Outputs.Paths())
1156
1157		imports := strings.Split(rule.Args["imports"], " ")
1158		android.AssertArrayString(t, "dumpapi should import filegroup/genrule as well", []string{
1159			// these are from foo-iface.srcs
1160			"-Ifoo/src",
1161			"-Ifoo/filegroup/sub",
1162			"-Iout/soong/.intermediates/foo/gen1/gen",
1163
1164			// this is from bar-iface.srcs
1165			"-Ifoo/src",
1166
1167			// this is from foo-iface.Local_include_dir
1168			"-Ifoo/src",
1169
1170			// these are from foo-iface.include_dirs
1171			"-Ipath1",
1172			"-Ipath2/sub",
1173		}, imports)
1174	}
1175}
1176
1177func TestAidlFlags(t *testing.T) {
1178	ctx, _ := testAidl(t, `
1179		aidl_interface {
1180			name: "myiface",
1181			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1182			flags: ["-Weverything", "-Werror"],
1183			backend: { rust: { enabled: true }}
1184		}
1185	`)
1186	for module, outputs := range map[string][]string{
1187		"myiface-V1-cpp-source":  {"a/Foo.h", "b/Bar.h"},
1188		"myiface-V1-java-source": {"a/Foo.java", "b/Bar.java"},
1189		"myiface-V1-ndk-source":  {"aidl/a/Foo.h", "aidl/b/Bar.h"},
1190		"myiface-V1-rust-source": {"a/Foo.rs", "b/Bar.rs"},
1191	} {
1192		for _, output := range outputs {
1193			t.Run(module+"/"+output, func(t *testing.T) {
1194				params := ctx.ModuleForTests(module, "").Output(output)
1195				assertContains(t, params.Args["optionalFlags"], "-Weverything")
1196				assertContains(t, params.Args["optionalFlags"], "-Werror")
1197			})
1198		}
1199	}
1200}
1201
1202func TestAidlModuleNameContainsVersion(t *testing.T) {
1203	testAidlError(t, "aidl_interface should not have '-V<number> suffix", `
1204		aidl_interface {
1205			name: "myiface-V2",
1206			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1207		}
1208	`)
1209	// Ugly, but okay
1210	testAidl(t, `
1211		aidl_interface {
1212			name: "myiface-V2aa",
1213			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1214		}
1215	`)
1216}
1217
1218func TestExplicitAidlModuleImport(t *testing.T) {
1219	for _, importVersion := range []string{"V1", "V2"} {
1220
1221		ctx, _ := testAidl(t, `
1222			aidl_interface {
1223				name: "foo",
1224				srcs: ["Foo.aidl"],
1225				versions: [
1226					"1",
1227				],
1228				imports: ["bar-`+importVersion+`"]
1229			}
1230
1231			aidl_interface {
1232				name: "bar",
1233				srcs: ["Bar.aidl"],
1234				versions: [
1235					"1",
1236				],
1237			}
1238		`, withFiles(map[string][]byte{
1239			"aidl_api/foo/1/Foo.aidl": nil,
1240			"aidl_api/foo/1/.hash":    nil,
1241			"aidl_api/bar/1/Bar.aidl": nil,
1242			"aidl_api/bar/1/.hash":    nil,
1243		}))
1244		for _, foo := range []string{"foo-V1-cpp", "foo-V2-cpp"} {
1245			ldRule := ctx.ModuleForTests(foo, nativeVariant).Rule("ld")
1246			libFlags := ldRule.Args["libFlags"]
1247			libBar := filepath.Join("bar-"+importVersion+"-cpp", nativeVariant, "bar-"+importVersion+"-cpp.so")
1248			if !strings.Contains(libFlags, libBar) {
1249				t.Errorf("%q is not found in %q", libBar, libFlags)
1250			}
1251
1252		}
1253	}
1254
1255	testAidlError(t, "module \"foo_interface\": imports: \"foo\" depends on \"bar\" version \"3\"", `
1256		aidl_interface {
1257			name: "foo",
1258			srcs: ["Foo.aidl"],
1259			versions: [
1260				"1",
1261			],
1262			imports: ["bar-V3"]
1263		}
1264
1265		aidl_interface {
1266			name: "bar",
1267			srcs: ["Bar.aidl"],
1268			versions: [
1269				"1",
1270			],
1271		}
1272	`, withFiles(map[string][]byte{
1273		"aidl_api/foo/1/Foo.aidl": nil,
1274		"aidl_api/foo/1/.hash":    nil,
1275		"aidl_api/bar/1/Bar.aidl": nil,
1276		"aidl_api/bar/1/.hash":    nil,
1277	}))
1278}
1279