-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunicode_test.go
More file actions
189 lines (172 loc) · 4.51 KB
/
unicode_test.go
File metadata and controls
189 lines (172 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package xterm
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestUnicodeServiceWcwidth(t *testing.T) {
t.Parallel()
type TestCase struct {
Name string
Input rune
Expected int
}
tests := []TestCase{
// Control characters: width 0
{"NUL", 0x00, 0},
{"BEL", 0x07, 0},
{"BS", 0x08, 0},
{"TAB", 0x09, 0},
{"LF", 0x0A, 0},
{"ESC", 0x1B, 0},
{"DEL", 0x7F, 0},
{"C1 control", 0x80, 0},
{"C1 end", 0x9F, 0},
// ASCII printable: width 1
{"space", ' ', 1},
{"A", 'A', 1},
{"z", 'z', 1},
{"tilde", '~', 1},
// Latin extended: width 1
{"a-umlaut", '\u00e4', 1},
{"n-tilde", '\u00f1', 1},
// CJK wide characters: width 2
{"CJK ideograph", '\u4e00', 2},
{"CJK ideograph 2", '\u9fff', 2},
{"Hangul syllable", '\uac00', 2},
{"Hangul syllable end", '\ud7a3', 2},
{"Fullwidth A", '\uff21', 2},
{"Fullwidth excl", '\uff01', 2},
{"CJK compat", '\uf900', 2},
// Korean Jamo: width 2
{"Jamo start", '\u1100', 2},
{"Jamo end", '\u115f', 2},
// Combining marks: width 0
{"combining acute", '\u0301', 0},
{"combining tilde", '\u0303', 0},
{"combining diaeresis", '\u0308', 0},
{"Thai combining", '\u0e34', 0},
{"variation selector", '\ufe0f', 0},
{"zero-width space", '\u200b', 0},
{"ZWNJ", '\u200c', 0},
{"ZWJ", '\u200d', 0},
// Special cases
{"left angle bracket", '\u2329', 2},
{"right angle bracket", '\u232a', 2},
{"0x303f exception", '\u303f', 1},
// Supplementary planes
{"CJK ext B", 0x20000, 2},
{"CJK ext B end", 0x2fffd, 2},
{"SMP char", 0x10000, 1},
{"high combining", 0x1D167, 0},
}
u := NewUnicodeService()
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
type Expectation struct {
Width int
}
got := Expectation{Width: u.Wcwidth(tc.Input)}
expected := Expectation{Width: tc.Expected}
if diff := cmp.Diff(expected, got); diff != "" {
t.Errorf("(-want +got):\n%s", diff)
}
})
}
}
func TestUnicodeServiceGetStringCellWidth(t *testing.T) {
t.Parallel()
type TestCase struct {
Name string
Input string
Expected int
}
tests := []TestCase{
{"empty string", "", 0},
{"ASCII", "hello", 5},
{"CJK", "你好", 4}, //nolint:gosmopolitan
{"mixed ASCII and CJK", "hi你好", 6}, //nolint:gosmopolitan
{"combining marks", "e\u0301", 1}, // é as e + combining acute
{"fullwidth", "\uff21\uff22", 4},
{"control chars ignored", "\x00\x01\x02", 0},
{"tab and newline", "\t\n", 0},
{"emoji supplementary", "\U0001F600", 1}, // basic emoji (not in wide table for v6)
{"CJK ext B string", "\U00020000", 2},
}
u := NewUnicodeService()
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
type Expectation struct {
Width int
}
got := Expectation{Width: u.GetStringCellWidth(tc.Input)}
expected := Expectation{Width: tc.Expected}
if diff := cmp.Diff(expected, got); diff != "" {
t.Errorf("(-want +got):\n%s", diff)
}
})
}
}
func TestUnicodeServiceWcwidthBMPBoundaries(t *testing.T) {
t.Parallel()
// Verify boundary conditions of the BMP table
type TestCase struct {
Name string
Input rune
Expected int
}
tests := []TestCase{
{"just below BMP", 0xFFFF, 1},
{"at BMP boundary", 0x10000, 1},
{"last wide CJK compat", 0xFAFF, 2},
{"first after CJK compat", 0xFB00, 1},
{"fullwidth end", 0xFF60, 2},
{"halfwidth start", 0xFF61, 1},
}
u := NewUnicodeService()
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
type Expectation struct {
Width int
}
got := Expectation{Width: u.Wcwidth(tc.Input)}
expected := Expectation{Width: tc.Expected}
if diff := cmp.Diff(expected, got); diff != "" {
t.Errorf("(-want +got):\n%s", diff)
}
})
}
}
func TestUnicodeServiceHighCombining(t *testing.T) {
t.Parallel()
type TestCase struct {
Name string
Input rune
Expected int
}
tests := []TestCase{
{"musical combining", 0x1D167, 0},
{"musical combining end", 0x1D169, 0},
{"variation selector supplement start", 0xE0100, 0},
{"variation selector supplement end", 0xE01EF, 0},
{"tag space", 0xE0020, 0},
{"language tag", 0xE0001, 0},
{"outside high combining", 0x1D166, 1},
}
u := NewUnicodeService()
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
type Expectation struct {
Width int
}
got := Expectation{Width: u.Wcwidth(tc.Input)}
expected := Expectation{Width: tc.Expected}
if diff := cmp.Diff(expected, got); diff != "" {
t.Errorf("(-want +got):\n%s", diff)
}
})
}
}