mirror of
https://github.com/tailscale/tailscale.git
synced 2026-06-11 21:02:39 +08:00
Some checks failed
checklocks / checklocks (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
Dockerfile build / deploy (push) Has been cancelled
CI / gomod-cache (push) Has been cancelled
CI / fuzz (push) Has been cancelled
CI / race-root-integration (1/4) (push) Has been cancelled
CI / race-root-integration (2/4) (push) Has been cancelled
CI / race-root-integration (3/4) (push) Has been cancelled
CI / race-root-integration (4/4) (push) Has been cancelled
CI / test (-race, amd64, 1/3) (push) Has been cancelled
CI / test (-race, amd64, 2/3) (push) Has been cancelled
CI / test (-race, amd64, 3/3) (push) Has been cancelled
CI / test (386) (push) Has been cancelled
CI / test (amd64) (push) Has been cancelled
CI / Windows (${{ matrix.name || matrix.shard}}) (win-bench, benchmarks) (push) Has been cancelled
CI / Windows (${{ matrix.name || matrix.shard}}) (win-shard-1-2, 1/2) (push) Has been cancelled
CI / Windows (${{ matrix.name || matrix.shard}}) (win-shard-2-2, 2/2) (push) Has been cancelled
CI / Windows (${{ matrix.name || matrix.shard}}) (win-tool-go, ./tool/go) (push) Has been cancelled
CI / privileged (push) Has been cancelled
CI / vm (push) Has been cancelled
CI / cross (386, linux) (push) Has been cancelled
CI / cross (amd64, darwin) (push) Has been cancelled
CI / cross (amd64, freebsd) (push) Has been cancelled
CI / cross (amd64, openbsd) (push) Has been cancelled
CI / cross (amd64, windows) (push) Has been cancelled
CI / cross (arm, 5, linux) (push) Has been cancelled
CI / cross (arm, 7, linux) (push) Has been cancelled
CI / cross (arm64, darwin) (push) Has been cancelled
CI / cross (arm64, linux) (push) Has been cancelled
CI / cross (arm64, windows) (push) Has been cancelled
CI / cross (loong64, linux) (push) Has been cancelled
CI / ios (push) Has been cancelled
CI / crossmin (amd64, illumos) (push) Has been cancelled
CI / crossmin (amd64, plan9) (push) Has been cancelled
CI / crossmin (amd64, solaris) (push) Has been cancelled
CI / crossmin (ppc64, aix) (push) Has been cancelled
CI / android (push) Has been cancelled
CI / wasm (push) Has been cancelled
CI / tailscale_go (push) Has been cancelled
CI / depaware (push) Has been cancelled
CI / go_generate (push) Has been cancelled
CI / go_mod_tidy (push) Has been cancelled
CI / licenses (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--with-tags-all=darwin, arm64, darwin, macOS) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--with-tags-all=linux, amd64, linux, Linux) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--with-tags-all=windows, amd64, windows, Windows) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--without-tags-any=windows,darwin,linux --shard=1/4, amd64, linux, Portable (1/4)) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--without-tags-any=windows,darwin,linux --shard=2/4, amd64, linux, Portable (2/4)) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--without-tags-any=windows,darwin,linux --shard=3/4, amd64, linux, Portable (3/4)) (push) Has been cancelled
CI / staticcheck (${{ matrix.name }}) (--without-tags-any=windows,darwin,linux --shard=4/4, amd64, linux, Portable (4/4)) (push) Has been cancelled
CI / notify_slack (push) Has been cancelled
CI / merge_blocker (push) Has been cancelled
CI / check_mergeability_strict (push) Has been cancelled
CI / check_mergeability (push) Has been cancelled
181 lines
4.4 KiB
Go
181 lines
4.4 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package set
|
|
|
|
import (
|
|
"maps"
|
|
"math"
|
|
"slices"
|
|
"testing"
|
|
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
func TestIntSet(t *testing.T) {
|
|
t.Run("Int64", func(t *testing.T) {
|
|
ss := make(Set[int64])
|
|
var si IntSet[int64]
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, -5)
|
|
deleteInt(t, ss, &si, 2)
|
|
deleteInt(t, ss, &si, 75)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, 2)
|
|
addInt(t, ss, &si, 75)
|
|
addInt(t, ss, &si, 75)
|
|
addInt(t, ss, &si, -3)
|
|
addInt(t, ss, &si, -3)
|
|
addInt(t, ss, &si, -3)
|
|
addInt(t, ss, &si, math.MinInt64)
|
|
addInt(t, ss, &si, 8)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, 77)
|
|
addInt(t, ss, &si, 76)
|
|
addInt(t, ss, &si, 76)
|
|
addInt(t, ss, &si, 76)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, -5)
|
|
addInt(t, ss, &si, 7)
|
|
addInt(t, ss, &si, -83)
|
|
addInt(t, ss, &si, math.MaxInt64)
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, -5)
|
|
deleteInt(t, ss, &si, 2)
|
|
deleteInt(t, ss, &si, 75)
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, math.MinInt64)
|
|
deleteInt(t, ss, &si, math.MaxInt64)
|
|
intValues(t, ss, si)
|
|
if !si.Equal(IntsOf(ss.Slice()...)) {
|
|
t.Errorf("{%v}.Equal({%v}) = false, want true", si, ss)
|
|
}
|
|
})
|
|
|
|
t.Run("Uint64", func(t *testing.T) {
|
|
ss := make(Set[uint64])
|
|
var si IntSet[uint64]
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, 5)
|
|
deleteInt(t, ss, &si, 2)
|
|
deleteInt(t, ss, &si, 75)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, 2)
|
|
addInt(t, ss, &si, 75)
|
|
addInt(t, ss, &si, 75)
|
|
addInt(t, ss, &si, 3)
|
|
addInt(t, ss, &si, 3)
|
|
addInt(t, ss, &si, 8)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, 77)
|
|
addInt(t, ss, &si, 76)
|
|
addInt(t, ss, &si, 76)
|
|
addInt(t, ss, &si, 76)
|
|
intValues(t, ss, si)
|
|
addInt(t, ss, &si, 5)
|
|
addInt(t, ss, &si, 7)
|
|
addInt(t, ss, &si, 83)
|
|
addInt(t, ss, &si, math.MaxInt64)
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, 5)
|
|
deleteInt(t, ss, &si, 2)
|
|
deleteInt(t, ss, &si, 75)
|
|
intValues(t, ss, si)
|
|
deleteInt(t, ss, &si, math.MaxInt64)
|
|
intValues(t, ss, si)
|
|
if !si.Equal(IntsOf(ss.Slice()...)) {
|
|
t.Errorf("{%v}.Equal({%v}) = false, want true", si, ss)
|
|
}
|
|
})
|
|
}
|
|
|
|
func intValues[T constraints.Integer](t testing.TB, ss Set[T], si IntSet[T]) {
|
|
got := slices.Collect(maps.Keys(ss))
|
|
slices.Sort(got)
|
|
want := slices.Collect(si.Values())
|
|
slices.Sort(want)
|
|
if !slices.Equal(got, want) {
|
|
t.Fatalf("Values mismatch:\n\tgot %v\n\twant %v", got, want)
|
|
}
|
|
if got, want := si.Len(), ss.Len(); got != want {
|
|
t.Fatalf("Len() = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func addInt[T constraints.Integer](t testing.TB, ss Set[T], si *IntSet[T], v T) {
|
|
t.Helper()
|
|
if got, want := si.Contains(v), ss.Contains(v); got != want {
|
|
t.Fatalf("Contains(%v) = %v, want %v", v, got, want)
|
|
}
|
|
ss.Add(v)
|
|
si.Add(v)
|
|
if !si.Contains(v) {
|
|
t.Fatalf("Contains(%v) = false, want true", v)
|
|
}
|
|
if got, want := si.Len(), ss.Len(); got != want {
|
|
t.Fatalf("Len() = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func deleteInt[T constraints.Integer](t testing.TB, ss Set[T], si *IntSet[T], v T) {
|
|
t.Helper()
|
|
if got, want := si.Contains(v), ss.Contains(v); got != want {
|
|
t.Fatalf("Contains(%v) = %v, want %v", v, got, want)
|
|
}
|
|
ss.Delete(v)
|
|
si.Delete(v)
|
|
if si.Contains(v) {
|
|
t.Fatalf("Contains(%v) = true, want false", v)
|
|
}
|
|
if got, want := si.Len(), ss.Len(); got != want {
|
|
t.Fatalf("Len() = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestZigZag(t *testing.T) {
|
|
t.Run("Int64", func(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
decoded int64
|
|
encoded uint64
|
|
}{
|
|
{math.MinInt64, math.MaxUint64},
|
|
{-2, 3},
|
|
{-1, 1},
|
|
{0, 0},
|
|
{1, 2},
|
|
{2, 4},
|
|
{math.MaxInt64, math.MaxUint64 - 1},
|
|
} {
|
|
encoded := encodeZigZag(tt.decoded)
|
|
if encoded != tt.encoded {
|
|
t.Errorf("encodeZigZag(%v) = %v, want %v", tt.decoded, encoded, tt.encoded)
|
|
}
|
|
decoded := decodeZigZag[int64](tt.encoded)
|
|
if decoded != tt.decoded {
|
|
t.Errorf("decodeZigZag(%v) = %v, want %v", tt.encoded, decoded, tt.decoded)
|
|
}
|
|
}
|
|
})
|
|
t.Run("Uint64", func(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
decoded uint64
|
|
encoded uint64
|
|
}{
|
|
{0, 0},
|
|
{1, 1},
|
|
{2, 2},
|
|
{math.MaxInt64, math.MaxInt64},
|
|
{math.MaxUint64, math.MaxUint64},
|
|
} {
|
|
encoded := encodeZigZag(tt.decoded)
|
|
if encoded != tt.encoded {
|
|
t.Errorf("encodeZigZag(%v) = %v, want %v", tt.decoded, encoded, tt.encoded)
|
|
}
|
|
decoded := decodeZigZag[uint64](tt.encoded)
|
|
if decoded != tt.decoded {
|
|
t.Errorf("decodeZigZag(%v) = %v, want %v", tt.encoded, decoded, tt.decoded)
|
|
}
|
|
}
|
|
})
|
|
}
|