Merge "Add SetProperties to json-module-graph" am: adf1b2a2cd
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1937639 Change-Id: Ibbb048f90c36f6b46210011adf886806147e00f3
This commit is contained in:
commit
b6fdee8f0a
3 changed files with 267 additions and 11 deletions
|
@ -19,6 +19,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
|
@ -1326,7 +1327,64 @@ func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
|
|||
}
|
||||
|
||||
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
|
||||
(*d)["Android"] = map[string]interface{}{}
|
||||
(*d)["Android"] = map[string]interface{}{
|
||||
// Properties set in Blueprint or in blueprint of a defaults modules
|
||||
"SetProperties": m.propertiesWithValues(),
|
||||
}
|
||||
}
|
||||
|
||||
type propInfo struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
func (m *ModuleBase) propertiesWithValues() []propInfo {
|
||||
var info []propInfo
|
||||
props := m.GetProperties()
|
||||
|
||||
var propsWithValues func(name string, v reflect.Value)
|
||||
propsWithValues = func(name string, v reflect.Value) {
|
||||
kind := v.Kind()
|
||||
switch kind {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
if v.IsNil() {
|
||||
return
|
||||
}
|
||||
propsWithValues(name, v.Elem())
|
||||
case reflect.Struct:
|
||||
if v.IsZero() {
|
||||
return
|
||||
}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
namePrefix := name
|
||||
sTyp := v.Type().Field(i)
|
||||
if proptools.ShouldSkipProperty(sTyp) {
|
||||
continue
|
||||
}
|
||||
if name != "" && !strings.HasSuffix(namePrefix, ".") {
|
||||
namePrefix += "."
|
||||
}
|
||||
if !proptools.IsEmbedded(sTyp) {
|
||||
namePrefix += sTyp.Name
|
||||
}
|
||||
sVal := v.Field(i)
|
||||
propsWithValues(namePrefix, sVal)
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
if v.IsNil() {
|
||||
return
|
||||
}
|
||||
elKind := v.Type().Elem().Kind()
|
||||
info = append(info, propInfo{name, elKind.String() + " " + kind.String()})
|
||||
default:
|
||||
info = append(info, propInfo{name, kind.String()})
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range props {
|
||||
propsWithValues("", reflect.ValueOf(p).Elem())
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
|
||||
|
|
|
@ -615,3 +615,204 @@ func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installM
|
|||
|
||||
return rules
|
||||
}
|
||||
|
||||
type PropsTestModuleEmbedded struct {
|
||||
Embedded_prop *string
|
||||
}
|
||||
|
||||
type propsTestModule struct {
|
||||
ModuleBase
|
||||
DefaultableModuleBase
|
||||
props struct {
|
||||
A string `android:"arch_variant"`
|
||||
B *bool
|
||||
C []string
|
||||
}
|
||||
otherProps struct {
|
||||
PropsTestModuleEmbedded
|
||||
|
||||
D *int64
|
||||
Nested struct {
|
||||
E *string
|
||||
}
|
||||
F *string `blueprint:"mutated"`
|
||||
}
|
||||
}
|
||||
|
||||
func propsTestModuleFactory() Module {
|
||||
module := &propsTestModule{}
|
||||
module.AddProperties(&module.props, &module.otherProps)
|
||||
InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
|
||||
InitDefaultableModule(module)
|
||||
return module
|
||||
}
|
||||
|
||||
type propsTestModuleDefaults struct {
|
||||
ModuleBase
|
||||
DefaultsModuleBase
|
||||
}
|
||||
|
||||
func propsTestModuleDefaultsFactory() Module {
|
||||
defaults := &propsTestModuleDefaults{}
|
||||
module := propsTestModule{}
|
||||
defaults.AddProperties(&module.props, &module.otherProps)
|
||||
InitDefaultsModule(defaults)
|
||||
return defaults
|
||||
}
|
||||
|
||||
func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
str := "abc"
|
||||
p.otherProps.F = &str
|
||||
}
|
||||
|
||||
func TestUsedProperties(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
bp string
|
||||
expectedProps []propInfo
|
||||
}{
|
||||
{
|
||||
desc: "only name",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"Name", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "some props",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
a: "abc",
|
||||
b: true,
|
||||
d: 123,
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"A", "string"},
|
||||
propInfo{"B", "bool"},
|
||||
propInfo{"D", "int64"},
|
||||
propInfo{"Name", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "unused non-pointer prop",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
b: true,
|
||||
d: 123,
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
// for non-pointer cannot distinguish between unused and intentionally set to empty
|
||||
propInfo{"A", "string"},
|
||||
propInfo{"B", "bool"},
|
||||
propInfo{"D", "int64"},
|
||||
propInfo{"Name", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "nested props",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
nested: {
|
||||
e: "abc",
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"Nested.E", "string"},
|
||||
propInfo{"Name", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "arch props",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
arch: {
|
||||
x86_64: {
|
||||
a: "abc",
|
||||
},
|
||||
}
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"Name", "string"},
|
||||
propInfo{"Arch.X86_64.A", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "embedded props",
|
||||
bp: `test {
|
||||
name: "foo",
|
||||
embedded_prop: "a",
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"Embedded_prop", "string"},
|
||||
propInfo{"Name", "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "defaults",
|
||||
bp: `
|
||||
test_defaults {
|
||||
name: "foo_defaults",
|
||||
a: "a",
|
||||
b: true,
|
||||
embedded_prop:"a",
|
||||
arch: {
|
||||
x86_64: {
|
||||
a: "a",
|
||||
},
|
||||
},
|
||||
}
|
||||
test {
|
||||
name: "foo",
|
||||
defaults: ["foo_defaults"],
|
||||
c: ["a"],
|
||||
nested: {
|
||||
e: "d",
|
||||
},
|
||||
target: {
|
||||
linux: {
|
||||
a: "a",
|
||||
},
|
||||
},
|
||||
}
|
||||
`,
|
||||
expectedProps: []propInfo{
|
||||
propInfo{"A", "string"},
|
||||
propInfo{"B", "bool"},
|
||||
propInfo{"C", "string slice"},
|
||||
propInfo{"Embedded_prop", "string"},
|
||||
propInfo{"Nested.E", "string"},
|
||||
propInfo{"Name", "string"},
|
||||
propInfo{"Arch.X86_64.A", "string"},
|
||||
propInfo{"Target.Linux.A", "string"},
|
||||
propInfo{"Defaults", "string slice"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
result := GroupFixturePreparers(
|
||||
PrepareForTestWithAllowMissingDependencies,
|
||||
PrepareForTestWithDefaults,
|
||||
FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
||||
ctx.RegisterModuleType("test", propsTestModuleFactory)
|
||||
ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
|
||||
}),
|
||||
FixtureWithRootAndroidBp(tc.bp),
|
||||
).RunTest(t)
|
||||
|
||||
foo := result.ModuleForTests("foo", "").Module().base()
|
||||
|
||||
AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,17 +244,14 @@ func TestAddJSONData(t *testing.T) {
|
|||
}
|
||||
jsonData := map[string]interface{}{}
|
||||
prebuiltStubsSources.AddJSONData(&jsonData)
|
||||
if fmt.Sprint(jsonData) != fmt.Sprint(
|
||||
expectedOut := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"Android": map[string]interface{}{},
|
||||
"Actions": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"Inputs": []string{},
|
||||
"Outputs": []string{},
|
||||
},
|
||||
},
|
||||
}) {
|
||||
t.Errorf("The JSON data map isn't as expected %s.", jsonData)
|
||||
"Inputs": []string{},
|
||||
"Outputs": []string{},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
|
||||
t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue