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/aidl_library"
28	"android/soong/android"
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		variables.Release_aidl_use_unfrozen = proptools.BoolPtr(false)
50	})
51}
52
53func setTestFreezeEnv() android.FixturePreparer {
54	return android.FixtureMergeEnv(map[string]string{
55		"AIDL_FROZEN_REL":    "true",
56		"AIDL_FROZEN_OWNERS": "aosp test",
57	})
58}
59
60func setUseUnfrozenOverrideEnvTrue() android.FixturePreparer {
61	return android.FixtureMergeEnv(map[string]string{
62		"AIDL_USE_UNFROZEN_OVERRIDE": "true",
63	})
64}
65
66func setUseUnfrozenOverrideEnvFalse() android.FixturePreparer {
67	return android.FixtureMergeEnv(map[string]string{
68		"AIDL_USE_UNFROZEN_OVERRIDE": "false",
69	})
70}
71
72func setTransitiveFreezeEnv() android.FixturePreparer {
73	return android.FixtureMergeEnv(map[string]string{
74		"AIDL_TRANSITIVE_FREEZE": "true",
75	})
76}
77
78func _testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) android.FixturePreparer {
79	t.Helper()
80
81	preparers := []android.FixturePreparer{}
82
83	preparers = append(preparers,
84		cc.PrepareForTestWithCcDefaultModules,
85		java.PrepareForTestWithJavaDefaultModules,
86		genrule.PrepareForTestWithGenRuleBuildComponents,
87		android.PrepareForTestWithNamespace,
88	)
89
90	bp = bp + `
91		package {
92			default_visibility: ["//visibility:public"],
93		}
94		java_defaults {
95			name: "aidl-java-module-defaults",
96		}
97		cc_defaults {
98			name: "aidl-cpp-module-defaults",
99		}
100		rust_defaults {
101			name: "aidl-rust-module-defaults",
102		}
103		cc_library {
104			name: "libbinder",
105			recovery_available: true,
106		}
107		cc_library_static {
108			name: "aidl-analyzer-main",
109			host_supported: true,
110			vendor_available: true,
111			recovery_available: true,
112		}
113		cc_library {
114			name: "libutils",
115			recovery_available: true,
116		}
117		cc_library {
118			name: "libcutils",
119			recovery_available: true,
120		}
121		cc_library {
122			name: "libbinder_ndk",
123			recovery_available: true,
124			stubs: {
125				versions: ["29"],
126			}
127		}
128		ndk_library {
129			name: "libbinder_ndk",
130			symbol_file: "libbinder_ndk.map.txt",
131			first_version: "29",
132		}
133		cc_library {
134			name: "liblog",
135			no_libcrt: true,
136			nocrt: true,
137			system_shared_libs: [],
138		}
139		rust_library {
140			name: "libstd",
141			crate_name: "std",
142			srcs: [""],
143			no_stdlibs: true,
144			sysroot: true,
145		}
146		rust_library {
147			name: "libtest",
148			crate_name: "test",
149			srcs: [""],
150			no_stdlibs: true,
151			sysroot: true,
152		}
153		rust_library {
154			name: "libbinder_rs",
155			crate_name: "binder",
156			srcs: [""],
157		}
158		rust_library {
159			name: "libstatic_assertions",
160			crate_name: "static_assertions",
161			srcs: [""],
162		}
163		rust_proc_macro {
164			name: "libasync_trait",
165			crate_name: "async_trait",
166			srcs: [""],
167			no_stdlibs: true,
168		}
169	`
170	preparers = append(preparers, android.FixtureWithRootAndroidBp(bp))
171	preparers = append(preparers, android.FixtureAddTextFile("system/tools/aidl/build/Android.bp", `
172		aidl_interfaces_metadata {
173			name: "aidl_metadata_json",
174			visibility: ["//system/tools/aidl:__subpackages__"],
175		}
176	`))
177
178	preparers = append(preparers, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
179		variables.Release_aidl_use_unfrozen = proptools.BoolPtr(true)
180	}))
181
182	preparers = append(preparers, customizers...)
183
184	preparers = append(preparers,
185		rust.PrepareForTestWithRustBuildComponents,
186		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
187			ctx.RegisterModuleType("aidl_interface", AidlInterfaceFactory)
188			ctx.RegisterModuleType("aidl_interface_defaults", AidlInterfaceDefaultsFactory)
189			ctx.RegisterModuleType("aidl_interfaces_metadata", aidlInterfacesMetadataSingletonFactory)
190			ctx.RegisterModuleType("rust_defaults", func() android.Module {
191				return rust.DefaultsFactory()
192			})
193			ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
194
195			ctx.PreArchMutators(registerPreArchMutators)
196			ctx.PostDepsMutators(registerPostDepsMutators)
197		}),
198	)
199
200	return android.GroupFixturePreparers(preparers...)
201}
202
203func testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) (*android.TestContext, android.Config) {
204	t.Helper()
205	preparer := _testAidl(t, bp, customizers...)
206	result := preparer.RunTest(t)
207	return result.TestContext, result.Config
208}
209
210func testAidlError(t *testing.T, pattern, bp string, customizers ...android.FixturePreparer) {
211	t.Helper()
212	preparer := _testAidl(t, bp, customizers...)
213	preparer.
214		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
215		RunTest(t)
216}
217
218// asserts that there are expected module regardless of variants
219func assertModulesExists(t *testing.T, ctx *android.TestContext, names ...string) {
220	t.Helper()
221	missing := []string{}
222	for _, name := range names {
223		variants := ctx.ModuleVariantsForTests(name)
224		if len(variants) == 0 {
225			missing = append(missing, name)
226		}
227	}
228	if len(missing) > 0 {
229		// find all the modules that do exist
230		allModuleNames := make(map[string]bool)
231		ctx.VisitAllModules(func(m blueprint.Module) {
232			allModuleNames[ctx.ModuleName(m)] = true
233		})
234		t.Errorf("expected modules(%v) not found. all modules: %v", missing, android.SortedKeys(allModuleNames))
235	}
236}
237
238func assertContains(t *testing.T, actual, expected string) {
239	t.Helper()
240	if !strings.Contains(actual, expected) {
241		t.Errorf("%q is not found in %q.", expected, actual)
242	}
243}
244
245func assertListContains(t *testing.T, actual []string, expected string) {
246	t.Helper()
247	for _, a := range actual {
248		if strings.Contains(a, expected) {
249			return
250		}
251	}
252	t.Errorf("%q is not found in %v.", expected, actual)
253}
254
255// Vintf module must have versions in release version
256func TestVintfWithoutVersionInRelease(t *testing.T) {
257	vintfWithoutVersionBp := `
258	aidl_interface {
259		name: "foo",
260		stability: "vintf",
261		srcs: [
262			"IFoo.aidl",
263		],
264		owner: "test",
265		backend: {
266			rust: {
267				enabled: true,
268			},
269		},
270	}`
271	expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) because`
272	testAidlError(t, expectedError, vintfWithoutVersionBp, setTestFreezeEnv())
273
274	ctx, _ := testAidl(t, vintfWithoutVersionBp, setReleaseEnv())
275	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
276	ctx, _ = testAidl(t, vintfWithoutVersionBp)
277	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
278}
279
280// Check if using unstable version in release cause an error.
281func TestUnstableVersionUsageInRelease(t *testing.T) {
282	unstableVersionUsageInJavaBp := `
283	aidl_interface {
284		name: "foo",
285		versions: [
286			"1",
287		],
288		srcs: [
289			"IFoo.aidl",
290		],
291	}
292	java_library {
293		name: "bar",
294		libs: ["foo-V2-java"],
295	}`
296	files := withFiles(map[string][]byte{
297		"aidl_api/foo/1/foo.1.aidl": nil,
298		"aidl_api/foo/1/.hash":      nil,
299	})
300
301	expectedError := `foo-V2-java is an unfrozen development version, and it can't be used because`
302	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
303	testAidl(t, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
304	testAidl(t, unstableVersionUsageInJavaBp, files)
305
306	// A stable version can be used in release version
307	stableVersionUsageInJavaBp := `
308	aidl_interface {
309		name: "foo",
310		versions: [
311			"1",
312		],
313		srcs: [
314			"IFoo.aidl",
315		],
316	}
317	java_library {
318		name: "bar",
319		libs: ["foo-V1-java"],
320	}`
321
322	testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), files)
323	testAidl(t, stableVersionUsageInJavaBp, setTestFreezeEnv(), files)
324	testAidl(t, stableVersionUsageInJavaBp, files)
325}
326
327func TestUsingUnstableVersionIndirectlyInRelease(t *testing.T) {
328	unstableVersionUsageInJavaBp := `
329	aidl_interface {
330		name: "xxx",
331		srcs: ["IFoo.aidl"],
332		versions: ["1"],
333	}
334	aidl_interface {
335		name: "foo",
336		imports: ["xxx-V2"],    // not OK
337		versions: ["1"],
338		srcs: ["IFoo.aidl"],
339	}
340	java_library {
341		name: "bar",
342		libs: ["foo-V1-java"],  // OK
343	}`
344	files := withFiles(map[string][]byte{
345		"aidl_api/foo/1/foo.1.aidl": nil,
346		"aidl_api/foo/1/.hash":      nil,
347		"aidl_api/xxx/1/foo.1.aidl": nil,
348		"aidl_api/xxx/1/.hash":      nil,
349	})
350
351	expectedError := `xxx-V2-java is an unfrozen development version`
352	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
353	testAidl(t, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
354	testAidl(t, unstableVersionUsageInJavaBp, files)
355}
356
357func TestFrozenTrueSimple(t *testing.T) {
358	frozenTest := `
359	aidl_interface {
360		name: "foo",
361		versions: ["1"],
362		frozen: true,
363		srcs: ["IFoo.aidl"],
364	}`
365	files := withFiles(map[string][]byte{
366		"aidl_api/foo/1/foo.1.aidl": nil,
367		"aidl_api/foo/1/.hash":      nil,
368	})
369
370	testAidl(t, frozenTest, files, setReleaseEnv())
371	testAidl(t, frozenTest, files, setTestFreezeEnv())
372	testAidl(t, frozenTest, files)
373}
374
375func TestFrozenWithNoVersions(t *testing.T) {
376	frozenTest := `
377	aidl_interface {
378		name: "foo",
379		frozen: true,
380		srcs: ["IFoo.aidl"],
381	}`
382	files := withFiles(map[string][]byte{
383		"aidl_api/foo/1/foo.1.aidl": nil,
384		"aidl_api/foo/1/.hash":      nil,
385	})
386
387	expectedError := `cannot be frozen without versions`
388	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
389	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
390	testAidlError(t, expectedError, frozenTest, files)
391}
392
393func TestFrozenImportingFrozen(t *testing.T) {
394	frozenTest := `
395	aidl_interface {
396		name: "xxx",
397		srcs: ["IFoo.aidl"],
398		frozen: true,
399		versions: ["1"],
400	}
401	aidl_interface {
402		name: "foo",
403		imports: ["xxx-V1"],
404		versions: ["1"],
405		frozen: true,
406		srcs: ["IFoo.aidl"],
407	}`
408	files := withFiles(map[string][]byte{
409		"aidl_api/foo/1/foo.1.aidl": nil,
410		"aidl_api/foo/1/.hash":      nil,
411		"aidl_api/xxx/1/foo.1.aidl": nil,
412		"aidl_api/xxx/1/.hash":      nil,
413	})
414
415	testAidl(t, frozenTest, files, setReleaseEnv())
416	testAidl(t, frozenTest, files, setTestFreezeEnv())
417	testAidl(t, frozenTest, files)
418}
419
420func TestFrozenImportingVersionUnfrozen(t *testing.T) {
421	frozenTest := `
422	aidl_interface {
423		name: "xxx",
424		srcs: ["IFoo.aidl"],
425		frozen: false,
426		versions: ["1"],
427	}
428	aidl_interface {
429		name: "foo",
430		imports: ["xxx-V1"],
431		versions: ["1"],
432		frozen: true,
433		srcs: ["IFoo.aidl"],
434	}`
435	files := withFiles(map[string][]byte{
436		"aidl_api/foo/1/foo.1.aidl": nil,
437		"aidl_api/foo/1/.hash":      nil,
438		"aidl_api/xxx/1/foo.1.aidl": nil,
439		"aidl_api/xxx/1/.hash":      nil,
440	})
441
442	testAidl(t, frozenTest, files, setReleaseEnv())
443	testAidl(t, frozenTest, files, setTestFreezeEnv())
444	testAidl(t, frozenTest, files)
445}
446
447func TestFrozenImportingUnfrozenWithFrozen(t *testing.T) {
448	frozenTest := `
449	aidl_interface {
450		name: "xxx",
451		srcs: ["IFoo.aidl"],
452		frozen: false,
453		versions: ["1"],
454	}
455	aidl_interface {
456		name: "foo",
457		imports: ["xxx"],
458		versions: ["1"],
459		frozen: true,
460		srcs: ["IFoo.aidl"],
461	}`
462	files := withFiles(map[string][]byte{
463		"aidl_api/foo/1/foo.1.aidl": nil,
464		"aidl_api/foo/1/.hash":      nil,
465		"aidl_api/xxx/1/foo.1.aidl": nil,
466		"aidl_api/xxx/1/.hash":      nil,
467	})
468
469	expectedError := `"foo" imports "xxx" which is not frozen. Either "foo" must`
470	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
471	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
472	testAidlError(t, expectedError, frozenTest, files)
473}
474
475func TestFrozenImportingUnfrozen(t *testing.T) {
476	frozenTest := `
477	aidl_interface {
478		name: "xxx",
479		srcs: ["IFoo.aidl"],
480		owner: "test",
481		frozen: false,
482	}
483	aidl_interface {
484		name: "foo",
485		imports: ["xxx"],
486		versions: ["1"],
487		frozen: true,
488		srcs: ["IFoo.aidl"],
489	}`
490	files := withFiles(map[string][]byte{
491		"aidl_api/foo/1/foo.1.aidl": nil,
492		"aidl_api/foo/1/.hash":      nil,
493		"aidl_api/xxx/1/foo.1.aidl": nil,
494		"aidl_api/xxx/1/.hash":      nil,
495	})
496
497	expectedError := `versions: must be set \(need to be frozen\) because`
498	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
499
500	expectedError = `"foo" imports "xxx" which is not frozen. Either "foo" must`
501	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
502	testAidlError(t, expectedError, frozenTest, files)
503}
504
505// This is allowed to keep legacy behavior. It could be prevented directly after API-freeze
506// if all frozen interfaces are explicitly marked `frozen: true,`.
507func TestFrozenImportingUnSpecified(t *testing.T) {
508	frozenTrueSimple := `
509	aidl_interface {
510		name: "xxx",
511		srcs: ["IFoo.aidl"],
512		versions: ["1"],
513	}
514	aidl_interface {
515		name: "foo",
516		imports: ["xxx-V1"],
517		versions: ["1"],
518		frozen: true,
519		srcs: ["IFoo.aidl"],
520	}`
521	files := withFiles(map[string][]byte{
522		"aidl_api/foo/1/foo.1.aidl": nil,
523		"aidl_api/foo/1/.hash":      nil,
524		"aidl_api/xxx/1/foo.1.aidl": nil,
525		"aidl_api/xxx/1/.hash":      nil,
526	})
527
528	testAidl(t, frozenTrueSimple, files, setReleaseEnv())
529	testAidl(t, frozenTrueSimple, files, setTestFreezeEnv())
530	testAidl(t, frozenTrueSimple, files)
531}
532
533// Keeping legacy behavior if "frozen" is not specified
534func TestImportingNewLegacy(t *testing.T) {
535	frozenTest := `
536	aidl_interface {
537		name: "xxx",
538		srcs: ["IFoo.aidl"],
539		versions: ["1"],
540	}
541	aidl_interface {
542		name: "foo",
543		imports: ["xxx-V2"],
544		versions_with_info: [
545			{version: "1", imports: ["xxx-V1"]},
546		],
547		srcs: ["IFoo.aidl"],
548	}`
549	files := withFiles(map[string][]byte{
550		"aidl_api/foo/1/foo.1.aidl": nil,
551		"aidl_api/foo/1/.hash":      nil,
552		"aidl_api/xxx/1/foo.1.aidl": nil,
553		"aidl_api/xxx/1/.hash":      nil,
554	})
555
556	testAidl(t, frozenTest, files, setReleaseEnv())
557	testAidl(t, frozenTest, files, setTestFreezeEnv())
558	testAidl(t, frozenTest, files)
559}
560
561// We don't have a way to know if if "xxx" has changes to it and will
562// need a new version without the "frozen" attribute. So we keep the
563// legacy behavior and assume "foo" is still importing the old version.
564func TestFrozenImportingNewLegacy(t *testing.T) {
565	frozenTest := `
566	aidl_interface {
567		name: "xxx",
568		srcs: ["IFoo.aidl"],
569		versions: ["1"],
570	}
571	aidl_interface {
572		name: "foo",
573		imports: ["xxx-V1"],
574		frozen: true,
575		versions_with_info: [
576			{version: "1", imports: ["xxx-V1"]},
577		],
578		srcs: ["IFoo.aidl"],
579	}`
580	files := withFiles(map[string][]byte{
581		"aidl_api/foo/1/foo.1.aidl": nil,
582		"aidl_api/foo/1/.hash":      nil,
583		"aidl_api/xxx/1/foo.1.aidl": nil,
584		"aidl_api/xxx/1/.hash":      nil,
585	})
586
587	testAidl(t, frozenTest, files, setReleaseEnv())
588	testAidl(t, frozenTest, files, setTestFreezeEnv())
589	testAidl(t, frozenTest, files)
590}
591
592func TestFrozenImportingNewImplicit(t *testing.T) {
593	frozenTest := `
594	aidl_interface {
595		name: "xxx",
596		srcs: ["IFoo.aidl"],
597		frozen: false,
598		versions: ["1"],
599	}
600	aidl_interface {
601		name: "foo",
602		imports: ["xxx"],
603		frozen: true,
604		versions_with_info: [
605			{version: "1", imports: ["xxx-V1"]},
606		],
607		srcs: ["IFoo.aidl"],
608	}`
609	files := withFiles(map[string][]byte{
610		"aidl_api/foo/1/foo.1.aidl": nil,
611		"aidl_api/foo/1/.hash":      nil,
612		"aidl_api/xxx/1/foo.1.aidl": nil,
613		"aidl_api/xxx/1/.hash":      nil,
614	})
615
616	expectedError := `"foo" imports "xxx" which is not frozen. Either "foo" must`
617	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
618	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
619	testAidlError(t, expectedError, frozenTest, files)
620}
621
622func TestImportingOwned(t *testing.T) {
623	frozenTest := `
624	aidl_interface {
625		name: "xxx",
626		srcs: ["IFoo.aidl"],
627		owner: "unknown-owner",
628		frozen: false,
629	}
630	aidl_interface {
631		name: "foo",
632		imports: ["xxx-V1"],
633		frozen: false,
634		versions_with_info: [
635			{version: "1", imports: []},
636		],
637		srcs: ["IFoo.aidl"],
638	}`
639	files := withFiles(map[string][]byte{
640		"aidl_api/foo/1/foo.1.aidl": nil,
641		"aidl_api/foo/1/.hash":      nil,
642	})
643
644	expectedError := "Android.bp:10:10: module \"foo_interface\": imports: \"foo\" imports \"xxx\" which is an interface owned by \"unknown-owner\". This is not allowed because the owned interface will not be frozen at the same time."
645	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
646	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
647	testAidlError(t, expectedError, frozenTest, files)
648}
649
650func TestImportingOwnedBothOwned(t *testing.T) {
651	frozenTest := `
652	aidl_interface {
653		name: "xxx",
654		srcs: ["IFoo.aidl"],
655		owner: "unknown-owner",
656		frozen: false,
657	}
658	aidl_interface {
659		name: "foo",
660		imports: ["xxx-V1"],
661		frozen: false,
662		versions_with_info: [
663			{version: "1", imports: []},
664		],
665		srcs: ["IFoo.aidl"],
666		owner: "unknown-owner-any",
667	}`
668	files := withFiles(map[string][]byte{
669		"aidl_api/foo/1/foo.1.aidl": nil,
670		"aidl_api/foo/1/.hash":      nil,
671	})
672
673	testAidl(t, frozenTest, files, setReleaseEnv())
674	testAidl(t, frozenTest, files, setTestFreezeEnv())
675	testAidl(t, frozenTest, files)
676}
677
678func TestFrozenImportingNewExplicit(t *testing.T) {
679	frozenTest := `
680	aidl_interface {
681		name: "xxx",
682		srcs: ["IFoo.aidl"],
683		frozen: false,
684		versions: ["1"],
685	}
686	aidl_interface {
687		name: "foo",
688		imports: ["xxx-V2"],
689		frozen: true,
690		versions_with_info: [
691			{version: "1", imports: ["xxx-V1"]},
692		],
693		srcs: ["IFoo.aidl"],
694	}`
695	files := withFiles(map[string][]byte{
696		"aidl_api/foo/1/foo.1.aidl": nil,
697		"aidl_api/foo/1/.hash":      nil,
698		"aidl_api/xxx/1/foo.1.aidl": nil,
699		"aidl_api/xxx/1/.hash":      nil,
700	})
701
702	expectedError := "This interface is 'frozen: true' but the imports have changed. Set 'frozen: false' to allow changes: \\n Version current imports: map\\[xxx:2\\]\\n Version 1 imports: map\\[xxx:1\\]\\n"
703	testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
704	testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
705	testAidlError(t, expectedError, frozenTest, files)
706}
707
708func TestNonFrozenImportingNewImplicit(t *testing.T) {
709	frozenTest := `
710	aidl_interface {
711		name: "xxx",
712		srcs: ["IFoo.aidl"],
713		frozen: false,
714		versions: ["1"],
715	}
716	aidl_interface {
717		name: "foo",
718		imports: ["xxx-V1"],
719		frozen: false,
720		versions_with_info: [
721			{version: "1", imports: ["xxx-V1"]},
722		],
723		srcs: ["IFoo.aidl"],
724	}`
725	files := withFiles(map[string][]byte{
726		"aidl_api/foo/1/foo.1.aidl": nil,
727		"aidl_api/foo/1/.hash":      nil,
728		"aidl_api/xxx/1/foo.1.aidl": nil,
729		"aidl_api/xxx/1/.hash":      nil,
730	})
731
732	testAidl(t, frozenTest, files, setReleaseEnv())
733	testAidl(t, frozenTest, files, setTestFreezeEnv())
734	testAidl(t, frozenTest, files)
735}
736
737// The module which has never been frozen and is not "unstable" is not allowed in release version.
738func TestNonVersionedModuleUsageInRelease(t *testing.T) {
739	nonVersionedModuleUsageInJavaBp := `
740	aidl_interface {
741		name: "foo",
742		srcs: [
743			"IFoo.aidl",
744		],
745		owner: "test",
746	}
747
748	java_library {
749		name: "bar",
750		libs: ["foo-V1-java"],
751	}`
752
753	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) because`
754	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
755	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
756	testAidl(t, nonVersionedModuleUsageInJavaBp)
757
758	nonVersionedUnstableModuleUsageInJavaBp := `
759	aidl_interface {
760		name: "foo",
761		srcs: [
762			"IFoo.aidl",
763		],
764		unstable: true,
765	}
766
767	java_library {
768		name: "bar",
769		libs: ["foo-java"],
770	}`
771
772	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv())
773	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setTestFreezeEnv())
774	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp)
775}
776
777func TestNonVersionedModuleOwnedByTestUsageInRelease(t *testing.T) {
778	nonVersionedModuleUsageInJavaBp := `
779	aidl_interface {
780		name: "foo",
781		owner: "test",
782		srcs: [
783			"IFoo.aidl",
784		],
785	}
786
787	java_library {
788		name: "bar",
789		libs: ["foo-V1-java"],
790	}`
791
792	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) because`
793	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
794	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
795	testAidl(t, nonVersionedModuleUsageInJavaBp)
796}
797
798func TestNonVersionedModuleOwnedByOtherUsageInRelease(t *testing.T) {
799	nonVersionedModuleUsageInJavaBp := `
800	aidl_interface {
801		name: "foo",
802		owner: "unknown-owner",
803		srcs: [
804			"IFoo.aidl",
805		],
806	}
807
808	java_library {
809		name: "bar",
810		libs: ["foo-V1-java"],
811	}`
812
813	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
814	testAidl(t, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
815	testAidl(t, nonVersionedModuleUsageInJavaBp)
816}
817
818func TestImportInRelease(t *testing.T) {
819	importInRelease := `
820	aidl_interface {
821		name: "foo",
822		srcs: [
823			"IFoo.aidl",
824		],
825		imports: ["bar-V1"],
826		versions: ["1"],
827	}
828
829	aidl_interface {
830		name: "bar",
831		srcs: [
832			"IBar.aidl",
833		],
834		versions: ["1"],
835	}
836	`
837	files := withFiles(map[string][]byte{
838		"aidl_api/foo/1/foo.1.aidl": nil,
839		"aidl_api/foo/1/.hash":      nil,
840		"aidl_api/bar/1/bar.1.aidl": nil,
841		"aidl_api/bar/1/.hash":      nil,
842	})
843
844	testAidl(t, importInRelease, setReleaseEnv(), files)
845	testAidl(t, importInRelease, setTestFreezeEnv(), files)
846	testAidl(t, importInRelease, files)
847}
848
849func TestUnstableVersionedModuleUsageInRelease(t *testing.T) {
850	nonVersionedModuleUsageInJavaBp := `
851	aidl_interface {
852		name: "foo",
853		srcs: [
854			"IFoo.aidl",
855		],
856		versions: ["1"],
857	}
858
859	java_library {
860		name: "bar",
861		libs: ["foo-V2-java"],
862	}`
863
864	expectedError := `module \"bar\" variant \"android_common\": foo-V2-java is an unfrozen development version`
865	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
866	testAidl(t, nonVersionedModuleUsageInJavaBp, withFiles(map[string][]byte{
867		"aidl_api/foo/1/foo.1.aidl": nil,
868		"aidl_api/foo/1/.hash":      nil,
869	}), setReleaseEnv())
870	testAidl(t, nonVersionedModuleUsageInJavaBp, withFiles(map[string][]byte{
871		"aidl_api/foo/1/foo.1.aidl": nil,
872		"aidl_api/foo/1/.hash":      nil,
873	}))
874}
875
876func TestUnstableVersionedModuleOwnedByTestUsageInRelease(t *testing.T) {
877	nonVersionedModuleUsageInJavaBp := `
878	aidl_interface {
879		name: "foo",
880		owner: "test",
881		srcs: [
882			"IFoo.aidl",
883		],
884		versions: ["1"],
885	}
886
887	java_library {
888		name: "bar",
889		libs: ["foo-V2-java"],
890	}`
891	files := withFiles(map[string][]byte{
892		"aidl_api/foo/1/foo.1.aidl": nil,
893		"aidl_api/foo/1/.hash":      nil,
894	})
895
896	expectedError := `Android.bp:11:2: module \"bar\" variant \"android_common\": foo-V2-java is an unfrozen development version`
897	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv(), files)
898	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv(), files)
899	testAidl(t, nonVersionedModuleUsageInJavaBp, files)
900}
901
902func TestFrozenModuleUsageInAllEnvs(t *testing.T) {
903	bp := `
904	aidl_interface {
905		name: "foo",
906        frozen: true,
907		srcs: [
908			"IFoo.aidl",
909		],
910		versions: ["1"],
911	}
912
913	java_library {
914		name: "bar",
915		libs: ["foo-V2-java"],
916	}`
917	files := withFiles(map[string][]byte{
918		"aidl_api/foo/1/foo.1.aidl": nil,
919		"aidl_api/foo/1/.hash":      nil,
920	})
921
922	expectedError := `Android.bp:11:2: module \"bar\" variant \"android_common\": foo-V2-java is an unfrozen development version`
923	testAidlError(t, expectedError, bp, setReleaseEnv(), files)
924	testAidlError(t, expectedError, bp, setTestFreezeEnv(), files)
925	testAidlError(t, expectedError, bp, files)
926}
927
928func TestUnstableVersionedModuleOwnedByOtherUsageInRelease(t *testing.T) {
929	nonVersionedModuleUsageInJavaBp := `
930	aidl_interface {
931		name: "foo",
932		owner: "unknown-owner",
933		srcs: [
934			"IFoo.aidl",
935		],
936		versions: ["1"],
937	}
938
939	java_library {
940		name: "bar",
941		libs: ["foo-V2-java"],
942	}`
943	files := withFiles(map[string][]byte{
944		"aidl_api/foo/1/foo.1.aidl": nil,
945		"aidl_api/foo/1/.hash":      nil,
946	})
947
948	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv(), files)
949	testAidl(t, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv(), files)
950	testAidl(t, nonVersionedModuleUsageInJavaBp, files)
951}
952
953func TestUnstableModules(t *testing.T) {
954	testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, `
955		aidl_interface {
956			name: "foo",
957			stability: "vintf",
958			unstable: true,
959			srcs: [
960				"IFoo.aidl",
961			],
962			backend: {
963				rust: {
964					enabled: true,
965				},
966			},
967		}
968	`)
969
970	testAidlError(t, `module "foo_interface": versions: cannot have versions for an unstable interface`, `
971		aidl_interface {
972			name: "foo",
973			versions: [
974				"1",
975			],
976			unstable: true,
977			srcs: [
978				"IFoo.aidl",
979			],
980			backend: {
981				rust: {
982					enabled: true,
983				},
984			},
985		}
986	`)
987
988	ctx, _ := testAidl(t, `
989		aidl_interface {
990			name: "foo",
991			unstable: true,
992			srcs: [
993				"IFoo.aidl",
994			],
995			backend: {
996				rust: {
997					enabled: true,
998				},
999			},
1000		}
1001	`)
1002
1003	assertModulesExists(t, ctx, "foo-java", "foo-rust", "foo-cpp", "foo-ndk")
1004}
1005
1006func TestCreatesModulesWithNoVersions(t *testing.T) {
1007	ctx, _ := testAidl(t, `
1008		aidl_interface {
1009			name: "foo",
1010			srcs: [
1011				"IFoo.aidl",
1012			],
1013			backend: {
1014				rust: {
1015					enabled: true,
1016				},
1017			},
1018		}
1019	`)
1020
1021	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
1022}
1023
1024func TestCreatesModulesWithFrozenVersions(t *testing.T) {
1025	// Each version should be under aidl_api/<name>/<ver>
1026	testAidlError(t, `No sources for a previous version in aidl_api/foo/1. Was a version manually added to .bp file?`, `
1027		aidl_interface {
1028			name: "foo",
1029			srcs: [
1030				"IFoo.aidl",
1031			],
1032			versions: [
1033				"1",
1034			],
1035			backend: {
1036				rust: {
1037					enabled: true,
1038				},
1039			},
1040		}
1041	`)
1042
1043	ctx, _ := testAidl(t, `
1044		aidl_interface {
1045			name: "foo",
1046			srcs: [
1047				"IFoo.aidl",
1048			],
1049			versions: [
1050				"1",
1051			],
1052			backend: {
1053				rust: {
1054					enabled: true,
1055				},
1056			},
1057		}
1058	`, withFiles(map[string][]byte{
1059		"aidl_api/foo/1/foo.1.aidl": nil,
1060		"aidl_api/foo/1/.hash":      nil,
1061	}))
1062
1063	// For frozen version "1"
1064	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
1065
1066	// For ToT (current)
1067	assertModulesExists(t, ctx, "foo-V2-java", "foo-V2-rust", "foo-V2-cpp", "foo-V2-ndk")
1068}
1069
1070func TestErrorsWithUnsortedVersions(t *testing.T) {
1071	testAidlError(t, `versions: should be sorted`, `
1072		aidl_interface {
1073			name: "foo",
1074			srcs: [
1075				"IFoo.aidl",
1076			],
1077			versions: [
1078				"2",
1079				"1",
1080			],
1081			backend: {
1082				rust: {
1083					enabled: true,
1084				},
1085			},
1086		}
1087	`)
1088}
1089
1090func TestErrorsWithDuplicateVersions(t *testing.T) {
1091	testAidlError(t, `versions: duplicate`, `
1092		aidl_interface {
1093			name: "foo",
1094			srcs: [
1095				"IFoo.aidl",
1096			],
1097			versions: [
1098				"1",
1099				"1",
1100			],
1101		}
1102	`)
1103}
1104
1105func TestErrorsWithNonPositiveVersions(t *testing.T) {
1106	testAidlError(t, `versions: should be > 0`, `
1107		aidl_interface {
1108			name: "foo",
1109			srcs: [
1110				"IFoo.aidl",
1111			],
1112			versions: [
1113				"-1",
1114				"1",
1115			],
1116		}
1117	`)
1118}
1119
1120func TestErrorsWithNonIntegerVersions(t *testing.T) {
1121	testAidlError(t, `versions: "first" is not an integer`, `
1122		aidl_interface {
1123			name: "foo",
1124			srcs: [
1125				"IFoo.aidl",
1126			],
1127			versions: [
1128				"first",
1129			],
1130		}
1131	`)
1132}
1133
1134const (
1135	androidVariant    = "android_common"
1136	nativeVariant     = "android_arm_armv7-a-neon_shared"
1137	nativeRustVariant = "android_arm_armv7-a-neon_dylib"
1138)
1139
1140func TestNativeOutputIsAlwaysVersioned(t *testing.T) {
1141	var ctx *android.TestContext
1142	assertOutput := func(moduleName, variant, outputFilename string) {
1143		t.Helper()
1144		paths := ctx.ModuleForTests(moduleName, variant).OutputFiles(ctx, t, "")
1145		if len(paths) != 1 || paths[0].Base() != outputFilename {
1146			t.Errorf("%s(%s): expected output %q, but got %v", moduleName, variant, outputFilename, paths)
1147		}
1148	}
1149
1150	// No versions
1151	ctx, _ = testAidl(t, `
1152		aidl_interface {
1153			name: "foo",
1154			srcs: [
1155				"IFoo.aidl",
1156			],
1157			backend: {
1158				rust: {
1159					enabled: true,
1160				},
1161			},
1162		}
1163	`)
1164	// Even though there is no version, generated modules have version(V1) unless it isn't an unstable interface.
1165	assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar")
1166
1167	assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so")
1168	assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so")
1169
1170	// With versions: "1", "2"
1171	ctx, _ = testAidl(t, `
1172		aidl_interface {
1173			name: "foo",
1174			srcs: [
1175				"IFoo.aidl",
1176			],
1177			versions: [
1178				"1", "2",
1179			],
1180			backend: {
1181				rust: {
1182					enabled: true,
1183				},
1184			},
1185		}
1186	`, withFiles(map[string][]byte{
1187		"aidl_api/foo/1/foo.1.aidl": nil,
1188		"aidl_api/foo/1/.hash":      nil,
1189		"aidl_api/foo/2/foo.2.aidl": nil,
1190		"aidl_api/foo/2/.hash":      nil,
1191	}))
1192
1193	// alias for the latest frozen version (=2)
1194	assertOutput("foo-V2-java", androidVariant, "foo-V2-java.jar")
1195	assertOutput("foo-V2-cpp", nativeVariant, "foo-V2-cpp.so")
1196	assertOutput("foo-V2-rust", nativeRustVariant, "libfoo_V2.dylib.so")
1197
1198	// frozen "1"
1199	assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar")
1200	assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so")
1201	assertOutput("foo-V1-rust", nativeRustVariant, "libfoo_V1.dylib.so")
1202
1203	// tot
1204	assertOutput("foo-V3-java", androidVariant, "foo-V3-java.jar")
1205	assertOutput("foo-V3-cpp", nativeVariant, "foo-V3-cpp.so")
1206	assertOutput("foo-V3-rust", nativeRustVariant, "libfoo_V3.dylib.so")
1207
1208	// skip ndk since they follow the same rule with cpp
1209}
1210
1211func TestImports(t *testing.T) {
1212	testAidlError(t, `Import does not exist:`, `
1213		aidl_interface {
1214			name: "foo",
1215			srcs: [
1216				"IFoo.aidl",
1217			],
1218			imports: [
1219				"bar",
1220			]
1221		}
1222	`)
1223
1224	testAidlError(t, `backend.java.enabled: Java backend not enabled in the imported AIDL interface "bar"`, `
1225		aidl_interface {
1226			name: "foo",
1227			srcs: [
1228				"IFoo.aidl",
1229			],
1230			imports: [
1231				"bar-V1",
1232			]
1233		}
1234		aidl_interface {
1235			name: "bar",
1236			srcs: [
1237				"IBar.aidl",
1238			],
1239			backend: {
1240				java: {
1241					enabled: false,
1242				},
1243			},
1244		}
1245	`)
1246
1247	testAidlError(t, `backend.cpp.enabled: C\+\+ backend not enabled in the imported AIDL interface "bar"`, `
1248		aidl_interface {
1249			name: "foo",
1250			srcs: [
1251				"IFoo.aidl",
1252			],
1253			imports: [
1254				"bar-V1",
1255			]
1256		}
1257		aidl_interface {
1258			name: "bar",
1259			srcs: [
1260				"IBar.aidl",
1261			],
1262			backend: {
1263				cpp: {
1264					enabled: false,
1265				},
1266			},
1267		}
1268	`)
1269
1270	testAidlError(t, `imports: "foo" depends on "bar" but does not specify a version`, `
1271		aidl_interface {
1272			name: "foo",
1273            unstable: true,
1274			srcs: [
1275				"IFoo.aidl",
1276			],
1277			imports: [
1278				"bar",
1279			]
1280		}
1281		aidl_interface {
1282			name: "bar",
1283			srcs: [
1284				"IBar.aidl",
1285			],
1286		}
1287	`)
1288
1289	ctx, _ := testAidl(t, `
1290		aidl_interface_defaults {
1291			name: "foo-defaults",
1292			srcs: [
1293				"IFoo.aidl",
1294			],
1295			backend: {
1296				rust: {
1297					enabled: true,
1298				},
1299			},
1300			imports: [
1301				"bar.1-V1",
1302			]
1303		}
1304		aidl_interface {
1305			name: "foo",
1306			defaults: ["foo-defaults"],
1307		}
1308		aidl_interface {
1309			name: "bar.1",
1310			srcs: [
1311				"IBar.aidl",
1312			],
1313			backend: {
1314				rust: {
1315					enabled: true,
1316				},
1317			},
1318		}
1319	`)
1320
1321	ldRule := ctx.ModuleForTests("foo-V1-cpp", nativeVariant).Rule("ld")
1322	libFlags := ldRule.Args["libFlags"]
1323	libBar := filepath.Join("bar.1-V1-cpp", nativeVariant, "bar.1-V1-cpp.so")
1324	if !strings.Contains(libFlags, libBar) {
1325		t.Errorf("%q is not found in %q", libBar, libFlags)
1326	}
1327
1328	rustcRule := ctx.ModuleForTests("foo-V1-rust", nativeRustVariant).Rule("rustc")
1329	libFlags = rustcRule.Args["libFlags"]
1330	libBar = filepath.Join("out", "soong", ".intermediates", "bar.1-V1-rust", nativeRustVariant, "unstripped", "libbar_1_V1.dylib.so")
1331	libBarFlag := "--extern bar_1=" + libBar
1332	if !strings.Contains(libFlags, libBarFlag) {
1333		t.Errorf("%q is not found in %q", libBarFlag, libFlags)
1334	}
1335}
1336
1337func TestDuplicatedVersions(t *testing.T) {
1338	// foo depends on myiface-V2-ndk via direct dep and also on
1339	// myiface-V1-ndk via indirect dep. This should be prohibited.
1340	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
1341		aidl_interface {
1342			name: "myiface",
1343			srcs: ["IFoo.aidl"],
1344			versions: ["1", "2"],
1345		}
1346
1347		cc_library {
1348			name: "foo",
1349			shared_libs: ["myiface-V2-ndk", "bar"],
1350		}
1351
1352		cc_library {
1353			name: "bar",
1354			shared_libs: ["myiface-V1-ndk"],
1355		}
1356
1357	`, withFiles(map[string][]byte{
1358		"aidl_api/myiface/1/myiface.1.aidl": nil,
1359		"aidl_api/myiface/1/.hash":          nil,
1360		"aidl_api/myiface/2/myiface.2.aidl": nil,
1361		"aidl_api/myiface/2/.hash":          nil,
1362	}))
1363	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
1364		aidl_interface {
1365			name: "myiface",
1366			srcs: ["IFoo.aidl"],
1367			versions: ["1"],
1368		}
1369
1370		aidl_interface {
1371			name: "myiface2",
1372			srcs: ["IBar.aidl"],
1373			imports: ["myiface-V2"]
1374		}
1375
1376		cc_library {
1377			name: "foobar",
1378			shared_libs: ["myiface-V1-ndk", "myiface2-V1-ndk"],
1379		}
1380
1381	`, withFiles(map[string][]byte{
1382		"aidl_api/myiface/1/myiface.1.aidl": nil,
1383		"aidl_api/myiface/1/.hash":          nil,
1384	}))
1385	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
1386		aidl_interface {
1387			name: "myiface",
1388			srcs: ["IFoo.aidl"],
1389			versions: ["1"],
1390		}
1391
1392		aidl_interface {
1393			name: "myiface2",
1394			srcs: ["IBar.aidl"],
1395			imports: ["myiface-V2"]
1396		}
1397
1398		cc_library {
1399			name: "foobar",
1400			srcs: [":myiface-V1-ndk-source"],
1401			shared_libs: ["myiface2-V1-ndk"],
1402		}
1403
1404	`, withFiles(map[string][]byte{
1405		"aidl_api/myiface/1/myiface.1.aidl": nil,
1406		"aidl_api/myiface/1/.hash":          nil,
1407	}))
1408	// Okay to reference two different
1409	testAidl(t, `
1410		aidl_interface {
1411			name: "myiface",
1412			srcs: ["IFoo.aidl"],
1413			versions: ["1"],
1414		}
1415		cc_library {
1416			name: "foobar",
1417			shared_libs: ["myiface-V1-cpp", "myiface-V1-ndk"],
1418		}
1419	`, withFiles(map[string][]byte{
1420		"aidl_api/myiface/1/myiface.1.aidl": nil,
1421		"aidl_api/myiface/1/.hash":          nil,
1422	}))
1423	testAidl(t, `
1424		aidl_interface {
1425			name: "myiface",
1426			srcs: ["IFoo.aidl"],
1427			versions: ["1"],
1428		}
1429
1430		aidl_interface {
1431			name: "myiface2",
1432			srcs: ["IBar.aidl"],
1433			imports: ["myiface-V2"]
1434		}
1435
1436		cc_library {
1437			name: "foobar",
1438			srcs: [":myiface-V2-ndk-source"],
1439			shared_libs: ["myiface2-V1-ndk"],
1440		}
1441
1442	`, withFiles(map[string][]byte{
1443		"aidl_api/myiface/1/myiface.1.aidl": nil,
1444		"aidl_api/myiface/1/.hash":          nil,
1445	}))
1446	testAidl(t, `
1447		aidl_interface {
1448			name: "myiface",
1449			srcs: ["IFoo.aidl"],
1450			versions: ["1"],
1451		}
1452
1453		aidl_interface {
1454			name: "myiface2",
1455			srcs: ["IBar.aidl"],
1456			imports: ["myiface-V2"]
1457		}
1458
1459		cc_library {
1460			name: "foobar",
1461			shared_libs: ["myiface-V2-ndk", "myiface2-V1-ndk"],
1462		}
1463
1464	`, withFiles(map[string][]byte{
1465		"aidl_api/myiface/1/myiface.1.aidl": nil,
1466		"aidl_api/myiface/1/.hash":          nil,
1467	}))
1468}
1469
1470func TestRecoveryAvailable(t *testing.T) {
1471	ctx, _ := testAidl(t, `
1472		aidl_interface {
1473			name: "myiface",
1474			recovery_available: true,
1475			srcs: ["IFoo.aidl"],
1476		}
1477	`)
1478	ctx.ModuleForTests("myiface-V1-ndk", "android_recovery_arm64_armv8-a_shared")
1479	ctx.ModuleForTests("myiface-V1-cpp", "android_recovery_arm64_armv8-a_shared")
1480}
1481
1482func TestRustDuplicateNames(t *testing.T) {
1483	testAidl(t, `
1484		aidl_interface {
1485			name: "myiface",
1486			srcs: ["dir/a/Foo.aidl", "dir/b/Foo.aidl"],
1487			backend: {
1488				rust: {
1489					enabled: true,
1490				},
1491			},
1492		}
1493	`)
1494}
1495
1496func TestAidlImportFlagsForImportedModules(t *testing.T) {
1497	customizer := withFiles(map[string][]byte{
1498		"foo/Android.bp": []byte(`
1499			aidl_interface {
1500				name: "foo-iface",
1501				srcs: ["a/Foo.aidl"],
1502				imports: ["bar-iface-V2"],
1503				versions: ["1"],
1504				headers: ["boq-iface-headers"],
1505			}
1506		`),
1507		"foo/a/Foo.aidl": nil,
1508		"foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
1509		"foo/aidl_api/foo-iface/1/a/Foo.aidl":       nil,
1510		"foo/aidl_api/foo-iface/1/.hash":            nil,
1511
1512		"bar/Android.bp": []byte(`
1513			aidl_interface {
1514				name: "bar-iface",
1515				srcs: ["b/Bar.aidl"],
1516				imports: ["baz-iface-V1"],
1517				versions: ["1"],
1518			}
1519		`),
1520		"bar/b/Bar.aidl": nil,
1521		"bar/aidl_api/bar-iface/current/b/Bar.aidl": nil,
1522		"bar/aidl_api/bar-iface/1/b/Bar.aidl":       nil,
1523		"bar/aidl_api/bar-iface/1/.hash":            nil,
1524
1525		"baz/Android.bp": []byte(`
1526			aidl_interface {
1527				name: "baz-iface",
1528				srcs: ["b/Baz.aidl"],
1529				include_dirs: ["baz-include"],
1530				versions: ["1"],
1531			}
1532		`),
1533		"baz/b/Baz.aidl": nil,
1534		"baz/aidl_api/baz-iface/current/b/Baz.aidl": nil,
1535		"baz/aidl_api/baz-iface/1/b/Baz.aidl":       nil,
1536		"baz/aidl_api/baz-iface/1/.hash":            nil,
1537
1538		"boq/Android.bp": []byte(`
1539			aidl_library {
1540				name: "boq-iface-headers",
1541				srcs: ["b/Boq.aidl"],
1542			}
1543		`),
1544		"boq/b/Baz.aidl": nil,
1545	})
1546	ctx, _ := testAidl(t, ``, customizer)
1547
1548	// checkapidump rule is to compare "compatibility" between ToT(dump) and "current"
1549	{
1550		rule := ctx.ModuleForTests("foo-iface_interface", "").Output("checkapi_dump.timestamp")
1551		android.AssertStringEquals(t, "checkapi(dump == current) imports", "-Iboq", rule.Args["imports"])
1552		android.AssertStringDoesContain(t, "checkapi(dump == current) optionalFlags",
1553			rule.Args["optionalFlags"],
1554			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
1555	}
1556
1557	// has_development rule runs --checkapi for equality between latest("1")
1558	// and ToT
1559	{
1560		rule := ctx.ModuleForTests("foo-iface_interface", "").Output("has_development")
1561		android.AssertStringDoesContain(t, "checkapi(dump == latest(1)) should import import's preprocessed",
1562			rule.RuleParams.Command,
1563			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
1564	}
1565
1566	// compile (v1)
1567	{
1568		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("a/Foo.cpp")
1569		android.AssertStringEquals(t, "compile(old=1) should import aidl_api/1",
1570			"-Iboq -Nfoo/aidl_api/foo-iface/1",
1571			rule.Args["imports"]+" "+rule.Args["nextImports"])
1572		android.AssertStringDoesContain(t, "compile(old=1) should import bar.preprocessed",
1573			rule.Args["optionalFlags"],
1574			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
1575	}
1576	// compile ToT(v2)
1577	{
1578		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
1579		android.AssertStringEquals(t, "compile(tot=2) should import base dirs of srcs", "-Iboq -Nfoo", rule.Args["imports"]+" "+rule.Args["nextImports"])
1580		android.AssertStringDoesContain(t, "compile(tot=2) should import bar.preprocessed",
1581			rule.Args["optionalFlags"],
1582			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
1583	}
1584}
1585
1586func TestAidlPreprocess(t *testing.T) {
1587	customizer := withFiles(map[string][]byte{
1588		"foo/Android.bp": []byte(`
1589			aidl_interface {
1590				name: "foo-iface",
1591				local_include_dir: "src",
1592				include_dirs: [
1593						"path1",
1594						"path2/sub",
1595				],
1596				srcs: [
1597						"src/foo/Foo.aidl",
1598				],
1599				imports: [
1600					"bar-iface",
1601				],
1602				unstable: true,
1603			}
1604			aidl_interface {
1605				name: "bar-iface",
1606				local_include_dir: "src",
1607				srcs: [
1608						"src/bar/Bar.aidl",
1609				],
1610				unstable: true,
1611			}
1612		`),
1613		"foo/src/foo/Foo.aidl": nil,
1614		"foo/src/bar/Bar.aidl": nil,
1615	})
1616	ctx, _ := testAidl(t, ``, customizer)
1617
1618	rule := ctx.ModuleForTests("foo-iface_interface", "").Output("preprocessed.aidl")
1619	android.AssertStringDoesContain(t, "preprocessing should import srcs and include_dirs",
1620		rule.RuleParams.Command,
1621		"-Ifoo/src -Ipath1 -Ipath2/sub")
1622	android.AssertStringDoesContain(t, "preprocessing should import import's preprocess",
1623		rule.RuleParams.Command,
1624		"-pout/soong/.intermediates/foo/bar-iface_interface/preprocessed.aidl")
1625}
1626
1627func TestAidlImportFlagsForUnstable(t *testing.T) {
1628	customizer := withFiles(map[string][]byte{
1629		"foo/Android.bp": []byte(`
1630			aidl_interface {
1631				name: "foo-iface",
1632				local_include_dir: "src",
1633				include_dirs: [
1634						"path1",
1635						"path2/sub",
1636				],
1637				srcs: [
1638						"src/foo/Foo.aidl",
1639				],
1640				imports: [
1641					"bar-iface",
1642				],
1643				unstable: true,
1644			}
1645			aidl_interface {
1646				name: "bar-iface",
1647				local_include_dir: "src",
1648				srcs: [
1649						"src/bar/Bar.aidl",
1650				],
1651				unstable: true,
1652			}
1653		`),
1654		"foo/src/foo/Foo.aidl": nil,
1655		"foo/src/bar/Bar.aidl": nil,
1656	})
1657	ctx, _ := testAidl(t, ``, customizer)
1658
1659	rule := ctx.ModuleForTests("foo-iface-cpp-source", "").Output("foo/Foo.cpp")
1660	android.AssertStringEquals(t, "compile(unstable) should import foo/base_dirs(target) and bar/base_dirs(imported)",
1661		"-Ipath1 -Ipath2/sub -Nfoo/src",
1662		rule.Args["imports"]+" "+rule.Args["nextImports"])
1663	android.AssertStringDoesContain(t, "compile(unstable) should import bar.preprocessed",
1664		rule.Args["optionalFlags"],
1665		"-pout/soong/.intermediates/foo/bar-iface_interface/preprocessed.aidl")
1666}
1667
1668func TestSupportsGenruleAndFilegroup(t *testing.T) {
1669	customizer := withFiles(map[string][]byte{
1670		"foo/Android.bp": []byte(`
1671			aidl_interface {
1672				name: "foo-iface",
1673				local_include_dir: "src",
1674				include_dirs: [
1675						"path1",
1676						"path2/sub",
1677				],
1678				srcs: [
1679						"src/foo/Foo.aidl",
1680						":filegroup1",
1681						":gen1",
1682				],
1683				imports: [
1684						"bar-iface-V1",
1685				],
1686				versions: ["1"],
1687			}
1688			filegroup {
1689				name: "filegroup1",
1690				path: "filegroup/sub",
1691				srcs: [
1692						"filegroup/sub/pkg/Bar.aidl",
1693				],
1694			}
1695			genrule {
1696				name: "gen1",
1697				cmd: "generate baz/Baz.aidl",
1698				out: [
1699					"baz/Baz.aidl",
1700				]
1701			}
1702			aidl_interface {
1703				name: "bar-iface",
1704				local_include_dir: "src",
1705				srcs: [
1706						"src/bar/Bar.aidl",
1707						":gen-bar",
1708				],
1709			}
1710			genrule {
1711				name: "gen-bar",
1712				cmd: "generate gen/GenBar.aidl",
1713				out: [
1714					"gen/GenBar.aidl",
1715				]
1716			}
1717		`),
1718		"foo/aidl_api/foo-iface/1/foo/Foo.aidl": nil,
1719		"foo/aidl_api/foo-iface/1/.hash":        nil,
1720		"foo/filegroup/sub/pkg/Bar.aidl":        nil,
1721		"foo/src/foo/Foo.aidl":                  nil,
1722	})
1723	ctx, _ := testAidl(t, ``, customizer)
1724
1725	// aidlCompile for snapshots (v1)
1726	{
1727		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp")
1728		android.AssertStringEquals(t, "compile(1) should import foo/aidl_api/1",
1729			"-Ipath1 -Ipath2/sub -Nfoo/aidl_api/foo-iface/1",
1730			rule.Args["imports"]+" "+rule.Args["nextImports"])
1731		android.AssertStringDoesContain(t, "compile(1) should import bar.preprocessed",
1732			rule.Args["optionalFlags"],
1733			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
1734	}
1735	// aidlCompile for ToT (v2)
1736	{
1737		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("foo/Foo.cpp")
1738		android.AssertStringEquals(t, "compile(tot=2) should import foo.base_dirs",
1739			"-Ipath1 -Ipath2/sub -Nfoo/src -Nfoo/filegroup/sub -Nout/soong/.intermediates/foo/gen1/gen",
1740			rule.Args["imports"]+" "+rule.Args["nextImports"])
1741		android.AssertStringDoesContain(t, "compile(tot=2) should import bar.preprocessed",
1742			rule.Args["optionalFlags"],
1743			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
1744	}
1745
1746	// dumpapi
1747	{
1748		rule := ctx.ModuleForTests("foo-iface_interface", "").Rule("aidlDumpApiRule")
1749		android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump srcs/filegroups/genrules", []string{
1750			"foo/src/foo/Foo.aidl",
1751			"foo/filegroup/sub/pkg/Bar.aidl",
1752			"out/soong/.intermediates/foo/gen1/gen/baz/Baz.aidl",
1753		}, rule.Inputs)
1754
1755		dumpDir := "out/soong/.intermediates/foo/foo-iface_interface/dump"
1756		android.AssertPathsRelativeToTopEquals(t, "dumpapi should dump with rel paths", []string{
1757			dumpDir + "/foo/Foo.aidl",
1758			dumpDir + "/pkg/Bar.aidl",
1759			dumpDir + "/baz/Baz.aidl",
1760			dumpDir + "/.hash",
1761		}, rule.Outputs.Paths())
1762
1763		android.AssertStringEquals(t, "dumpapi should import base_dirs and include_dirs",
1764			"-Ifoo/src -Ifoo/filegroup/sub -Iout/soong/.intermediates/foo/gen1/gen -Ipath1 -Ipath2/sub",
1765			rule.Args["imports"])
1766		android.AssertStringDoesContain(t, "dumpapi should import bar.preprocessed",
1767			rule.Args["optionalFlags"],
1768			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
1769	}
1770}
1771
1772func TestAidlFlags(t *testing.T) {
1773	ctx, _ := testAidl(t, `
1774		aidl_interface {
1775			name: "myiface",
1776			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1777			flags: ["-Weverything", "-Werror"],
1778			backend: { rust: { enabled: true }}
1779		}
1780	`)
1781	for module, outputs := range map[string][]string{
1782		"myiface-V1-cpp-source":  {"a/Foo.h", "b/Bar.h"},
1783		"myiface-V1-java-source": {"a/Foo.java", "b/Bar.java"},
1784		"myiface-V1-ndk-source":  {"aidl/a/Foo.h", "aidl/b/Bar.h"},
1785		"myiface-V1-rust-source": {"a/Foo.rs", "b/Bar.rs"},
1786	} {
1787		for _, output := range outputs {
1788			t.Run(module+"/"+output, func(t *testing.T) {
1789				params := ctx.ModuleForTests(module, "").Output(output)
1790				assertContains(t, params.Args["optionalFlags"], "-Weverything")
1791				assertContains(t, params.Args["optionalFlags"], "-Werror")
1792			})
1793		}
1794	}
1795}
1796
1797func TestAidlModuleJavaSdkVersionDeterminesMinSdkVersion(t *testing.T) {
1798	ctx, _ := testAidl(t, `
1799		aidl_interface {
1800			name: "myiface",
1801			srcs: ["a/Foo.aidl"],
1802			backend: {
1803				java: {
1804					sdk_version: "28",
1805				},
1806			},
1807		}
1808	`, java.FixtureWithPrebuiltApis(map[string][]string{"28": {"foo"}}))
1809	params := ctx.ModuleForTests("myiface-V1-java-source", "").Output("a/Foo.java")
1810	assertContains(t, params.Args["optionalFlags"], "--min_sdk_version 28")
1811}
1812
1813func TestAidlModuleNameContainsVersion(t *testing.T) {
1814	testAidlError(t, "aidl_interface should not have '-V<number> suffix", `
1815		aidl_interface {
1816			name: "myiface-V2",
1817			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1818		}
1819	`)
1820	// Ugly, but okay
1821	testAidl(t, `
1822		aidl_interface {
1823			name: "myiface-V2aa",
1824			srcs: ["a/Foo.aidl", "b/Bar.aidl"],
1825		}
1826	`)
1827}
1828
1829func TestExplicitAidlModuleImport(t *testing.T) {
1830	for _, importVersion := range []string{"V1", "V2"} {
1831
1832		ctx, _ := testAidl(t, `
1833			aidl_interface {
1834				name: "foo",
1835				srcs: ["Foo.aidl"],
1836				versions: [
1837					"1",
1838				],
1839				imports: ["bar-`+importVersion+`"]
1840			}
1841
1842			aidl_interface {
1843				name: "bar",
1844				srcs: ["Bar.aidl"],
1845				versions: [
1846					"1",
1847				],
1848			}
1849		`, withFiles(map[string][]byte{
1850			"aidl_api/foo/1/Foo.aidl": nil,
1851			"aidl_api/foo/1/.hash":    nil,
1852			"aidl_api/bar/1/Bar.aidl": nil,
1853			"aidl_api/bar/1/.hash":    nil,
1854		}))
1855		for _, foo := range []string{"foo-V1-cpp", "foo-V2-cpp"} {
1856			ldRule := ctx.ModuleForTests(foo, nativeVariant).Rule("ld")
1857			libFlags := ldRule.Args["libFlags"]
1858			libBar := filepath.Join("bar-"+importVersion+"-cpp", nativeVariant, "bar-"+importVersion+"-cpp.so")
1859			if !strings.Contains(libFlags, libBar) {
1860				t.Errorf("%q is not found in %q", libBar, libFlags)
1861			}
1862
1863		}
1864	}
1865
1866	testAidlError(t, "module \"foo_interface\": imports: \"foo\" depends on \"bar\" version \"3\"", `
1867		aidl_interface {
1868			name: "foo",
1869			srcs: ["Foo.aidl"],
1870			versions: [
1871				"1",
1872			],
1873			imports: ["bar-V3"]
1874		}
1875
1876		aidl_interface {
1877			name: "bar",
1878			srcs: ["Bar.aidl"],
1879			versions: [
1880				"1",
1881			],
1882		}
1883	`, withFiles(map[string][]byte{
1884		"aidl_api/foo/1/Foo.aidl": nil,
1885		"aidl_api/foo/1/.hash":    nil,
1886		"aidl_api/bar/1/Bar.aidl": nil,
1887		"aidl_api/bar/1/.hash":    nil,
1888	}))
1889}
1890
1891func TestUseVersionedPreprocessedWhenImporotedWithVersions(t *testing.T) {
1892	ctx, _ := testAidl(t, `
1893		aidl_interface {
1894			name: "unstable-foo",
1895			srcs: ["foo/Foo.aidl"],
1896			imports: [
1897					"bar-V2",
1898					"baz-V1",
1899					"unstable-bar",
1900			],
1901			unstable: true,
1902		}
1903		aidl_interface {
1904			name: "foo",
1905			srcs: ["foo/Foo.aidl"],
1906			imports: [
1907					"bar-V1",
1908					"baz-V1",
1909			],
1910			versions: ["1"],
1911		}
1912		aidl_interface {
1913			name: "foo-no-versions",
1914			srcs: ["foo/Foo.aidl"],
1915			imports: [
1916					"bar-V2",
1917			],
1918		}
1919		aidl_interface {
1920			name: "bar",
1921			srcs: ["bar/Bar.aidl"],
1922			versions: ["1"],
1923		}
1924		aidl_interface {
1925			name: "unstable-bar",
1926			srcs: ["bar/Bar.aidl"],
1927			unstable: true,
1928		}
1929		aidl_interface {
1930			name: "baz",
1931			srcs: ["baz/Baz.aidl"],
1932			versions: ["1"],
1933		}
1934	`, withFiles(map[string][]byte{
1935		"foo/Foo.aidl":                nil,
1936		"bar/Bar.aidl":                nil,
1937		"baz/Baz.aidl":                nil,
1938		"aidl_api/foo/1/foo/Foo.aidl": nil,
1939		"aidl_api/foo/1/.hash":        nil,
1940		"aidl_api/bar/1/bar/Bar.aidl": nil,
1941		"aidl_api/bar/1/.hash":        nil,
1942		"aidl_api/baz/1/baz/Baz.aidl": nil,
1943		"aidl_api/baz/1/.hash":        nil,
1944	}))
1945	{
1946		rule := ctx.ModuleForTests("foo-V2-java-source", "").Output("foo/Foo.java")
1947		android.AssertStringDoesContain(t, "foo-V2(tot) imports bar-V1 for 'bar-V1'", rule.Args["optionalFlags"],
1948			"-pout/soong/.intermediates/bar_interface/1/preprocessed.aidl")
1949		android.AssertStringDoesContain(t, "foo-V2(tot) imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
1950			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
1951	}
1952	{
1953		rule := ctx.ModuleForTests("foo-V1-java-source", "").Output("foo/Foo.java")
1954		android.AssertStringDoesContain(t, "foo-V1 imports bar-V1(latest) for 'bar'", rule.Args["optionalFlags"],
1955			"-pout/soong/.intermediates/bar_interface/1/preprocessed.aidl")
1956		android.AssertStringDoesContain(t, "foo-V1 imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
1957			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
1958	}
1959	{
1960		rule := ctx.ModuleForTests("unstable-foo-java-source", "").Output("foo/Foo.java")
1961		android.AssertStringDoesContain(t, "unstable-foo imports bar-V2(latest) for 'bar'", rule.Args["optionalFlags"],
1962			"-pout/soong/.intermediates/bar_interface/2/preprocessed.aidl")
1963		android.AssertStringDoesContain(t, "unstable-foo imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
1964			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
1965		android.AssertStringDoesContain(t, "unstable-foo imports unstable-bar(ToT) for 'unstable-bar'", rule.Args["optionalFlags"],
1966			"-pout/soong/.intermediates/unstable-bar_interface/preprocessed.aidl")
1967	}
1968	{
1969		rule := ctx.ModuleForTests("foo-no-versions-V1-java-source", "").Output("foo/Foo.java")
1970		android.AssertStringDoesContain(t, "foo-no-versions-V1(latest) imports bar-V2(latest) for 'bar'", rule.Args["optionalFlags"],
1971			"-pout/soong/.intermediates/bar_interface/2/preprocessed.aidl")
1972	}
1973}
1974
1975func FindModule(ctx *android.TestContext, name, variant, dir string) android.Module {
1976	var module android.Module
1977	ctx.VisitAllModules(func(m blueprint.Module) {
1978		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant && ctx.ModuleDir(m) == dir {
1979			module = m.(android.Module)
1980		}
1981	})
1982	if module == nil {
1983		m := ctx.ModuleForTests(name, variant).Module()
1984		panic(fmt.Errorf("failed to find module %q variant %q dir %q, but found one in %q",
1985			name, variant, dir, ctx.ModuleDir(m)))
1986	}
1987	return module
1988}
1989
1990func TestDuplicateInterfacesWithTheSameNameInDifferentSoongNamespaces(t *testing.T) {
1991	ctx, _ := testAidl(t, ``, withFiles(map[string][]byte{
1992		"common/Android.bp": []byte(`
1993		  aidl_interface {
1994				name: "common",
1995				srcs: ["ICommon.aidl"],
1996				versions: ["1", "2"],
1997			}
1998		`),
1999		"common/aidl_api/common/1/ICommon.aidl": nil,
2000		"common/aidl_api/common/1/.hash":        nil,
2001		"common/aidl_api/common/2/ICommon.aidl": nil,
2002		"common/aidl_api/common/2/.hash":        nil,
2003		"vendor/a/Android.bp": []byte(`
2004			soong_namespace {}
2005		`),
2006		"vendor/a/foo/Android.bp": []byte(`
2007			aidl_interface {
2008				name: "foo",
2009				owner: "vendor",
2010				srcs: ["IFoo.aidl"],
2011				imports: ["common-V1"],
2012			}
2013		`),
2014		"vendor/b/Android.bp": []byte(`
2015			soong_namespace {}
2016		`),
2017		"vendor/b/foo/Android.bp": []byte(`
2018			aidl_interface {
2019				name: "foo",
2020				owner: "vendor",
2021				srcs: ["IFoo.aidl"],
2022				imports: ["common-V2"],
2023			}
2024		`),
2025	}))
2026
2027	aFooV1Java := FindModule(ctx, "foo-V1-java", "android_common", "vendor/a/foo").(*java.Library)
2028	android.AssertStringListContains(t, "a/foo deps", aFooV1Java.CompilerDeps(), "common-V1-java")
2029
2030	bFooV1Java := FindModule(ctx, "foo-V1-java", "android_common", "vendor/b/foo").(*java.Library)
2031	android.AssertStringListContains(t, "a/foo deps", bFooV1Java.CompilerDeps(), "common-V2-java")
2032}
2033
2034func TestUnstableChecksForAidlInterfacesInDifferentNamespaces(t *testing.T) {
2035	files := withFiles(map[string][]byte{
2036		"vendor/a/Android.bp": []byte(`
2037			soong_namespace {}
2038		`),
2039		"vendor/a/foo/Android.bp": []byte(`
2040			aidl_interface {
2041				name: "foo",
2042				owner: "vendor",
2043				srcs: ["IFoo.aidl"],
2044				versions: ["1", "2"],
2045			}
2046			java_library {
2047				name: "bar",
2048				libs: ["foo-V2-java"],  // OK
2049			}
2050		`),
2051		"vendor/a/foo/aidl_api/foo/1/IFoo.aidl": nil,
2052		"vendor/a/foo/aidl_api/foo/1/.hash":     nil,
2053		"vendor/a/foo/aidl_api/foo/2/IFoo.aidl": nil,
2054		"vendor/a/foo/aidl_api/foo/2/.hash":     nil,
2055		"vendor/b/Android.bp": []byte(`
2056			soong_namespace {}
2057		`),
2058		"vendor/b/foo/Android.bp": []byte(`
2059			aidl_interface {
2060				name: "foo",
2061				owner: "vendor",
2062				srcs: ["IFoo.aidl"],
2063				versions: ["1"],
2064			}
2065			java_library {
2066				name: "bar",
2067				libs: ["foo-V1-java"],  // OK
2068			}
2069		`),
2070		"vendor/b/foo/aidl_api/foo/1/IFoo.aidl": nil,
2071		"vendor/b/foo/aidl_api/foo/1/.hash":     nil,
2072	})
2073
2074	testAidl(t, ``, files, setReleaseEnv())
2075	testAidl(t, ``, files, setTestFreezeEnv())
2076	testAidl(t, ``, files)
2077}
2078
2079func TestVersionsWithInfoAndVersions(t *testing.T) {
2080	conflictingFields := `
2081	aidl_interface {
2082		name: "foo",
2083		versions: [
2084			"1",
2085		],
2086		versions_with_info: [
2087			{
2088				version: "1",
2089			}
2090		],
2091	}
2092	`
2093	files := withFiles(map[string][]byte{
2094		"aidl_api/foo/1/foo.1.aidl": nil,
2095		"aidl_api/foo/1/.hash":      nil,
2096	})
2097
2098	expectedError := `Use versions_with_info instead of versions.`
2099	testAidlError(t, expectedError, conflictingFields, files)
2100}
2101
2102func TestVersionsWithInfo(t *testing.T) {
2103	ctx, _ := testAidl(t, ``, withFiles(map[string][]byte{
2104		"common/Android.bp": []byte(`
2105		  aidl_interface {
2106				name: "common",
2107				srcs: ["ICommon.aidl"],
2108				versions: ["1", "2"],
2109			}
2110		`),
2111		"common/aidl_api/common/1/ICommon.aidl": nil,
2112		"common/aidl_api/common/1/.hash":        nil,
2113		"common/aidl_api/common/2/ICommon.aidl": nil,
2114		"common/aidl_api/common/2/.hash":        nil,
2115		"foo/Android.bp": []byte(`
2116			aidl_interface {
2117				name: "foo",
2118				srcs: ["IFoo.aidl"],
2119				imports: ["common-V3"],
2120				versions_with_info: [
2121					{version: "1", imports: ["common-V1"]},
2122					{version: "2", imports: ["common-V2"]},
2123				]
2124			}
2125		`),
2126		"foo/aidl_api/foo/1/IFoo.aidl": nil,
2127		"foo/aidl_api/foo/1/.hash":     nil,
2128		"foo/aidl_api/foo/2/IFoo.aidl": nil,
2129		"foo/aidl_api/foo/2/.hash":     nil,
2130	}))
2131
2132	fooV1Java := FindModule(ctx, "foo-V1-java", "android_common", "foo").(*java.Library)
2133	android.AssertStringListContains(t, "a/foo-v1 deps", fooV1Java.CompilerDeps(), "common-V1-java")
2134
2135	fooV2Java := FindModule(ctx, "foo-V2-java", "android_common", "foo").(*java.Library)
2136	android.AssertStringListContains(t, "a/foo-v2 deps", fooV2Java.CompilerDeps(), "common-V2-java")
2137
2138	fooV3Java := FindModule(ctx, "foo-V3-java", "android_common", "foo").(*java.Library)
2139	android.AssertStringListContains(t, "a/foo-v3 deps", fooV3Java.CompilerDeps(), "common-V3-java")
2140}
2141
2142func TestVersionsWithInfoImport(t *testing.T) {
2143	testAidlError(t, "imports in versions_with_info must specify its version", ``, withFiles(map[string][]byte{
2144		"common/Android.bp": []byte(`
2145		  aidl_interface {
2146				name: "common",
2147				srcs: ["ICommon.aidl"],
2148				versions: ["1", "2"],
2149			}
2150		`),
2151		"common/aidl_api/common/1/ICommon.aidl": nil,
2152		"common/aidl_api/common/1/.hash":        nil,
2153		"common/aidl_api/common/2/ICommon.aidl": nil,
2154		"common/aidl_api/common/2/.hash":        nil,
2155		"foo/Android.bp": []byte(`
2156			aidl_interface {
2157				name: "foo",
2158				srcs: ["IFoo.aidl"],
2159				imports: ["common"],
2160				versions_with_info: [
2161					{version: "1", imports: ["common"]},
2162					{version: "2", imports: ["common-V2"]},
2163				]
2164			}
2165		`),
2166		"foo/aidl_api/foo/1/IFoo.aidl": nil,
2167		"foo/aidl_api/foo/1/.hash":     nil,
2168		"foo/aidl_api/foo/2/IFoo.aidl": nil,
2169		"foo/aidl_api/foo/2/.hash":     nil,
2170	}))
2171}
2172
2173func TestFreezeApiDeps(t *testing.T) {
2174	for _, transitive := range []bool{true, false} {
2175		for _, testcase := range []struct {
2176			string
2177			bool
2178		}{{"common-V3", true}, {"common-V2", false}} {
2179			im := testcase.string
2180			customizers := []android.FixturePreparer{
2181				withFiles(map[string][]byte{
2182					"common/Android.bp": []byte(`
2183				  aidl_interface {
2184						name: "common",
2185						frozen: false,
2186						srcs: ["ICommon.aidl"],
2187						versions: ["1", "2"],
2188					}
2189				`),
2190					"common/aidl_api/common/1/ICommon.aidl": nil,
2191					"common/aidl_api/common/1/.hash":        nil,
2192					"common/aidl_api/common/2/ICommon.aidl": nil,
2193					"common/aidl_api/common/2/.hash":        nil,
2194					"foo/Android.bp": []byte(fmt.Sprintf(`
2195					aidl_interface {
2196						name: "foo",
2197						srcs: ["IFoo.aidl"],
2198						imports: ["%s"],
2199						frozen: false,
2200						versions_with_info: [
2201							{version: "1", imports: ["common-V1"]},
2202							{version: "2", imports: ["common-V2"]},
2203						]
2204					}
2205				`, im)),
2206					"foo/aidl_api/foo/1/IFoo.aidl": nil,
2207					"foo/aidl_api/foo/1/.hash":     nil,
2208					"foo/aidl_api/foo/2/IFoo.aidl": nil,
2209					"foo/aidl_api/foo/2/.hash":     nil,
2210				}),
2211			}
2212			if transitive {
2213				customizers = append(customizers, setTransitiveFreezeEnv())
2214			}
2215
2216			ctx, _ := testAidl(t, ``, customizers...)
2217			shouldHaveDep := transitive && testcase.bool
2218			fooFreezeApiRule := ctx.ModuleForTests("foo_interface", "").Output("update_or_freeze_api_3.timestamp")
2219			commonFreezeApiOutput := ctx.ModuleForTests("common_interface", "").Output("update_or_freeze_api_3.timestamp").Output.String()
2220			testMethod := android.AssertStringListDoesNotContain
2221			if shouldHaveDep {
2222				testMethod = android.AssertStringListContains
2223			}
2224			testMethod(t, "Only if AIDL_TRANSITIVE_FREEZE is set and an aidl_interface depends on an another aidl_interface's ToT version, an imported aidl_interface should be frozen as well.",
2225				fooFreezeApiRule.Implicits.Strings(), commonFreezeApiOutput)
2226		}
2227	}
2228}
2229
2230func TestAidlNoUnfrozen(t *testing.T) {
2231	customizer := withFiles(map[string][]byte{
2232		"foo/Android.bp": []byte(`
2233			aidl_interface {
2234				name: "foo-iface",
2235				srcs: ["a/Foo.aidl"],
2236				versions: ["1", "2"],
2237			}
2238		`),
2239		"foo/a/Foo.aidl": nil,
2240		"foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
2241		"foo/aidl_api/foo-iface/1/a/Foo.aidl":       nil,
2242		"foo/aidl_api/foo-iface/1/.hash":            nil,
2243		"foo/aidl_api/foo-iface/2/a/Foo.aidl":       nil,
2244		"foo/aidl_api/foo-iface/2/.hash":            nil,
2245	})
2246	// setReleaseEnv() to set RELEASE_AIDL_USE_UNFROZEN to false
2247	ctx, _ := testAidl(t, ``, setReleaseEnv(), customizer)
2248
2249	// compile (v1)
2250	{
2251		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("a/Foo.cpp")
2252		android.AssertStringDoesNotContain(t, "Frozen versions should not have the -previous_api_dir set",
2253			rule.Args["optionalFlags"],
2254			"-previous")
2255	}
2256	// compile (v2)
2257	{
2258		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
2259		android.AssertStringDoesNotContain(t, "Frozen versions should not have the -previous_api_dir set",
2260			rule.Args["optionalFlags"],
2261			"-previous")
2262	}
2263	// compile ToT(v3)
2264	{
2265		rule := ctx.ModuleForTests("foo-iface-V3-cpp-source", "").Output("a/Foo.cpp")
2266		android.AssertStringDoesContain(t, "An unfrozen interface with previously frozen version must have --previous_api_dir when RELEASE_AIDL_USE_UNFROZEN is false (setReleaseEnv())",
2267			rule.Args["optionalFlags"],
2268			"-previous_api_dir")
2269		android.AssertStringDoesContain(t, "An unfrozen interface with previously frozen version must have --previous_hash when RELEASE_AIDL_USE_UNFROZEN is false (setReleaseEnv())",
2270			rule.Args["optionalFlags"],
2271			"-previous_hash")
2272		android.AssertStringDoesContain(t, "--previous_hash must use the last frozen version's hash file",
2273			rule.Args["optionalFlags"],
2274			"foo-iface/2/.hash")
2275	}
2276}
2277
2278func TestAidlUsingUnfrozen(t *testing.T) {
2279	customizer := withFiles(map[string][]byte{
2280		"foo/Android.bp": []byte(`
2281			aidl_interface {
2282				name: "foo-iface",
2283				srcs: ["a/Foo.aidl"],
2284				versions: ["1", "2"],
2285			}
2286		`),
2287		"foo/a/Foo.aidl": nil,
2288		"foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
2289		"foo/aidl_api/foo-iface/1/a/Foo.aidl":       nil,
2290		"foo/aidl_api/foo-iface/1/.hash":            nil,
2291		"foo/aidl_api/foo-iface/2/a/Foo.aidl":       nil,
2292		"foo/aidl_api/foo-iface/2/.hash":            nil,
2293	})
2294	ctx, _ := testAidl(t, ``, customizer)
2295
2296	// compile (v2)
2297	{
2298		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
2299		android.AssertStringDoesNotContain(t, "Frozen versions should not have the -previous_api_dir set",
2300			rule.Args["optionalFlags"],
2301			"-previous")
2302	}
2303	// compile ToT(v3)
2304	{
2305		rule := ctx.ModuleForTests("foo-iface-V3-cpp-source", "").Output("a/Foo.cpp")
2306		android.AssertStringDoesNotContain(t, "Unfrozen versions should not have the -previous options when RELEASE_AIDL_USE_UNFROZEN is true (default)",
2307			rule.Args["optionalFlags"],
2308			"-previous")
2309	}
2310}
2311
2312func TestAidlUseUnfrozenOverrideFalse(t *testing.T) {
2313	customizer := withFiles(map[string][]byte{
2314		"foo/Android.bp": []byte(`
2315                        aidl_interface {
2316                                name: "foo-iface",
2317                                srcs: ["a/Foo.aidl"],
2318                                versions: ["1"],
2319                        }
2320                `),
2321		"foo/a/Foo.aidl": nil, "foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
2322		"foo/aidl_api/foo-iface/1/a/Foo.aidl": nil, "foo/aidl_api/foo-iface/1/.hash": nil,
2323	})
2324	ctx, _ := testAidl(t, ``, setUseUnfrozenOverrideEnvFalse(), customizer)
2325
2326	rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
2327	android.AssertStringDoesContain(t, "Unfrozen interfaces should have -previous_api_dir set when overriding the RELEASE_AIDL_USE_UNFROZEN flag",
2328		rule.Args["optionalFlags"],
2329		"-previous")
2330}
2331
2332func TestAidlUseUnfrozenOverrideTrue(t *testing.T) {
2333	customizer := withFiles(map[string][]byte{
2334		"foo/Android.bp": []byte(`
2335                        aidl_interface {
2336                                name: "foo-iface",
2337                                srcs: ["a/Foo.aidl"],
2338                                versions: ["1"],
2339                        }
2340                `),
2341		"foo/a/Foo.aidl": nil, "foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
2342		"foo/aidl_api/foo-iface/1/a/Foo.aidl": nil, "foo/aidl_api/foo-iface/1/.hash": nil,
2343	})
2344	ctx, _ := testAidl(t, ``, setUseUnfrozenOverrideEnvTrue(), customizer)
2345
2346	rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
2347	android.AssertStringDoesNotContain(t, "Unfrozen interfaces should not have -previous_api_dir set when overriding the RELEASE_AIDL_USE_UNFROZEN flag",
2348		rule.Args["optionalFlags"],
2349		"-previous")
2350}
2351