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
This commit is contained in:
Paul Duffin
2022-05-04 11:39:52 +00:00
parent a0bab18a47
commit 799962789a
2 changed files with 463 additions and 31 deletions

View File

@@ -19,7 +19,14 @@ import (
)
type defaultsTestProperties struct {
Foo []string
Foo []string
Bar []string
Nested struct {
Fizz *bool
}
Other struct {
Buzz *string
}
}
type defaultsTestModule struct {
@@ -130,3 +137,167 @@ func TestDefaultsAllowMissingDependencies(t *testing.T) {
// 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)
}