xref: /aosp_15_r20/build/soong/fsgen/filesystem_creator_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2024 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 fsgen
16
17import (
18	"android/soong/android"
19	"android/soong/etc"
20	"android/soong/filesystem"
21	"android/soong/java"
22	"testing"
23
24	"github.com/google/blueprint/proptools"
25)
26
27var prepareForTestWithFsgenBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
28
29func TestFileSystemCreatorSystemImageProps(t *testing.T) {
30	result := android.GroupFixturePreparers(
31		android.PrepareForIntegrationTestWithAndroid,
32		android.PrepareForTestWithAndroidBuildComponents,
33		android.PrepareForTestWithAllowMissingDependencies,
34		filesystem.PrepareForTestWithFilesystemBuildComponents,
35		prepareForTestWithFsgenBuildComponents,
36		android.FixtureModifyConfig(func(config android.Config) {
37			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.BoardAvbEnable = true
38			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
39				map[string]android.PartitionQualifiedVariablesType{
40					"system": {
41						BoardAvbKeyPath:       "external/avb/test/data/testkey_rsa4096.pem",
42						BoardAvbAlgorithm:     "SHA256_RSA4096",
43						BoardAvbRollbackIndex: "0",
44						BoardFileSystemType:   "ext4",
45					},
46				}
47		}),
48		android.FixtureMergeMockFs(android.MockFS{
49			"external/avb/test/data/testkey_rsa4096.pem": nil,
50			"external/avb/test/Android.bp": []byte(`
51			filegroup {
52				name: "avb_testkey_rsa4096",
53				srcs: ["data/testkey_rsa4096.pem"],
54			}
55			`),
56			"build/soong/fsgen/Android.bp": []byte(`
57			soong_filesystem_creator {
58				name: "foo",
59			}
60			`),
61		}),
62	).RunTest(t)
63
64	fooSystem := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().(interface {
65		FsProps() filesystem.FilesystemProperties
66	})
67	android.AssertBoolEquals(
68		t,
69		"Property expected to match the product variable 'BOARD_AVB_ENABLE'",
70		true,
71		proptools.Bool(fooSystem.FsProps().Use_avb),
72	)
73	android.AssertStringEquals(
74		t,
75		"Property the avb_private_key property to be set to the existing filegroup",
76		":avb_testkey_rsa4096",
77		proptools.String(fooSystem.FsProps().Avb_private_key),
78	)
79	android.AssertStringEquals(
80		t,
81		"Property expected to match the product variable 'BOARD_AVB_ALGORITHM'",
82		"SHA256_RSA4096",
83		proptools.String(fooSystem.FsProps().Avb_algorithm),
84	)
85	android.AssertIntEquals(
86		t,
87		"Property expected to match the product variable 'BOARD_AVB_SYSTEM_ROLLBACK_INDEX'",
88		0,
89		proptools.Int(fooSystem.FsProps().Rollback_index),
90	)
91	android.AssertStringEquals(
92		t,
93		"Property expected to match the product variable 'BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE'",
94		"ext4",
95		proptools.String(fooSystem.FsProps().Type),
96	)
97}
98
99func TestFileSystemCreatorSetPartitionDeps(t *testing.T) {
100	result := android.GroupFixturePreparers(
101		android.PrepareForIntegrationTestWithAndroid,
102		android.PrepareForTestWithAndroidBuildComponents,
103		android.PrepareForTestWithAllowMissingDependencies,
104		filesystem.PrepareForTestWithFilesystemBuildComponents,
105		prepareForTestWithFsgenBuildComponents,
106		java.PrepareForTestWithJavaBuildComponents,
107		java.PrepareForTestWithJavaDefaultModules,
108		android.FixtureModifyConfig(func(config android.Config) {
109			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar", "baz"}
110			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
111				map[string]android.PartitionQualifiedVariablesType{
112					"system": {
113						BoardFileSystemType: "ext4",
114					},
115				}
116		}),
117		android.FixtureMergeMockFs(android.MockFS{
118			"external/avb/test/data/testkey_rsa4096.pem": nil,
119			"build/soong/fsgen/Android.bp": []byte(`
120			soong_filesystem_creator {
121				name: "foo",
122			}
123			`),
124		}),
125	).RunTestWithBp(t, `
126	java_library {
127		name: "bar",
128		srcs: ["A.java"],
129	}
130	java_library {
131		name: "baz",
132		srcs: ["A.java"],
133		product_specific: true,
134	}
135	`)
136
137	android.AssertBoolEquals(
138		t,
139		"Generated system image expected to depend on system partition installed \"bar\"",
140		true,
141		java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "bar"),
142	)
143	android.AssertBoolEquals(
144		t,
145		"Generated system image expected to not depend on product partition installed \"baz\"",
146		false,
147		java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "baz"),
148	)
149}
150
151func TestFileSystemCreatorDepsWithNamespace(t *testing.T) {
152	result := android.GroupFixturePreparers(
153		android.PrepareForIntegrationTestWithAndroid,
154		android.PrepareForTestWithAndroidBuildComponents,
155		android.PrepareForTestWithAllowMissingDependencies,
156		android.PrepareForTestWithNamespace,
157		android.PrepareForTestWithArchMutator,
158		filesystem.PrepareForTestWithFilesystemBuildComponents,
159		prepareForTestWithFsgenBuildComponents,
160		java.PrepareForTestWithJavaBuildComponents,
161		java.PrepareForTestWithJavaDefaultModules,
162		android.FixtureModifyConfig(func(config android.Config) {
163			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar"}
164			config.TestProductVariables.NamespacesToExport = []string{"a/b"}
165			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
166				map[string]android.PartitionQualifiedVariablesType{
167					"system": {
168						BoardFileSystemType: "ext4",
169					},
170				}
171		}),
172		android.PrepareForNativeBridgeEnabled,
173		android.FixtureMergeMockFs(android.MockFS{
174			"external/avb/test/data/testkey_rsa4096.pem": nil,
175			"build/soong/fsgen/Android.bp": []byte(`
176			soong_filesystem_creator {
177				name: "foo",
178			}
179			`),
180			"a/b/Android.bp": []byte(`
181			soong_namespace{
182			}
183			java_library {
184				name: "bar",
185				srcs: ["A.java"],
186				compile_multilib: "64",
187			}
188			`),
189			"c/d/Android.bp": []byte(`
190			soong_namespace{
191			}
192			java_library {
193				name: "bar",
194				srcs: ["A.java"],
195			}
196			`),
197		}),
198	).RunTest(t)
199
200	var packagingProps android.PackagingProperties
201	for _, prop := range result.ModuleForTests("test_product_generated_system_image", "android_common").Module().GetProperties() {
202		if packagingPropStruct, ok := prop.(*android.PackagingProperties); ok {
203			packagingProps = *packagingPropStruct
204		}
205	}
206	moduleDeps := packagingProps.Multilib.Lib64.Deps
207
208	eval := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
209	android.AssertStringListContains(
210		t,
211		"Generated system image expected to depend on \"bar\" defined in \"a/b\" namespace",
212		moduleDeps.GetOrDefault(eval, nil),
213		"//a/b:bar",
214	)
215	android.AssertStringListDoesNotContain(
216		t,
217		"Generated system image expected to not depend on \"bar\" defined in \"c/d\" namespace",
218		moduleDeps.GetOrDefault(eval, nil),
219		"//c/d:bar",
220	)
221}
222
223func TestRemoveOverriddenModulesFromDeps(t *testing.T) {
224	result := android.GroupFixturePreparers(
225		android.PrepareForIntegrationTestWithAndroid,
226		android.PrepareForTestWithAndroidBuildComponents,
227		android.PrepareForTestWithAllowMissingDependencies,
228		prepareForTestWithFsgenBuildComponents,
229		java.PrepareForTestWithJavaBuildComponents,
230		android.FixtureMergeMockFs(android.MockFS{
231			"external/avb/test/data/testkey_rsa4096.pem": nil,
232			"build/soong/fsgen/Android.bp": []byte(`
233			soong_filesystem_creator {
234				name: "foo",
235			}
236			`),
237		}),
238		android.FixtureModifyConfig(func(config android.Config) {
239			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"libfoo", "libbar"}
240		}),
241	).RunTestWithBp(t, `
242java_library {
243	name: "libfoo",
244}
245java_library {
246	name: "libbar",
247	required: ["libbaz"],
248}
249java_library {
250	name: "libbaz",
251	overrides: ["libfoo"], // overrides libfoo
252}
253	`)
254	resolvedSystemDeps := result.TestContext.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps["system"]
255	_, libFooInDeps := (*resolvedSystemDeps)["libfoo"]
256	android.AssertBoolEquals(t, "libfoo should not appear in deps because it has been overridden by libbaz. The latter is a required dep of libbar, which is listed in PRODUCT_PACKAGES", false, libFooInDeps)
257}
258
259func TestPrebuiltEtcModuleGen(t *testing.T) {
260	result := android.GroupFixturePreparers(
261		android.PrepareForIntegrationTestWithAndroid,
262		android.PrepareForTestWithAndroidBuildComponents,
263		android.PrepareForTestWithAllowMissingDependencies,
264		filesystem.PrepareForTestWithFilesystemBuildComponents,
265		prepareForTestWithFsgenBuildComponents,
266		android.FixtureModifyConfig(func(config android.Config) {
267			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles = []string{
268				"frameworks/base/config/preloaded-classes:system/etc/preloaded-classes",
269				"frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl:system/usr/keylayout/subdir/Vendor_0079_Product_0011.kl",
270				"frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl:system/usr/keylayout/subdir/Vendor_0079_Product_18d4.kl",
271				"some/non/existing/file.txt:system/etc/file.txt",
272				"device/sample/etc/apns-full-conf.xml:product/etc/apns-conf.xml:google",
273				"device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml",
274			}
275			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
276				map[string]android.PartitionQualifiedVariablesType{
277					"system": {
278						BoardFileSystemType: "ext4",
279					},
280				}
281		}),
282		android.FixtureMergeMockFs(android.MockFS{
283			"external/avb/test/data/testkey_rsa4096.pem": nil,
284			"build/soong/fsgen/Android.bp": []byte(`
285			soong_filesystem_creator {
286				name: "foo",
287			}
288			`),
289			"frameworks/base/config/preloaded-classes":                   nil,
290			"frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl": nil,
291			"frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl": nil,
292			"device/sample/etc/apns-full-conf.xml":                       nil,
293		}),
294	).RunTest(t)
295
296	checkModuleProp := func(m android.Module, matcher func(actual interface{}) bool) bool {
297		for _, prop := range m.GetProperties() {
298
299			if matcher(prop) {
300				return true
301			}
302		}
303		return false
304	}
305
306	// check generated prebuilt_* module type install path and install partition
307	generatedModule := result.ModuleForTests("system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module()
308	etcModule, _ := generatedModule.(*etc.PrebuiltEtc)
309	android.AssertStringEquals(
310		t,
311		"module expected to have etc install path",
312		"etc",
313		etcModule.BaseDir(),
314	)
315	android.AssertBoolEquals(
316		t,
317		"module expected to be installed in system partition",
318		true,
319		!generatedModule.InstallInProduct() &&
320			!generatedModule.InstallInVendor() &&
321			!generatedModule.InstallInSystemExt(),
322	)
323
324	// check generated prebuilt_* module specifies correct relative_install_path property
325	generatedModule = result.ModuleForTests("system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module()
326	etcModule, _ = generatedModule.(*etc.PrebuiltEtc)
327	android.AssertStringEquals(
328		t,
329		"module expected to set correct relative_install_path properties",
330		"subdir",
331		etcModule.SubDir(),
332	)
333
334	// check that prebuilt_* module is not generated for non existing source file
335	android.AssertPanicMessageContains(
336		t,
337		"prebuilt_* module not generated for non existing source file",
338		"failed to find module \"system-some_non_existing-etc-0\"",
339		func() { result.ModuleForTests("system-some_non_existing-etc-0", "android_arm64_armv8-a") },
340	)
341
342	// check that duplicate src file can exist in PRODUCT_COPY_FILES and generates separate modules
343	generatedModule0 := result.ModuleForTests("product-device_sample_etc-etc-0", "android_arm64_armv8-a").Module()
344	generatedModule1 := result.ModuleForTests("product-device_sample_etc-etc-1", "android_arm64_armv8-a").Module()
345
346	// check that generated prebuilt_* module sets correct srcs and dsts property
347	eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
348	android.AssertBoolEquals(
349		t,
350		"module expected to set correct srcs and dsts properties",
351		true,
352		checkModuleProp(generatedModule0, func(actual interface{}) bool {
353			if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
354				srcs := p.Srcs.GetOrDefault(eval, nil)
355				dsts := p.Dsts.GetOrDefault(eval, nil)
356				return len(srcs) == 1 &&
357					srcs[0] == "apns-full-conf.xml" &&
358					len(dsts) == 1 &&
359					dsts[0] == "apns-conf.xml"
360			}
361			return false
362		}),
363	)
364
365	// check that generated prebuilt_* module sets correct srcs and dsts property
366	eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
367	android.AssertBoolEquals(
368		t,
369		"module expected to set correct srcs and dsts properties",
370		true,
371		checkModuleProp(generatedModule1, func(actual interface{}) bool {
372			if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
373				srcs := p.Srcs.GetOrDefault(eval, nil)
374				dsts := p.Dsts.GetOrDefault(eval, nil)
375				return len(srcs) == 1 &&
376					srcs[0] == "apns-full-conf.xml" &&
377					len(dsts) == 1 &&
378					dsts[0] == "apns-conf-2.xml"
379			}
380			return false
381		}),
382	)
383}
384