xref: /aosp_15_r20/build/soong/android/util_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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