Snap for 7347062 from 6ec1dbf6d48e295cafc4161d8fc006abfb20281d to sc-d1-release
Change-Id: I52c8986b460dd48aa86293a2430015c7ca3f4c2e
diff --git a/bpmodify/bpmodify.go b/bpmodify/bpmodify.go
index 0190f19..29d28f0 100644
--- a/bpmodify/bpmodify.go
+++ b/bpmodify/bpmodify.go
@@ -30,6 +30,8 @@
targetedProperty = new(qualifiedProperty)
addIdents = new(identSet)
removeIdents = new(identSet)
+
+ setString *string
)
func init() {
@@ -38,6 +40,7 @@
flag.Var(targetedProperty, "property", "fully qualified `name` of property to modify (default \"deps\")")
flag.Var(addIdents, "a", "comma or whitespace separated list of identifiers to add")
flag.Var(removeIdents, "r", "comma or whitespace separated list of identifiers to remove")
+ flag.Var(stringPtrFlag{&setString}, "str", "set a string property")
flag.Usage = usage
}
@@ -147,14 +150,18 @@
return false, []error{err}
}
if prop == nil {
- if len(addIdents.idents) == 0 {
+ if len(addIdents.idents) > 0 {
+ // We are adding something to a non-existing list prop, so we need to create it first.
+ prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes(), &parser.List{})
+ } else if setString != nil {
+ // We setting a non-existent string property, so we need to create it first.
+ prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes(), &parser.String{})
+ } else {
// We cannot find an existing prop, and we aren't adding anything to the prop,
// which means we must be removing something from a non-existing prop,
// which means this is a noop.
return false, nil
}
- // Else we are adding something to a non-existing prop, so we need to create it first.
- prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes())
if err != nil {
// Here should be unreachable, but still handle it for completeness.
return false, []error{err}
@@ -166,16 +173,18 @@
}
func getRecursiveProperty(module *parser.Module, name string, prefixes []string) (prop *parser.Property, err error) {
- prop, _, err = getOrCreateRecursiveProperty(module, name, prefixes, false)
+ prop, _, err = getOrCreateRecursiveProperty(module, name, prefixes, nil)
return prop, err
}
-func createRecursiveProperty(module *parser.Module, name string, prefixes []string) (prop *parser.Property, modified bool, err error) {
- return getOrCreateRecursiveProperty(module, name, prefixes, true)
+func createRecursiveProperty(module *parser.Module, name string, prefixes []string,
+ empty parser.Expression) (prop *parser.Property, modified bool, err error) {
+
+ return getOrCreateRecursiveProperty(module, name, prefixes, empty)
}
func getOrCreateRecursiveProperty(module *parser.Module, name string, prefixes []string,
- createIfNotFound bool) (prop *parser.Property, modified bool, err error) {
+ empty parser.Expression) (prop *parser.Property, modified bool, err error) {
m := &module.Map
for i, prefix := range prefixes {
if prop, found := m.GetProperty(prefix); found {
@@ -187,7 +196,7 @@
return nil, false, fmt.Errorf("Expected property %q to be a map, found %s",
strings.Join(prefixes[:i+1], "."), prop.Value.Type())
}
- } else if createIfNotFound {
+ } else if empty != nil {
mm := &parser.Map{}
m.Properties = append(m.Properties, &parser.Property{Name: prefix, Value: mm})
m = mm
@@ -201,8 +210,8 @@
if prop, found := m.GetProperty(name); found {
// We've found a property in the AST, which must mean we didn't modify the AST.
return prop, false, nil
- } else if createIfNotFound {
- prop = &parser.Property{Name: name, Value: &parser.List{}}
+ } else if empty != nil {
+ prop = &parser.Property{Name: name, Value: empty}
m.Properties = append(m.Properties, prop)
return prop, true, nil
} else {
@@ -222,26 +231,37 @@
paramName, moduleName)}
}
- list, ok := value.(*parser.List)
- if !ok {
- return false, []error{fmt.Errorf("expected parameter %s in module %s to be list, found %s",
- paramName, moduleName, value.Type().String())}
- }
+ if len(addIdents.idents) > 0 || len(removeIdents.idents) > 0 {
+ list, ok := value.(*parser.List)
+ if !ok {
+ return false, []error{fmt.Errorf("expected parameter %s in module %s to be list, found %s",
+ paramName, moduleName, value.Type().String())}
+ }
- wasSorted := parser.ListIsSorted(list)
+ wasSorted := parser.ListIsSorted(list)
- for _, a := range addIdents.idents {
- m := parser.AddStringToList(list, a)
- modified = modified || m
- }
+ for _, a := range addIdents.idents {
+ m := parser.AddStringToList(list, a)
+ modified = modified || m
+ }
- for _, r := range removeIdents.idents {
- m := parser.RemoveStringFromList(list, r)
- modified = modified || m
- }
+ for _, r := range removeIdents.idents {
+ m := parser.RemoveStringFromList(list, r)
+ modified = modified || m
+ }
- if (wasSorted || *sortLists) && modified {
- parser.SortList(file, list)
+ if (wasSorted || *sortLists) && modified {
+ parser.SortList(file, list)
+ }
+ } else if setString != nil {
+ str, ok := value.(*parser.String)
+ if !ok {
+ return false, []error{fmt.Errorf("expected parameter %s in module %s to be string, found %s",
+ paramName, moduleName, value.Type().String())}
+ }
+
+ str.Value = *setString
+ modified = true
}
return modified, nil
@@ -304,8 +324,8 @@
return
}
- if len(addIdents.idents) == 0 && len(removeIdents.idents) == 0 {
- report(fmt.Errorf("-a or -r parameter is required"))
+ if len(addIdents.idents) == 0 && len(removeIdents.idents) == 0 && setString == nil {
+ report(fmt.Errorf("-a, -r or -str parameter is required"))
return
}
@@ -352,6 +372,22 @@
}
+type stringPtrFlag struct {
+ s **string
+}
+
+func (f stringPtrFlag) Set(s string) error {
+ *f.s = &s
+ return nil
+}
+
+func (f stringPtrFlag) String() string {
+ if f.s == nil || *f.s == nil {
+ return ""
+ }
+ return **f.s
+}
+
type identSet struct {
idents []string
all bool
diff --git a/bpmodify/bpmodify_test.go b/bpmodify/bpmodify_test.go
index 26b5d82..a92d439 100644
--- a/bpmodify/bpmodify_test.go
+++ b/bpmodify/bpmodify_test.go
@@ -19,234 +19,270 @@
"testing"
"github.com/google/blueprint/parser"
+ "github.com/google/blueprint/proptools"
)
var testCases = []struct {
+ name string
input string
output string
property string
addSet string
removeSet string
+ setString *string
}{
{
- `
- cc_foo {
- name: "foo",
- }
+ name: "add",
+ input: `
+ cc_foo {
+ name: "foo",
+ }
`,
- `
- cc_foo {
- name: "foo",
- deps: ["bar"],
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ deps: ["bar"],
+ }
`,
- "deps",
- "bar",
- "",
+ property: "deps",
+ addSet: "bar",
},
{
- `
- cc_foo {
- name: "foo",
- deps: ["bar"],
- }
+ name: "remove",
+ input: `
+ cc_foo {
+ name: "foo",
+ deps: ["bar"],
+ }
`,
- `
- cc_foo {
- name: "foo",
- deps: [],
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ deps: [],
+ }
`,
- "deps",
- "",
- "bar",
+ property: "deps",
+ removeSet: "bar",
},
{
- `
- cc_foo {
- name: "foo",
- }
+ name: "nested add",
+ input: `
+ cc_foo {
+ name: "foo",
+ }
`,
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "dep2",
- "nested_dep",],
+ output: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "dep2",
+ "nested_dep",],
+ },
},
- },
- }
+ }
`,
- "arch.arm.deps",
- "nested_dep,dep2",
- "",
+ property: "arch.arm.deps",
+ addSet: "nested_dep,dep2",
},
{
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "dep2",
- "nested_dep",
- ],
+ name: "nested remove",
+ input: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "dep2",
+ "nested_dep",
+ ],
+ },
},
- },
- }
+ }
`,
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- ],
+ output: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ ],
+ },
},
- },
- }
+ }
`,
- "arch.arm.deps",
- "",
- "nested_dep,dep2",
+ property: "arch.arm.deps",
+ removeSet: "nested_dep,dep2",
},
{
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "nested_dep",
- "dep2",
- ],
+ name: "add existing",
+ input: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "nested_dep",
+ "dep2",
+ ],
+ },
},
- },
- }
+ }
`,
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "nested_dep",
- "dep2",
- ],
+ output: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "nested_dep",
+ "dep2",
+ ],
+ },
},
- },
- }
+ }
`,
- "arch.arm.deps",
- "dep2,dep2",
- "",
+ property: "arch.arm.deps",
+ addSet: "dep2,dep2",
},
{
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "nested_dep",
- "dep2",
- ],
+ name: "remove missing",
+ input: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "nested_dep",
+ "dep2",
+ ],
+ },
},
- },
- }
+ }
`,
- `
- cc_foo {
- name: "foo",
- arch: {
- arm: {
- deps: [
- "nested_dep",
- "dep2",
- ],
+ output: `
+ cc_foo {
+ name: "foo",
+ arch: {
+ arm: {
+ deps: [
+ "nested_dep",
+ "dep2",
+ ],
+ },
},
- },
- }
+ }
`,
- "arch.arm.deps",
- "",
- "dep3,dep4",
+ property: "arch.arm.deps",
+ removeSet: "dep3,dep4",
},
{
- `
- cc_foo {
- name: "foo",
- }
+ name: "remove non existent",
+ input: `
+ cc_foo {
+ name: "foo",
+ }
`,
- `
- cc_foo {
- name: "foo",
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ }
`,
- "deps",
- "",
- "bar",
+ property: "deps",
+ removeSet: "bar",
},
{
- `
- cc_foo {
- name: "foo",
- arch: {},
- }
+ name: "remove non existent nested",
+ input: `
+ cc_foo {
+ name: "foo",
+ arch: {},
+ }
`,
- `
- cc_foo {
- name: "foo",
- arch: {},
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ arch: {},
+ }
`,
- "arch.arm.deps",
- "",
- "dep3,dep4",
+ property: "arch.arm.deps",
+ removeSet: "dep3,dep4",
},
{
- `
- cc_foo {
- name: "foo",
- versions: ["1", "2"],
- }
+ name: "add numeric sorted",
+ input: `
+ cc_foo {
+ name: "foo",
+ versions: ["1", "2"],
+ }
`,
- `
- cc_foo {
- name: "foo",
- versions: [
- "1",
- "2",
- "10",
- ],
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ versions: [
+ "1",
+ "2",
+ "10",
+ ],
+ }
`,
- "versions",
- "10",
- "",
+ property: "versions",
+ addSet: "10",
},
{
- `
- cc_foo {
- name: "foo",
- deps: ["bar-v1-bar", "bar-v2-bar"],
- }
+ name: "add mixed sorted",
+ input: `
+ cc_foo {
+ name: "foo",
+ deps: ["bar-v1-bar", "bar-v2-bar"],
+ }
`,
- `
- cc_foo {
- name: "foo",
- deps: [
- "bar-v1-bar",
- "bar-v2-bar",
- "bar-v10-bar",
- ],
- }
+ output: `
+ cc_foo {
+ name: "foo",
+ deps: [
+ "bar-v1-bar",
+ "bar-v2-bar",
+ "bar-v10-bar",
+ ],
+ }
`,
- "deps",
- "bar-v10-bar",
- "",
+ property: "deps",
+ addSet: "bar-v10-bar",
+ },
+ {
+ name: "set string",
+ input: `
+ cc_foo {
+ name: "foo",
+ }
+ `,
+ output: `
+ cc_foo {
+ name: "foo",
+ foo: "bar",
+ }
+ `,
+ property: "foo",
+ setString: proptools.StringPtr("bar"),
+ },
+ {
+ name: "set existing string",
+ input: `
+ cc_foo {
+ name: "foo",
+ foo: "baz",
+ }
+ `,
+ output: `
+ cc_foo {
+ name: "foo",
+ foo: "bar",
+ }
+ `,
+ property: "foo",
+ setString: proptools.StringPtr("bar"),
},
}
@@ -260,42 +296,43 @@
func TestProcessModule(t *testing.T) {
for i, testCase := range testCases {
- targetedProperty.Set(testCase.property)
- addIdents.Set(testCase.addSet)
- removeIdents.Set(testCase.removeSet)
+ t.Run(testCase.name, func(t *testing.T) {
+ targetedProperty.Set(testCase.property)
+ addIdents.Set(testCase.addSet)
+ removeIdents.Set(testCase.removeSet)
+ setString = testCase.setString
- inAst, errs := parser.ParseAndEval("", strings.NewReader(testCase.input), parser.NewScope(nil))
- if len(errs) > 0 {
- t.Errorf("test case %d:", i)
- for _, err := range errs {
- t.Errorf(" %s", err)
- }
- t.Errorf("failed to parse:")
- t.Errorf("%+v", testCase)
- continue
- }
-
- if inModule, ok := inAst.Defs[0].(*parser.Module); !ok {
- t.Errorf("test case %d:", i)
- t.Errorf(" input must only contain a single module definition: %s", testCase.input)
- continue
- } else {
- _, errs := processModule(inModule, "", inAst)
+ inAst, errs := parser.ParseAndEval("", strings.NewReader(testCase.input), parser.NewScope(nil))
if len(errs) > 0 {
- t.Errorf("test case %d:", i)
for _, err := range errs {
t.Errorf(" %s", err)
}
+ t.Errorf("failed to parse:")
+ t.Errorf("%+v", testCase)
+ t.FailNow()
}
- inModuleText, _ := parser.Print(inAst)
- inModuleString := string(inModuleText)
- if simplifyModuleDefinition(inModuleString) != simplifyModuleDefinition(testCase.output) {
- t.Errorf("test case %d:", i)
- t.Errorf("expected module definition:")
- t.Errorf(" %s", testCase.output)
- t.Errorf("actual module definition:")
- t.Errorf(" %s", inModuleString)
+
+ if inModule, ok := inAst.Defs[0].(*parser.Module); !ok {
+ t.Fatalf(" input must only contain a single module definition: %s", testCase.input)
+ } else {
+ _, errs := processModule(inModule, "", inAst)
+ if len(errs) > 0 {
+ t.Errorf("test case %d:", i)
+ for _, err := range errs {
+ t.Errorf(" %s", err)
+ }
+ }
+ inModuleText, _ := parser.Print(inAst)
+ inModuleString := string(inModuleText)
+ if simplifyModuleDefinition(inModuleString) != simplifyModuleDefinition(testCase.output) {
+ t.Errorf("test case %d:", i)
+ t.Errorf("expected module definition:")
+ t.Errorf(" %s", testCase.output)
+ t.Errorf("actual module definition:")
+ t.Errorf(" %s", inModuleString)
+ }
}
- }
+ })
}
+
}