1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage parser 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "strings" 19*333d2b36SAndroid Build Coastguard Worker "testing" 20*333d2b36SAndroid Build Coastguard Worker) 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Workervar splitNTestCases = []struct { 23*333d2b36SAndroid Build Coastguard Worker in *MakeString 24*333d2b36SAndroid Build Coastguard Worker expected []*MakeString 25*333d2b36SAndroid Build Coastguard Worker sep string 26*333d2b36SAndroid Build Coastguard Worker n int 27*333d2b36SAndroid Build Coastguard Worker}{ 28*333d2b36SAndroid Build Coastguard Worker { 29*333d2b36SAndroid Build Coastguard Worker // "a b c$(var1)d e f$(var2) h i j" 30*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a b c", "var1", "d e f", "var2", " h i j"), 31*333d2b36SAndroid Build Coastguard Worker sep: " ", 32*333d2b36SAndroid Build Coastguard Worker n: -1, 33*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 34*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 35*333d2b36SAndroid Build Coastguard Worker genMakeString("b"), 36*333d2b36SAndroid Build Coastguard Worker genMakeString("c", "var1", "d"), 37*333d2b36SAndroid Build Coastguard Worker genMakeString("e"), 38*333d2b36SAndroid Build Coastguard Worker genMakeString("f", "var2", ""), 39*333d2b36SAndroid Build Coastguard Worker genMakeString("h"), 40*333d2b36SAndroid Build Coastguard Worker genMakeString("i"), 41*333d2b36SAndroid Build Coastguard Worker genMakeString("j"), 42*333d2b36SAndroid Build Coastguard Worker }, 43*333d2b36SAndroid Build Coastguard Worker }, 44*333d2b36SAndroid Build Coastguard Worker { 45*333d2b36SAndroid Build Coastguard Worker // "a b c$(var1)d e f$(var2) h i j" 46*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a b c", "var1", "d e f", "var2", " h i j"), 47*333d2b36SAndroid Build Coastguard Worker sep: " ", 48*333d2b36SAndroid Build Coastguard Worker n: 3, 49*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 50*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 51*333d2b36SAndroid Build Coastguard Worker genMakeString("b"), 52*333d2b36SAndroid Build Coastguard Worker genMakeString("c", "var1", "d e f", "var2", " h i j"), 53*333d2b36SAndroid Build Coastguard Worker }, 54*333d2b36SAndroid Build Coastguard Worker }, 55*333d2b36SAndroid Build Coastguard Worker { 56*333d2b36SAndroid Build Coastguard Worker // "$(var1) $(var2)" 57*333d2b36SAndroid Build Coastguard Worker in: genMakeString("", "var1", " ", "var2", ""), 58*333d2b36SAndroid Build Coastguard Worker sep: " ", 59*333d2b36SAndroid Build Coastguard Worker n: -1, 60*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 61*333d2b36SAndroid Build Coastguard Worker genMakeString("", "var1", ""), 62*333d2b36SAndroid Build Coastguard Worker genMakeString("", "var2", ""), 63*333d2b36SAndroid Build Coastguard Worker }, 64*333d2b36SAndroid Build Coastguard Worker }, 65*333d2b36SAndroid Build Coastguard Worker { 66*333d2b36SAndroid Build Coastguard Worker // "a,,b,c," 67*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a,,b,c,"), 68*333d2b36SAndroid Build Coastguard Worker sep: ",", 69*333d2b36SAndroid Build Coastguard Worker n: -1, 70*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 71*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 72*333d2b36SAndroid Build Coastguard Worker genMakeString(""), 73*333d2b36SAndroid Build Coastguard Worker genMakeString("b"), 74*333d2b36SAndroid Build Coastguard Worker genMakeString("c"), 75*333d2b36SAndroid Build Coastguard Worker genMakeString(""), 76*333d2b36SAndroid Build Coastguard Worker }, 77*333d2b36SAndroid Build Coastguard Worker }, 78*333d2b36SAndroid Build Coastguard Worker { 79*333d2b36SAndroid Build Coastguard Worker // "x$(var1)y bar" 80*333d2b36SAndroid Build Coastguard Worker in: genMakeString("x", "var1", "y bar"), 81*333d2b36SAndroid Build Coastguard Worker sep: " ", 82*333d2b36SAndroid Build Coastguard Worker n: 2, 83*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 84*333d2b36SAndroid Build Coastguard Worker genMakeString("x", "var1", "y"), 85*333d2b36SAndroid Build Coastguard Worker genMakeString("bar"), 86*333d2b36SAndroid Build Coastguard Worker }, 87*333d2b36SAndroid Build Coastguard Worker }, 88*333d2b36SAndroid Build Coastguard Worker} 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Workerfunc TestMakeStringSplitN(t *testing.T) { 91*333d2b36SAndroid Build Coastguard Worker for _, test := range splitNTestCases { 92*333d2b36SAndroid Build Coastguard Worker got := test.in.SplitN(test.sep, test.n) 93*333d2b36SAndroid Build Coastguard Worker gotString := dumpArray(got) 94*333d2b36SAndroid Build Coastguard Worker expectedString := dumpArray(test.expected) 95*333d2b36SAndroid Build Coastguard Worker if gotString != expectedString { 96*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected:\n%s\ngot:\n%s", expectedString, gotString) 97*333d2b36SAndroid Build Coastguard Worker } 98*333d2b36SAndroid Build Coastguard Worker } 99*333d2b36SAndroid Build Coastguard Worker} 100*333d2b36SAndroid Build Coastguard Worker 101*333d2b36SAndroid Build Coastguard Workervar valueTestCases = []struct { 102*333d2b36SAndroid Build Coastguard Worker in *MakeString 103*333d2b36SAndroid Build Coastguard Worker expected string 104*333d2b36SAndroid Build Coastguard Worker}{ 105*333d2b36SAndroid Build Coastguard Worker { 106*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a b"), 107*333d2b36SAndroid Build Coastguard Worker expected: "a b", 108*333d2b36SAndroid Build Coastguard Worker }, 109*333d2b36SAndroid Build Coastguard Worker { 110*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a\\ \\\tb\\\\"), 111*333d2b36SAndroid Build Coastguard Worker expected: "a \tb\\", 112*333d2b36SAndroid Build Coastguard Worker }, 113*333d2b36SAndroid Build Coastguard Worker { 114*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a\\b\\"), 115*333d2b36SAndroid Build Coastguard Worker expected: "a\\b\\", 116*333d2b36SAndroid Build Coastguard Worker }, 117*333d2b36SAndroid Build Coastguard Worker} 118*333d2b36SAndroid Build Coastguard Worker 119*333d2b36SAndroid Build Coastguard Workerfunc TestMakeStringValue(t *testing.T) { 120*333d2b36SAndroid Build Coastguard Worker for _, test := range valueTestCases { 121*333d2b36SAndroid Build Coastguard Worker got := test.in.Value(nil) 122*333d2b36SAndroid Build Coastguard Worker if got != test.expected { 123*333d2b36SAndroid Build Coastguard Worker t.Errorf("\nwith: %q\nwant: %q\n got: %q", test.in.Dump(), test.expected, got) 124*333d2b36SAndroid Build Coastguard Worker } 125*333d2b36SAndroid Build Coastguard Worker } 126*333d2b36SAndroid Build Coastguard Worker} 127*333d2b36SAndroid Build Coastguard Worker 128*333d2b36SAndroid Build Coastguard Workervar splitWordsTestCases = []struct { 129*333d2b36SAndroid Build Coastguard Worker in *MakeString 130*333d2b36SAndroid Build Coastguard Worker expected []*MakeString 131*333d2b36SAndroid Build Coastguard Worker}{ 132*333d2b36SAndroid Build Coastguard Worker { 133*333d2b36SAndroid Build Coastguard Worker in: genMakeString(""), 134*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{}, 135*333d2b36SAndroid Build Coastguard Worker }, 136*333d2b36SAndroid Build Coastguard Worker { 137*333d2b36SAndroid Build Coastguard Worker in: genMakeString(` a b\ c d`), 138*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 139*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 140*333d2b36SAndroid Build Coastguard Worker genMakeString(`b\ c`), 141*333d2b36SAndroid Build Coastguard Worker genMakeString("d"), 142*333d2b36SAndroid Build Coastguard Worker }, 143*333d2b36SAndroid Build Coastguard Worker }, 144*333d2b36SAndroid Build Coastguard Worker { 145*333d2b36SAndroid Build Coastguard Worker in: SimpleMakeString(" a\tb"+`\`+"\t"+`\ c d `, NoPos), 146*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 147*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 148*333d2b36SAndroid Build Coastguard Worker genMakeString("b" + `\` + "\t" + `\ c`), 149*333d2b36SAndroid Build Coastguard Worker genMakeString("d"), 150*333d2b36SAndroid Build Coastguard Worker }, 151*333d2b36SAndroid Build Coastguard Worker }, 152*333d2b36SAndroid Build Coastguard Worker { 153*333d2b36SAndroid Build Coastguard Worker in: genMakeString(`a\\ b\\\ c d`), 154*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 155*333d2b36SAndroid Build Coastguard Worker genMakeString(`a\\`), 156*333d2b36SAndroid Build Coastguard Worker genMakeString(`b\\\ c`), 157*333d2b36SAndroid Build Coastguard Worker genMakeString("d"), 158*333d2b36SAndroid Build Coastguard Worker }, 159*333d2b36SAndroid Build Coastguard Worker }, 160*333d2b36SAndroid Build Coastguard Worker { 161*333d2b36SAndroid Build Coastguard Worker in: genMakeString(`\\ a`), 162*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 163*333d2b36SAndroid Build Coastguard Worker genMakeString(`\\`), 164*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 165*333d2b36SAndroid Build Coastguard Worker }, 166*333d2b36SAndroid Build Coastguard Worker }, 167*333d2b36SAndroid Build Coastguard Worker { 168*333d2b36SAndroid Build Coastguard Worker // " " 169*333d2b36SAndroid Build Coastguard Worker in: &MakeString{ 170*333d2b36SAndroid Build Coastguard Worker Strings: []string{" \t \t"}, 171*333d2b36SAndroid Build Coastguard Worker Variables: nil, 172*333d2b36SAndroid Build Coastguard Worker }, 173*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{}, 174*333d2b36SAndroid Build Coastguard Worker }, 175*333d2b36SAndroid Build Coastguard Worker { 176*333d2b36SAndroid Build Coastguard Worker // " a $(X)b c " 177*333d2b36SAndroid Build Coastguard Worker in: genMakeString(" a ", "X", "b c "), 178*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 179*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 180*333d2b36SAndroid Build Coastguard Worker genMakeString("", "X", "b"), 181*333d2b36SAndroid Build Coastguard Worker genMakeString("c"), 182*333d2b36SAndroid Build Coastguard Worker }, 183*333d2b36SAndroid Build Coastguard Worker }, 184*333d2b36SAndroid Build Coastguard Worker { 185*333d2b36SAndroid Build Coastguard Worker // " a b$(X)c d" 186*333d2b36SAndroid Build Coastguard Worker in: genMakeString(" a b", "X", "c d"), 187*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 188*333d2b36SAndroid Build Coastguard Worker genMakeString("a"), 189*333d2b36SAndroid Build Coastguard Worker genMakeString("b", "X", "c"), 190*333d2b36SAndroid Build Coastguard Worker genMakeString("d"), 191*333d2b36SAndroid Build Coastguard Worker }, 192*333d2b36SAndroid Build Coastguard Worker }, 193*333d2b36SAndroid Build Coastguard Worker { 194*333d2b36SAndroid Build Coastguard Worker // "$(X) $(Y)" 195*333d2b36SAndroid Build Coastguard Worker in: genMakeString("", "X", " ", "Y", ""), 196*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 197*333d2b36SAndroid Build Coastguard Worker genMakeString("", "X", ""), 198*333d2b36SAndroid Build Coastguard Worker genMakeString("", "Y", ""), 199*333d2b36SAndroid Build Coastguard Worker }, 200*333d2b36SAndroid Build Coastguard Worker }, 201*333d2b36SAndroid Build Coastguard Worker { 202*333d2b36SAndroid Build Coastguard Worker // " a$(X) b" 203*333d2b36SAndroid Build Coastguard Worker in: genMakeString(" a", "X", " b"), 204*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 205*333d2b36SAndroid Build Coastguard Worker genMakeString("a", "X", ""), 206*333d2b36SAndroid Build Coastguard Worker genMakeString("b"), 207*333d2b36SAndroid Build Coastguard Worker }, 208*333d2b36SAndroid Build Coastguard Worker }, 209*333d2b36SAndroid Build Coastguard Worker { 210*333d2b36SAndroid Build Coastguard Worker // "a$(X) b$(Y) " 211*333d2b36SAndroid Build Coastguard Worker in: genMakeString("a", "X", " b", "Y", " "), 212*333d2b36SAndroid Build Coastguard Worker expected: []*MakeString{ 213*333d2b36SAndroid Build Coastguard Worker genMakeString("a", "X", ""), 214*333d2b36SAndroid Build Coastguard Worker genMakeString("b", "Y", ""), 215*333d2b36SAndroid Build Coastguard Worker }, 216*333d2b36SAndroid Build Coastguard Worker }, 217*333d2b36SAndroid Build Coastguard Worker} 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Workerfunc TestMakeStringWords(t *testing.T) { 220*333d2b36SAndroid Build Coastguard Worker for _, test := range splitWordsTestCases { 221*333d2b36SAndroid Build Coastguard Worker got := test.in.Words() 222*333d2b36SAndroid Build Coastguard Worker gotString := dumpArray(got) 223*333d2b36SAndroid Build Coastguard Worker expectedString := dumpArray(test.expected) 224*333d2b36SAndroid Build Coastguard Worker if gotString != expectedString { 225*333d2b36SAndroid Build Coastguard Worker t.Errorf("with:\n%q\nexpected:\n%s\ngot:\n%s", test.in.Dump(), expectedString, gotString) 226*333d2b36SAndroid Build Coastguard Worker } 227*333d2b36SAndroid Build Coastguard Worker } 228*333d2b36SAndroid Build Coastguard Worker} 229*333d2b36SAndroid Build Coastguard Worker 230*333d2b36SAndroid Build Coastguard Workervar endsWithTestCases = []struct { 231*333d2b36SAndroid Build Coastguard Worker in *MakeString 232*333d2b36SAndroid Build Coastguard Worker endsWith rune 233*333d2b36SAndroid Build Coastguard Worker expected bool 234*333d2b36SAndroid Build Coastguard Worker}{ 235*333d2b36SAndroid Build Coastguard Worker { 236*333d2b36SAndroid Build Coastguard Worker in: genMakeString("foo", "X", "bar ="), 237*333d2b36SAndroid Build Coastguard Worker endsWith: '=', 238*333d2b36SAndroid Build Coastguard Worker expected: true, 239*333d2b36SAndroid Build Coastguard Worker }, 240*333d2b36SAndroid Build Coastguard Worker { 241*333d2b36SAndroid Build Coastguard Worker in: genMakeString("foo", "X", "bar ="), 242*333d2b36SAndroid Build Coastguard Worker endsWith: ':', 243*333d2b36SAndroid Build Coastguard Worker expected: false, 244*333d2b36SAndroid Build Coastguard Worker }, 245*333d2b36SAndroid Build Coastguard Worker { 246*333d2b36SAndroid Build Coastguard Worker in: genMakeString("foo", "X", ""), 247*333d2b36SAndroid Build Coastguard Worker endsWith: '=', 248*333d2b36SAndroid Build Coastguard Worker expected: false, 249*333d2b36SAndroid Build Coastguard Worker }, 250*333d2b36SAndroid Build Coastguard Worker} 251*333d2b36SAndroid Build Coastguard Worker 252*333d2b36SAndroid Build Coastguard Workerfunc TestMakeStringEndsWith(t *testing.T) { 253*333d2b36SAndroid Build Coastguard Worker for _, test := range endsWithTestCases { 254*333d2b36SAndroid Build Coastguard Worker if test.in.EndsWith(test.endsWith) != test.expected { 255*333d2b36SAndroid Build Coastguard Worker t.Errorf("with:\n%q\nexpected:\n%t\ngot:\n%t", test.in.Dump(), test.expected, !test.expected) 256*333d2b36SAndroid Build Coastguard Worker } 257*333d2b36SAndroid Build Coastguard Worker } 258*333d2b36SAndroid Build Coastguard Worker} 259*333d2b36SAndroid Build Coastguard Worker 260*333d2b36SAndroid Build Coastguard Workerfunc dumpArray(a []*MakeString) string { 261*333d2b36SAndroid Build Coastguard Worker ret := make([]string, len(a)) 262*333d2b36SAndroid Build Coastguard Worker 263*333d2b36SAndroid Build Coastguard Worker for i, s := range a { 264*333d2b36SAndroid Build Coastguard Worker ret[i] = s.Dump() 265*333d2b36SAndroid Build Coastguard Worker } 266*333d2b36SAndroid Build Coastguard Worker 267*333d2b36SAndroid Build Coastguard Worker return strings.Join(ret, "|||") 268*333d2b36SAndroid Build Coastguard Worker} 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Worker// generates MakeString from alternating string chunks and variable names, 271*333d2b36SAndroid Build Coastguard Worker// e.g., genMakeString("a", "X", "b") returns MakeString for "a$(X)b" 272*333d2b36SAndroid Build Coastguard Workerfunc genMakeString(items ...string) *MakeString { 273*333d2b36SAndroid Build Coastguard Worker n := len(items) / 2 274*333d2b36SAndroid Build Coastguard Worker if len(items) != (2*n + 1) { 275*333d2b36SAndroid Build Coastguard Worker panic("genMakeString expects odd number of arguments") 276*333d2b36SAndroid Build Coastguard Worker } 277*333d2b36SAndroid Build Coastguard Worker 278*333d2b36SAndroid Build Coastguard Worker ms := &MakeString{Strings: make([]string, n+1), Variables: make([]Variable, n)} 279*333d2b36SAndroid Build Coastguard Worker ms.Strings[0] = items[0] 280*333d2b36SAndroid Build Coastguard Worker for i := 1; i <= n; i++ { 281*333d2b36SAndroid Build Coastguard Worker ms.Variables[i-1] = Variable{Name: SimpleMakeString(items[2*i-1], NoPos)} 282*333d2b36SAndroid Build Coastguard Worker ms.Strings[i] = items[2*i] 283*333d2b36SAndroid Build Coastguard Worker } 284*333d2b36SAndroid Build Coastguard Worker return ms 285*333d2b36SAndroid Build Coastguard Worker} 286