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