xref: /aosp_15_r20/build/soong/etc/prebuilt_etc_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package etc
16
17import (
18	"os"
19	"path/filepath"
20	"testing"
21
22	"github.com/google/blueprint/proptools"
23
24	"android/soong/android"
25)
26
27func TestMain(m *testing.M) {
28	os.Exit(m.Run())
29}
30
31var prepareForPrebuiltEtcTest = android.GroupFixturePreparers(
32	android.PrepareForTestWithArchMutator,
33	PrepareForTestWithPrebuiltEtc,
34	android.FixtureMergeMockFs(android.MockFS{
35		"foo.conf": nil,
36		"bar.conf": nil,
37		"baz.conf": nil,
38	}),
39)
40
41func TestPrebuiltEtcVariants(t *testing.T) {
42	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
43		prebuilt_etc {
44			name: "foo.conf",
45			src: "foo.conf",
46		}
47		prebuilt_etc {
48			name: "bar.conf",
49			src: "bar.conf",
50			recovery_available: true,
51		}
52		prebuilt_etc {
53			name: "baz.conf",
54			src: "baz.conf",
55			recovery: true,
56		}
57	`)
58
59	foo_variants := result.ModuleVariantsForTests("foo.conf")
60	if len(foo_variants) != 1 {
61		t.Errorf("expected 1, got %#v", foo_variants)
62	}
63
64	bar_variants := result.ModuleVariantsForTests("bar.conf")
65	if len(bar_variants) != 2 {
66		t.Errorf("expected 2, got %#v", bar_variants)
67	}
68
69	baz_variants := result.ModuleVariantsForTests("baz.conf")
70	if len(baz_variants) != 1 {
71		t.Errorf("expected 1, got %#v", baz_variants)
72	}
73}
74
75func TestPrebuiltEtcOutputPath(t *testing.T) {
76	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
77		prebuilt_etc {
78			name: "foo.conf",
79			src: "foo.conf",
80			filename: "foo.installed.conf",
81		}
82	`)
83
84	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
85	android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePaths[0].Base())
86}
87
88func TestPrebuiltEtcGlob(t *testing.T) {
89	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
90		prebuilt_etc {
91			name: "my_foo",
92			src: "foo.*",
93		}
94		prebuilt_etc {
95			name: "my_bar",
96			src: "bar.*",
97			filename_from_src: true,
98		}
99	`)
100
101	p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
102	android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePaths[0].Base())
103
104	p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
105	android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePaths[0].Base())
106}
107
108func TestPrebuiltEtcMultipleSrcs(t *testing.T) {
109	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
110		prebuilt_etc {
111			name: "foo",
112			srcs: ["*.conf"],
113		}
114	`)
115
116	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
117	android.AssertStringEquals(t, "output file path", "bar.conf", p.outputFilePaths[0].Base())
118	android.AssertStringEquals(t, "output file path", "baz.conf", p.outputFilePaths[1].Base())
119	android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base())
120}
121
122func TestPrebuiltEtcDsts(t *testing.T) {
123	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
124		prebuilt_etc {
125			name: "foo",
126			srcs: ["foo.conf", "bar.conf"],
127			dsts: ["foodir/foo.conf", "bardir/extradir/different.name"],
128		}
129	`)
130
131	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
132	android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base())
133	android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
134
135	expectedPaths := [...]string{
136		"out/soong/target/product/test_device/system/etc/foodir",
137		"out/soong/target/product/test_device/system/etc/bardir/extradir",
138	}
139	android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
140	android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
141}
142
143func TestPrebuiltEtcDstsPlusRelativeInstallPath(t *testing.T) {
144	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
145		prebuilt_etc {
146			name: "foo",
147			srcs: ["foo.conf", "bar.conf"],
148			dsts: ["foodir/foo.conf", "bardir/extradir/different.name"],
149			relative_install_path: "somewhere",
150		}
151	`)
152
153	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
154	android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base())
155	android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
156
157	expectedPaths := [...]string{
158		"out/soong/target/product/test_device/system/etc/somewhere/foodir",
159		"out/soong/target/product/test_device/system/etc/somewhere/bardir/extradir",
160	}
161	android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
162	android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
163}
164
165func TestPrebuiltEtcDstsSrcGlob(t *testing.T) {
166	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
167		prebuilt_etc {
168			name: "foo",
169			srcs: ["*.conf"],
170			dsts: ["a.conf", "b.conf", "c.conf"],
171		}
172	`)
173
174	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
175	android.AssertStringEquals(t, "output file path", "a.conf", p.outputFilePaths[0].Base())
176	android.AssertStringEquals(t, "output file path", "b.conf", p.outputFilePaths[1].Base())
177	android.AssertStringEquals(t, "output file path", "c.conf", p.outputFilePaths[2].Base())
178}
179
180func TestPrebuiltEtcDstsSrcGlobDstsTooShort(t *testing.T) {
181	prepareForPrebuiltEtcTest.
182		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")).
183		RunTestWithBp(t, `
184			prebuilt_etc {
185				name: "foo",
186				srcs: ["*.conf"],
187				dsts: ["a.conf", "b.conf"],
188			}
189		`)
190}
191
192func TestPrebuiltEtcDstsSrcGlobDstsTooLong(t *testing.T) {
193	prepareForPrebuiltEtcTest.
194		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")).
195		RunTestWithBp(t, `
196			prebuilt_etc {
197				name: "foo",
198				srcs: ["*.conf"],
199				dsts: ["a.conf", "b.conf", "c.conf", "d.conf"],
200			}
201		`)
202}
203
204func TestPrebuiltEtcCannotDstsWithSrc(t *testing.T) {
205	prepareForPrebuiltEtcTest.
206		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Must use srcs")).
207		RunTestWithBp(t, `
208			prebuilt_etc {
209				name: "foo.conf",
210				src: "foo.conf",
211				dsts: ["a.conf"],
212			}
213		`)
214}
215
216func TestPrebuiltEtcCannotDstsWithFilenameFromSrc(t *testing.T) {
217	prepareForPrebuiltEtcTest.
218		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Cannot set filename_from_src")).
219		RunTestWithBp(t, `
220			prebuilt_etc {
221				name: "foo.conf",
222				srcs: ["foo.conf"],
223				dsts: ["a.conf"],
224				filename_from_src: true,
225			}
226		`)
227}
228
229func TestPrebuiltEtcAndroidMk(t *testing.T) {
230	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
231		prebuilt_etc {
232			name: "foo",
233			src: "foo.conf",
234			owner: "abc",
235			filename_from_src: true,
236			required: ["modA", "moduleB"],
237			host_required: ["hostModA", "hostModB"],
238			target_required: ["targetModA"],
239		}
240	`)
241
242	expected := map[string][]string{
243		"LOCAL_MODULE":                  {"foo"},
244		"LOCAL_MODULE_CLASS":            {"ETC"},
245		"LOCAL_MODULE_OWNER":            {"abc"},
246		"LOCAL_INSTALLED_MODULE_STEM":   {"foo.conf"},
247		"LOCAL_REQUIRED_MODULES":        {"modA", "moduleB"},
248		"LOCAL_HOST_REQUIRED_MODULES":   {"hostModA", "hostModB"},
249		"LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"},
250		"LOCAL_SOONG_MODULE_TYPE":       {"prebuilt_etc"},
251	}
252
253	mod := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
254	entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
255	for k, expectedValue := range expected {
256		if value, ok := entries.EntryMap[k]; ok {
257			android.AssertDeepEquals(t, k, expectedValue, value)
258		} else {
259			t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
260		}
261	}
262}
263
264func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
265	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
266		prebuilt_etc {
267			name: "foo.conf",
268			src: "foo.conf",
269			relative_install_path: "bar",
270		}
271	`)
272
273	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
274	expected := "out/soong/target/product/test_device/system/etc/bar"
275	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
276}
277
278func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
279	prepareForPrebuiltEtcTest.
280		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")).
281		RunTestWithBp(t, `
282			prebuilt_etc {
283				name: "foo.conf",
284				src: "foo.conf",
285				sub_dir: "bar",
286				relative_install_path: "bar",
287			}
288		`)
289}
290
291func TestPrebuiltEtcHost(t *testing.T) {
292	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
293		prebuilt_etc_host {
294			name: "foo.conf",
295			src: "foo.conf",
296		}
297	`)
298
299	buildOS := result.Config.BuildOS.String()
300	p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
301	if !p.Host() {
302		t.Errorf("host bit is not set for a prebuilt_etc_host module.")
303	}
304}
305
306func TestPrebuiltEtcAllowMissingDependencies(t *testing.T) {
307	result := android.GroupFixturePreparers(
308		prepareForPrebuiltEtcTest,
309		android.PrepareForTestDisallowNonExistentPaths,
310		android.FixtureModifyConfig(
311			func(config android.Config) {
312				config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
313			}),
314	).RunTestWithBp(t, `
315		prebuilt_etc {
316			name: "foo.conf",
317			filename_from_src: true,
318			arch: {
319				x86: {
320					src: "x86.conf",
321				},
322			},
323		}
324	`)
325
326	android.AssertStringEquals(t, "expected error rule", "android/soong/android.Error",
327		result.ModuleForTests("foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String())
328}
329
330func TestPrebuiltRootInstallDirPath(t *testing.T) {
331	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
332		prebuilt_root {
333			name: "foo.conf",
334			src: "foo.conf",
335			filename: "foo.conf",
336		}
337	`)
338
339	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
340	expected := "out/soong/target/product/test_device/system"
341	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
342}
343
344func TestPrebuiltRootInstallDirPathValidate(t *testing.T) {
345	prepareForPrebuiltEtcTest.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("filename cannot contain separator")).RunTestWithBp(t, `
346		prebuilt_root {
347			name: "foo.conf",
348			src: "foo.conf",
349			filename: "foo/bar.conf",
350		}
351	`)
352}
353
354func TestPrebuiltAvbInstallDirPath(t *testing.T) {
355	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
356		prebuilt_avb {
357			name: "foo.conf",
358			src: "foo.conf",
359			filename: "foo.conf",
360			//recovery: true,
361		}
362	`)
363
364	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
365	expected := "out/soong/target/product/test_device/root/avb"
366	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
367}
368
369func TestPrebuiltAvdInstallDirPathValidate(t *testing.T) {
370	prepareForPrebuiltEtcTest.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("filename cannot contain separator")).RunTestWithBp(t, `
371		prebuilt_avb {
372			name: "foo.conf",
373			src: "foo.conf",
374			filename: "foo/bar.conf",
375		}
376	`)
377}
378
379func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
380	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
381		prebuilt_usr_share {
382			name: "foo.conf",
383			src: "foo.conf",
384			sub_dir: "bar",
385		}
386	`)
387
388	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
389	expected := "out/soong/target/product/test_device/system/usr/share/bar"
390	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
391}
392
393func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
394	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
395		prebuilt_usr_share_host {
396			name: "foo.conf",
397			src: "foo.conf",
398			sub_dir: "bar",
399		}
400	`)
401
402	buildOS := result.Config.BuildOS.String()
403	p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
404	expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar")
405	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
406}
407
408func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) {
409	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
410	prebuilt_usr_hyphendata {
411			name: "foo.conf",
412			src: "foo.conf",
413			sub_dir: "bar",
414		}
415	`)
416
417	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
418	expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar"
419	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
420}
421
422func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) {
423	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
424	prebuilt_usr_keylayout {
425			name: "foo.conf",
426			src: "foo.conf",
427			sub_dir: "bar",
428		}
429	`)
430
431	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
432	expected := "out/soong/target/product/test_device/system/usr/keylayout/bar"
433	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
434}
435
436func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) {
437	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
438	prebuilt_usr_keychars {
439			name: "foo.conf",
440			src: "foo.conf",
441			sub_dir: "bar",
442		}
443	`)
444
445	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
446	expected := "out/soong/target/product/test_device/system/usr/keychars/bar"
447	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
448}
449
450func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) {
451	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
452	prebuilt_usr_idc {
453			name: "foo.conf",
454			src: "foo.conf",
455			sub_dir: "bar",
456		}
457	`)
458
459	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
460	expected := "out/soong/target/product/test_device/system/usr/idc/bar"
461	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
462}
463
464func TestPrebuiltFontInstallDirPath(t *testing.T) {
465	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
466		prebuilt_font {
467			name: "foo.conf",
468			src: "foo.conf",
469		}
470	`)
471
472	p := result.Module("foo.conf", "android_common").(*PrebuiltEtc)
473	expected := "out/soong/target/product/test_device/system/fonts"
474	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
475}
476
477func TestPrebuiltOverlayInstallDirPath(t *testing.T) {
478	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
479		prebuilt_overlay {
480			name: "foo.conf",
481			src: "foo.conf",
482		}
483	`)
484
485	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
486	expected := "out/soong/target/product/test_device/system/overlay"
487	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
488}
489
490func TestPrebuiltFirmwareDirPath(t *testing.T) {
491	targetPath := "out/soong/target/product/test_device"
492	tests := []struct {
493		description  string
494		config       string
495		expectedPath string
496	}{{
497		description: "prebuilt: system firmware",
498		config: `
499			prebuilt_firmware {
500				name: "foo.conf",
501				src: "foo.conf",
502			}`,
503		expectedPath: filepath.Join(targetPath, "system/etc/firmware"),
504	}, {
505		description: "prebuilt: vendor firmware",
506		config: `
507			prebuilt_firmware {
508				name: "foo.conf",
509				src: "foo.conf",
510				soc_specific: true,
511				sub_dir: "sub_dir",
512			}`,
513		expectedPath: filepath.Join(targetPath, "vendor/firmware/sub_dir"),
514	}}
515	for _, tt := range tests {
516		t.Run(tt.description, func(t *testing.T) {
517			result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
518			p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
519			android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
520		})
521	}
522}
523
524func TestPrebuiltDSPDirPath(t *testing.T) {
525	targetPath := "out/soong/target/product/test_device"
526	tests := []struct {
527		description  string
528		config       string
529		expectedPath string
530	}{{
531		description: "prebuilt: system dsp",
532		config: `
533			prebuilt_dsp {
534				name: "foo.conf",
535				src: "foo.conf",
536			}`,
537		expectedPath: filepath.Join(targetPath, "system/etc/dsp"),
538	}, {
539		description: "prebuilt: vendor dsp",
540		config: `
541			prebuilt_dsp {
542				name: "foo.conf",
543				src: "foo.conf",
544				soc_specific: true,
545				sub_dir: "sub_dir",
546			}`,
547		expectedPath: filepath.Join(targetPath, "vendor/dsp/sub_dir"),
548	}}
549	for _, tt := range tests {
550		t.Run(tt.description, func(t *testing.T) {
551			result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
552			p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
553			android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
554		})
555	}
556}
557
558func TestPrebuiltRFSADirPath(t *testing.T) {
559	targetPath := "out/soong/target/product/test_device"
560	tests := []struct {
561		description  string
562		config       string
563		expectedPath string
564	}{{
565		description: "prebuilt: system rfsa",
566		config: `
567			prebuilt_rfsa {
568				name: "foo.conf",
569				src: "foo.conf",
570			}`,
571		expectedPath: filepath.Join(targetPath, "system/lib/rfsa"),
572	}, {
573		description: "prebuilt: vendor rfsa",
574		config: `
575			prebuilt_rfsa {
576				name: "foo.conf",
577				src: "foo.conf",
578				soc_specific: true,
579				sub_dir: "sub_dir",
580			}`,
581		expectedPath: filepath.Join(targetPath, "vendor/lib/rfsa/sub_dir"),
582	}}
583	for _, tt := range tests {
584		t.Run(tt.description, func(t *testing.T) {
585			result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
586			p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
587			android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
588		})
589	}
590}
591
592func TestPrebuiltMediaAutoDirPath(t *testing.T) {
593	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
594		prebuilt_media {
595			name: "foo",
596			src: "Alarm_Beep_01.ogg",
597			product_specific: true,
598			relative_install_path: "alarms"
599		}
600	`)
601
602	p := result.Module("foo", "android_common").(*PrebuiltEtc)
603	expected := "out/soong/target/product/test_device/product/media/alarms"
604	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
605}
606