Add protected_properties support in defaults modules
Previously, there was no way to prevent a module from overriding a
value provided by a defaults. That made it difficult to ensure
consistency across modules, e.g. for modules that use
framework-module-defaults.
This change adds the protected_properties property to defaults modules
which allows a default module to list those properties that should not
be changed by a module applying those defaults.
Properties can either be listed explicitly by name, or it can just be
a single "*" in which case all properties that are set on the defaults
will be protected.
Bug: 230841626
Test: m nothing
Change-Id: Ibb0e482c2856a572437e7818466f41c5493baf33
diff --git a/android/defaults_test.go b/android/defaults_test.go
index a7542ab..d80f40c 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -19,7 +19,14 @@
)
type defaultsTestProperties struct {
- Foo []string
+ Foo []string
+ Bar []string
+ Nested struct {
+ Fizz *bool
+ }
+ Other struct {
+ Buzz *string
+ }
}
type defaultsTestModule struct {
@@ -130,3 +137,167 @@
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
}
+
+func TestProtectedProperties_ProtectedPropertyNotSet(t *testing.T) {
+ bp := `
+ defaults {
+ name: "transitive",
+ protected_properties: ["foo"],
+ }
+ `
+
+ GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "module \"transitive\": foo: is not set; protected properties must be explicitly set")).
+ RunTest(t)
+}
+
+func TestProtectedProperties_ProtectedPropertyNotLeaf(t *testing.T) {
+ bp := `
+ defaults {
+ name: "transitive",
+ protected_properties: ["nested"],
+ nested: {
+ fizz: true,
+ },
+ }
+ `
+
+ GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qmodule "transitive": nested: property is not supported by this module type "defaults"\E`)).
+ RunTest(t)
+}
+
+// TestProtectedProperties_ApplyDefaults makes sure that the protected_properties property has
+// defaults applied.
+func TestProtectedProperties_HasDefaultsApplied(t *testing.T) {
+
+ bp := `
+ defaults {
+ name: "transitive",
+ protected_properties: ["foo"],
+ foo: ["transitive"],
+ }
+
+ defaults {
+ name: "defaults",
+ defaults: ["transitive"],
+ protected_properties: ["bar"],
+ bar: ["defaults"],
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ defaults := result.Module("defaults", "").(DefaultsModule)
+ AssertDeepEquals(t, "defaults protected properties", []string{"foo", "bar"}, defaults.protectedProperties())
+}
+
+// TestProtectedProperties_ProtectAllProperties makes sure that protected_properties: ["*"] protects
+// all properties.
+func TestProtectedProperties_ProtectAllProperties(t *testing.T) {
+
+ bp := `
+ defaults {
+ name: "transitive",
+ protected_properties: ["other.buzz"],
+ other: {
+ buzz: "transitive",
+ },
+ }
+
+ defaults {
+ name: "defaults",
+ defaults: ["transitive"],
+ visibility: ["//visibility:private"],
+ protected_properties: ["*"],
+ foo: ["other"],
+ bar: ["defaults"],
+ nested: {
+ fizz: true,
+ }
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ defaults := result.Module("defaults", "").(DefaultsModule)
+ AssertDeepEquals(t, "defaults protected properties", []string{"other.buzz", "bar", "foo", "nested.fizz"},
+ defaults.protectedProperties())
+}
+
+func TestProtectedProperties_DetectedOverride(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults",
+ protected_properties: ["foo", "nested.fizz"],
+ foo: ["defaults"],
+ nested: {
+ fizz: true,
+ },
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ foo: ["module"],
+ nested: {
+ fizz: false,
+ },
+ }
+ `
+
+ GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ `\Qmodule "foo": attempts to append ["module"] to protected property "foo"'s value of ["defaults"] defined in module "defaults"\E`,
+ `\Qmodule "foo": attempts to override protected property "nested.fizz" defined in module "defaults" with a different value (override true with false) so removing the property may necessitate other changes.\E`,
+ })).RunTest(t)
+}
+
+func TestProtectedProperties_DefaultsConflict(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults1",
+ protected_properties: ["other.buzz"],
+ other: {
+ buzz: "value",
+ },
+ }
+
+ defaults {
+ name: "defaults2",
+ protected_properties: ["other.buzz"],
+ other: {
+ buzz: "another",
+ },
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults1", "defaults2"],
+ }
+ `
+
+ GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qmodule "foo": has conflicting default values for protected property "other.buzz":
+ defaults module "defaults1" provides value "value"
+ defaults module "defaults2" provides value "another"\E`,
+ )).RunTest(t)
+}