mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-26 11:35:35 +00:00
9784cae23b
This makes it easy to compact slices that contain duplicate elements by sorting and then uniqing. This is an alternative to constructing an intermediate map and then extracting elements from it. It also provides more control over equality than using a map key does. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
89 lines
1.9 KiB
Go
89 lines
1.9 KiB
Go
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package uniq_test
|
|
|
|
import (
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"tailscale.com/util/uniq"
|
|
)
|
|
|
|
func TestModifySlice(t *testing.T) {
|
|
tests := []struct {
|
|
in []int
|
|
want []int
|
|
}{
|
|
{in: []int{0, 1, 2}, want: []int{0, 1, 2}},
|
|
{in: []int{0, 1, 2, 2}, want: []int{0, 1, 2}},
|
|
{in: []int{0, 0, 1, 2}, want: []int{0, 1, 2}},
|
|
{in: []int{0, 1, 0, 2}, want: []int{0, 1, 0, 2}},
|
|
{in: []int{0}, want: []int{0}},
|
|
{in: []int{0, 0}, want: []int{0}},
|
|
{in: []int{}, want: []int{}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
in := make([]int, len(test.in))
|
|
copy(in, test.in)
|
|
uniq.ModifySlice(&test.in, func(i, j int) bool { return test.in[i] == test.in[j] })
|
|
if !reflect.DeepEqual(test.in, test.want) {
|
|
t.Errorf("uniq.Slice(%v) = %v, want %v", in, test.in, test.want)
|
|
}
|
|
start := len(test.in)
|
|
test.in = test.in[:cap(test.in)]
|
|
for i := start; i < len(in); i++ {
|
|
if test.in[i] != 0 {
|
|
t.Errorf("uniq.Slice(%v): non-0 in tail of %v at index %v", in, test.in, i)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark(b *testing.B) {
|
|
benches := []struct {
|
|
name string
|
|
reset func(s []byte)
|
|
}{
|
|
{name: "AllDups",
|
|
reset: func(s []byte) {
|
|
for i := range s {
|
|
s[i] = '*'
|
|
}
|
|
},
|
|
},
|
|
{name: "NoDups",
|
|
reset: func(s []byte) {
|
|
for i := range s {
|
|
s[i] = byte(i)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, bb := range benches {
|
|
b.Run(bb.name, func(b *testing.B) {
|
|
for size := 1; size <= 4096; size *= 16 {
|
|
b.Run(strconv.Itoa(size), func(b *testing.B) {
|
|
benchmark(b, 64, bb.reset)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func benchmark(b *testing.B, size int64, reset func(s []byte)) {
|
|
b.ReportAllocs()
|
|
b.SetBytes(size)
|
|
s := make([]byte, size)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
s = s[:size]
|
|
reset(s)
|
|
uniq.ModifySlice(&s, func(i, j int) bool { return s[i] == s[j] })
|
|
}
|
|
}
|