1
2
3
4
5 package utf8_test
6
7 import (
8 "bytes"
9 "strings"
10 "testing"
11 "unicode"
12 . "unicode/utf8"
13 )
14
15
16 func init() {
17 if MaxRune != unicode.MaxRune {
18 panic("utf8.MaxRune is wrong")
19 }
20 if RuneError != unicode.ReplacementChar {
21 panic("utf8.RuneError is wrong")
22 }
23 }
24
25
26 func TestConstants(t *testing.T) {
27 if MaxRune != unicode.MaxRune {
28 t.Errorf("utf8.MaxRune is wrong: %x should be %x", MaxRune, unicode.MaxRune)
29 }
30 if RuneError != unicode.ReplacementChar {
31 t.Errorf("utf8.RuneError is wrong: %x should be %x", RuneError, unicode.ReplacementChar)
32 }
33 }
34
35 type Utf8Map struct {
36 r rune
37 str string
38 }
39
40 var utf8map = []Utf8Map{
41 {0x0000, "\x00"},
42 {0x0001, "\x01"},
43 {0x007e, "\x7e"},
44 {0x007f, "\x7f"},
45 {0x0080, "\xc2\x80"},
46 {0x0081, "\xc2\x81"},
47 {0x00bf, "\xc2\xbf"},
48 {0x00c0, "\xc3\x80"},
49 {0x00c1, "\xc3\x81"},
50 {0x00c8, "\xc3\x88"},
51 {0x00d0, "\xc3\x90"},
52 {0x00e0, "\xc3\xa0"},
53 {0x00f0, "\xc3\xb0"},
54 {0x00f8, "\xc3\xb8"},
55 {0x00ff, "\xc3\xbf"},
56 {0x0100, "\xc4\x80"},
57 {0x07ff, "\xdf\xbf"},
58 {0x0400, "\xd0\x80"},
59 {0x0800, "\xe0\xa0\x80"},
60 {0x0801, "\xe0\xa0\x81"},
61 {0x1000, "\xe1\x80\x80"},
62 {0xd000, "\xed\x80\x80"},
63 {0xd7ff, "\xed\x9f\xbf"},
64 {0xe000, "\xee\x80\x80"},
65 {0xfffe, "\xef\xbf\xbe"},
66 {0xffff, "\xef\xbf\xbf"},
67 {0x10000, "\xf0\x90\x80\x80"},
68 {0x10001, "\xf0\x90\x80\x81"},
69 {0x40000, "\xf1\x80\x80\x80"},
70 {0x10fffe, "\xf4\x8f\xbf\xbe"},
71 {0x10ffff, "\xf4\x8f\xbf\xbf"},
72 {0xFFFD, "\xef\xbf\xbd"},
73 }
74
75 var surrogateMap = []Utf8Map{
76 {0xd800, "\xed\xa0\x80"},
77 {0xdfff, "\xed\xbf\xbf"},
78 }
79
80 var testStrings = []string{
81 "",
82 "abcd",
83 "☺☻☹",
84 "日a本b語ç日ð本Ê語þ日¥本¼語i日©",
85 "日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
86 "\x80\x80\x80\x80",
87 }
88
89 func TestFullRune(t *testing.T) {
90 for _, m := range utf8map {
91 b := []byte(m.str)
92 if !FullRune(b) {
93 t.Errorf("FullRune(%q) (%U) = false, want true", b, m.r)
94 }
95 s := m.str
96 if !FullRuneInString(s) {
97 t.Errorf("FullRuneInString(%q) (%U) = false, want true", s, m.r)
98 }
99 b1 := b[0 : len(b)-1]
100 if FullRune(b1) {
101 t.Errorf("FullRune(%q) = true, want false", b1)
102 }
103 s1 := string(b1)
104 if FullRuneInString(s1) {
105 t.Errorf("FullRune(%q) = true, want false", s1)
106 }
107 }
108 for _, s := range []string{"\xc0", "\xc1"} {
109 b := []byte(s)
110 if !FullRune(b) {
111 t.Errorf("FullRune(%q) = false, want true", s)
112 }
113 if !FullRuneInString(s) {
114 t.Errorf("FullRuneInString(%q) = false, want true", s)
115 }
116 }
117 }
118
119 func TestEncodeRune(t *testing.T) {
120 for _, m := range utf8map {
121 b := []byte(m.str)
122 var buf [10]byte
123 n := EncodeRune(buf[0:], m.r)
124 b1 := buf[0:n]
125 if !bytes.Equal(b, b1) {
126 t.Errorf("EncodeRune(%#04x) = %q want %q", m.r, b1, b)
127 }
128 }
129 }
130
131 func TestAppendRune(t *testing.T) {
132 for _, m := range utf8map {
133 if buf := AppendRune(nil, m.r); string(buf) != m.str {
134 t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str)
135 }
136 if buf := AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str {
137 t.Errorf("AppendRune(init, %#04x) = %s, want %s", m.r, buf, "init"+m.str)
138 }
139 }
140 }
141
142 func TestDecodeRune(t *testing.T) {
143 for _, m := range utf8map {
144 b := []byte(m.str)
145 r, size := DecodeRune(b)
146 if r != m.r || size != len(b) {
147 t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
148 }
149 s := m.str
150 r, size = DecodeRuneInString(s)
151 if r != m.r || size != len(b) {
152 t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
153 }
154
155
156 r, size = DecodeRune(b[0:cap(b)])
157 if r != m.r || size != len(b) {
158 t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
159 }
160 s = m.str + "\x00"
161 r, size = DecodeRuneInString(s)
162 if r != m.r || size != len(b) {
163 t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
164 }
165
166
167 wantsize := 1
168 if wantsize >= len(b) {
169 wantsize = 0
170 }
171 r, size = DecodeRune(b[0 : len(b)-1])
172 if r != RuneError || size != wantsize {
173 t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b[:len(b)-1], r, size, RuneError, wantsize)
174 }
175 s = m.str[0 : len(m.str)-1]
176 r, size = DecodeRuneInString(s)
177 if r != RuneError || size != wantsize {
178 t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, wantsize)
179 }
180
181
182 if len(b) == 1 {
183 b[0] = 0x80
184 } else {
185 b[len(b)-1] = 0x7F
186 }
187 r, size = DecodeRune(b)
188 if r != RuneError || size != 1 {
189 t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, RuneError, 1)
190 }
191 s = string(b)
192 r, size = DecodeRuneInString(s)
193 if r != RuneError || size != 1 {
194 t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, 1)
195 }
196
197 }
198 }
199
200 func TestDecodeSurrogateRune(t *testing.T) {
201 for _, m := range surrogateMap {
202 b := []byte(m.str)
203 r, size := DecodeRune(b)
204 if r != RuneError || size != 1 {
205 t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
206 }
207 s := m.str
208 r, size = DecodeRuneInString(s)
209 if r != RuneError || size != 1 {
210 t.Errorf("DecodeRuneInString(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
211 }
212 }
213 }
214
215
216
217 func TestSequencing(t *testing.T) {
218 for _, ts := range testStrings {
219 for _, m := range utf8map {
220 for _, s := range []string{ts + m.str, m.str + ts, ts + m.str + ts} {
221 testSequence(t, s)
222 }
223 }
224 }
225 }
226
227 func runtimeRuneCount(s string) int {
228 return len([]rune(s))
229 }
230
231
232
233
234
235 func TestRuntimeConversion(t *testing.T) {
236 for _, ts := range testStrings {
237 count := RuneCountInString(ts)
238 if n := runtimeRuneCount(ts); n != count {
239 t.Errorf("%q: len([]rune()) counted %d runes; got %d from RuneCountInString", ts, n, count)
240 break
241 }
242
243 runes := []rune(ts)
244 if n := len(runes); n != count {
245 t.Errorf("%q: []rune() has length %d; got %d from RuneCountInString", ts, n, count)
246 break
247 }
248 i := 0
249 for _, r := range ts {
250 if r != runes[i] {
251 t.Errorf("%q[%d]: expected %c (%U); got %c (%U)", ts, i, runes[i], runes[i], r, r)
252 }
253 i++
254 }
255 }
256 }
257
258 var invalidSequenceTests = []string{
259 "\xed\xa0\x80\x80",
260 "\xed\xbf\xbf\x80",
261
262
263 "\x91\x80\x80\x80",
264
265
266 "\xC2\x7F\x80\x80",
267 "\xC2\xC0\x80\x80",
268 "\xDF\x7F\x80\x80",
269 "\xDF\xC0\x80\x80",
270
271
272 "\xE0\x9F\xBF\x80",
273 "\xE0\xA0\x7F\x80",
274 "\xE0\xBF\xC0\x80",
275 "\xE0\xC0\x80\x80",
276
277
278 "\xE1\x7F\xBF\x80",
279 "\xE1\x80\x7F\x80",
280 "\xE1\xBF\xC0\x80",
281 "\xE1\xC0\x80\x80",
282
283
284 "\xED\x7F\xBF\x80",
285 "\xED\x80\x7F\x80",
286 "\xED\x9F\xC0\x80",
287 "\xED\xA0\x80\x80",
288
289
290 "\xF0\x8F\xBF\xBF",
291 "\xF0\x90\x7F\xBF",
292 "\xF0\x90\x80\x7F",
293 "\xF0\xBF\xBF\xC0",
294 "\xF0\xBF\xC0\x80",
295 "\xF0\xC0\x80\x80",
296
297
298 "\xF1\x7F\xBF\xBF",
299 "\xF1\x80\x7F\xBF",
300 "\xF1\x80\x80\x7F",
301 "\xF1\xBF\xBF\xC0",
302 "\xF1\xBF\xC0\x80",
303 "\xF1\xC0\x80\x80",
304
305
306 "\xF4\x7F\xBF\xBF",
307 "\xF4\x80\x7F\xBF",
308 "\xF4\x80\x80\x7F",
309 "\xF4\x8F\xBF\xC0",
310 "\xF4\x8F\xC0\x80",
311 "\xF4\x90\x80\x80",
312 }
313
314 func runtimeDecodeRune(s string) rune {
315 for _, r := range s {
316 return r
317 }
318 return -1
319 }
320
321 func TestDecodeInvalidSequence(t *testing.T) {
322 for _, s := range invalidSequenceTests {
323 r1, _ := DecodeRune([]byte(s))
324 if want := RuneError; r1 != want {
325 t.Errorf("DecodeRune(%#x) = %#04x, want %#04x", s, r1, want)
326 return
327 }
328 r2, _ := DecodeRuneInString(s)
329 if want := RuneError; r2 != want {
330 t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s, r2, want)
331 return
332 }
333 if r1 != r2 {
334 t.Errorf("DecodeRune(%#x) = %#04x mismatch with DecodeRuneInString(%q) = %#04x", s, r1, s, r2)
335 return
336 }
337 r3 := runtimeDecodeRune(s)
338 if r2 != r3 {
339 t.Errorf("DecodeRuneInString(%q) = %#04x mismatch with runtime.decoderune(%q) = %#04x", s, r2, s, r3)
340 return
341 }
342 }
343 }
344
345 func testSequence(t *testing.T, s string) {
346 type info struct {
347 index int
348 r rune
349 }
350 index := make([]info, len(s))
351 b := []byte(s)
352 si := 0
353 j := 0
354 for i, r := range s {
355 if si != i {
356 t.Errorf("Sequence(%q) mismatched index %d, want %d", s, si, i)
357 return
358 }
359 index[j] = info{i, r}
360 j++
361 r1, size1 := DecodeRune(b[i:])
362 if r != r1 {
363 t.Errorf("DecodeRune(%q) = %#04x, want %#04x", s[i:], r1, r)
364 return
365 }
366 r2, size2 := DecodeRuneInString(s[i:])
367 if r != r2 {
368 t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s[i:], r2, r)
369 return
370 }
371 if size1 != size2 {
372 t.Errorf("DecodeRune/DecodeRuneInString(%q) size mismatch %d/%d", s[i:], size1, size2)
373 return
374 }
375 si += size1
376 }
377 j--
378 for si = len(s); si > 0; {
379 r1, size1 := DecodeLastRune(b[0:si])
380 r2, size2 := DecodeLastRuneInString(s[0:si])
381 if size1 != size2 {
382 t.Errorf("DecodeLastRune/DecodeLastRuneInString(%q, %d) size mismatch %d/%d", s, si, size1, size2)
383 return
384 }
385 if r1 != index[j].r {
386 t.Errorf("DecodeLastRune(%q, %d) = %#04x, want %#04x", s, si, r1, index[j].r)
387 return
388 }
389 if r2 != index[j].r {
390 t.Errorf("DecodeLastRuneInString(%q, %d) = %#04x, want %#04x", s, si, r2, index[j].r)
391 return
392 }
393 si -= size1
394 if si != index[j].index {
395 t.Errorf("DecodeLastRune(%q) index mismatch at %d, want %d", s, si, index[j].index)
396 return
397 }
398 j--
399 }
400 if si != 0 {
401 t.Errorf("DecodeLastRune(%q) finished at %d, not 0", s, si)
402 }
403 }
404
405
406 func TestNegativeRune(t *testing.T) {
407 errorbuf := make([]byte, UTFMax)
408 errorbuf = errorbuf[0:EncodeRune(errorbuf, RuneError)]
409 buf := make([]byte, UTFMax)
410 buf = buf[0:EncodeRune(buf, -1)]
411 if !bytes.Equal(buf, errorbuf) {
412 t.Errorf("incorrect encoding [% x] for -1; expected [% x]", buf, errorbuf)
413 }
414 }
415
416 type RuneCountTest struct {
417 in string
418 out int
419 }
420
421 var runecounttests = []RuneCountTest{
422 {"abcd", 4},
423 {"☺☻☹", 3},
424 {"1,2,3,4", 7},
425 {"\xe2\x00", 2},
426 {"\xe2\x80", 2},
427 {"a\xe2\x80", 3},
428 }
429
430 func TestRuneCount(t *testing.T) {
431 for _, tt := range runecounttests {
432 if out := RuneCountInString(tt.in); out != tt.out {
433 t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
434 }
435 if out := RuneCount([]byte(tt.in)); out != tt.out {
436 t.Errorf("RuneCount(%q) = %d, want %d", tt.in, out, tt.out)
437 }
438 }
439 }
440
441 func TestRuneCountNonASCIIAllocation(t *testing.T) {
442 if n := testing.AllocsPerRun(10, func() {
443 s := []byte("日本語日本語日本語日")
444 _ = RuneCount(s)
445 }); n > 0 {
446 t.Errorf("unexpected RuneCount allocation, got %v, want 0", n)
447 }
448 }
449
450 type RuneLenTest struct {
451 r rune
452 size int
453 }
454
455 var runelentests = []RuneLenTest{
456 {0, 1},
457 {'e', 1},
458 {'é', 2},
459 {'☺', 3},
460 {RuneError, 3},
461 {MaxRune, 4},
462 {0xD800, -1},
463 {0xDFFF, -1},
464 {MaxRune + 1, -1},
465 {-1, -1},
466 }
467
468 func TestRuneLen(t *testing.T) {
469 for _, tt := range runelentests {
470 if size := RuneLen(tt.r); size != tt.size {
471 t.Errorf("RuneLen(%#U) = %d, want %d", tt.r, size, tt.size)
472 }
473 }
474 }
475
476 type ValidTest struct {
477 in string
478 out bool
479 }
480
481 var validTests = []ValidTest{
482 {"", true},
483 {"a", true},
484 {"abc", true},
485 {"Ж", true},
486 {"ЖЖ", true},
487 {"брэд-ЛГТМ", true},
488 {"☺☻☹", true},
489 {"aa\xe2", false},
490 {string([]byte{66, 250}), false},
491 {string([]byte{66, 250, 67}), false},
492 {"a\uFFFDb", true},
493 {string("\xF4\x8F\xBF\xBF"), true},
494 {string("\xF4\x90\x80\x80"), false},
495 {string("\xF7\xBF\xBF\xBF"), false},
496 {string("\xFB\xBF\xBF\xBF\xBF"), false},
497 {string("\xc0\x80"), false},
498 {string("\xed\xa0\x80"), false},
499 {string("\xed\xbf\xbf"), false},
500 }
501
502 func TestValid(t *testing.T) {
503 for _, tt := range validTests {
504 if Valid([]byte(tt.in)) != tt.out {
505 t.Errorf("Valid(%q) = %v; want %v", tt.in, !tt.out, tt.out)
506 }
507 if ValidString(tt.in) != tt.out {
508 t.Errorf("ValidString(%q) = %v; want %v", tt.in, !tt.out, tt.out)
509 }
510 }
511 }
512
513 type ValidRuneTest struct {
514 r rune
515 ok bool
516 }
517
518 var validrunetests = []ValidRuneTest{
519 {0, true},
520 {'e', true},
521 {'é', true},
522 {'☺', true},
523 {RuneError, true},
524 {MaxRune, true},
525 {0xD7FF, true},
526 {0xD800, false},
527 {0xDFFF, false},
528 {0xE000, true},
529 {MaxRune + 1, false},
530 {-1, false},
531 }
532
533 func TestValidRune(t *testing.T) {
534 for _, tt := range validrunetests {
535 if ok := ValidRune(tt.r); ok != tt.ok {
536 t.Errorf("ValidRune(%#U) = %t, want %t", tt.r, ok, tt.ok)
537 }
538 }
539 }
540
541 func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
542 s := []byte("0123456789")
543 for i := 0; i < b.N; i++ {
544 RuneCount(s)
545 }
546 }
547
548 func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
549 s := []byte("日本語日本語日本語日")
550 for i := 0; i < b.N; i++ {
551 RuneCount(s)
552 }
553 }
554
555 func BenchmarkRuneCountInStringTenASCIIChars(b *testing.B) {
556 for i := 0; i < b.N; i++ {
557 RuneCountInString("0123456789")
558 }
559 }
560
561 func BenchmarkRuneCountInStringTenJapaneseChars(b *testing.B) {
562 for i := 0; i < b.N; i++ {
563 RuneCountInString("日本語日本語日本語日")
564 }
565 }
566
567 var ascii100000 = strings.Repeat("0123456789", 10000)
568
569 func BenchmarkValidTenASCIIChars(b *testing.B) {
570 s := []byte("0123456789")
571 for i := 0; i < b.N; i++ {
572 Valid(s)
573 }
574 }
575
576 func BenchmarkValid100KASCIIChars(b *testing.B) {
577 s := []byte(ascii100000)
578 for i := 0; i < b.N; i++ {
579 Valid(s)
580 }
581 }
582
583 func BenchmarkValidTenJapaneseChars(b *testing.B) {
584 s := []byte("日本語日本語日本語日")
585 for i := 0; i < b.N; i++ {
586 Valid(s)
587 }
588 }
589 func BenchmarkValidLongMostlyASCII(b *testing.B) {
590 longMostlyASCII := []byte(longStringMostlyASCII)
591 for i := 0; i < b.N; i++ {
592 Valid(longMostlyASCII)
593 }
594 }
595
596 func BenchmarkValidLongJapanese(b *testing.B) {
597 longJapanese := []byte(longStringJapanese)
598 for i := 0; i < b.N; i++ {
599 Valid(longJapanese)
600 }
601 }
602
603 func BenchmarkValidStringTenASCIIChars(b *testing.B) {
604 for i := 0; i < b.N; i++ {
605 ValidString("0123456789")
606 }
607 }
608
609 func BenchmarkValidString100KASCIIChars(b *testing.B) {
610 for i := 0; i < b.N; i++ {
611 ValidString(ascii100000)
612 }
613 }
614
615 func BenchmarkValidStringTenJapaneseChars(b *testing.B) {
616 for i := 0; i < b.N; i++ {
617 ValidString("日本語日本語日本語日")
618 }
619 }
620
621 func BenchmarkValidStringLongMostlyASCII(b *testing.B) {
622 for i := 0; i < b.N; i++ {
623 ValidString(longStringMostlyASCII)
624 }
625 }
626
627 func BenchmarkValidStringLongJapanese(b *testing.B) {
628 for i := 0; i < b.N; i++ {
629 ValidString(longStringJapanese)
630 }
631 }
632
633 var longStringMostlyASCII string
634 var longStringJapanese string
635
636 func init() {
637 const japanese = "日本語日本語日本語日"
638 var b strings.Builder
639 for i := 0; b.Len() < 100_000; i++ {
640 if i%100 == 0 {
641 b.WriteString(japanese)
642 } else {
643 b.WriteString("0123456789")
644 }
645 }
646 longStringMostlyASCII = b.String()
647 longStringJapanese = strings.Repeat(japanese, 100_000/len(japanese))
648 }
649
650 func BenchmarkEncodeASCIIRune(b *testing.B) {
651 buf := make([]byte, UTFMax)
652 for i := 0; i < b.N; i++ {
653 EncodeRune(buf, 'a')
654 }
655 }
656
657 func BenchmarkEncodeSpanishRune(b *testing.B) {
658 buf := make([]byte, UTFMax)
659 for i := 0; i < b.N; i++ {
660 EncodeRune(buf, 'Ñ')
661 }
662 }
663
664 func BenchmarkEncodeJapaneseRune(b *testing.B) {
665 buf := make([]byte, UTFMax)
666 for i := 0; i < b.N; i++ {
667 EncodeRune(buf, '本')
668 }
669 }
670
671 func BenchmarkEncodeMaxRune(b *testing.B) {
672 buf := make([]byte, UTFMax)
673 for i := 0; i < b.N; i++ {
674 EncodeRune(buf, MaxRune)
675 }
676 }
677
678 func BenchmarkEncodeInvalidRuneMaxPlusOne(b *testing.B) {
679 buf := make([]byte, UTFMax)
680 for i := 0; i < b.N; i++ {
681 EncodeRune(buf, MaxRune+1)
682 }
683 }
684
685 func BenchmarkEncodeInvalidRuneSurrogate(b *testing.B) {
686 buf := make([]byte, UTFMax)
687 for i := 0; i < b.N; i++ {
688 EncodeRune(buf, 0xD800)
689 }
690 }
691
692 func BenchmarkEncodeInvalidRuneNegative(b *testing.B) {
693 buf := make([]byte, UTFMax)
694 for i := 0; i < b.N; i++ {
695 EncodeRune(buf, -1)
696 }
697 }
698
699 func BenchmarkAppendASCIIRune(b *testing.B) {
700 buf := make([]byte, UTFMax)
701 for i := 0; i < b.N; i++ {
702 AppendRune(buf[:0], 'a')
703 }
704 }
705
706 func BenchmarkAppendSpanishRune(b *testing.B) {
707 buf := make([]byte, UTFMax)
708 for i := 0; i < b.N; i++ {
709 AppendRune(buf[:0], 'Ñ')
710 }
711 }
712
713 func BenchmarkAppendJapaneseRune(b *testing.B) {
714 buf := make([]byte, UTFMax)
715 for i := 0; i < b.N; i++ {
716 AppendRune(buf[:0], '本')
717 }
718 }
719
720 func BenchmarkAppendMaxRune(b *testing.B) {
721 buf := make([]byte, UTFMax)
722 for i := 0; i < b.N; i++ {
723 AppendRune(buf[:0], MaxRune)
724 }
725 }
726
727 func BenchmarkAppendInvalidRuneMaxPlusOne(b *testing.B) {
728 buf := make([]byte, UTFMax)
729 for i := 0; i < b.N; i++ {
730 AppendRune(buf[:0], MaxRune+1)
731 }
732 }
733
734 func BenchmarkAppendInvalidRuneSurrogate(b *testing.B) {
735 buf := make([]byte, UTFMax)
736 for i := 0; i < b.N; i++ {
737 AppendRune(buf[:0], 0xD800)
738 }
739 }
740
741 func BenchmarkAppendInvalidRuneNegative(b *testing.B) {
742 buf := make([]byte, UTFMax)
743 for i := 0; i < b.N; i++ {
744 AppendRune(buf[:0], -1)
745 }
746 }
747
748 func BenchmarkDecodeASCIIRune(b *testing.B) {
749 a := []byte{'a'}
750 for i := 0; i < b.N; i++ {
751 DecodeRune(a)
752 }
753 }
754
755 func BenchmarkDecodeJapaneseRune(b *testing.B) {
756 nihon := []byte("本")
757 for i := 0; i < b.N; i++ {
758 DecodeRune(nihon)
759 }
760 }
761
762
763
764 var boolSink bool
765
766 func BenchmarkFullRune(b *testing.B) {
767 benchmarks := []struct {
768 name string
769 data []byte
770 }{
771 {"ASCII", []byte("a")},
772 {"Incomplete", []byte("\xf0\x90\x80")},
773 {"Japanese", []byte("本")},
774 }
775 for _, bm := range benchmarks {
776 b.Run(bm.name, func(b *testing.B) {
777 for i := 0; i < b.N; i++ {
778 boolSink = FullRune(bm.data)
779 }
780 })
781 }
782 }
783
View as plain text