1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved. 2*1fa6dee9SAndroid Build Coastguard Worker// 3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*1fa6dee9SAndroid Build Coastguard Worker// 7*1fa6dee9SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*1fa6dee9SAndroid Build Coastguard Worker// 9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License. 14*1fa6dee9SAndroid Build Coastguard Worker 15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint 16*1fa6dee9SAndroid Build Coastguard Worker 17*1fa6dee9SAndroid Build Coastguard Workerimport ( 18*1fa6dee9SAndroid Build Coastguard Worker "reflect" 19*1fa6dee9SAndroid Build Coastguard Worker "slices" 20*1fa6dee9SAndroid Build Coastguard Worker "strconv" 21*1fa6dee9SAndroid Build Coastguard Worker "strings" 22*1fa6dee9SAndroid Build Coastguard Worker "testing" 23*1fa6dee9SAndroid Build Coastguard Worker "unsafe" 24*1fa6dee9SAndroid Build Coastguard Worker) 25*1fa6dee9SAndroid Build Coastguard Worker 26*1fa6dee9SAndroid Build Coastguard Workertype testVariableRef struct { 27*1fa6dee9SAndroid Build Coastguard Worker start, end int 28*1fa6dee9SAndroid Build Coastguard Worker name string 29*1fa6dee9SAndroid Build Coastguard Worker} 30*1fa6dee9SAndroid Build Coastguard Worker 31*1fa6dee9SAndroid Build Coastguard Workerfunc TestParseNinjaString(t *testing.T) { 32*1fa6dee9SAndroid Build Coastguard Worker testCases := []struct { 33*1fa6dee9SAndroid Build Coastguard Worker input string 34*1fa6dee9SAndroid Build Coastguard Worker vars []string 35*1fa6dee9SAndroid Build Coastguard Worker value string 36*1fa6dee9SAndroid Build Coastguard Worker eval string 37*1fa6dee9SAndroid Build Coastguard Worker err string 38*1fa6dee9SAndroid Build Coastguard Worker }{ 39*1fa6dee9SAndroid Build Coastguard Worker { 40*1fa6dee9SAndroid Build Coastguard Worker input: "abc def $ghi jkl", 41*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"ghi"}, 42*1fa6dee9SAndroid Build Coastguard Worker value: "abc def ${namespace.ghi} jkl", 43*1fa6dee9SAndroid Build Coastguard Worker eval: "abc def GHI jkl", 44*1fa6dee9SAndroid Build Coastguard Worker }, 45*1fa6dee9SAndroid Build Coastguard Worker { 46*1fa6dee9SAndroid Build Coastguard Worker input: "abc def $ghi$jkl", 47*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"ghi", "jkl"}, 48*1fa6dee9SAndroid Build Coastguard Worker value: "abc def ${namespace.ghi}${namespace.jkl}", 49*1fa6dee9SAndroid Build Coastguard Worker eval: "abc def GHIJKL", 50*1fa6dee9SAndroid Build Coastguard Worker }, 51*1fa6dee9SAndroid Build Coastguard Worker { 52*1fa6dee9SAndroid Build Coastguard Worker input: "foo $012_-345xyz_! bar", 53*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"012_-345xyz_"}, 54*1fa6dee9SAndroid Build Coastguard Worker value: "foo ${namespace.012_-345xyz_}! bar", 55*1fa6dee9SAndroid Build Coastguard Worker eval: "foo 012_-345XYZ_! bar", 56*1fa6dee9SAndroid Build Coastguard Worker }, 57*1fa6dee9SAndroid Build Coastguard Worker { 58*1fa6dee9SAndroid Build Coastguard Worker input: "foo ${012_-345xyz_} bar", 59*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"012_-345xyz_"}, 60*1fa6dee9SAndroid Build Coastguard Worker value: "foo ${namespace.012_-345xyz_} bar", 61*1fa6dee9SAndroid Build Coastguard Worker eval: "foo 012_-345XYZ_ bar", 62*1fa6dee9SAndroid Build Coastguard Worker }, 63*1fa6dee9SAndroid Build Coastguard Worker { 64*1fa6dee9SAndroid Build Coastguard Worker input: "foo ${012_-345xyz_} bar", 65*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"012_-345xyz_"}, 66*1fa6dee9SAndroid Build Coastguard Worker value: "foo ${namespace.012_-345xyz_} bar", 67*1fa6dee9SAndroid Build Coastguard Worker eval: "foo 012_-345XYZ_ bar", 68*1fa6dee9SAndroid Build Coastguard Worker }, 69*1fa6dee9SAndroid Build Coastguard Worker { 70*1fa6dee9SAndroid Build Coastguard Worker input: "foo $$ bar", 71*1fa6dee9SAndroid Build Coastguard Worker vars: nil, 72*1fa6dee9SAndroid Build Coastguard Worker value: "foo $$ bar", 73*1fa6dee9SAndroid Build Coastguard Worker eval: "foo $$ bar", 74*1fa6dee9SAndroid Build Coastguard Worker }, 75*1fa6dee9SAndroid Build Coastguard Worker { 76*1fa6dee9SAndroid Build Coastguard Worker input: "$foo${bar}", 77*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"foo", "bar"}, 78*1fa6dee9SAndroid Build Coastguard Worker value: "${namespace.foo}${namespace.bar}", 79*1fa6dee9SAndroid Build Coastguard Worker eval: "FOOBAR", 80*1fa6dee9SAndroid Build Coastguard Worker }, 81*1fa6dee9SAndroid Build Coastguard Worker { 82*1fa6dee9SAndroid Build Coastguard Worker input: "$foo$$", 83*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"foo"}, 84*1fa6dee9SAndroid Build Coastguard Worker value: "${namespace.foo}$$", 85*1fa6dee9SAndroid Build Coastguard Worker eval: "FOO$$", 86*1fa6dee9SAndroid Build Coastguard Worker }, 87*1fa6dee9SAndroid Build Coastguard Worker { 88*1fa6dee9SAndroid Build Coastguard Worker input: "foo bar", 89*1fa6dee9SAndroid Build Coastguard Worker vars: nil, 90*1fa6dee9SAndroid Build Coastguard Worker value: "foo bar", 91*1fa6dee9SAndroid Build Coastguard Worker eval: "foo bar", 92*1fa6dee9SAndroid Build Coastguard Worker }, 93*1fa6dee9SAndroid Build Coastguard Worker { 94*1fa6dee9SAndroid Build Coastguard Worker input: " foo ", 95*1fa6dee9SAndroid Build Coastguard Worker vars: nil, 96*1fa6dee9SAndroid Build Coastguard Worker value: "$ foo ", 97*1fa6dee9SAndroid Build Coastguard Worker eval: "$ foo ", 98*1fa6dee9SAndroid Build Coastguard Worker }, 99*1fa6dee9SAndroid Build Coastguard Worker { 100*1fa6dee9SAndroid Build Coastguard Worker input: "\tfoo ", 101*1fa6dee9SAndroid Build Coastguard Worker vars: nil, 102*1fa6dee9SAndroid Build Coastguard Worker value: "\tfoo ", 103*1fa6dee9SAndroid Build Coastguard Worker eval: "\tfoo ", 104*1fa6dee9SAndroid Build Coastguard Worker }, 105*1fa6dee9SAndroid Build Coastguard Worker { 106*1fa6dee9SAndroid Build Coastguard Worker input: "\nfoo ", 107*1fa6dee9SAndroid Build Coastguard Worker vars: nil, 108*1fa6dee9SAndroid Build Coastguard Worker value: "$\nfoo ", 109*1fa6dee9SAndroid Build Coastguard Worker eval: "\nfoo ", 110*1fa6dee9SAndroid Build Coastguard Worker }, 111*1fa6dee9SAndroid Build Coastguard Worker { 112*1fa6dee9SAndroid Build Coastguard Worker input: " $foo ", 113*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"foo"}, 114*1fa6dee9SAndroid Build Coastguard Worker value: "$ ${namespace.foo} ", 115*1fa6dee9SAndroid Build Coastguard Worker eval: " FOO ", 116*1fa6dee9SAndroid Build Coastguard Worker }, 117*1fa6dee9SAndroid Build Coastguard Worker { 118*1fa6dee9SAndroid Build Coastguard Worker input: "\t$foo ", 119*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"foo"}, 120*1fa6dee9SAndroid Build Coastguard Worker value: "\t${namespace.foo} ", 121*1fa6dee9SAndroid Build Coastguard Worker eval: "\tFOO ", 122*1fa6dee9SAndroid Build Coastguard Worker }, 123*1fa6dee9SAndroid Build Coastguard Worker { 124*1fa6dee9SAndroid Build Coastguard Worker input: "\n$foo ", 125*1fa6dee9SAndroid Build Coastguard Worker vars: []string{"foo"}, 126*1fa6dee9SAndroid Build Coastguard Worker value: "$\n${namespace.foo} ", 127*1fa6dee9SAndroid Build Coastguard Worker eval: "\nFOO ", 128*1fa6dee9SAndroid Build Coastguard Worker }, 129*1fa6dee9SAndroid Build Coastguard Worker { 130*1fa6dee9SAndroid Build Coastguard Worker input: "foo $ bar", 131*1fa6dee9SAndroid Build Coastguard Worker err: `error parsing ninja string "foo $ bar": invalid character after '$' at byte offset 5`, 132*1fa6dee9SAndroid Build Coastguard Worker }, 133*1fa6dee9SAndroid Build Coastguard Worker { 134*1fa6dee9SAndroid Build Coastguard Worker input: "foo $", 135*1fa6dee9SAndroid Build Coastguard Worker err: "unexpected end of string after '$'", 136*1fa6dee9SAndroid Build Coastguard Worker }, 137*1fa6dee9SAndroid Build Coastguard Worker { 138*1fa6dee9SAndroid Build Coastguard Worker input: "foo ${} bar", 139*1fa6dee9SAndroid Build Coastguard Worker err: `error parsing ninja string "foo ${} bar": empty variable name at byte offset 6`, 140*1fa6dee9SAndroid Build Coastguard Worker }, 141*1fa6dee9SAndroid Build Coastguard Worker { 142*1fa6dee9SAndroid Build Coastguard Worker input: "foo ${abc!} bar", 143*1fa6dee9SAndroid Build Coastguard Worker err: `error parsing ninja string "foo ${abc!} bar": invalid character in variable name at byte offset 9`, 144*1fa6dee9SAndroid Build Coastguard Worker }, 145*1fa6dee9SAndroid Build Coastguard Worker { 146*1fa6dee9SAndroid Build Coastguard Worker input: "foo ${abc", 147*1fa6dee9SAndroid Build Coastguard Worker err: "unexpected end of string in variable name", 148*1fa6dee9SAndroid Build Coastguard Worker }, 149*1fa6dee9SAndroid Build Coastguard Worker } 150*1fa6dee9SAndroid Build Coastguard Worker 151*1fa6dee9SAndroid Build Coastguard Worker for _, testCase := range testCases { 152*1fa6dee9SAndroid Build Coastguard Worker t.Run(testCase.input, func(t *testing.T) { 153*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "namespace.") 154*1fa6dee9SAndroid Build Coastguard Worker variablesMap := map[Variable]*ninjaString{} 155*1fa6dee9SAndroid Build Coastguard Worker for _, varName := range testCase.vars { 156*1fa6dee9SAndroid Build Coastguard Worker _, err := scope.LookupVariable(varName) 157*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 158*1fa6dee9SAndroid Build Coastguard Worker v, err := scope.AddLocalVariable(varName, strings.ToUpper(varName)) 159*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 160*1fa6dee9SAndroid Build Coastguard Worker t.Fatalf("error creating scope: %s", err) 161*1fa6dee9SAndroid Build Coastguard Worker } 162*1fa6dee9SAndroid Build Coastguard Worker variablesMap[v] = simpleNinjaString(strings.ToUpper(varName)) 163*1fa6dee9SAndroid Build Coastguard Worker } 164*1fa6dee9SAndroid Build Coastguard Worker } 165*1fa6dee9SAndroid Build Coastguard Worker 166*1fa6dee9SAndroid Build Coastguard Worker output, err := parseNinjaString(scope, testCase.input) 167*1fa6dee9SAndroid Build Coastguard Worker if err == nil { 168*1fa6dee9SAndroid Build Coastguard Worker if g, w := output.Value(&nameTracker{}), testCase.value; g != w { 169*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect Value output, want %q, got %q", w, g) 170*1fa6dee9SAndroid Build Coastguard Worker } 171*1fa6dee9SAndroid Build Coastguard Worker 172*1fa6dee9SAndroid Build Coastguard Worker eval, err := output.Eval(variablesMap) 173*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 174*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("unexpected error in Eval: %s", err) 175*1fa6dee9SAndroid Build Coastguard Worker } 176*1fa6dee9SAndroid Build Coastguard Worker if g, w := eval, testCase.eval; g != w { 177*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect Eval output, want %q, got %q", w, g) 178*1fa6dee9SAndroid Build Coastguard Worker } 179*1fa6dee9SAndroid Build Coastguard Worker } 180*1fa6dee9SAndroid Build Coastguard Worker var errStr string 181*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 182*1fa6dee9SAndroid Build Coastguard Worker errStr = err.Error() 183*1fa6dee9SAndroid Build Coastguard Worker } 184*1fa6dee9SAndroid Build Coastguard Worker if err != nil && err.Error() != testCase.err { 185*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("unexpected error:") 186*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" input: %q", testCase.input) 187*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" expected: %q", testCase.err) 188*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" got: %q", errStr) 189*1fa6dee9SAndroid Build Coastguard Worker } 190*1fa6dee9SAndroid Build Coastguard Worker }) 191*1fa6dee9SAndroid Build Coastguard Worker } 192*1fa6dee9SAndroid Build Coastguard Worker} 193*1fa6dee9SAndroid Build Coastguard Worker 194*1fa6dee9SAndroid Build Coastguard Workerfunc TestParseNinjaStringWithImportedVar(t *testing.T) { 195*1fa6dee9SAndroid Build Coastguard Worker pctx := &packageContext{} 196*1fa6dee9SAndroid Build Coastguard Worker pkgNames := map[*packageContext]string{ 197*1fa6dee9SAndroid Build Coastguard Worker pctx: "impPkg", 198*1fa6dee9SAndroid Build Coastguard Worker } 199*1fa6dee9SAndroid Build Coastguard Worker ImpVar := &staticVariable{pctx: pctx, name_: "ImpVar"} 200*1fa6dee9SAndroid Build Coastguard Worker impScope := newScope(nil) 201*1fa6dee9SAndroid Build Coastguard Worker impScope.AddVariable(ImpVar) 202*1fa6dee9SAndroid Build Coastguard Worker scope := newScope(nil) 203*1fa6dee9SAndroid Build Coastguard Worker scope.AddImport("impPkg", impScope) 204*1fa6dee9SAndroid Build Coastguard Worker 205*1fa6dee9SAndroid Build Coastguard Worker input := "abc def ${impPkg.ImpVar} ghi" 206*1fa6dee9SAndroid Build Coastguard Worker output, err := parseNinjaString(scope, input) 207*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 208*1fa6dee9SAndroid Build Coastguard Worker t.Fatalf("unexpected error: %s", err) 209*1fa6dee9SAndroid Build Coastguard Worker } 210*1fa6dee9SAndroid Build Coastguard Worker 211*1fa6dee9SAndroid Build Coastguard Worker expect := []variableReference{{8, 24, ImpVar}} 212*1fa6dee9SAndroid Build Coastguard Worker if !reflect.DeepEqual(*output.variables, expect) { 213*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 214*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" input: %q", input) 215*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", expect) 216*1fa6dee9SAndroid Build Coastguard Worker t.Errorf(" got: %#v", *output.variables) 217*1fa6dee9SAndroid Build Coastguard Worker } 218*1fa6dee9SAndroid Build Coastguard Worker 219*1fa6dee9SAndroid Build Coastguard Worker if g, w := output.Value(&nameTracker{pkgNames: pkgNames}), "abc def ${g.impPkg.ImpVar} ghi"; g != w { 220*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect Value output, want %q got %q", w, g) 221*1fa6dee9SAndroid Build Coastguard Worker } 222*1fa6dee9SAndroid Build Coastguard Worker} 223*1fa6dee9SAndroid Build Coastguard Worker 224*1fa6dee9SAndroid Build Coastguard Workerfunc Test_parseNinjaOrSimpleStrings(t *testing.T) { 225*1fa6dee9SAndroid Build Coastguard Worker testCases := []struct { 226*1fa6dee9SAndroid Build Coastguard Worker name string 227*1fa6dee9SAndroid Build Coastguard Worker in []string 228*1fa6dee9SAndroid Build Coastguard Worker outStrings []string 229*1fa6dee9SAndroid Build Coastguard Worker outNinjaStrings []string 230*1fa6dee9SAndroid Build Coastguard Worker sameSlice bool 231*1fa6dee9SAndroid Build Coastguard Worker }{ 232*1fa6dee9SAndroid Build Coastguard Worker { 233*1fa6dee9SAndroid Build Coastguard Worker name: "nil", 234*1fa6dee9SAndroid Build Coastguard Worker in: nil, 235*1fa6dee9SAndroid Build Coastguard Worker sameSlice: true, 236*1fa6dee9SAndroid Build Coastguard Worker }, 237*1fa6dee9SAndroid Build Coastguard Worker { 238*1fa6dee9SAndroid Build Coastguard Worker name: "empty", 239*1fa6dee9SAndroid Build Coastguard Worker in: []string{}, 240*1fa6dee9SAndroid Build Coastguard Worker sameSlice: true, 241*1fa6dee9SAndroid Build Coastguard Worker }, 242*1fa6dee9SAndroid Build Coastguard Worker { 243*1fa6dee9SAndroid Build Coastguard Worker name: "string", 244*1fa6dee9SAndroid Build Coastguard Worker in: []string{"abc"}, 245*1fa6dee9SAndroid Build Coastguard Worker sameSlice: true, 246*1fa6dee9SAndroid Build Coastguard Worker }, 247*1fa6dee9SAndroid Build Coastguard Worker { 248*1fa6dee9SAndroid Build Coastguard Worker name: "ninja string", 249*1fa6dee9SAndroid Build Coastguard Worker in: []string{"$abc"}, 250*1fa6dee9SAndroid Build Coastguard Worker outStrings: nil, 251*1fa6dee9SAndroid Build Coastguard Worker outNinjaStrings: []string{"${abc}"}, 252*1fa6dee9SAndroid Build Coastguard Worker }, 253*1fa6dee9SAndroid Build Coastguard Worker { 254*1fa6dee9SAndroid Build Coastguard Worker name: "ninja string first", 255*1fa6dee9SAndroid Build Coastguard Worker in: []string{"$abc", "def", "ghi"}, 256*1fa6dee9SAndroid Build Coastguard Worker outStrings: []string{"def", "ghi"}, 257*1fa6dee9SAndroid Build Coastguard Worker outNinjaStrings: []string{"${abc}"}, 258*1fa6dee9SAndroid Build Coastguard Worker }, 259*1fa6dee9SAndroid Build Coastguard Worker { 260*1fa6dee9SAndroid Build Coastguard Worker name: "ninja string middle", 261*1fa6dee9SAndroid Build Coastguard Worker in: []string{"abc", "$def", "ghi"}, 262*1fa6dee9SAndroid Build Coastguard Worker outStrings: []string{"abc", "ghi"}, 263*1fa6dee9SAndroid Build Coastguard Worker outNinjaStrings: []string{"${def}"}, 264*1fa6dee9SAndroid Build Coastguard Worker }, 265*1fa6dee9SAndroid Build Coastguard Worker { 266*1fa6dee9SAndroid Build Coastguard Worker name: "ninja string last", 267*1fa6dee9SAndroid Build Coastguard Worker in: []string{"abc", "def", "$ghi"}, 268*1fa6dee9SAndroid Build Coastguard Worker outStrings: []string{"abc", "def"}, 269*1fa6dee9SAndroid Build Coastguard Worker outNinjaStrings: []string{"${ghi}"}, 270*1fa6dee9SAndroid Build Coastguard Worker }, 271*1fa6dee9SAndroid Build Coastguard Worker } 272*1fa6dee9SAndroid Build Coastguard Worker 273*1fa6dee9SAndroid Build Coastguard Worker for _, tt := range testCases { 274*1fa6dee9SAndroid Build Coastguard Worker t.Run(tt.name, func(t *testing.T) { 275*1fa6dee9SAndroid Build Coastguard Worker inCopy := slices.Clone(tt.in) 276*1fa6dee9SAndroid Build Coastguard Worker 277*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "") 278*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("abc", "abc") 279*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("def", "def") 280*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("ghi", "ghi") 281*1fa6dee9SAndroid Build Coastguard Worker gotNinjaStrings, gotStrings, err := parseNinjaOrSimpleStrings(scope, tt.in) 282*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 283*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("unexpected error %s", err) 284*1fa6dee9SAndroid Build Coastguard Worker } 285*1fa6dee9SAndroid Build Coastguard Worker 286*1fa6dee9SAndroid Build Coastguard Worker wantStrings := tt.outStrings 287*1fa6dee9SAndroid Build Coastguard Worker if tt.sameSlice { 288*1fa6dee9SAndroid Build Coastguard Worker wantStrings = tt.in 289*1fa6dee9SAndroid Build Coastguard Worker } 290*1fa6dee9SAndroid Build Coastguard Worker 291*1fa6dee9SAndroid Build Coastguard Worker wantNinjaStrings := tt.outNinjaStrings 292*1fa6dee9SAndroid Build Coastguard Worker 293*1fa6dee9SAndroid Build Coastguard Worker var evaluatedNinjaStrings []string 294*1fa6dee9SAndroid Build Coastguard Worker if gotNinjaStrings != nil { 295*1fa6dee9SAndroid Build Coastguard Worker evaluatedNinjaStrings = make([]string, 0, len(gotNinjaStrings)) 296*1fa6dee9SAndroid Build Coastguard Worker for _, ns := range gotNinjaStrings { 297*1fa6dee9SAndroid Build Coastguard Worker evaluatedNinjaStrings = append(evaluatedNinjaStrings, ns.Value(&nameTracker{})) 298*1fa6dee9SAndroid Build Coastguard Worker } 299*1fa6dee9SAndroid Build Coastguard Worker } 300*1fa6dee9SAndroid Build Coastguard Worker 301*1fa6dee9SAndroid Build Coastguard Worker if !reflect.DeepEqual(gotStrings, wantStrings) { 302*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect strings output, want %q got %q", wantStrings, gotStrings) 303*1fa6dee9SAndroid Build Coastguard Worker } 304*1fa6dee9SAndroid Build Coastguard Worker if !reflect.DeepEqual(evaluatedNinjaStrings, wantNinjaStrings) { 305*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("incorrect ninja strings output, want %q got %q", wantNinjaStrings, evaluatedNinjaStrings) 306*1fa6dee9SAndroid Build Coastguard Worker } 307*1fa6dee9SAndroid Build Coastguard Worker if len(inCopy) != len(tt.in) && (len(tt.in) == 0 || !reflect.DeepEqual(inCopy, tt.in)) { 308*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("input modified, want %#v, got %#v", inCopy, tt.in) 309*1fa6dee9SAndroid Build Coastguard Worker } 310*1fa6dee9SAndroid Build Coastguard Worker 311*1fa6dee9SAndroid Build Coastguard Worker if (unsafe.SliceData(tt.in) == unsafe.SliceData(gotStrings)) != tt.sameSlice { 312*1fa6dee9SAndroid Build Coastguard Worker if tt.sameSlice { 313*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("expected input and output slices to have the same backing arrays") 314*1fa6dee9SAndroid Build Coastguard Worker } else { 315*1fa6dee9SAndroid Build Coastguard Worker t.Errorf("expected input and output slices to have different backing arrays") 316*1fa6dee9SAndroid Build Coastguard Worker } 317*1fa6dee9SAndroid Build Coastguard Worker } 318*1fa6dee9SAndroid Build Coastguard Worker 319*1fa6dee9SAndroid Build Coastguard Worker }) 320*1fa6dee9SAndroid Build Coastguard Worker } 321*1fa6dee9SAndroid Build Coastguard Worker} 322*1fa6dee9SAndroid Build Coastguard Worker 323*1fa6dee9SAndroid Build Coastguard Workerfunc Benchmark_parseNinjaString(b *testing.B) { 324*1fa6dee9SAndroid Build Coastguard Worker b.Run("constant", func(b *testing.B) { 325*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 10, 100, 1000} { 326*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 327*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 328*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 329*1fa6dee9SAndroid Build Coastguard Worker _ = simpleNinjaString(strings.Repeat("a", l)) 330*1fa6dee9SAndroid Build Coastguard Worker } 331*1fa6dee9SAndroid Build Coastguard Worker }) 332*1fa6dee9SAndroid Build Coastguard Worker } 333*1fa6dee9SAndroid Build Coastguard Worker }) 334*1fa6dee9SAndroid Build Coastguard Worker b.Run("variable", func(b *testing.B) { 335*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 10, 100, 1000} { 336*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "") 337*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("a", strings.Repeat("b", l/3)) 338*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 339*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 340*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 341*1fa6dee9SAndroid Build Coastguard Worker _, _ = parseNinjaString(scope, strings.Repeat("a", l/3)+"${a}"+strings.Repeat("a", l/3)) 342*1fa6dee9SAndroid Build Coastguard Worker } 343*1fa6dee9SAndroid Build Coastguard Worker }) 344*1fa6dee9SAndroid Build Coastguard Worker } 345*1fa6dee9SAndroid Build Coastguard Worker }) 346*1fa6dee9SAndroid Build Coastguard Worker b.Run("variables", func(b *testing.B) { 347*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 2, 3, 4, 5, 10, 100, 1000} { 348*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "") 349*1fa6dee9SAndroid Build Coastguard Worker str := strings.Repeat("a", 10) 350*1fa6dee9SAndroid Build Coastguard Worker for i := 0; i < l; i++ { 351*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("a"+strconv.Itoa(i), strings.Repeat("b", 10)) 352*1fa6dee9SAndroid Build Coastguard Worker str += "${a" + strconv.Itoa(i) + "}" 353*1fa6dee9SAndroid Build Coastguard Worker } 354*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 355*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 356*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 357*1fa6dee9SAndroid Build Coastguard Worker _, _ = parseNinjaString(scope, str) 358*1fa6dee9SAndroid Build Coastguard Worker } 359*1fa6dee9SAndroid Build Coastguard Worker }) 360*1fa6dee9SAndroid Build Coastguard Worker } 361*1fa6dee9SAndroid Build Coastguard Worker }) 362*1fa6dee9SAndroid Build Coastguard Worker 363*1fa6dee9SAndroid Build Coastguard Worker} 364*1fa6dee9SAndroid Build Coastguard Worker 365*1fa6dee9SAndroid Build Coastguard Workerfunc BenchmarkNinjaString_Value(b *testing.B) { 366*1fa6dee9SAndroid Build Coastguard Worker b.Run("constant", func(b *testing.B) { 367*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 10, 100, 1000} { 368*1fa6dee9SAndroid Build Coastguard Worker ns := simpleNinjaString(strings.Repeat("a", l)) 369*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 370*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 371*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 372*1fa6dee9SAndroid Build Coastguard Worker ns.Value(&nameTracker{}) 373*1fa6dee9SAndroid Build Coastguard Worker } 374*1fa6dee9SAndroid Build Coastguard Worker }) 375*1fa6dee9SAndroid Build Coastguard Worker } 376*1fa6dee9SAndroid Build Coastguard Worker }) 377*1fa6dee9SAndroid Build Coastguard Worker b.Run("variable", func(b *testing.B) { 378*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 10, 100, 1000} { 379*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "") 380*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("a", strings.Repeat("b", l/3)) 381*1fa6dee9SAndroid Build Coastguard Worker ns, _ := parseNinjaString(scope, strings.Repeat("a", l/3)+"${a}"+strings.Repeat("a", l/3)) 382*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 383*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 384*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 385*1fa6dee9SAndroid Build Coastguard Worker ns.Value(&nameTracker{}) 386*1fa6dee9SAndroid Build Coastguard Worker } 387*1fa6dee9SAndroid Build Coastguard Worker }) 388*1fa6dee9SAndroid Build Coastguard Worker } 389*1fa6dee9SAndroid Build Coastguard Worker }) 390*1fa6dee9SAndroid Build Coastguard Worker b.Run("variables", func(b *testing.B) { 391*1fa6dee9SAndroid Build Coastguard Worker for _, l := range []int{1, 2, 3, 4, 5, 10, 100, 1000} { 392*1fa6dee9SAndroid Build Coastguard Worker scope := newLocalScope(nil, "") 393*1fa6dee9SAndroid Build Coastguard Worker str := strings.Repeat("a", 10) 394*1fa6dee9SAndroid Build Coastguard Worker for i := 0; i < l; i++ { 395*1fa6dee9SAndroid Build Coastguard Worker scope.AddLocalVariable("a"+strconv.Itoa(i), strings.Repeat("b", 10)) 396*1fa6dee9SAndroid Build Coastguard Worker str += "${a" + strconv.Itoa(i) + "}" 397*1fa6dee9SAndroid Build Coastguard Worker } 398*1fa6dee9SAndroid Build Coastguard Worker ns, _ := parseNinjaString(scope, str) 399*1fa6dee9SAndroid Build Coastguard Worker b.Run(strconv.Itoa(l), func(b *testing.B) { 400*1fa6dee9SAndroid Build Coastguard Worker b.ReportAllocs() 401*1fa6dee9SAndroid Build Coastguard Worker for n := 0; n < b.N; n++ { 402*1fa6dee9SAndroid Build Coastguard Worker ns.Value(&nameTracker{}) 403*1fa6dee9SAndroid Build Coastguard Worker } 404*1fa6dee9SAndroid Build Coastguard Worker }) 405*1fa6dee9SAndroid Build Coastguard Worker } 406*1fa6dee9SAndroid Build Coastguard Worker }) 407*1fa6dee9SAndroid Build Coastguard Worker 408*1fa6dee9SAndroid Build Coastguard Worker} 409