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 android 16 17import ( 18 "fmt" 19 "reflect" 20 "testing" 21) 22 23var firstUniqueStringsTestCases = []struct { 24 in []string 25 out []string 26}{ 27 { 28 in: []string{"a"}, 29 out: []string{"a"}, 30 }, 31 { 32 in: []string{"a", "b"}, 33 out: []string{"a", "b"}, 34 }, 35 { 36 in: []string{"a", "a"}, 37 out: []string{"a"}, 38 }, 39 { 40 in: []string{"a", "b", "a"}, 41 out: []string{"a", "b"}, 42 }, 43 { 44 in: []string{"b", "a", "a"}, 45 out: []string{"b", "a"}, 46 }, 47 { 48 in: []string{"a", "a", "b"}, 49 out: []string{"a", "b"}, 50 }, 51 { 52 in: []string{"a", "b", "a", "b"}, 53 out: []string{"a", "b"}, 54 }, 55 { 56 in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"}, 57 out: []string{"liblog", "libdl", "libc++", "libc", "libm"}, 58 }, 59} 60 61func TestFirstUniqueStrings(t *testing.T) { 62 for _, testCase := range firstUniqueStringsTestCases { 63 out := FirstUniqueStrings(testCase.in) 64 if !reflect.DeepEqual(out, testCase.out) { 65 t.Errorf("incorrect output:") 66 t.Errorf(" input: %#v", testCase.in) 67 t.Errorf(" expected: %#v", testCase.out) 68 t.Errorf(" got: %#v", out) 69 } 70 } 71} 72 73var lastUniqueStringsTestCases = []struct { 74 in []string 75 out []string 76}{ 77 { 78 in: []string{"a"}, 79 out: []string{"a"}, 80 }, 81 { 82 in: []string{"a", "b"}, 83 out: []string{"a", "b"}, 84 }, 85 { 86 in: []string{"a", "a"}, 87 out: []string{"a"}, 88 }, 89 { 90 in: []string{"a", "b", "a"}, 91 out: []string{"b", "a"}, 92 }, 93 { 94 in: []string{"b", "a", "a"}, 95 out: []string{"b", "a"}, 96 }, 97 { 98 in: []string{"a", "a", "b"}, 99 out: []string{"a", "b"}, 100 }, 101 { 102 in: []string{"a", "b", "a", "b"}, 103 out: []string{"a", "b"}, 104 }, 105 { 106 in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"}, 107 out: []string{"liblog", "libc++", "libdl", "libc", "libm"}, 108 }, 109} 110 111func TestLastUniqueStrings(t *testing.T) { 112 for _, testCase := range lastUniqueStringsTestCases { 113 out := LastUniqueStrings(testCase.in) 114 if !reflect.DeepEqual(out, testCase.out) { 115 t.Errorf("incorrect output:") 116 t.Errorf(" input: %#v", testCase.in) 117 t.Errorf(" expected: %#v", testCase.out) 118 t.Errorf(" got: %#v", out) 119 } 120 } 121} 122 123func TestJoinWithPrefix(t *testing.T) { 124 testcases := []struct { 125 name string 126 input []string 127 expected string 128 }{ 129 { 130 name: "zero_inputs", 131 input: []string{}, 132 expected: "", 133 }, 134 { 135 name: "one_input", 136 input: []string{"a"}, 137 expected: "prefix:a", 138 }, 139 { 140 name: "two_inputs", 141 input: []string{"a", "b"}, 142 expected: "prefix:a prefix:b", 143 }, 144 } 145 146 prefix := "prefix:" 147 148 for _, testCase := range testcases { 149 t.Run(testCase.name, func(t *testing.T) { 150 out := JoinWithPrefix(testCase.input, prefix) 151 if out != testCase.expected { 152 t.Errorf("incorrect output:") 153 t.Errorf(" input: %#v", testCase.input) 154 t.Errorf(" prefix: %#v", prefix) 155 t.Errorf(" expected: %#v", testCase.expected) 156 t.Errorf(" got: %#v", out) 157 } 158 }) 159 } 160} 161 162func TestIndexList(t *testing.T) { 163 input := []string{"a", "b", "c"} 164 165 testcases := []struct { 166 key string 167 expected int 168 }{ 169 { 170 key: "a", 171 expected: 0, 172 }, 173 { 174 key: "b", 175 expected: 1, 176 }, 177 { 178 key: "c", 179 expected: 2, 180 }, 181 { 182 key: "X", 183 expected: -1, 184 }, 185 } 186 187 for _, testCase := range testcases { 188 t.Run(testCase.key, func(t *testing.T) { 189 out := IndexList(testCase.key, input) 190 if out != testCase.expected { 191 t.Errorf("incorrect output:") 192 t.Errorf(" key: %#v", testCase.key) 193 t.Errorf(" input: %#v", input) 194 t.Errorf(" expected: %#v", testCase.expected) 195 t.Errorf(" got: %#v", out) 196 } 197 }) 198 } 199} 200 201func TestInList(t *testing.T) { 202 input := []string{"a"} 203 204 testcases := []struct { 205 key string 206 expected bool 207 }{ 208 { 209 key: "a", 210 expected: true, 211 }, 212 { 213 key: "X", 214 expected: false, 215 }, 216 } 217 218 for _, testCase := range testcases { 219 t.Run(testCase.key, func(t *testing.T) { 220 out := InList(testCase.key, input) 221 if out != testCase.expected { 222 t.Errorf("incorrect output:") 223 t.Errorf(" key: %#v", testCase.key) 224 t.Errorf(" input: %#v", input) 225 t.Errorf(" expected: %#v", testCase.expected) 226 t.Errorf(" got: %#v", out) 227 } 228 }) 229 } 230} 231 232func TestPrefixInList(t *testing.T) { 233 prefixes := []string{"a", "b"} 234 235 testcases := []struct { 236 str string 237 expected bool 238 }{ 239 { 240 str: "a-example", 241 expected: true, 242 }, 243 { 244 str: "b-example", 245 expected: true, 246 }, 247 { 248 str: "X-example", 249 expected: false, 250 }, 251 } 252 253 for _, testCase := range testcases { 254 t.Run(testCase.str, func(t *testing.T) { 255 out := PrefixInList(testCase.str, prefixes) 256 if out != testCase.expected { 257 t.Errorf("incorrect output:") 258 t.Errorf(" str: %#v", testCase.str) 259 t.Errorf(" prefixes: %#v", prefixes) 260 t.Errorf(" expected: %#v", testCase.expected) 261 t.Errorf(" got: %#v", out) 262 } 263 }) 264 } 265} 266 267func TestFilterList(t *testing.T) { 268 input := []string{"a", "b", "c", "c", "b", "d", "a"} 269 filter := []string{"a", "c"} 270 remainder, filtered := FilterList(input, filter) 271 272 expected := []string{"b", "b", "d"} 273 if !reflect.DeepEqual(remainder, expected) { 274 t.Errorf("incorrect remainder output:") 275 t.Errorf(" input: %#v", input) 276 t.Errorf(" filter: %#v", filter) 277 t.Errorf(" expected: %#v", expected) 278 t.Errorf(" got: %#v", remainder) 279 } 280 281 expected = []string{"a", "c", "c", "a"} 282 if !reflect.DeepEqual(filtered, expected) { 283 t.Errorf("incorrect filtered output:") 284 t.Errorf(" input: %#v", input) 285 t.Errorf(" filter: %#v", filter) 286 t.Errorf(" expected: %#v", expected) 287 t.Errorf(" got: %#v", filtered) 288 } 289} 290 291func TestRemoveListFromList(t *testing.T) { 292 input := []string{"a", "b", "c", "d", "a", "c", "d"} 293 filter := []string{"a", "c"} 294 expected := []string{"b", "d", "d"} 295 out := RemoveListFromList(input, filter) 296 if !reflect.DeepEqual(out, expected) { 297 t.Errorf("incorrect output:") 298 t.Errorf(" input: %#v", input) 299 t.Errorf(" filter: %#v", filter) 300 t.Errorf(" expected: %#v", expected) 301 t.Errorf(" got: %#v", out) 302 } 303} 304 305func TestRemoveFromList(t *testing.T) { 306 testcases := []struct { 307 name string 308 key string 309 input []string 310 expectedFound bool 311 expectedOut []string 312 }{ 313 { 314 name: "remove_one_match", 315 key: "a", 316 input: []string{"a", "b", "c"}, 317 expectedFound: true, 318 expectedOut: []string{"b", "c"}, 319 }, 320 { 321 name: "remove_three_matches", 322 key: "a", 323 input: []string{"a", "b", "a", "c", "a"}, 324 expectedFound: true, 325 expectedOut: []string{"b", "c"}, 326 }, 327 { 328 name: "remove_zero_matches", 329 key: "X", 330 input: []string{"a", "b", "a", "c", "a"}, 331 expectedFound: false, 332 expectedOut: []string{"a", "b", "a", "c", "a"}, 333 }, 334 { 335 name: "remove_all_matches", 336 key: "a", 337 input: []string{"a", "a", "a", "a"}, 338 expectedFound: true, 339 expectedOut: []string{}, 340 }, 341 } 342 343 for _, testCase := range testcases { 344 t.Run(testCase.name, func(t *testing.T) { 345 found, out := RemoveFromList(testCase.key, testCase.input) 346 if found != testCase.expectedFound { 347 t.Errorf("incorrect output:") 348 t.Errorf(" key: %#v", testCase.key) 349 t.Errorf(" input: %#v", testCase.input) 350 t.Errorf(" expected: %#v", testCase.expectedFound) 351 t.Errorf(" got: %#v", found) 352 } 353 if !reflect.DeepEqual(out, testCase.expectedOut) { 354 t.Errorf("incorrect output:") 355 t.Errorf(" key: %#v", testCase.key) 356 t.Errorf(" input: %#v", testCase.input) 357 t.Errorf(" expected: %#v", testCase.expectedOut) 358 t.Errorf(" got: %#v", out) 359 } 360 }) 361 } 362} 363 364func ExampleCopyOf() { 365 a := []string{"1", "2", "3"} 366 b := CopyOf(a) 367 a[0] = "-1" 368 fmt.Printf("a = %q\n", a) 369 fmt.Printf("b = %q\n", b) 370 371 // Output: 372 // a = ["-1" "2" "3"] 373 // b = ["1" "2" "3"] 374} 375 376func ExampleCopyOf_append() { 377 a := make([]string, 1, 2) 378 a[0] = "foo" 379 380 fmt.Println("Without CopyOf:") 381 b := append(a, "bar") 382 c := append(a, "baz") 383 fmt.Printf("a = %q\n", a) 384 fmt.Printf("b = %q\n", b) 385 fmt.Printf("c = %q\n", c) 386 387 a = make([]string, 1, 2) 388 a[0] = "foo" 389 390 fmt.Println("With CopyOf:") 391 b = append(CopyOf(a), "bar") 392 c = append(CopyOf(a), "baz") 393 fmt.Printf("a = %q\n", a) 394 fmt.Printf("b = %q\n", b) 395 fmt.Printf("c = %q\n", c) 396 397 // Output: 398 // Without CopyOf: 399 // a = ["foo"] 400 // b = ["foo" "baz"] 401 // c = ["foo" "baz"] 402 // With CopyOf: 403 // a = ["foo"] 404 // b = ["foo" "bar"] 405 // c = ["foo" "baz"] 406} 407