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 android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "cmp" 19*333d2b36SAndroid Build Coastguard Worker "fmt" 20*333d2b36SAndroid Build Coastguard Worker "reflect" 21*333d2b36SAndroid Build Coastguard Worker "strconv" 22*333d2b36SAndroid Build Coastguard Worker "strings" 23*333d2b36SAndroid Build Coastguard Worker "testing" 24*333d2b36SAndroid Build Coastguard Worker "unsafe" 25*333d2b36SAndroid Build Coastguard Worker) 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Workervar firstUniqueStringsTestCases = []struct { 28*333d2b36SAndroid Build Coastguard Worker in []string 29*333d2b36SAndroid Build Coastguard Worker out []string 30*333d2b36SAndroid Build Coastguard Worker}{ 31*333d2b36SAndroid Build Coastguard Worker { 32*333d2b36SAndroid Build Coastguard Worker in: []string{"a"}, 33*333d2b36SAndroid Build Coastguard Worker out: []string{"a"}, 34*333d2b36SAndroid Build Coastguard Worker }, 35*333d2b36SAndroid Build Coastguard Worker { 36*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b"}, 37*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 38*333d2b36SAndroid Build Coastguard Worker }, 39*333d2b36SAndroid Build Coastguard Worker { 40*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "a"}, 41*333d2b36SAndroid Build Coastguard Worker out: []string{"a"}, 42*333d2b36SAndroid Build Coastguard Worker }, 43*333d2b36SAndroid Build Coastguard Worker { 44*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b", "a"}, 45*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 46*333d2b36SAndroid Build Coastguard Worker }, 47*333d2b36SAndroid Build Coastguard Worker { 48*333d2b36SAndroid Build Coastguard Worker in: []string{"b", "a", "a"}, 49*333d2b36SAndroid Build Coastguard Worker out: []string{"b", "a"}, 50*333d2b36SAndroid Build Coastguard Worker }, 51*333d2b36SAndroid Build Coastguard Worker { 52*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "a", "b"}, 53*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 54*333d2b36SAndroid Build Coastguard Worker }, 55*333d2b36SAndroid Build Coastguard Worker { 56*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b", "a", "b"}, 57*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 58*333d2b36SAndroid Build Coastguard Worker }, 59*333d2b36SAndroid Build Coastguard Worker { 60*333d2b36SAndroid Build Coastguard Worker in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"}, 61*333d2b36SAndroid Build Coastguard Worker out: []string{"liblog", "libdl", "libc++", "libc", "libm"}, 62*333d2b36SAndroid Build Coastguard Worker }, 63*333d2b36SAndroid Build Coastguard Worker} 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Workerfunc TestFirstUniqueStrings(t *testing.T) { 66*333d2b36SAndroid Build Coastguard Worker f := func(t *testing.T, imp func([]string) []string, in, want []string) { 67*333d2b36SAndroid Build Coastguard Worker t.Helper() 68*333d2b36SAndroid Build Coastguard Worker out := imp(in) 69*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(out, want) { 70*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 71*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", in) 72*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", want) 73*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 74*333d2b36SAndroid Build Coastguard Worker } 75*333d2b36SAndroid Build Coastguard Worker } 76*333d2b36SAndroid Build Coastguard Worker 77*333d2b36SAndroid Build Coastguard Worker for _, testCase := range firstUniqueStringsTestCases { 78*333d2b36SAndroid Build Coastguard Worker t.Run("list", func(t *testing.T) { 79*333d2b36SAndroid Build Coastguard Worker f(t, firstUniqueList[string], testCase.in, testCase.out) 80*333d2b36SAndroid Build Coastguard Worker }) 81*333d2b36SAndroid Build Coastguard Worker t.Run("map", func(t *testing.T) { 82*333d2b36SAndroid Build Coastguard Worker f(t, firstUniqueMap[string], testCase.in, testCase.out) 83*333d2b36SAndroid Build Coastguard Worker }) 84*333d2b36SAndroid Build Coastguard Worker } 85*333d2b36SAndroid Build Coastguard Worker} 86*333d2b36SAndroid Build Coastguard Worker 87*333d2b36SAndroid Build Coastguard Workervar lastUniqueStringsTestCases = []struct { 88*333d2b36SAndroid Build Coastguard Worker in []string 89*333d2b36SAndroid Build Coastguard Worker out []string 90*333d2b36SAndroid Build Coastguard Worker}{ 91*333d2b36SAndroid Build Coastguard Worker { 92*333d2b36SAndroid Build Coastguard Worker in: []string{"a"}, 93*333d2b36SAndroid Build Coastguard Worker out: []string{"a"}, 94*333d2b36SAndroid Build Coastguard Worker }, 95*333d2b36SAndroid Build Coastguard Worker { 96*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b"}, 97*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 98*333d2b36SAndroid Build Coastguard Worker }, 99*333d2b36SAndroid Build Coastguard Worker { 100*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "a"}, 101*333d2b36SAndroid Build Coastguard Worker out: []string{"a"}, 102*333d2b36SAndroid Build Coastguard Worker }, 103*333d2b36SAndroid Build Coastguard Worker { 104*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b", "a"}, 105*333d2b36SAndroid Build Coastguard Worker out: []string{"b", "a"}, 106*333d2b36SAndroid Build Coastguard Worker }, 107*333d2b36SAndroid Build Coastguard Worker { 108*333d2b36SAndroid Build Coastguard Worker in: []string{"b", "a", "a"}, 109*333d2b36SAndroid Build Coastguard Worker out: []string{"b", "a"}, 110*333d2b36SAndroid Build Coastguard Worker }, 111*333d2b36SAndroid Build Coastguard Worker { 112*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "a", "b"}, 113*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 114*333d2b36SAndroid Build Coastguard Worker }, 115*333d2b36SAndroid Build Coastguard Worker { 116*333d2b36SAndroid Build Coastguard Worker in: []string{"a", "b", "a", "b"}, 117*333d2b36SAndroid Build Coastguard Worker out: []string{"a", "b"}, 118*333d2b36SAndroid Build Coastguard Worker }, 119*333d2b36SAndroid Build Coastguard Worker { 120*333d2b36SAndroid Build Coastguard Worker in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"}, 121*333d2b36SAndroid Build Coastguard Worker out: []string{"liblog", "libc++", "libdl", "libc", "libm"}, 122*333d2b36SAndroid Build Coastguard Worker }, 123*333d2b36SAndroid Build Coastguard Worker} 124*333d2b36SAndroid Build Coastguard Worker 125*333d2b36SAndroid Build Coastguard Workerfunc TestLastUniqueStrings(t *testing.T) { 126*333d2b36SAndroid Build Coastguard Worker for _, testCase := range lastUniqueStringsTestCases { 127*333d2b36SAndroid Build Coastguard Worker out := LastUniqueStrings(testCase.in) 128*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(out, testCase.out) { 129*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 130*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", testCase.in) 131*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.out) 132*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 133*333d2b36SAndroid Build Coastguard Worker } 134*333d2b36SAndroid Build Coastguard Worker } 135*333d2b36SAndroid Build Coastguard Worker} 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Workerfunc TestJoinWithPrefix(t *testing.T) { 138*333d2b36SAndroid Build Coastguard Worker testcases := []struct { 139*333d2b36SAndroid Build Coastguard Worker name string 140*333d2b36SAndroid Build Coastguard Worker input []string 141*333d2b36SAndroid Build Coastguard Worker expected string 142*333d2b36SAndroid Build Coastguard Worker }{ 143*333d2b36SAndroid Build Coastguard Worker { 144*333d2b36SAndroid Build Coastguard Worker name: "zero_inputs", 145*333d2b36SAndroid Build Coastguard Worker input: []string{}, 146*333d2b36SAndroid Build Coastguard Worker expected: "", 147*333d2b36SAndroid Build Coastguard Worker }, 148*333d2b36SAndroid Build Coastguard Worker { 149*333d2b36SAndroid Build Coastguard Worker name: "one_input", 150*333d2b36SAndroid Build Coastguard Worker input: []string{"a"}, 151*333d2b36SAndroid Build Coastguard Worker expected: "prefix:a", 152*333d2b36SAndroid Build Coastguard Worker }, 153*333d2b36SAndroid Build Coastguard Worker { 154*333d2b36SAndroid Build Coastguard Worker name: "two_inputs", 155*333d2b36SAndroid Build Coastguard Worker input: []string{"a", "b"}, 156*333d2b36SAndroid Build Coastguard Worker expected: "prefix:a prefix:b", 157*333d2b36SAndroid Build Coastguard Worker }, 158*333d2b36SAndroid Build Coastguard Worker } 159*333d2b36SAndroid Build Coastguard Worker 160*333d2b36SAndroid Build Coastguard Worker prefix := "prefix:" 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker for _, testCase := range testcases { 163*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 164*333d2b36SAndroid Build Coastguard Worker out := JoinWithPrefix(testCase.input, prefix) 165*333d2b36SAndroid Build Coastguard Worker if out != testCase.expected { 166*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 167*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", testCase.input) 168*333d2b36SAndroid Build Coastguard Worker t.Errorf(" prefix: %#v", prefix) 169*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expected) 170*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 171*333d2b36SAndroid Build Coastguard Worker } 172*333d2b36SAndroid Build Coastguard Worker }) 173*333d2b36SAndroid Build Coastguard Worker } 174*333d2b36SAndroid Build Coastguard Worker} 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Workerfunc TestIndexList(t *testing.T) { 177*333d2b36SAndroid Build Coastguard Worker input := []string{"a", "b", "c"} 178*333d2b36SAndroid Build Coastguard Worker 179*333d2b36SAndroid Build Coastguard Worker testcases := []struct { 180*333d2b36SAndroid Build Coastguard Worker key string 181*333d2b36SAndroid Build Coastguard Worker expected int 182*333d2b36SAndroid Build Coastguard Worker }{ 183*333d2b36SAndroid Build Coastguard Worker { 184*333d2b36SAndroid Build Coastguard Worker key: "a", 185*333d2b36SAndroid Build Coastguard Worker expected: 0, 186*333d2b36SAndroid Build Coastguard Worker }, 187*333d2b36SAndroid Build Coastguard Worker { 188*333d2b36SAndroid Build Coastguard Worker key: "b", 189*333d2b36SAndroid Build Coastguard Worker expected: 1, 190*333d2b36SAndroid Build Coastguard Worker }, 191*333d2b36SAndroid Build Coastguard Worker { 192*333d2b36SAndroid Build Coastguard Worker key: "c", 193*333d2b36SAndroid Build Coastguard Worker expected: 2, 194*333d2b36SAndroid Build Coastguard Worker }, 195*333d2b36SAndroid Build Coastguard Worker { 196*333d2b36SAndroid Build Coastguard Worker key: "X", 197*333d2b36SAndroid Build Coastguard Worker expected: -1, 198*333d2b36SAndroid Build Coastguard Worker }, 199*333d2b36SAndroid Build Coastguard Worker } 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker for _, testCase := range testcases { 202*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.key, func(t *testing.T) { 203*333d2b36SAndroid Build Coastguard Worker out := IndexList(testCase.key, input) 204*333d2b36SAndroid Build Coastguard Worker if out != testCase.expected { 205*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 206*333d2b36SAndroid Build Coastguard Worker t.Errorf(" key: %#v", testCase.key) 207*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", input) 208*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expected) 209*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 210*333d2b36SAndroid Build Coastguard Worker } 211*333d2b36SAndroid Build Coastguard Worker }) 212*333d2b36SAndroid Build Coastguard Worker } 213*333d2b36SAndroid Build Coastguard Worker} 214*333d2b36SAndroid Build Coastguard Worker 215*333d2b36SAndroid Build Coastguard Workerfunc TestInList(t *testing.T) { 216*333d2b36SAndroid Build Coastguard Worker input := []string{"a"} 217*333d2b36SAndroid Build Coastguard Worker 218*333d2b36SAndroid Build Coastguard Worker testcases := []struct { 219*333d2b36SAndroid Build Coastguard Worker key string 220*333d2b36SAndroid Build Coastguard Worker expected bool 221*333d2b36SAndroid Build Coastguard Worker }{ 222*333d2b36SAndroid Build Coastguard Worker { 223*333d2b36SAndroid Build Coastguard Worker key: "a", 224*333d2b36SAndroid Build Coastguard Worker expected: true, 225*333d2b36SAndroid Build Coastguard Worker }, 226*333d2b36SAndroid Build Coastguard Worker { 227*333d2b36SAndroid Build Coastguard Worker key: "X", 228*333d2b36SAndroid Build Coastguard Worker expected: false, 229*333d2b36SAndroid Build Coastguard Worker }, 230*333d2b36SAndroid Build Coastguard Worker } 231*333d2b36SAndroid Build Coastguard Worker 232*333d2b36SAndroid Build Coastguard Worker for _, testCase := range testcases { 233*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.key, func(t *testing.T) { 234*333d2b36SAndroid Build Coastguard Worker out := InList(testCase.key, input) 235*333d2b36SAndroid Build Coastguard Worker if out != testCase.expected { 236*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 237*333d2b36SAndroid Build Coastguard Worker t.Errorf(" key: %#v", testCase.key) 238*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", input) 239*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expected) 240*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 241*333d2b36SAndroid Build Coastguard Worker } 242*333d2b36SAndroid Build Coastguard Worker }) 243*333d2b36SAndroid Build Coastguard Worker } 244*333d2b36SAndroid Build Coastguard Worker} 245*333d2b36SAndroid Build Coastguard Worker 246*333d2b36SAndroid Build Coastguard Workerfunc TestPrefixInList(t *testing.T) { 247*333d2b36SAndroid Build Coastguard Worker prefixes := []string{"a", "b"} 248*333d2b36SAndroid Build Coastguard Worker 249*333d2b36SAndroid Build Coastguard Worker testcases := []struct { 250*333d2b36SAndroid Build Coastguard Worker str string 251*333d2b36SAndroid Build Coastguard Worker expected bool 252*333d2b36SAndroid Build Coastguard Worker }{ 253*333d2b36SAndroid Build Coastguard Worker { 254*333d2b36SAndroid Build Coastguard Worker str: "a-example", 255*333d2b36SAndroid Build Coastguard Worker expected: true, 256*333d2b36SAndroid Build Coastguard Worker }, 257*333d2b36SAndroid Build Coastguard Worker { 258*333d2b36SAndroid Build Coastguard Worker str: "b-example", 259*333d2b36SAndroid Build Coastguard Worker expected: true, 260*333d2b36SAndroid Build Coastguard Worker }, 261*333d2b36SAndroid Build Coastguard Worker { 262*333d2b36SAndroid Build Coastguard Worker str: "X-example", 263*333d2b36SAndroid Build Coastguard Worker expected: false, 264*333d2b36SAndroid Build Coastguard Worker }, 265*333d2b36SAndroid Build Coastguard Worker } 266*333d2b36SAndroid Build Coastguard Worker 267*333d2b36SAndroid Build Coastguard Worker for _, testCase := range testcases { 268*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.str, func(t *testing.T) { 269*333d2b36SAndroid Build Coastguard Worker out := HasAnyPrefix(testCase.str, prefixes) 270*333d2b36SAndroid Build Coastguard Worker if out != testCase.expected { 271*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 272*333d2b36SAndroid Build Coastguard Worker t.Errorf(" str: %#v", testCase.str) 273*333d2b36SAndroid Build Coastguard Worker t.Errorf(" prefixes: %#v", prefixes) 274*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expected) 275*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 276*333d2b36SAndroid Build Coastguard Worker } 277*333d2b36SAndroid Build Coastguard Worker }) 278*333d2b36SAndroid Build Coastguard Worker } 279*333d2b36SAndroid Build Coastguard Worker} 280*333d2b36SAndroid Build Coastguard Worker 281*333d2b36SAndroid Build Coastguard Workerfunc TestFilterList(t *testing.T) { 282*333d2b36SAndroid Build Coastguard Worker input := []string{"a", "b", "c", "c", "b", "d", "a"} 283*333d2b36SAndroid Build Coastguard Worker filter := []string{"a", "c"} 284*333d2b36SAndroid Build Coastguard Worker remainder, filtered := FilterList(input, filter) 285*333d2b36SAndroid Build Coastguard Worker 286*333d2b36SAndroid Build Coastguard Worker expected := []string{"b", "b", "d"} 287*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(remainder, expected) { 288*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect remainder output:") 289*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", input) 290*333d2b36SAndroid Build Coastguard Worker t.Errorf(" filter: %#v", filter) 291*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", expected) 292*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", remainder) 293*333d2b36SAndroid Build Coastguard Worker } 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Worker expected = []string{"a", "c", "c", "a"} 296*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(filtered, expected) { 297*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect filtered output:") 298*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", input) 299*333d2b36SAndroid Build Coastguard Worker t.Errorf(" filter: %#v", filter) 300*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", expected) 301*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", filtered) 302*333d2b36SAndroid Build Coastguard Worker } 303*333d2b36SAndroid Build Coastguard Worker} 304*333d2b36SAndroid Build Coastguard Worker 305*333d2b36SAndroid Build Coastguard Workerfunc TestFilterListPred(t *testing.T) { 306*333d2b36SAndroid Build Coastguard Worker pred := func(s string) bool { return strings.HasPrefix(s, "a/") } 307*333d2b36SAndroid Build Coastguard Worker AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "b/a", "a/b"}, pred), []string{"a/c", "a/b"}) 308*333d2b36SAndroid Build Coastguard Worker AssertArrayString(t, "filter", FilterListPred([]string{"b/c", "a/a", "b/b"}, pred), []string{"a/a"}) 309*333d2b36SAndroid Build Coastguard Worker AssertArrayString(t, "filter", FilterListPred([]string{"c/c", "b/a", "c/b"}, pred), []string{}) 310*333d2b36SAndroid Build Coastguard Worker AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "a/a", "a/b"}, pred), []string{"a/c", "a/a", "a/b"}) 311*333d2b36SAndroid Build Coastguard Worker} 312*333d2b36SAndroid Build Coastguard Worker 313*333d2b36SAndroid Build Coastguard Workerfunc TestRemoveListFromList(t *testing.T) { 314*333d2b36SAndroid Build Coastguard Worker input := []string{"a", "b", "c", "d", "a", "c", "d"} 315*333d2b36SAndroid Build Coastguard Worker filter := []string{"a", "c"} 316*333d2b36SAndroid Build Coastguard Worker expected := []string{"b", "d", "d"} 317*333d2b36SAndroid Build Coastguard Worker out := RemoveListFromList(input, filter) 318*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(out, expected) { 319*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 320*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", input) 321*333d2b36SAndroid Build Coastguard Worker t.Errorf(" filter: %#v", filter) 322*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", expected) 323*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 324*333d2b36SAndroid Build Coastguard Worker } 325*333d2b36SAndroid Build Coastguard Worker} 326*333d2b36SAndroid Build Coastguard Worker 327*333d2b36SAndroid Build Coastguard Workerfunc TestRemoveFromList(t *testing.T) { 328*333d2b36SAndroid Build Coastguard Worker testcases := []struct { 329*333d2b36SAndroid Build Coastguard Worker name string 330*333d2b36SAndroid Build Coastguard Worker key string 331*333d2b36SAndroid Build Coastguard Worker input []string 332*333d2b36SAndroid Build Coastguard Worker expectedFound bool 333*333d2b36SAndroid Build Coastguard Worker expectedOut []string 334*333d2b36SAndroid Build Coastguard Worker }{ 335*333d2b36SAndroid Build Coastguard Worker { 336*333d2b36SAndroid Build Coastguard Worker name: "remove_one_match", 337*333d2b36SAndroid Build Coastguard Worker key: "a", 338*333d2b36SAndroid Build Coastguard Worker input: []string{"a", "b", "c"}, 339*333d2b36SAndroid Build Coastguard Worker expectedFound: true, 340*333d2b36SAndroid Build Coastguard Worker expectedOut: []string{"b", "c"}, 341*333d2b36SAndroid Build Coastguard Worker }, 342*333d2b36SAndroid Build Coastguard Worker { 343*333d2b36SAndroid Build Coastguard Worker name: "remove_three_matches", 344*333d2b36SAndroid Build Coastguard Worker key: "a", 345*333d2b36SAndroid Build Coastguard Worker input: []string{"a", "b", "a", "c", "a"}, 346*333d2b36SAndroid Build Coastguard Worker expectedFound: true, 347*333d2b36SAndroid Build Coastguard Worker expectedOut: []string{"b", "c"}, 348*333d2b36SAndroid Build Coastguard Worker }, 349*333d2b36SAndroid Build Coastguard Worker { 350*333d2b36SAndroid Build Coastguard Worker name: "remove_zero_matches", 351*333d2b36SAndroid Build Coastguard Worker key: "X", 352*333d2b36SAndroid Build Coastguard Worker input: []string{"a", "b", "a", "c", "a"}, 353*333d2b36SAndroid Build Coastguard Worker expectedFound: false, 354*333d2b36SAndroid Build Coastguard Worker expectedOut: []string{"a", "b", "a", "c", "a"}, 355*333d2b36SAndroid Build Coastguard Worker }, 356*333d2b36SAndroid Build Coastguard Worker { 357*333d2b36SAndroid Build Coastguard Worker name: "remove_all_matches", 358*333d2b36SAndroid Build Coastguard Worker key: "a", 359*333d2b36SAndroid Build Coastguard Worker input: []string{"a", "a", "a", "a"}, 360*333d2b36SAndroid Build Coastguard Worker expectedFound: true, 361*333d2b36SAndroid Build Coastguard Worker expectedOut: []string{}, 362*333d2b36SAndroid Build Coastguard Worker }, 363*333d2b36SAndroid Build Coastguard Worker } 364*333d2b36SAndroid Build Coastguard Worker 365*333d2b36SAndroid Build Coastguard Worker for _, testCase := range testcases { 366*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 367*333d2b36SAndroid Build Coastguard Worker found, out := RemoveFromList(testCase.key, testCase.input) 368*333d2b36SAndroid Build Coastguard Worker if found != testCase.expectedFound { 369*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 370*333d2b36SAndroid Build Coastguard Worker t.Errorf(" key: %#v", testCase.key) 371*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", testCase.input) 372*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expectedFound) 373*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", found) 374*333d2b36SAndroid Build Coastguard Worker } 375*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(out, testCase.expectedOut) { 376*333d2b36SAndroid Build Coastguard Worker t.Errorf("incorrect output:") 377*333d2b36SAndroid Build Coastguard Worker t.Errorf(" key: %#v", testCase.key) 378*333d2b36SAndroid Build Coastguard Worker t.Errorf(" input: %#v", testCase.input) 379*333d2b36SAndroid Build Coastguard Worker t.Errorf(" expected: %#v", testCase.expectedOut) 380*333d2b36SAndroid Build Coastguard Worker t.Errorf(" got: %#v", out) 381*333d2b36SAndroid Build Coastguard Worker } 382*333d2b36SAndroid Build Coastguard Worker }) 383*333d2b36SAndroid Build Coastguard Worker } 384*333d2b36SAndroid Build Coastguard Worker} 385*333d2b36SAndroid Build Coastguard Worker 386*333d2b36SAndroid Build Coastguard Workerfunc TestCopyOfEmptyAndNil(t *testing.T) { 387*333d2b36SAndroid Build Coastguard Worker emptyList := []string{} 388*333d2b36SAndroid Build Coastguard Worker copyOfEmptyList := CopyOf(emptyList) 389*333d2b36SAndroid Build Coastguard Worker AssertBoolEquals(t, "Copy of an empty list should be an empty list and not nil", true, copyOfEmptyList != nil) 390*333d2b36SAndroid Build Coastguard Worker copyOfNilList := CopyOf([]string(nil)) 391*333d2b36SAndroid Build Coastguard Worker AssertBoolEquals(t, "Copy of a nil list should be a nil list and not an empty list", true, copyOfNilList == nil) 392*333d2b36SAndroid Build Coastguard Worker} 393*333d2b36SAndroid Build Coastguard Worker 394*333d2b36SAndroid Build Coastguard Workerfunc ExampleCopyOf() { 395*333d2b36SAndroid Build Coastguard Worker a := []string{"1", "2", "3"} 396*333d2b36SAndroid Build Coastguard Worker b := CopyOf(a) 397*333d2b36SAndroid Build Coastguard Worker a[0] = "-1" 398*333d2b36SAndroid Build Coastguard Worker fmt.Printf("a = %q\n", a) 399*333d2b36SAndroid Build Coastguard Worker fmt.Printf("b = %q\n", b) 400*333d2b36SAndroid Build Coastguard Worker 401*333d2b36SAndroid Build Coastguard Worker // Output: 402*333d2b36SAndroid Build Coastguard Worker // a = ["-1" "2" "3"] 403*333d2b36SAndroid Build Coastguard Worker // b = ["1" "2" "3"] 404*333d2b36SAndroid Build Coastguard Worker} 405*333d2b36SAndroid Build Coastguard Worker 406*333d2b36SAndroid Build Coastguard Workerfunc ExampleCopyOf_append() { 407*333d2b36SAndroid Build Coastguard Worker a := make([]string, 1, 2) 408*333d2b36SAndroid Build Coastguard Worker a[0] = "foo" 409*333d2b36SAndroid Build Coastguard Worker 410*333d2b36SAndroid Build Coastguard Worker fmt.Println("Without CopyOf:") 411*333d2b36SAndroid Build Coastguard Worker b := append(a, "bar") 412*333d2b36SAndroid Build Coastguard Worker c := append(a, "baz") 413*333d2b36SAndroid Build Coastguard Worker fmt.Printf("a = %q\n", a) 414*333d2b36SAndroid Build Coastguard Worker fmt.Printf("b = %q\n", b) 415*333d2b36SAndroid Build Coastguard Worker fmt.Printf("c = %q\n", c) 416*333d2b36SAndroid Build Coastguard Worker 417*333d2b36SAndroid Build Coastguard Worker a = make([]string, 1, 2) 418*333d2b36SAndroid Build Coastguard Worker a[0] = "foo" 419*333d2b36SAndroid Build Coastguard Worker 420*333d2b36SAndroid Build Coastguard Worker fmt.Println("With CopyOf:") 421*333d2b36SAndroid Build Coastguard Worker b = append(CopyOf(a), "bar") 422*333d2b36SAndroid Build Coastguard Worker c = append(CopyOf(a), "baz") 423*333d2b36SAndroid Build Coastguard Worker fmt.Printf("a = %q\n", a) 424*333d2b36SAndroid Build Coastguard Worker fmt.Printf("b = %q\n", b) 425*333d2b36SAndroid Build Coastguard Worker fmt.Printf("c = %q\n", c) 426*333d2b36SAndroid Build Coastguard Worker 427*333d2b36SAndroid Build Coastguard Worker // Output: 428*333d2b36SAndroid Build Coastguard Worker // Without CopyOf: 429*333d2b36SAndroid Build Coastguard Worker // a = ["foo"] 430*333d2b36SAndroid Build Coastguard Worker // b = ["foo" "baz"] 431*333d2b36SAndroid Build Coastguard Worker // c = ["foo" "baz"] 432*333d2b36SAndroid Build Coastguard Worker // With CopyOf: 433*333d2b36SAndroid Build Coastguard Worker // a = ["foo"] 434*333d2b36SAndroid Build Coastguard Worker // b = ["foo" "bar"] 435*333d2b36SAndroid Build Coastguard Worker // c = ["foo" "baz"] 436*333d2b36SAndroid Build Coastguard Worker} 437*333d2b36SAndroid Build Coastguard Worker 438*333d2b36SAndroid Build Coastguard Workerfunc TestSplitFileExt(t *testing.T) { 439*333d2b36SAndroid Build Coastguard Worker t.Run("soname with version", func(t *testing.T) { 440*333d2b36SAndroid Build Coastguard Worker root, suffix, ext := SplitFileExt("libtest.so.1.0.30") 441*333d2b36SAndroid Build Coastguard Worker expected := "libtest" 442*333d2b36SAndroid Build Coastguard Worker if root != expected { 443*333d2b36SAndroid Build Coastguard Worker t.Errorf("root should be %q but got %q", expected, root) 444*333d2b36SAndroid Build Coastguard Worker } 445*333d2b36SAndroid Build Coastguard Worker expected = ".so.1.0.30" 446*333d2b36SAndroid Build Coastguard Worker if suffix != expected { 447*333d2b36SAndroid Build Coastguard Worker t.Errorf("suffix should be %q but got %q", expected, suffix) 448*333d2b36SAndroid Build Coastguard Worker } 449*333d2b36SAndroid Build Coastguard Worker expected = ".so" 450*333d2b36SAndroid Build Coastguard Worker if ext != expected { 451*333d2b36SAndroid Build Coastguard Worker t.Errorf("ext should be %q but got %q", expected, ext) 452*333d2b36SAndroid Build Coastguard Worker } 453*333d2b36SAndroid Build Coastguard Worker }) 454*333d2b36SAndroid Build Coastguard Worker 455*333d2b36SAndroid Build Coastguard Worker t.Run("soname with svn version", func(t *testing.T) { 456*333d2b36SAndroid Build Coastguard Worker root, suffix, ext := SplitFileExt("libtest.so.1svn") 457*333d2b36SAndroid Build Coastguard Worker expected := "libtest" 458*333d2b36SAndroid Build Coastguard Worker if root != expected { 459*333d2b36SAndroid Build Coastguard Worker t.Errorf("root should be %q but got %q", expected, root) 460*333d2b36SAndroid Build Coastguard Worker } 461*333d2b36SAndroid Build Coastguard Worker expected = ".so.1svn" 462*333d2b36SAndroid Build Coastguard Worker if suffix != expected { 463*333d2b36SAndroid Build Coastguard Worker t.Errorf("suffix should be %q but got %q", expected, suffix) 464*333d2b36SAndroid Build Coastguard Worker } 465*333d2b36SAndroid Build Coastguard Worker expected = ".so" 466*333d2b36SAndroid Build Coastguard Worker if ext != expected { 467*333d2b36SAndroid Build Coastguard Worker t.Errorf("ext should be %q but got %q", expected, ext) 468*333d2b36SAndroid Build Coastguard Worker } 469*333d2b36SAndroid Build Coastguard Worker }) 470*333d2b36SAndroid Build Coastguard Worker 471*333d2b36SAndroid Build Coastguard Worker t.Run("version numbers in the middle should be ignored", func(t *testing.T) { 472*333d2b36SAndroid Build Coastguard Worker root, suffix, ext := SplitFileExt("libtest.1.0.30.so") 473*333d2b36SAndroid Build Coastguard Worker expected := "libtest.1.0.30" 474*333d2b36SAndroid Build Coastguard Worker if root != expected { 475*333d2b36SAndroid Build Coastguard Worker t.Errorf("root should be %q but got %q", expected, root) 476*333d2b36SAndroid Build Coastguard Worker } 477*333d2b36SAndroid Build Coastguard Worker expected = ".so" 478*333d2b36SAndroid Build Coastguard Worker if suffix != expected { 479*333d2b36SAndroid Build Coastguard Worker t.Errorf("suffix should be %q but got %q", expected, suffix) 480*333d2b36SAndroid Build Coastguard Worker } 481*333d2b36SAndroid Build Coastguard Worker expected = ".so" 482*333d2b36SAndroid Build Coastguard Worker if ext != expected { 483*333d2b36SAndroid Build Coastguard Worker t.Errorf("ext should be %q but got %q", expected, ext) 484*333d2b36SAndroid Build Coastguard Worker } 485*333d2b36SAndroid Build Coastguard Worker }) 486*333d2b36SAndroid Build Coastguard Worker 487*333d2b36SAndroid Build Coastguard Worker t.Run("no known file extension", func(t *testing.T) { 488*333d2b36SAndroid Build Coastguard Worker root, suffix, ext := SplitFileExt("test.exe") 489*333d2b36SAndroid Build Coastguard Worker expected := "test" 490*333d2b36SAndroid Build Coastguard Worker if root != expected { 491*333d2b36SAndroid Build Coastguard Worker t.Errorf("root should be %q but got %q", expected, root) 492*333d2b36SAndroid Build Coastguard Worker } 493*333d2b36SAndroid Build Coastguard Worker expected = ".exe" 494*333d2b36SAndroid Build Coastguard Worker if suffix != expected { 495*333d2b36SAndroid Build Coastguard Worker t.Errorf("suffix should be %q but got %q", expected, suffix) 496*333d2b36SAndroid Build Coastguard Worker } 497*333d2b36SAndroid Build Coastguard Worker if ext != expected { 498*333d2b36SAndroid Build Coastguard Worker t.Errorf("ext should be %q but got %q", expected, ext) 499*333d2b36SAndroid Build Coastguard Worker } 500*333d2b36SAndroid Build Coastguard Worker }) 501*333d2b36SAndroid Build Coastguard Worker} 502*333d2b36SAndroid Build Coastguard Worker 503*333d2b36SAndroid Build Coastguard Workerfunc Test_Shard(t *testing.T) { 504*333d2b36SAndroid Build Coastguard Worker type args struct { 505*333d2b36SAndroid Build Coastguard Worker strings []string 506*333d2b36SAndroid Build Coastguard Worker shardSize int 507*333d2b36SAndroid Build Coastguard Worker } 508*333d2b36SAndroid Build Coastguard Worker tests := []struct { 509*333d2b36SAndroid Build Coastguard Worker name string 510*333d2b36SAndroid Build Coastguard Worker args args 511*333d2b36SAndroid Build Coastguard Worker want [][]string 512*333d2b36SAndroid Build Coastguard Worker }{ 513*333d2b36SAndroid Build Coastguard Worker { 514*333d2b36SAndroid Build Coastguard Worker name: "empty", 515*333d2b36SAndroid Build Coastguard Worker args: args{ 516*333d2b36SAndroid Build Coastguard Worker strings: nil, 517*333d2b36SAndroid Build Coastguard Worker shardSize: 1, 518*333d2b36SAndroid Build Coastguard Worker }, 519*333d2b36SAndroid Build Coastguard Worker want: [][]string(nil), 520*333d2b36SAndroid Build Coastguard Worker }, 521*333d2b36SAndroid Build Coastguard Worker { 522*333d2b36SAndroid Build Coastguard Worker name: "single shard", 523*333d2b36SAndroid Build Coastguard Worker args: args{ 524*333d2b36SAndroid Build Coastguard Worker strings: []string{"a", "b"}, 525*333d2b36SAndroid Build Coastguard Worker shardSize: 2, 526*333d2b36SAndroid Build Coastguard Worker }, 527*333d2b36SAndroid Build Coastguard Worker want: [][]string{{"a", "b"}}, 528*333d2b36SAndroid Build Coastguard Worker }, 529*333d2b36SAndroid Build Coastguard Worker { 530*333d2b36SAndroid Build Coastguard Worker name: "single short shard", 531*333d2b36SAndroid Build Coastguard Worker args: args{ 532*333d2b36SAndroid Build Coastguard Worker strings: []string{"a", "b"}, 533*333d2b36SAndroid Build Coastguard Worker shardSize: 3, 534*333d2b36SAndroid Build Coastguard Worker }, 535*333d2b36SAndroid Build Coastguard Worker want: [][]string{{"a", "b"}}, 536*333d2b36SAndroid Build Coastguard Worker }, 537*333d2b36SAndroid Build Coastguard Worker { 538*333d2b36SAndroid Build Coastguard Worker name: "shard per input", 539*333d2b36SAndroid Build Coastguard Worker args: args{ 540*333d2b36SAndroid Build Coastguard Worker strings: []string{"a", "b", "c"}, 541*333d2b36SAndroid Build Coastguard Worker shardSize: 1, 542*333d2b36SAndroid Build Coastguard Worker }, 543*333d2b36SAndroid Build Coastguard Worker want: [][]string{{"a"}, {"b"}, {"c"}}, 544*333d2b36SAndroid Build Coastguard Worker }, 545*333d2b36SAndroid Build Coastguard Worker { 546*333d2b36SAndroid Build Coastguard Worker name: "balanced shards", 547*333d2b36SAndroid Build Coastguard Worker args: args{ 548*333d2b36SAndroid Build Coastguard Worker strings: []string{"a", "b", "c", "d"}, 549*333d2b36SAndroid Build Coastguard Worker shardSize: 2, 550*333d2b36SAndroid Build Coastguard Worker }, 551*333d2b36SAndroid Build Coastguard Worker want: [][]string{{"a", "b"}, {"c", "d"}}, 552*333d2b36SAndroid Build Coastguard Worker }, 553*333d2b36SAndroid Build Coastguard Worker { 554*333d2b36SAndroid Build Coastguard Worker name: "unbalanced shards", 555*333d2b36SAndroid Build Coastguard Worker args: args{ 556*333d2b36SAndroid Build Coastguard Worker strings: []string{"a", "b", "c"}, 557*333d2b36SAndroid Build Coastguard Worker shardSize: 2, 558*333d2b36SAndroid Build Coastguard Worker }, 559*333d2b36SAndroid Build Coastguard Worker want: [][]string{{"a", "b"}, {"c"}}, 560*333d2b36SAndroid Build Coastguard Worker }, 561*333d2b36SAndroid Build Coastguard Worker } 562*333d2b36SAndroid Build Coastguard Worker for _, tt := range tests { 563*333d2b36SAndroid Build Coastguard Worker t.Run(tt.name, func(t *testing.T) { 564*333d2b36SAndroid Build Coastguard Worker t.Run("strings", func(t *testing.T) { 565*333d2b36SAndroid Build Coastguard Worker if got := ShardStrings(tt.args.strings, tt.args.shardSize); !reflect.DeepEqual(got, tt.want) { 566*333d2b36SAndroid Build Coastguard Worker t.Errorf("ShardStrings(%v, %v) = %v, want %v", 567*333d2b36SAndroid Build Coastguard Worker tt.args.strings, tt.args.shardSize, got, tt.want) 568*333d2b36SAndroid Build Coastguard Worker } 569*333d2b36SAndroid Build Coastguard Worker }) 570*333d2b36SAndroid Build Coastguard Worker 571*333d2b36SAndroid Build Coastguard Worker t.Run("paths", func(t *testing.T) { 572*333d2b36SAndroid Build Coastguard Worker stringsToPaths := func(strings []string) Paths { 573*333d2b36SAndroid Build Coastguard Worker if strings == nil { 574*333d2b36SAndroid Build Coastguard Worker return nil 575*333d2b36SAndroid Build Coastguard Worker } 576*333d2b36SAndroid Build Coastguard Worker paths := make(Paths, len(strings)) 577*333d2b36SAndroid Build Coastguard Worker for i, s := range strings { 578*333d2b36SAndroid Build Coastguard Worker paths[i] = PathForTesting(s) 579*333d2b36SAndroid Build Coastguard Worker } 580*333d2b36SAndroid Build Coastguard Worker return paths 581*333d2b36SAndroid Build Coastguard Worker } 582*333d2b36SAndroid Build Coastguard Worker 583*333d2b36SAndroid Build Coastguard Worker paths := stringsToPaths(tt.args.strings) 584*333d2b36SAndroid Build Coastguard Worker 585*333d2b36SAndroid Build Coastguard Worker var want []Paths 586*333d2b36SAndroid Build Coastguard Worker if sWant := tt.want; sWant != nil { 587*333d2b36SAndroid Build Coastguard Worker want = make([]Paths, len(sWant)) 588*333d2b36SAndroid Build Coastguard Worker for i, w := range sWant { 589*333d2b36SAndroid Build Coastguard Worker want[i] = stringsToPaths(w) 590*333d2b36SAndroid Build Coastguard Worker } 591*333d2b36SAndroid Build Coastguard Worker } 592*333d2b36SAndroid Build Coastguard Worker 593*333d2b36SAndroid Build Coastguard Worker if got := ShardPaths(paths, tt.args.shardSize); !reflect.DeepEqual(got, want) { 594*333d2b36SAndroid Build Coastguard Worker t.Errorf("ShardPaths(%v, %v) = %v, want %v", 595*333d2b36SAndroid Build Coastguard Worker paths, tt.args.shardSize, got, want) 596*333d2b36SAndroid Build Coastguard Worker } 597*333d2b36SAndroid Build Coastguard Worker }) 598*333d2b36SAndroid Build Coastguard Worker }) 599*333d2b36SAndroid Build Coastguard Worker } 600*333d2b36SAndroid Build Coastguard Worker} 601*333d2b36SAndroid Build Coastguard Worker 602*333d2b36SAndroid Build Coastguard Workerfunc BenchmarkFirstUniqueStrings(b *testing.B) { 603*333d2b36SAndroid Build Coastguard Worker implementations := []struct { 604*333d2b36SAndroid Build Coastguard Worker name string 605*333d2b36SAndroid Build Coastguard Worker f func([]string) []string 606*333d2b36SAndroid Build Coastguard Worker }{ 607*333d2b36SAndroid Build Coastguard Worker { 608*333d2b36SAndroid Build Coastguard Worker name: "list", 609*333d2b36SAndroid Build Coastguard Worker f: firstUniqueList[string], 610*333d2b36SAndroid Build Coastguard Worker }, 611*333d2b36SAndroid Build Coastguard Worker { 612*333d2b36SAndroid Build Coastguard Worker name: "map", 613*333d2b36SAndroid Build Coastguard Worker f: firstUniqueMap[string], 614*333d2b36SAndroid Build Coastguard Worker }, 615*333d2b36SAndroid Build Coastguard Worker { 616*333d2b36SAndroid Build Coastguard Worker name: "optimal", 617*333d2b36SAndroid Build Coastguard Worker f: FirstUniqueStrings, 618*333d2b36SAndroid Build Coastguard Worker }, 619*333d2b36SAndroid Build Coastguard Worker } 620*333d2b36SAndroid Build Coastguard Worker const maxSize = 1024 621*333d2b36SAndroid Build Coastguard Worker uniqueStrings := make([]string, maxSize) 622*333d2b36SAndroid Build Coastguard Worker for i := range uniqueStrings { 623*333d2b36SAndroid Build Coastguard Worker uniqueStrings[i] = strconv.Itoa(i) 624*333d2b36SAndroid Build Coastguard Worker } 625*333d2b36SAndroid Build Coastguard Worker sameString := make([]string, maxSize) 626*333d2b36SAndroid Build Coastguard Worker for i := range sameString { 627*333d2b36SAndroid Build Coastguard Worker sameString[i] = uniqueStrings[0] 628*333d2b36SAndroid Build Coastguard Worker } 629*333d2b36SAndroid Build Coastguard Worker 630*333d2b36SAndroid Build Coastguard Worker f := func(b *testing.B, imp func([]string) []string, s []string) { 631*333d2b36SAndroid Build Coastguard Worker for i := 0; i < b.N; i++ { 632*333d2b36SAndroid Build Coastguard Worker b.ReportAllocs() 633*333d2b36SAndroid Build Coastguard Worker s = append([]string(nil), s...) 634*333d2b36SAndroid Build Coastguard Worker imp(s) 635*333d2b36SAndroid Build Coastguard Worker } 636*333d2b36SAndroid Build Coastguard Worker } 637*333d2b36SAndroid Build Coastguard Worker 638*333d2b36SAndroid Build Coastguard Worker for n := 1; n <= maxSize; n <<= 1 { 639*333d2b36SAndroid Build Coastguard Worker b.Run(strconv.Itoa(n), func(b *testing.B) { 640*333d2b36SAndroid Build Coastguard Worker for _, implementation := range implementations { 641*333d2b36SAndroid Build Coastguard Worker b.Run(implementation.name, func(b *testing.B) { 642*333d2b36SAndroid Build Coastguard Worker b.Run("same", func(b *testing.B) { 643*333d2b36SAndroid Build Coastguard Worker f(b, implementation.f, sameString[:n]) 644*333d2b36SAndroid Build Coastguard Worker }) 645*333d2b36SAndroid Build Coastguard Worker b.Run("unique", func(b *testing.B) { 646*333d2b36SAndroid Build Coastguard Worker f(b, implementation.f, uniqueStrings[:n]) 647*333d2b36SAndroid Build Coastguard Worker }) 648*333d2b36SAndroid Build Coastguard Worker }) 649*333d2b36SAndroid Build Coastguard Worker } 650*333d2b36SAndroid Build Coastguard Worker }) 651*333d2b36SAndroid Build Coastguard Worker } 652*333d2b36SAndroid Build Coastguard Worker} 653*333d2b36SAndroid Build Coastguard Worker 654*333d2b36SAndroid Build Coastguard Workerfunc testSortedKeysHelper[K cmp.Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) { 655*333d2b36SAndroid Build Coastguard Worker t.Helper() 656*333d2b36SAndroid Build Coastguard Worker t.Run(name, func(t *testing.T) { 657*333d2b36SAndroid Build Coastguard Worker actual := SortedKeys(input) 658*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(actual, expected) { 659*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected %v, got %v", expected, actual) 660*333d2b36SAndroid Build Coastguard Worker } 661*333d2b36SAndroid Build Coastguard Worker }) 662*333d2b36SAndroid Build Coastguard Worker} 663*333d2b36SAndroid Build Coastguard Worker 664*333d2b36SAndroid Build Coastguard Workerfunc TestSortedKeys(t *testing.T) { 665*333d2b36SAndroid Build Coastguard Worker testSortedKeysHelper(t, "simple", map[string]string{ 666*333d2b36SAndroid Build Coastguard Worker "b": "bar", 667*333d2b36SAndroid Build Coastguard Worker "a": "foo", 668*333d2b36SAndroid Build Coastguard Worker }, []string{ 669*333d2b36SAndroid Build Coastguard Worker "a", 670*333d2b36SAndroid Build Coastguard Worker "b", 671*333d2b36SAndroid Build Coastguard Worker }) 672*333d2b36SAndroid Build Coastguard Worker testSortedKeysHelper(t, "ints", map[int]interface{}{ 673*333d2b36SAndroid Build Coastguard Worker 10: nil, 674*333d2b36SAndroid Build Coastguard Worker 5: nil, 675*333d2b36SAndroid Build Coastguard Worker }, []int{ 676*333d2b36SAndroid Build Coastguard Worker 5, 677*333d2b36SAndroid Build Coastguard Worker 10, 678*333d2b36SAndroid Build Coastguard Worker }) 679*333d2b36SAndroid Build Coastguard Worker 680*333d2b36SAndroid Build Coastguard Worker testSortedKeysHelper(t, "nil", map[string]string(nil), nil) 681*333d2b36SAndroid Build Coastguard Worker testSortedKeysHelper(t, "empty", map[string]string{}, nil) 682*333d2b36SAndroid Build Coastguard Worker} 683*333d2b36SAndroid Build Coastguard Worker 684*333d2b36SAndroid Build Coastguard Workerfunc TestSortedStringValues(t *testing.T) { 685*333d2b36SAndroid Build Coastguard Worker testCases := []struct { 686*333d2b36SAndroid Build Coastguard Worker name string 687*333d2b36SAndroid Build Coastguard Worker in interface{} 688*333d2b36SAndroid Build Coastguard Worker expected []string 689*333d2b36SAndroid Build Coastguard Worker }{ 690*333d2b36SAndroid Build Coastguard Worker { 691*333d2b36SAndroid Build Coastguard Worker name: "nil", 692*333d2b36SAndroid Build Coastguard Worker in: map[string]string(nil), 693*333d2b36SAndroid Build Coastguard Worker expected: nil, 694*333d2b36SAndroid Build Coastguard Worker }, 695*333d2b36SAndroid Build Coastguard Worker { 696*333d2b36SAndroid Build Coastguard Worker name: "empty", 697*333d2b36SAndroid Build Coastguard Worker in: map[string]string{}, 698*333d2b36SAndroid Build Coastguard Worker expected: nil, 699*333d2b36SAndroid Build Coastguard Worker }, 700*333d2b36SAndroid Build Coastguard Worker { 701*333d2b36SAndroid Build Coastguard Worker name: "simple", 702*333d2b36SAndroid Build Coastguard Worker in: map[string]string{"foo": "a", "bar": "b"}, 703*333d2b36SAndroid Build Coastguard Worker expected: []string{"a", "b"}, 704*333d2b36SAndroid Build Coastguard Worker }, 705*333d2b36SAndroid Build Coastguard Worker { 706*333d2b36SAndroid Build Coastguard Worker name: "duplicates", 707*333d2b36SAndroid Build Coastguard Worker in: map[string]string{"foo": "a", "bar": "b", "baz": "b"}, 708*333d2b36SAndroid Build Coastguard Worker expected: []string{"a", "b", "b"}, 709*333d2b36SAndroid Build Coastguard Worker }, 710*333d2b36SAndroid Build Coastguard Worker } 711*333d2b36SAndroid Build Coastguard Worker 712*333d2b36SAndroid Build Coastguard Worker for _, tt := range testCases { 713*333d2b36SAndroid Build Coastguard Worker t.Run(tt.name, func(t *testing.T) { 714*333d2b36SAndroid Build Coastguard Worker got := SortedStringValues(tt.in) 715*333d2b36SAndroid Build Coastguard Worker if g, w := got, tt.expected; !reflect.DeepEqual(g, w) { 716*333d2b36SAndroid Build Coastguard Worker t.Errorf("wanted %q, got %q", w, g) 717*333d2b36SAndroid Build Coastguard Worker } 718*333d2b36SAndroid Build Coastguard Worker }) 719*333d2b36SAndroid Build Coastguard Worker } 720*333d2b36SAndroid Build Coastguard Worker} 721*333d2b36SAndroid Build Coastguard Worker 722*333d2b36SAndroid Build Coastguard Workerfunc TestSortedUniqueStringValues(t *testing.T) { 723*333d2b36SAndroid Build Coastguard Worker testCases := []struct { 724*333d2b36SAndroid Build Coastguard Worker name string 725*333d2b36SAndroid Build Coastguard Worker in interface{} 726*333d2b36SAndroid Build Coastguard Worker expected []string 727*333d2b36SAndroid Build Coastguard Worker }{ 728*333d2b36SAndroid Build Coastguard Worker { 729*333d2b36SAndroid Build Coastguard Worker name: "nil", 730*333d2b36SAndroid Build Coastguard Worker in: map[string]string(nil), 731*333d2b36SAndroid Build Coastguard Worker expected: nil, 732*333d2b36SAndroid Build Coastguard Worker }, 733*333d2b36SAndroid Build Coastguard Worker { 734*333d2b36SAndroid Build Coastguard Worker name: "empty", 735*333d2b36SAndroid Build Coastguard Worker in: map[string]string{}, 736*333d2b36SAndroid Build Coastguard Worker expected: nil, 737*333d2b36SAndroid Build Coastguard Worker }, 738*333d2b36SAndroid Build Coastguard Worker { 739*333d2b36SAndroid Build Coastguard Worker name: "simple", 740*333d2b36SAndroid Build Coastguard Worker in: map[string]string{"foo": "a", "bar": "b"}, 741*333d2b36SAndroid Build Coastguard Worker expected: []string{"a", "b"}, 742*333d2b36SAndroid Build Coastguard Worker }, 743*333d2b36SAndroid Build Coastguard Worker { 744*333d2b36SAndroid Build Coastguard Worker name: "duplicates", 745*333d2b36SAndroid Build Coastguard Worker in: map[string]string{"foo": "a", "bar": "b", "baz": "b"}, 746*333d2b36SAndroid Build Coastguard Worker expected: []string{"a", "b"}, 747*333d2b36SAndroid Build Coastguard Worker }, 748*333d2b36SAndroid Build Coastguard Worker } 749*333d2b36SAndroid Build Coastguard Worker 750*333d2b36SAndroid Build Coastguard Worker for _, tt := range testCases { 751*333d2b36SAndroid Build Coastguard Worker t.Run(tt.name, func(t *testing.T) { 752*333d2b36SAndroid Build Coastguard Worker got := SortedUniqueStringValues(tt.in) 753*333d2b36SAndroid Build Coastguard Worker if g, w := got, tt.expected; !reflect.DeepEqual(g, w) { 754*333d2b36SAndroid Build Coastguard Worker t.Errorf("wanted %q, got %q", w, g) 755*333d2b36SAndroid Build Coastguard Worker } 756*333d2b36SAndroid Build Coastguard Worker }) 757*333d2b36SAndroid Build Coastguard Worker } 758*333d2b36SAndroid Build Coastguard Worker} 759*333d2b36SAndroid Build Coastguard Worker 760*333d2b36SAndroid Build Coastguard Workervar reverseTestCases = []struct { 761*333d2b36SAndroid Build Coastguard Worker name string 762*333d2b36SAndroid Build Coastguard Worker in []string 763*333d2b36SAndroid Build Coastguard Worker expected []string 764*333d2b36SAndroid Build Coastguard Worker}{ 765*333d2b36SAndroid Build Coastguard Worker { 766*333d2b36SAndroid Build Coastguard Worker name: "nil", 767*333d2b36SAndroid Build Coastguard Worker in: nil, 768*333d2b36SAndroid Build Coastguard Worker expected: nil, 769*333d2b36SAndroid Build Coastguard Worker }, 770*333d2b36SAndroid Build Coastguard Worker { 771*333d2b36SAndroid Build Coastguard Worker name: "empty", 772*333d2b36SAndroid Build Coastguard Worker in: []string{}, 773*333d2b36SAndroid Build Coastguard Worker expected: []string{}, 774*333d2b36SAndroid Build Coastguard Worker }, 775*333d2b36SAndroid Build Coastguard Worker { 776*333d2b36SAndroid Build Coastguard Worker name: "one", 777*333d2b36SAndroid Build Coastguard Worker in: []string{"one"}, 778*333d2b36SAndroid Build Coastguard Worker expected: []string{"one"}, 779*333d2b36SAndroid Build Coastguard Worker }, 780*333d2b36SAndroid Build Coastguard Worker { 781*333d2b36SAndroid Build Coastguard Worker name: "even", 782*333d2b36SAndroid Build Coastguard Worker in: []string{"one", "two"}, 783*333d2b36SAndroid Build Coastguard Worker expected: []string{"two", "one"}, 784*333d2b36SAndroid Build Coastguard Worker }, 785*333d2b36SAndroid Build Coastguard Worker { 786*333d2b36SAndroid Build Coastguard Worker name: "odd", 787*333d2b36SAndroid Build Coastguard Worker in: []string{"one", "two", "three"}, 788*333d2b36SAndroid Build Coastguard Worker expected: []string{"three", "two", "one"}, 789*333d2b36SAndroid Build Coastguard Worker }, 790*333d2b36SAndroid Build Coastguard Worker} 791*333d2b36SAndroid Build Coastguard Worker 792*333d2b36SAndroid Build Coastguard Workerfunc TestReverseSliceInPlace(t *testing.T) { 793*333d2b36SAndroid Build Coastguard Worker for _, testCase := range reverseTestCases { 794*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 795*333d2b36SAndroid Build Coastguard Worker slice := CopyOf(testCase.in) 796*333d2b36SAndroid Build Coastguard Worker slice2 := slice 797*333d2b36SAndroid Build Coastguard Worker ReverseSliceInPlace(slice) 798*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(slice, testCase.expected) { 799*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected %#v, got %#v", testCase.expected, slice) 800*333d2b36SAndroid Build Coastguard Worker } 801*333d2b36SAndroid Build Coastguard Worker if unsafe.SliceData(slice) != unsafe.SliceData(slice2) { 802*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected slices to share backing array") 803*333d2b36SAndroid Build Coastguard Worker } 804*333d2b36SAndroid Build Coastguard Worker }) 805*333d2b36SAndroid Build Coastguard Worker } 806*333d2b36SAndroid Build Coastguard Worker} 807*333d2b36SAndroid Build Coastguard Worker 808*333d2b36SAndroid Build Coastguard Workerfunc TestReverseSlice(t *testing.T) { 809*333d2b36SAndroid Build Coastguard Worker for _, testCase := range reverseTestCases { 810*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 811*333d2b36SAndroid Build Coastguard Worker slice := ReverseSlice(testCase.in) 812*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(slice, testCase.expected) { 813*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected %#v, got %#v", testCase.expected, slice) 814*333d2b36SAndroid Build Coastguard Worker } 815*333d2b36SAndroid Build Coastguard Worker if cap(slice) > 0 && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) { 816*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected slices to have different backing arrays") 817*333d2b36SAndroid Build Coastguard Worker } 818*333d2b36SAndroid Build Coastguard Worker }) 819*333d2b36SAndroid Build Coastguard Worker } 820*333d2b36SAndroid Build Coastguard Worker} 821*333d2b36SAndroid Build Coastguard Worker 822*333d2b36SAndroid Build Coastguard Workervar hasIntersectionTestCases = []struct { 823*333d2b36SAndroid Build Coastguard Worker name string 824*333d2b36SAndroid Build Coastguard Worker l1 []string 825*333d2b36SAndroid Build Coastguard Worker l2 []string 826*333d2b36SAndroid Build Coastguard Worker expected bool 827*333d2b36SAndroid Build Coastguard Worker}{ 828*333d2b36SAndroid Build Coastguard Worker { 829*333d2b36SAndroid Build Coastguard Worker name: "empty", 830*333d2b36SAndroid Build Coastguard Worker l1: []string{"a", "b", "c"}, 831*333d2b36SAndroid Build Coastguard Worker l2: []string{}, 832*333d2b36SAndroid Build Coastguard Worker expected: false, 833*333d2b36SAndroid Build Coastguard Worker }, 834*333d2b36SAndroid Build Coastguard Worker { 835*333d2b36SAndroid Build Coastguard Worker name: "both empty", 836*333d2b36SAndroid Build Coastguard Worker l1: []string{}, 837*333d2b36SAndroid Build Coastguard Worker l2: []string{}, 838*333d2b36SAndroid Build Coastguard Worker expected: false, 839*333d2b36SAndroid Build Coastguard Worker }, 840*333d2b36SAndroid Build Coastguard Worker { 841*333d2b36SAndroid Build Coastguard Worker name: "identical", 842*333d2b36SAndroid Build Coastguard Worker l1: []string{"a", "b", "c"}, 843*333d2b36SAndroid Build Coastguard Worker l2: []string{"a", "b", "c"}, 844*333d2b36SAndroid Build Coastguard Worker expected: true, 845*333d2b36SAndroid Build Coastguard Worker }, 846*333d2b36SAndroid Build Coastguard Worker { 847*333d2b36SAndroid Build Coastguard Worker name: "duplicates", 848*333d2b36SAndroid Build Coastguard Worker l1: []string{"a", "a", "a"}, 849*333d2b36SAndroid Build Coastguard Worker l2: []string{"a", "b", "c"}, 850*333d2b36SAndroid Build Coastguard Worker expected: true, 851*333d2b36SAndroid Build Coastguard Worker }, 852*333d2b36SAndroid Build Coastguard Worker { 853*333d2b36SAndroid Build Coastguard Worker name: "duplicates with no intersection", 854*333d2b36SAndroid Build Coastguard Worker l1: []string{"d", "d", "d", "d"}, 855*333d2b36SAndroid Build Coastguard Worker l2: []string{"a", "b", "c"}, 856*333d2b36SAndroid Build Coastguard Worker expected: false, 857*333d2b36SAndroid Build Coastguard Worker }, 858*333d2b36SAndroid Build Coastguard Worker} 859*333d2b36SAndroid Build Coastguard Worker 860*333d2b36SAndroid Build Coastguard Workerfunc TestHasIntersection(t *testing.T) { 861*333d2b36SAndroid Build Coastguard Worker for _, testCase := range hasIntersectionTestCases { 862*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 863*333d2b36SAndroid Build Coastguard Worker hasIntersection := HasIntersection(testCase.l1, testCase.l2) 864*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(hasIntersection, testCase.expected) { 865*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected %#v, got %#v", testCase.expected, hasIntersection) 866*333d2b36SAndroid Build Coastguard Worker } 867*333d2b36SAndroid Build Coastguard Worker }) 868*333d2b36SAndroid Build Coastguard Worker } 869*333d2b36SAndroid Build Coastguard Worker} 870*333d2b36SAndroid Build Coastguard Worker 871*333d2b36SAndroid Build Coastguard Workervar prettyConcatTestCases = []struct { 872*333d2b36SAndroid Build Coastguard Worker name string 873*333d2b36SAndroid Build Coastguard Worker list []string 874*333d2b36SAndroid Build Coastguard Worker quote bool 875*333d2b36SAndroid Build Coastguard Worker lastSeparator string 876*333d2b36SAndroid Build Coastguard Worker expected string 877*333d2b36SAndroid Build Coastguard Worker}{ 878*333d2b36SAndroid Build Coastguard Worker { 879*333d2b36SAndroid Build Coastguard Worker name: "empty", 880*333d2b36SAndroid Build Coastguard Worker list: []string{}, 881*333d2b36SAndroid Build Coastguard Worker quote: false, 882*333d2b36SAndroid Build Coastguard Worker lastSeparator: "and", 883*333d2b36SAndroid Build Coastguard Worker expected: ``, 884*333d2b36SAndroid Build Coastguard Worker }, 885*333d2b36SAndroid Build Coastguard Worker { 886*333d2b36SAndroid Build Coastguard Worker name: "single", 887*333d2b36SAndroid Build Coastguard Worker list: []string{"a"}, 888*333d2b36SAndroid Build Coastguard Worker quote: true, 889*333d2b36SAndroid Build Coastguard Worker lastSeparator: "and", 890*333d2b36SAndroid Build Coastguard Worker expected: `"a"`, 891*333d2b36SAndroid Build Coastguard Worker }, 892*333d2b36SAndroid Build Coastguard Worker { 893*333d2b36SAndroid Build Coastguard Worker name: "with separator", 894*333d2b36SAndroid Build Coastguard Worker list: []string{"a", "b", "c"}, 895*333d2b36SAndroid Build Coastguard Worker quote: true, 896*333d2b36SAndroid Build Coastguard Worker lastSeparator: "or", 897*333d2b36SAndroid Build Coastguard Worker expected: `"a", "b", or "c"`, 898*333d2b36SAndroid Build Coastguard Worker }, 899*333d2b36SAndroid Build Coastguard Worker { 900*333d2b36SAndroid Build Coastguard Worker name: "without separator", 901*333d2b36SAndroid Build Coastguard Worker list: []string{"a", "b", "c"}, 902*333d2b36SAndroid Build Coastguard Worker quote: false, 903*333d2b36SAndroid Build Coastguard Worker lastSeparator: "", 904*333d2b36SAndroid Build Coastguard Worker expected: `a, b, c`, 905*333d2b36SAndroid Build Coastguard Worker }, 906*333d2b36SAndroid Build Coastguard Worker} 907*333d2b36SAndroid Build Coastguard Worker 908*333d2b36SAndroid Build Coastguard Workerfunc TestPrettyConcat(t *testing.T) { 909*333d2b36SAndroid Build Coastguard Worker for _, testCase := range prettyConcatTestCases { 910*333d2b36SAndroid Build Coastguard Worker t.Run(testCase.name, func(t *testing.T) { 911*333d2b36SAndroid Build Coastguard Worker concatString := PrettyConcat(testCase.list, testCase.quote, testCase.lastSeparator) 912*333d2b36SAndroid Build Coastguard Worker if !reflect.DeepEqual(concatString, testCase.expected) { 913*333d2b36SAndroid Build Coastguard Worker t.Errorf("expected %#v, got %#v", testCase.expected, concatString) 914*333d2b36SAndroid Build Coastguard Worker } 915*333d2b36SAndroid Build Coastguard Worker }) 916*333d2b36SAndroid Build Coastguard Worker } 917*333d2b36SAndroid Build Coastguard Worker} 918