返回 DeepSeek-Reasonix
natsort_test.go
根目录 / internal / fileref / natsort_test.go
1 package fileref
2
3 import "testing"
4
5 func TestNaturalLess(t *testing.T) {
6 tests := []struct {
7 a, b string
8 want bool
9 }{
10 // Basic numeric comparison
11 {"file2", "file10", true},
12 {"file10", "file2", false},
13 {"2", "10", true},
14 {"10", "2", false},
15 {"a2b", "a10b", true},
16 {"a10b", "a2b", false},
17
18 // Chinese filenames (#6042)
19 {"第1章.md", "第10章.md", true},
20 {"第10章.md", "第1章.md", false},
21 {"第1卷.md", "第2卷.md", true},
22 {"第2卷.md", "第10卷.md", true},
23 {"第19卷.md", "第20卷.md", true},
24
25 // Equal strings
26 {"abc", "abc", false},
27 {"file1", "file1", false},
28
29 // Case insensitive
30 {"ABC", "abc", false},
31 {"File1", "file2", true},
32 {"FILE10", "file2", false},
33
34 // Leading zeros
35 {"file01", "file1", false}, // "01"(2) vs "1"(1): same number, shorter string first → "file1" < "file01"
36 {"file1", "file01", true},
37 {"file01", "file001", true}, // both 1, length 2 vs 3 → "file01" < "file001"
38
39 // Mixed digit/non-digit: digits first
40 {"1a", "a1", true},
41
42 // Prefix relationship (shorter first)
43 {"abc", "abcd", true},
44 {"abcd", "abc", false},
45 {"a", "a1", true},
46 {"a1", "a", false},
47
48 // Multi-number segments
49 {"v1.2.3", "v1.10.0", true},
50 {"v1.10.0", "v1.2.3", false},
51 {"a1b2c3", "a1b10c3", true},
52
53 // Edge: empty
54 {"", "a", true},
55 {"a", "", false},
56 {"", "", false},
57
58 // Version-like strings
59 {"v1.9.0", "v1.10.0", true},
60 {"v1.10.0", "v1.9.0", false},
61
62 // Real-world filenames
63 {"report-2.pdf", "report-10.pdf", true},
64 {"img_1.png", "img_10.png", true},
65 {"log.1", "log.10", true},
66 {"test_001.go", "test_002.go", true},
67
68 // Numbers at different positions
69 {"abc10def", "abc2def", false},
70 {"abc2def", "abc10def", true},
71 }
72
73 for _, tt := range tests {
74 got := NaturalLess(tt.a, tt.b)
75 if got != tt.want {
76 t.Errorf("NaturalLess(%q, %q) = %v, want %v", tt.a, tt.b, got, tt.want)
77 }
78 }
79 }
80
81 func TestNaturalLessSort(t *testing.T) {
82 // Verify the ordering is transitive across a full sort.
83 items := []string{
84 "第10卷.md", "第1卷.md", "第2卷.md",
85 "第20卷.md", "第11卷.md", "第19卷.md",
86 }
87 expected := []string{
88 "第1卷.md", "第2卷.md", "第10卷.md",
89 "第11卷.md", "第19卷.md", "第20卷.md",
90 }
91
92 sorted := make([]string, len(items))
93 copy(sorted, items)
94 for i := range sorted {
95 for j := i + 1; j < len(sorted); j++ {
96 if NaturalLess(sorted[j], sorted[i]) {
97 sorted[i], sorted[j] = sorted[j], sorted[i]
98 }
99 }
100 }
101
102 for i := range sorted {
103 if sorted[i] != expected[i] {
104 t.Errorf("sorted[%d] = %q, want %q; full sorted: %v", i, sorted[i], expected[i], sorted)
105 break
106 }
107 }
108 }
109
109 lines GO