blob: fa76d3800f960312e6d83ed8eb2b2e5370edab09 [file] [log] [blame]
// Copyright 2026 The Go 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 natural_test
import (
"fmt"
"slices"
"testing"
"golang.org/x/pkgsite/internal/natural"
)
var tests = []struct {
a, b string
want int
}{
{"", "", 0},
{"a", "", 1},
{"abc", "abc", 0},
{"ab", "abc", -1},
{"x", "ab", 1},
{"x", "a", 1},
{"b", "x", -1},
{"x0", "x#1", -1},
{"a", "aa", -1},
{"a", "a1", -1},
{"ab", "a1", 1},
{"a", "0", 1},
{"A", "0", 1},
{"file1.txt", "file2.txt", -1},
{"file10.txt", "file2.txt", 1},
{"file1000.txt", "file2.txt", 1},
{"file0001.txt", "file2.txt", -1},
{"file00a.txt", "file000a.txt", -1},
{"a10", "a010", -1},
{"1e6", "10e5", -1},
{"0xAB", "0xB", -1},
{"-5", "-10", -1},
{"a1b2", "a01b3", -1},
{"file_1.txt", "file_10.txt", -1},
{"file1.txt", "file1.txt", 0},
{"fileA.txt", "fileB.txt", -1},
{"file1A.txt", "file1B.txt", -1},
{"Uint8x16", "Uint32x8", -1},
{"Uint32x16", "Uint32x8", 1},
{"Uint10000000000000000000000", "Uint20000000000000000000000", -1},
{"Uint10000000000000000000000abc", "Uint10000000000000000000000abc", 0},
{"a1a1a1a1a1a1a1a1a1a1a1", "a1a1a1a1a1a1a1a1a1a1a1", 0},
{"a1a1a1a1a1a1a1a1a1a1a10", "a1a1a1a1a1a1a1a1a1a1a1", 1},
}
func TestCompare(t *testing.T) {
for _, tt := range tests {
if got := natural.Compare(tt.a, tt.b); got != tt.want {
t.Errorf("Compare(%q, %q) = %d; want %d", tt.a, tt.b, got, tt.want)
}
if got := natural.Compare(tt.b, tt.a); got != -tt.want {
t.Errorf("Compare(%q, %q) = %d; want %d", tt.b, tt.a, got, -tt.want)
}
}
}
func TestSliceSort(t *testing.T) {
types := []string{"Uint32x16", "Uint16x32", "Uint8x64", "Uint64x8"}
want := []string{"Uint8x64", "Uint16x32", "Uint32x16", "Uint64x8"}
slices.SortFunc(types, natural.Compare)
if !slices.Equal(types, want) {
t.Errorf("types = %v; want %v", types, want)
}
}
func BenchmarkCompare(b *testing.B) {
var tests = []struct {
a, b string
}{
0: {"Uint8x16", "Uint32x8"},
1: {"Uint32x16", "Uint32x8"},
2: {"func(Uint64x4) AsUint32x8() Uint32x8", "func(Uint64x4) AsUint32x8() Uint32x8"},
3: {"func(Uint64x4) AsUint32x8() Uint32x8", "func(Uint64x4) AsUint8x32() Uint8x32"},
4: {"Uint10000000000000000000000", "Uint20000000000000000000000"},
5: {"a1a1a1a1a1a1a1a1a1a1a1", "a1a1a1a1a1a1a1a1a1a1a1"},
6: {"a1a1a1a1a1a1a1a1a1a1a10", "a1a1a1a1a1a1a1a1a1a1a1"},
}
for i, test := range tests {
b.Run(fmt.Sprintf("%d", i), func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
natural.Compare(test.a, test.b)
}
})
}
}
func FuzzTransitivity(f *testing.F) {
f.Add("", "", "")
f.Fuzz(func(t *testing.T, a string, b string, c string) {
ab := natural.Compare(a, b)
bc := natural.Compare(b, c)
ca := natural.Compare(c, a)
// when the total is 3 or -3, it means that there is a cycle in comparison.
if tot := ab + bc + ca; tot == 3 || tot == -3 {
t.Errorf("Compare(%q, %q) = %d", a, b, ab)
t.Errorf("Compare(%q, %q) = %d", b, c, bc)
t.Errorf("Compare(%q, %q) = %d", c, a, ca)
}
})
}