| // Copyright 2020 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package main |
| |
| import ( |
| "strings" |
| "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 |
| }{ |
| { |
| name: "add", |
| input: ` |
| cc_foo { |
| name: "foo", |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| deps: ["bar"], |
| } |
| `, |
| property: "deps", |
| addSet: "bar", |
| }, |
| { |
| name: "remove", |
| input: ` |
| cc_foo { |
| name: "foo", |
| deps: ["bar"], |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| deps: [], |
| } |
| `, |
| property: "deps", |
| removeSet: "bar", |
| }, |
| { |
| name: "nested add", |
| input: ` |
| cc_foo { |
| name: "foo", |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "dep2", |
| "nested_dep",], |
| }, |
| }, |
| } |
| `, |
| property: "arch.arm.deps", |
| addSet: "nested_dep,dep2", |
| }, |
| { |
| name: "nested remove", |
| input: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "dep2", |
| "nested_dep", |
| ], |
| }, |
| }, |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| ], |
| }, |
| }, |
| } |
| `, |
| property: "arch.arm.deps", |
| removeSet: "nested_dep,dep2", |
| }, |
| { |
| name: "add existing", |
| input: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "nested_dep", |
| "dep2", |
| ], |
| }, |
| }, |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "nested_dep", |
| "dep2", |
| ], |
| }, |
| }, |
| } |
| `, |
| property: "arch.arm.deps", |
| addSet: "dep2,dep2", |
| }, |
| { |
| name: "remove missing", |
| input: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "nested_dep", |
| "dep2", |
| ], |
| }, |
| }, |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| arch: { |
| arm: { |
| deps: [ |
| "nested_dep", |
| "dep2", |
| ], |
| }, |
| }, |
| } |
| `, |
| property: "arch.arm.deps", |
| removeSet: "dep3,dep4", |
| }, |
| { |
| name: "remove non existent", |
| input: ` |
| cc_foo { |
| name: "foo", |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| } |
| `, |
| property: "deps", |
| removeSet: "bar", |
| }, |
| { |
| name: "remove non existent nested", |
| input: ` |
| cc_foo { |
| name: "foo", |
| arch: {}, |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| arch: {}, |
| } |
| `, |
| property: "arch.arm.deps", |
| removeSet: "dep3,dep4", |
| }, |
| { |
| name: "add numeric sorted", |
| input: ` |
| cc_foo { |
| name: "foo", |
| versions: ["1", "2"], |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| versions: [ |
| "1", |
| "2", |
| "10", |
| ], |
| } |
| `, |
| property: "versions", |
| addSet: "10", |
| }, |
| { |
| name: "add mixed sorted", |
| input: ` |
| cc_foo { |
| name: "foo", |
| deps: ["bar-v1-bar", "bar-v2-bar"], |
| } |
| `, |
| output: ` |
| cc_foo { |
| name: "foo", |
| deps: [ |
| "bar-v1-bar", |
| "bar-v2-bar", |
| "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"), |
| }, |
| } |
| |
| func simplifyModuleDefinition(def string) string { |
| var result string |
| for _, line := range strings.Split(def, "\n") { |
| result += strings.TrimSpace(line) |
| } |
| return result |
| } |
| |
| func TestProcessModule(t *testing.T) { |
| for i, testCase := range testCases { |
| 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 { |
| for _, err := range errs { |
| t.Errorf(" %s", err) |
| } |
| t.Errorf("failed to parse:") |
| t.Errorf("%+v", testCase) |
| t.FailNow() |
| } |
| |
| 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) |
| } |
| } |
| }) |
| } |
| |
| } |