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