OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / unicode / norm / normalize_test.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package norm
6
7 import (
8         "bytes"
9         "flag"
10         "fmt"
11         "io"
12         "log"
13         "strings"
14         "testing"
15         "unicode/utf8"
16
17         "golang.org/x/text/internal/testtext"
18         "golang.org/x/text/transform"
19 )
20
21 var (
22         testn = flag.Int("testn", -1, "specific test number to run or -1 for all")
23 )
24
25 // pc replaces any rune r that is repeated n times, for n > 1, with r{n}.
26 func pc(s string) []byte {
27         b := bytes.NewBuffer(make([]byte, 0, len(s)))
28         for i := 0; i < len(s); {
29                 r, sz := utf8.DecodeRuneInString(s[i:])
30                 n := 0
31                 if sz == 1 {
32                         // Special-case one-byte case to handle repetition for invalid UTF-8.
33                         for c := s[i]; i+n < len(s) && s[i+n] == c; n++ {
34                         }
35                 } else {
36                         for _, r2 := range s[i:] {
37                                 if r2 != r {
38                                         break
39                                 }
40                                 n++
41                         }
42                 }
43                 b.WriteString(s[i : i+sz])
44                 if n > 1 {
45                         fmt.Fprintf(b, "{%d}", n)
46                 }
47                 i += sz * n
48         }
49         return b.Bytes()
50 }
51
52 // pidx finds the index from which two strings start to differ, plus context.
53 // It returns the index and ellipsis if the index is greater than 0.
54 func pidx(a, b string) (i int, prefix string) {
55         for ; i < len(a) && i < len(b) && a[i] == b[i]; i++ {
56         }
57         if i < 8 {
58                 return 0, ""
59         }
60         i -= 3 // ensure taking at least one full rune before the difference.
61         for k := i - 7; i > k && !utf8.RuneStart(a[i]); i-- {
62         }
63         return i, "..."
64 }
65
66 type PositionTest struct {
67         input  string
68         pos    int
69         buffer string // expected contents of reorderBuffer, if applicable
70 }
71
72 type positionFunc func(rb *reorderBuffer, s string) (int, []byte)
73
74 func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
75         rb := reorderBuffer{}
76         rb.init(f, nil)
77         for i, test := range tests {
78                 rb.reset()
79                 rb.src = inputString(test.input)
80                 rb.nsrc = len(test.input)
81                 pos, out := fn(&rb, test.input)
82                 if pos != test.pos {
83                         t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
84                 }
85                 if outs := string(out); outs != test.buffer {
86                         k, pfx := pidx(outs, test.buffer)
87                         t.Errorf("%s:%d: buffer \nwas  %s%+q; \nwant %s%+q", name, i, pfx, pc(outs[k:]), pfx, pc(test.buffer[k:]))
88                 }
89         }
90 }
91
92 func grave(n int) string {
93         return rep(0x0300, n)
94 }
95
96 func rep(r rune, n int) string {
97         return strings.Repeat(string(r), n)
98 }
99
100 const segSize = maxByteBufferSize
101
102 var cgj = GraphemeJoiner
103
104 var decomposeSegmentTests = []PositionTest{
105         // illegal runes
106         {"\xC2", 0, ""},
107         {"\xC0", 1, "\xC0"},
108         {"\u00E0\x80", 2, "\u0061\u0300"},
109         // starter
110         {"a", 1, "a"},
111         {"ab", 1, "a"},
112         // starter + composing
113         {"a\u0300", 3, "a\u0300"},
114         {"a\u0300b", 3, "a\u0300"},
115         // with decomposition
116         {"\u00C0", 2, "A\u0300"},
117         {"\u00C0b", 2, "A\u0300"},
118         // long
119         {grave(31), 60, grave(30) + cgj},
120         {"a" + grave(31), 61, "a" + grave(30) + cgj},
121
122         // Stability tests: see http://www.unicode.org/review/pr-29.html.
123         // U+0300 COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;;
124         // U+0B47 ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
125         // U+0B3E ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
126         // U+1100 HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
127         // U+1161 HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;;
128         {"\u0B47\u0300\u0B3E", 8, "\u0B47\u0300\u0B3E"},
129         {"\u1100\u0300\u1161", 8, "\u1100\u0300\u1161"},
130         {"\u0B47\u0B3E", 6, "\u0B47\u0B3E"},
131         {"\u1100\u1161", 6, "\u1100\u1161"},
132
133         // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
134         // Sequence of decomposing characters that are starters and modifiers.
135         {"\u0d4a" + strings.Repeat("\u0d3e", 31), 90, "\u0d46" + strings.Repeat("\u0d3e", 30) + cgj},
136
137         {grave(30), 60, grave(30)},
138         // U+FF9E is a starter, but decomposes to U+3099, which is not.
139         {grave(30) + "\uff9e", 60, grave(30) + cgj},
140         // ends with incomplete UTF-8 encoding
141         {"\xCC", 0, ""},
142         {"\u0300\xCC", 2, "\u0300"},
143 }
144
145 func decomposeSegmentF(rb *reorderBuffer, s string) (int, []byte) {
146         rb.initString(NFD, s)
147         rb.setFlusher(nil, appendFlush)
148         p := decomposeSegment(rb, 0, true)
149         return p, rb.out
150 }
151
152 func TestDecomposeSegment(t *testing.T) {
153         runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests)
154 }
155
156 var firstBoundaryTests = []PositionTest{
157         // no boundary
158         {"", -1, ""},
159         {"\u0300", -1, ""},
160         {"\x80\x80", -1, ""},
161         // illegal runes
162         {"\xff", 0, ""},
163         {"\u0300\xff", 2, ""},
164         {"\u0300\xc0\x80\x80", 2, ""},
165         // boundaries
166         {"a", 0, ""},
167         {"\u0300a", 2, ""},
168         // Hangul
169         {"\u1103\u1161", 0, ""},
170         {"\u110B\u1173\u11B7", 0, ""},
171         {"\u1161\u110B\u1173\u11B7", 3, ""},
172         {"\u1173\u11B7\u1103\u1161", 6, ""},
173         // too many combining characters.
174         {grave(maxNonStarters - 1), -1, ""},
175         {grave(maxNonStarters), 60, ""},
176         {grave(maxNonStarters + 1), 60, ""},
177 }
178
179 func firstBoundaryF(rb *reorderBuffer, s string) (int, []byte) {
180         return rb.f.form.FirstBoundary([]byte(s)), nil
181 }
182
183 func firstBoundaryStringF(rb *reorderBuffer, s string) (int, []byte) {
184         return rb.f.form.FirstBoundaryInString(s), nil
185 }
186
187 func TestFirstBoundary(t *testing.T) {
188         runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
189         runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
190 }
191
192 func TestNextBoundary(t *testing.T) {
193         testCases := []struct {
194                 input string
195                 atEOF bool
196                 want  int
197         }{
198                 // no boundary
199                 {"", true, 0},
200                 {"", false, -1},
201                 {"\u0300", true, 2},
202                 {"\u0300", false, -1},
203                 {"\x80\x80", true, 1},
204                 {"\x80\x80", false, 1},
205                 // illegal runes
206                 {"\xff", false, 1},
207                 {"\u0300\xff", false, 2},
208                 {"\u0300\xc0\x80\x80", false, 2},
209                 {"\xc2\x80\x80", false, 2},
210                 {"\xc2", false, -1},
211                 {"\xc2", true, 1},
212                 {"a\u0300\xc2", false, -1},
213                 {"a\u0300\xc2", true, 3},
214                 // boundaries
215                 {"a", true, 1},
216                 {"a", false, -1},
217                 {"aa", false, 1},
218                 {"\u0300", true, 2},
219                 {"\u0300", false, -1},
220                 {"\u0300a", false, 2},
221                 // Hangul
222                 {"\u1103\u1161", true, 6},
223                 {"\u1103\u1161", false, -1},
224                 {"\u110B\u1173\u11B7", false, -1},
225                 {"\u110B\u1173\u11B7\u110B\u1173\u11B7", false, 9},
226                 {"\u1161\u110B\u1173\u11B7", false, 3},
227                 {"\u1173\u11B7\u1103\u1161", false, 6},
228                 // too many combining characters.
229                 {grave(maxNonStarters - 1), false, -1},
230                 {grave(maxNonStarters), false, 60},
231                 {grave(maxNonStarters + 1), false, 60},
232         }
233
234         for _, tc := range testCases {
235                 if got := NFC.NextBoundary([]byte(tc.input), tc.atEOF); got != tc.want {
236                         t.Errorf("NextBoundary(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want)
237                 }
238                 if got := NFC.NextBoundaryInString(tc.input, tc.atEOF); got != tc.want {
239                         t.Errorf("NextBoundaryInString(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want)
240                 }
241         }
242 }
243
244 var decomposeToLastTests = []PositionTest{
245         // ends with inert character
246         {"Hello!", 6, ""},
247         {"\u0632", 2, ""},
248         {"a\u0301\u0635", 5, ""},
249         // ends with non-inert starter
250         {"a", 0, "a"},
251         {"a\u0301a", 3, "a"},
252         {"a\u0301\u03B9", 3, "\u03B9"},
253         {"a\u0327", 0, "a\u0327"},
254         // illegal runes
255         {"\xFF", 1, ""},
256         {"aa\xFF", 3, ""},
257         {"\xC0\x80\x80", 3, ""},
258         {"\xCC\x80\x80", 3, ""},
259         // ends with incomplete UTF-8 encoding
260         {"a\xCC", 2, ""},
261         // ends with combining characters
262         {"\u0300\u0301", 0, "\u0300\u0301"},
263         {"a\u0300\u0301", 0, "a\u0300\u0301"},
264         {"a\u0301\u0308", 0, "a\u0301\u0308"},
265         {"a\u0308\u0301", 0, "a\u0308\u0301"},
266         {"aaaa\u0300\u0301", 3, "a\u0300\u0301"},
267         {"\u0300a\u0300\u0301", 2, "a\u0300\u0301"},
268         {"\u00C0", 0, "A\u0300"},
269         {"a\u00C0", 1, "A\u0300"},
270         // decomposing
271         {"a\u0300\u00E0", 3, "a\u0300"},
272         // multisegment decompositions (flushes leading segments)
273         {"a\u0300\uFDC0", 7, "\u064A"},
274         {"\uFDC0" + grave(29), 4, "\u064A" + grave(29)},
275         {"\uFDC0" + grave(30), 4, "\u064A" + grave(30)},
276         {"\uFDC0" + grave(31), 5, grave(30)},
277         {"\uFDFA" + grave(14), 31, "\u0645" + grave(14)},
278         // Overflow
279         {"\u00E0" + grave(29), 0, "a" + grave(30)},
280         {"\u00E0" + grave(30), 2, grave(30)},
281         // Hangul
282         {"a\u1103", 1, "\u1103"},
283         {"a\u110B", 1, "\u110B"},
284         {"a\u110B\u1173", 1, "\u110B\u1173"},
285         // See comment in composition.go:compBoundaryAfter.
286         {"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"},
287         {"a\uC73C", 1, "\u110B\u1173"},
288         {"다음", 3, "\u110B\u1173\u11B7"},
289         {"다", 0, "\u1103\u1161"},
290         {"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"},
291         {"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"},
292         {"다음음", 6, "\u110B\u1173\u11B7"},
293         {"음다다", 6, "\u1103\u1161"},
294         // maximized buffer
295         {"a" + grave(30), 0, "a" + grave(30)},
296         // Buffer overflow
297         {"a" + grave(31), 3, grave(30)},
298         // weird UTF-8
299         {"a\u0300\u11B7", 0, "a\u0300\u11B7"},
300 }
301
302 func decomposeToLast(rb *reorderBuffer, s string) (int, []byte) {
303         rb.setFlusher([]byte(s), appendFlush)
304         decomposeToLastBoundary(rb)
305         buf := rb.flush(nil)
306         return len(rb.out), buf
307 }
308
309 func TestDecomposeToLastBoundary(t *testing.T) {
310         runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests)
311 }
312
313 var lastBoundaryTests = []PositionTest{
314         // ends with inert character
315         {"Hello!", 6, ""},
316         {"\u0632", 2, ""},
317         // ends with non-inert starter
318         {"a", 0, ""},
319         // illegal runes
320         {"\xff", 1, ""},
321         {"aa\xff", 3, ""},
322         {"a\xff\u0300", 1, ""}, // TODO: should probably be 2.
323         {"\xc0\x80\x80", 3, ""},
324         {"\xc0\x80\x80\u0300", 3, ""},
325         // ends with incomplete UTF-8 encoding
326         {"\xCC", -1, ""},
327         {"\xE0\x80", -1, ""},
328         {"\xF0\x80\x80", -1, ""},
329         {"a\xCC", 0, ""},
330         {"\x80\xCC", 1, ""},
331         {"\xCC\xCC", 1, ""},
332         // ends with combining characters
333         {"a\u0300\u0301", 0, ""},
334         {"aaaa\u0300\u0301", 3, ""},
335         {"\u0300a\u0300\u0301", 2, ""},
336         {"\u00C2", 0, ""},
337         {"a\u00C2", 1, ""},
338         // decomposition may recombine
339         {"\u0226", 0, ""},
340         // no boundary
341         {"", -1, ""},
342         {"\u0300\u0301", -1, ""},
343         {"\u0300", -1, ""},
344         {"\x80\x80", -1, ""},
345         {"\x80\x80\u0301", -1, ""},
346         // Hangul
347         {"다음", 3, ""},
348         {"다", 0, ""},
349         {"\u1103\u1161\u110B\u1173\u11B7", 6, ""},
350         {"\u110B\u1173\u11B7\u1103\u1161", 9, ""},
351         // too many combining characters.
352         {grave(maxNonStarters - 1), -1, ""},
353         // May still be preceded with a non-starter.
354         {grave(maxNonStarters), -1, ""},
355         // May still need to insert a cgj after the last combiner.
356         {grave(maxNonStarters + 1), 2, ""},
357         {grave(maxNonStarters + 2), 4, ""},
358
359         {"a" + grave(maxNonStarters-1), 0, ""},
360         {"a" + grave(maxNonStarters), 0, ""},
361         // May still need to insert a cgj after the last combiner.
362         {"a" + grave(maxNonStarters+1), 3, ""},
363         {"a" + grave(maxNonStarters+2), 5, ""},
364 }
365
366 func lastBoundaryF(rb *reorderBuffer, s string) (int, []byte) {
367         return rb.f.form.LastBoundary([]byte(s)), nil
368 }
369
370 func TestLastBoundary(t *testing.T) {
371         runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests)
372 }
373
374 type spanTest struct {
375         input string
376         atEOF bool
377         n     int
378         err   error
379 }
380
381 var quickSpanTests = []spanTest{
382         {"", true, 0, nil},
383         // starters
384         {"a", true, 1, nil},
385         {"abc", true, 3, nil},
386         {"\u043Eb", true, 3, nil},
387         // incomplete last rune.
388         {"\xCC", true, 1, nil},
389         {"\xCC", false, 0, transform.ErrShortSrc},
390         {"a\xCC", true, 2, nil},
391         {"a\xCC", false, 0, transform.ErrShortSrc}, // TODO: could be 1 for NFD
392         // incorrectly ordered combining characters
393         {"\u0300\u0316", true, 0, transform.ErrEndOfSpan},
394         {"\u0300\u0316", false, 0, transform.ErrEndOfSpan},
395         {"\u0300\u0316cd", true, 0, transform.ErrEndOfSpan},
396         {"\u0300\u0316cd", false, 0, transform.ErrEndOfSpan},
397         // have a maximum number of combining characters.
398         {rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
399         {"a" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
400         {"Ɵ" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
401         {"aa" + rep(0x035D, 30) + "\u035B", true, 1, transform.ErrEndOfSpan},
402         {rep(0x035D, 30) + cgj + "\u035B", true, 64, nil},
403         {"a" + rep(0x035D, 30) + cgj + "\u035B", true, 65, nil},
404         {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil},
405         {"aa" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil},
406
407         {"a" + rep(0x035D, 30) + cgj + "\u035B", false, 61, transform.ErrShortSrc},
408         {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc},
409         {"aa" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc},
410 }
411
412 var quickSpanNFDTests = []spanTest{
413         // needs decomposing
414         {"\u00C0", true, 0, transform.ErrEndOfSpan},
415         {"abc\u00C0", true, 3, transform.ErrEndOfSpan},
416         // correctly ordered combining characters
417         {"\u0300", true, 2, nil},
418         {"ab\u0300", true, 4, nil},
419         {"ab\u0300cd", true, 6, nil},
420         {"\u0300cd", true, 4, nil},
421         {"\u0316\u0300", true, 4, nil},
422         {"ab\u0316\u0300", true, 6, nil},
423         {"ab\u0316\u0300cd", true, 8, nil},
424         {"ab\u0316\u0300\u00C0", true, 6, transform.ErrEndOfSpan},
425         {"\u0316\u0300cd", true, 6, nil},
426         {"\u043E\u0308b", true, 5, nil},
427         // incorrectly ordered combining characters
428         {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan}, // TODO: we could skip 'b' as well.
429         {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan},
430         // Hangul
431         {"같은", true, 0, transform.ErrEndOfSpan},
432 }
433
434 var quickSpanNFCTests = []spanTest{
435         // okay composed
436         {"\u00C0", true, 2, nil},
437         {"abc\u00C0", true, 5, nil},
438         // correctly ordered combining characters
439         // TODO: b may combine with modifiers, which is why this fails. We could
440         // make a more precise test that that actually checks whether last
441         // characters combines. Probably not worth it.
442         {"ab\u0300", true, 1, transform.ErrEndOfSpan},
443         {"ab\u0300cd", true, 1, transform.ErrEndOfSpan},
444         {"ab\u0316\u0300", true, 1, transform.ErrEndOfSpan},
445         {"ab\u0316\u0300cd", true, 1, transform.ErrEndOfSpan},
446         {"\u00C0\u035D", true, 4, nil},
447         // we do not special case leading combining characters
448         {"\u0300cd", true, 0, transform.ErrEndOfSpan},
449         {"\u0300", true, 0, transform.ErrEndOfSpan},
450         {"\u0316\u0300", true, 0, transform.ErrEndOfSpan},
451         {"\u0316\u0300cd", true, 0, transform.ErrEndOfSpan},
452         // incorrectly ordered combining characters
453         {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan},
454         {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan},
455         // Hangul
456         {"같은", true, 6, nil},
457         {"같은", false, 3, transform.ErrShortSrc},
458         // We return the start of the violating segment in case of overflow.
459         {grave(30) + "\uff9e", true, 0, transform.ErrEndOfSpan},
460         {grave(30), true, 0, transform.ErrEndOfSpan},
461 }
462
463 func runSpanTests(t *testing.T, name string, f Form, testCases []spanTest) {
464         for i, tc := range testCases {
465                 s := fmt.Sprintf("Bytes/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF)
466                 ok := testtext.Run(t, s, func(t *testing.T) {
467                         n, err := f.Span([]byte(tc.input), tc.atEOF)
468                         if n != tc.n || err != tc.err {
469                                 t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err)
470                         }
471                 })
472                 if !ok {
473                         continue // Don't do the String variant if the Bytes variant failed.
474                 }
475                 s = fmt.Sprintf("String/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF)
476                 testtext.Run(t, s, func(t *testing.T) {
477                         n, err := f.SpanString(tc.input, tc.atEOF)
478                         if n != tc.n || err != tc.err {
479                                 t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err)
480                         }
481                 })
482         }
483 }
484
485 func TestSpan(t *testing.T) {
486         runSpanTests(t, "NFD", NFD, quickSpanTests)
487         runSpanTests(t, "NFD", NFD, quickSpanNFDTests)
488         runSpanTests(t, "NFC", NFC, quickSpanTests)
489         runSpanTests(t, "NFC", NFC, quickSpanNFCTests)
490 }
491
492 var isNormalTests = []PositionTest{
493         {"", 1, ""},
494         // illegal runes
495         {"\xff", 1, ""},
496         // starters
497         {"a", 1, ""},
498         {"abc", 1, ""},
499         {"\u043Eb", 1, ""},
500         // incorrectly ordered combining characters
501         {"\u0300\u0316", 0, ""},
502         {"ab\u0300\u0316", 0, ""},
503         {"ab\u0300\u0316cd", 0, ""},
504         {"\u0300\u0316cd", 0, ""},
505 }
506 var isNormalNFDTests = []PositionTest{
507         // needs decomposing
508         {"\u00C0", 0, ""},
509         {"abc\u00C0", 0, ""},
510         // correctly ordered combining characters
511         {"\u0300", 1, ""},
512         {"ab\u0300", 1, ""},
513         {"ab\u0300cd", 1, ""},
514         {"\u0300cd", 1, ""},
515         {"\u0316\u0300", 1, ""},
516         {"ab\u0316\u0300", 1, ""},
517         {"ab\u0316\u0300cd", 1, ""},
518         {"\u0316\u0300cd", 1, ""},
519         {"\u043E\u0308b", 1, ""},
520         // Hangul
521         {"같은", 0, ""},
522 }
523 var isNormalNFCTests = []PositionTest{
524         // okay composed
525         {"\u00C0", 1, ""},
526         {"abc\u00C0", 1, ""},
527         // need reordering
528         {"a\u0300", 0, ""},
529         {"a\u0300cd", 0, ""},
530         {"a\u0316\u0300", 0, ""},
531         {"a\u0316\u0300cd", 0, ""},
532         // correctly ordered combining characters
533         {"ab\u0300", 1, ""},
534         {"ab\u0300cd", 1, ""},
535         {"ab\u0316\u0300", 1, ""},
536         {"ab\u0316\u0300cd", 1, ""},
537         {"\u00C0\u035D", 1, ""},
538         {"\u0300", 1, ""},
539         {"\u0316\u0300cd", 1, ""},
540         // Hangul
541         {"같은", 1, ""},
542 }
543
544 var isNormalNFKXTests = []PositionTest{
545         // Special case.
546         {"\u00BC", 0, ""},
547 }
548
549 func isNormalF(rb *reorderBuffer, s string) (int, []byte) {
550         if rb.f.form.IsNormal([]byte(s)) {
551                 return 1, nil
552         }
553         return 0, nil
554 }
555
556 func isNormalStringF(rb *reorderBuffer, s string) (int, []byte) {
557         if rb.f.form.IsNormalString(s) {
558                 return 1, nil
559         }
560         return 0, nil
561 }
562
563 func TestIsNormal(t *testing.T) {
564         runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
565         runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
566         runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
567         runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
568         runPosTests(t, "TestIsNormalNFKD1", NFKD, isNormalF, isNormalTests)
569         runPosTests(t, "TestIsNormalNFKD2", NFKD, isNormalF, isNormalNFDTests)
570         runPosTests(t, "TestIsNormalNFKD3", NFKD, isNormalF, isNormalNFKXTests)
571         runPosTests(t, "TestIsNormalNFKC1", NFKC, isNormalF, isNormalTests)
572         runPosTests(t, "TestIsNormalNFKC2", NFKC, isNormalF, isNormalNFCTests)
573         runPosTests(t, "TestIsNormalNFKC3", NFKC, isNormalF, isNormalNFKXTests)
574 }
575
576 func TestIsNormalString(t *testing.T) {
577         runPosTests(t, "TestIsNormalNFD1", NFD, isNormalStringF, isNormalTests)
578         runPosTests(t, "TestIsNormalNFD2", NFD, isNormalStringF, isNormalNFDTests)
579         runPosTests(t, "TestIsNormalNFC1", NFC, isNormalStringF, isNormalTests)
580         runPosTests(t, "TestIsNormalNFC2", NFC, isNormalStringF, isNormalNFCTests)
581 }
582
583 type AppendTest struct {
584         left  string
585         right string
586         out   string
587 }
588
589 type appendFunc func(f Form, out []byte, s string) []byte
590
591 var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
592
593 func runNormTests(t *testing.T, name string, fn appendFunc) {
594         for f := NFC; f <= NFKD; f++ {
595                 runAppendTests(t, name, f, fn, normTests[f])
596         }
597 }
598
599 func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) {
600         for i, test := range tests {
601                 t.Run(fmt.Sprintf("%s/%d", fstr[f], i), func(t *testing.T) {
602                         id := pc(test.left + test.right)
603                         if *testn >= 0 && i != *testn {
604                                 return
605                         }
606                         t.Run("fn", func(t *testing.T) {
607                                 out := []byte(test.left)
608                                 have := string(fn(f, out, test.right))
609                                 if len(have) != len(test.out) {
610                                         t.Errorf("%+q: length is %d; want %d (%+q vs %+q)", id, len(have), len(test.out), pc(have), pc(test.out))
611                                 }
612                                 if have != test.out {
613                                         k, pf := pidx(have, test.out)
614                                         t.Errorf("%+q:\nwas  %s%+q; \nwant %s%+q", id, pf, pc(have[k:]), pf, pc(test.out[k:]))
615                                 }
616                         })
617
618                         // Bootstrap by normalizing input. Ensures that the various variants
619                         // behave the same.
620                         for g := NFC; g <= NFKD; g++ {
621                                 if f == g {
622                                         continue
623                                 }
624                                 t.Run(fstr[g], func(t *testing.T) {
625                                         want := g.String(test.left + test.right)
626                                         have := string(fn(g, g.AppendString(nil, test.left), test.right))
627                                         if len(have) != len(want) {
628                                                 t.Errorf("%+q: length is %d; want %d (%+q vs %+q)", id, len(have), len(want), pc(have), pc(want))
629                                         }
630                                         if have != want {
631                                                 k, pf := pidx(have, want)
632                                                 t.Errorf("%+q:\nwas  %s%+q; \nwant %s%+q", id, pf, pc(have[k:]), pf, pc(want[k:]))
633                                         }
634                                 })
635                         }
636                 })
637         }
638 }
639
640 var normTests = [][]AppendTest{
641         appendTestsNFC,
642         appendTestsNFD,
643         appendTestsNFKC,
644         appendTestsNFKD,
645 }
646
647 var appendTestsNFC = []AppendTest{
648         {"", ascii, ascii},
649         {"", txt_all, txt_all},
650         {"\uff9e", grave(30), "\uff9e" + grave(29) + cgj + grave(1)},
651         {grave(30), "\uff9e", grave(30) + cgj + "\uff9e"},
652
653         // Tests designed for Iter.
654         { // ordering of non-composing combining characters
655                 "",
656                 "\u0305\u0316",
657                 "\u0316\u0305",
658         },
659         { // segment overflow
660                 "",
661                 "a" + rep(0x0305, maxNonStarters+4) + "\u0316",
662                 "a" + rep(0x0305, maxNonStarters) + cgj + "\u0316" + rep(0x305, 4),
663         },
664
665         { // Combine across non-blocking non-starters.
666                 // U+0327 COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;;
667                 // U+0325 COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;;
668                 "", "a\u0327\u0325", "\u1e01\u0327",
669         },
670
671         { // Jamo V+T does not combine.
672                 "",
673                 "\u1161\u11a8",
674                 "\u1161\u11a8",
675         },
676
677         // Stability tests: see http://www.unicode.org/review/pr-29.html.
678         {"", "\u0b47\u0300\u0b3e", "\u0b47\u0300\u0b3e"},
679         {"", "\u1100\u0300\u1161", "\u1100\u0300\u1161"},
680         {"", "\u0b47\u0b3e", "\u0b4b"},
681         {"", "\u1100\u1161", "\uac00"},
682
683         // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
684         { // 0d4a starts a new segment.
685                 "",
686                 "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
687                 "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
688         },
689
690         { // Split combining characters.
691                 // TODO: don't insert CGJ before starters.
692                 "",
693                 "\u0d46" + strings.Repeat("\u0d3e", 31),
694                 "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
695         },
696
697         { // Split combining characters.
698                 "",
699                 "\u0d4a" + strings.Repeat("\u0d3e", 30),
700                 "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
701         },
702
703         { //  https://golang.org/issues/20079
704                 "",
705                 "\xeb\u0344",
706                 "\xeb\u0308\u0301",
707         },
708
709         { //  https://golang.org/issues/20079
710                 "",
711                 "\uac00" + strings.Repeat("\u0300", 30),
712                 "\uac00" + strings.Repeat("\u0300", 29) + "\u034f\u0300",
713         },
714
715         { //  https://golang.org/issues/20079
716                 "",
717                 "\xeb" + strings.Repeat("\u0300", 31),
718                 "\xeb" + strings.Repeat("\u0300", 30) + "\u034f\u0300",
719         },
720 }
721
722 var appendTestsNFD = []AppendTest{
723 // TODO: Move some of the tests here.
724 }
725
726 var appendTestsNFKC = []AppendTest{
727         // empty buffers
728         {"", "", ""},
729         {"a", "", "a"},
730         {"", "a", "a"},
731         {"", "\u0041\u0307\u0304", "\u01E0"},
732         // segment split across buffers
733         {"", "a\u0300b", "\u00E0b"},
734         {"a", "\u0300b", "\u00E0b"},
735         {"a", "\u0300\u0316", "\u00E0\u0316"},
736         {"a", "\u0316\u0300", "\u00E0\u0316"},
737         {"a", "\u0300a\u0300", "\u00E0\u00E0"},
738         {"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"},
739         {"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"},
740         {"a\u0300", "\u0327", "\u00E0\u0327"},
741         {"a\u0327", "\u0300", "\u00E0\u0327"},
742         {"a\u0316", "\u0300", "\u00E0\u0316"},
743         {"\u0041\u0307", "\u0304", "\u01E0"},
744         // Hangul
745         {"", "\u110B\u1173", "\uC73C"},
746         {"", "\u1103\u1161", "\uB2E4"},
747         {"", "\u110B\u1173\u11B7", "\uC74C"},
748         {"", "\u320E", "\x28\uAC00\x29"},
749         {"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"},
750         {"\u1103", "\u1161", "\uB2E4"},
751         {"\u110B", "\u1173\u11B7", "\uC74C"},
752         {"\u110B\u1173", "\u11B7", "\uC74C"},
753         {"\uC73C", "\u11B7", "\uC74C"},
754         // UTF-8 encoding split across buffers
755         {"a\xCC", "\x80", "\u00E0"},
756         {"a\xCC", "\x80b", "\u00E0b"},
757         {"a\xCC", "\x80a\u0300", "\u00E0\u00E0"},
758         {"a\xCC", "\x80\x80", "\u00E0\x80"},
759         {"a\xCC", "\x80\xCC", "\u00E0\xCC"},
760         {"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"},
761         // ending in incomplete UTF-8 encoding
762         {"", "\xCC", "\xCC"},
763         {"a", "\xCC", "a\xCC"},
764         {"a", "b\xCC", "ab\xCC"},
765         {"\u0226", "\xCC", "\u0226\xCC"},
766         // illegal runes
767         {"", "\x80", "\x80"},
768         {"", "\x80\x80\x80", "\x80\x80\x80"},
769         {"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"},
770         {"", "a\x80", "a\x80"},
771         {"", "a\x80\x80\x80", "a\x80\x80\x80"},
772         {"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"},
773         {"a", "\x80\x80\x80", "a\x80\x80\x80"},
774         // overflow
775         {"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)},
776         {strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)},
777         {strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)},
778         // overflow of combining characters
779         {"", grave(34), grave(30) + cgj + grave(4)},
780         {"", grave(36), grave(30) + cgj + grave(6)},
781         {grave(29), grave(5), grave(30) + cgj + grave(4)},
782         {grave(30), grave(4), grave(30) + cgj + grave(4)},
783         {grave(30), grave(3), grave(30) + cgj + grave(3)},
784         {grave(30) + "\xCC", "\x80", grave(30) + cgj + grave(1)},
785         {"", "\uFDFA" + grave(14), "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645" + grave(14)},
786         {"", "\uFDFA" + grave(28) + "\u0316", "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645\u0316" + grave(28)},
787         // - First rune has a trailing non-starter.
788         {"\u00d5", grave(30), "\u00d5" + grave(29) + cgj + grave(1)},
789         // - U+FF9E decomposes into a non-starter in compatibility mode. A CGJ must be
790         //   inserted even when FF9E starts a new segment.
791         {"\uff9e", grave(30), "\u3099" + grave(29) + cgj + grave(1)},
792         {grave(30), "\uff9e", grave(30) + cgj + "\u3099"},
793         // - Many non-starter decompositions in a row causing overflow.
794         {"", rep(0x340, 31), rep(0x300, 30) + cgj + "\u0300"},
795         {"", rep(0xFF9E, 31), rep(0x3099, 30) + cgj + "\u3099"},
796
797         {"", "\u0644\u0625" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + "\u0300\u0300"},
798         {"", "\ufef9" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + rep(0x0300, 2)},
799         {"", "\ufef9" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + rep(0x0300, 2)},
800
801         // U+0F81 TIBETAN VOWEL SIGN REVERSED II splits into two modifiers.
802         {"", "\u0f7f" + rep(0xf71, 29) + "\u0f81", "\u0f7f" + rep(0xf71, 29) + cgj + "\u0f71\u0f80"},
803         {"", "\u0f7f" + rep(0xf71, 28) + "\u0f81", "\u0f7f" + rep(0xf71, 29) + "\u0f80"},
804         {"", "\u0f7f" + rep(0xf81, 16), "\u0f7f" + rep(0xf71, 15) + rep(0xf80, 15) + cgj + "\u0f71\u0f80"},
805
806         // weird UTF-8
807         {"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"},
808         {"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"},
809         {"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"},
810         {"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"},
811         {"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
812         {"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
813         {"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
814         {"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
815
816         {"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)},
817         // large input.
818         {"", strings.Repeat("a\u0300\u0316", 31), strings.Repeat("\u00E0\u0316", 31)},
819         {"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)},
820         {"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)},
821         {"", "\u0041\u0307\u0304", "\u01E0"},
822 }
823
824 var appendTestsNFKD = []AppendTest{
825         {"", "a" + grave(64), "a" + grave(30) + cgj + grave(30) + cgj + grave(4)},
826
827         { // segment overflow on unchanged character
828                 "",
829                 "a" + grave(64) + "\u0316",
830                 "a" + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(4),
831         },
832         { // segment overflow on unchanged character + start value
833                 "",
834                 "a" + grave(98) + "\u0316",
835                 "a" + grave(30) + cgj + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(8),
836         },
837         { // segment overflow on decomposition. (U+0340 decomposes to U+0300.)
838                 "",
839                 "a" + grave(59) + "\u0340",
840                 "a" + grave(30) + cgj + grave(30),
841         },
842         { // segment overflow on non-starter decomposition
843                 "",
844                 "a" + grave(33) + "\u0340" + grave(30) + "\u0320",
845                 "a" + grave(30) + cgj + grave(30) + cgj + "\u0320" + grave(4),
846         },
847         { // start value after ASCII overflow
848                 "",
849                 rep('a', segSize) + grave(32) + "\u0320",
850                 rep('a', segSize) + grave(30) + cgj + "\u0320" + grave(2),
851         },
852         { // Jamo overflow
853                 "",
854                 "\u1100\u1161" + grave(30) + "\u0320" + grave(2),
855                 "\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
856         },
857         { // Hangul
858                 "",
859                 "\uac00",
860                 "\u1100\u1161",
861         },
862         { // Hangul overflow
863                 "",
864                 "\uac00" + grave(32) + "\u0320",
865                 "\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
866         },
867         { // Hangul overflow in Hangul mode.
868                 "",
869                 "\uac00\uac00" + grave(32) + "\u0320",
870                 "\u1100\u1161\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
871         },
872         { // Hangul overflow in Hangul mode.
873                 "",
874                 strings.Repeat("\uac00", 3) + grave(32) + "\u0320",
875                 strings.Repeat("\u1100\u1161", 3) + grave(29) + cgj + "\u0320" + grave(3),
876         },
877         { // start value after cc=0
878                 "",
879                 "您您" + grave(34) + "\u0320",
880                 "您您" + grave(30) + cgj + "\u0320" + grave(4),
881         },
882         { // start value after normalization
883                 "",
884                 "\u0300\u0320a" + grave(34) + "\u0320",
885                 "\u0320\u0300a" + grave(30) + cgj + "\u0320" + grave(4),
886         },
887         {
888                 // U+0F81 TIBETAN VOWEL SIGN REVERSED II splits into two modifiers.
889                 "",
890                 "a\u0f7f" + rep(0xf71, 29) + "\u0f81",
891                 "a\u0f7f" + rep(0xf71, 29) + cgj + "\u0f71\u0f80",
892         },
893 }
894
895 func TestAppend(t *testing.T) {
896         runNormTests(t, "Append", func(f Form, out []byte, s string) []byte {
897                 return f.Append(out, []byte(s)...)
898         })
899 }
900
901 func TestAppendString(t *testing.T) {
902         runNormTests(t, "AppendString", func(f Form, out []byte, s string) []byte {
903                 return f.AppendString(out, s)
904         })
905 }
906
907 func TestBytes(t *testing.T) {
908         runNormTests(t, "Bytes", func(f Form, out []byte, s string) []byte {
909                 buf := []byte{}
910                 buf = append(buf, out...)
911                 buf = append(buf, s...)
912                 return f.Bytes(buf)
913         })
914 }
915
916 func TestString(t *testing.T) {
917         runNormTests(t, "String", func(f Form, out []byte, s string) []byte {
918                 outs := string(out) + s
919                 return []byte(f.String(outs))
920         })
921 }
922
923 func TestLinking(t *testing.T) {
924         const prog = `
925         package main
926         import "fmt"
927         import "golang.org/x/text/unicode/norm"
928         func main() { fmt.Println(norm.%s) }
929         `
930         baseline, errB := testtext.CodeSize(fmt.Sprintf(prog, "MaxSegmentSize"))
931         withTables, errT := testtext.CodeSize(fmt.Sprintf(prog, `NFC.String("")`))
932         if errB != nil || errT != nil {
933                 t.Skipf("code size failed: %v and %v", errB, errT)
934         }
935         // Tables are at least 50K
936         if d := withTables - baseline; d < 50*1024 {
937                 t.Errorf("tables appear not to be dropped: %d - %d = %d",
938                         withTables, baseline, d)
939         }
940 }
941
942 func appendBench(f Form, in []byte) func() {
943         buf := make([]byte, 0, 4*len(in))
944         return func() {
945                 f.Append(buf, in...)
946         }
947 }
948
949 func bytesBench(f Form, in []byte) func() {
950         return func() {
951                 f.Bytes(in)
952         }
953 }
954
955 func iterBench(f Form, in []byte) func() {
956         iter := Iter{}
957         return func() {
958                 iter.Init(f, in)
959                 for !iter.Done() {
960                         iter.Next()
961                 }
962         }
963 }
964
965 func transformBench(f Form, in []byte) func() {
966         buf := make([]byte, 4*len(in))
967         return func() {
968                 if _, n, err := f.Transform(buf, in, true); err != nil || len(in) != n {
969                         log.Panic(n, len(in), err)
970                 }
971         }
972 }
973
974 func readerBench(f Form, in []byte) func() {
975         buf := make([]byte, 4*len(in))
976         return func() {
977                 r := f.Reader(bytes.NewReader(in))
978                 var err error
979                 for err == nil {
980                         _, err = r.Read(buf)
981                 }
982                 if err != io.EOF {
983                         panic("")
984                 }
985         }
986 }
987
988 func writerBench(f Form, in []byte) func() {
989         buf := make([]byte, 0, 4*len(in))
990         return func() {
991                 r := f.Writer(bytes.NewBuffer(buf))
992                 if _, err := r.Write(in); err != nil {
993                         panic("")
994                 }
995         }
996 }
997
998 func appendBenchmarks(bm []func(), f Form, in []byte) []func() {
999         bm = append(bm, appendBench(f, in))
1000         bm = append(bm, iterBench(f, in))
1001         bm = append(bm, transformBench(f, in))
1002         bm = append(bm, readerBench(f, in))
1003         bm = append(bm, writerBench(f, in))
1004         return bm
1005 }
1006
1007 func doFormBenchmark(b *testing.B, inf, f Form, s string) {
1008         b.StopTimer()
1009         in := inf.Bytes([]byte(s))
1010         bm := appendBenchmarks(nil, f, in)
1011         b.SetBytes(int64(len(in) * len(bm)))
1012         b.StartTimer()
1013         for i := 0; i < b.N; i++ {
1014                 for _, fn := range bm {
1015                         fn()
1016                 }
1017         }
1018 }
1019
1020 func doSingle(b *testing.B, f func(Form, []byte) func(), s []byte) {
1021         b.StopTimer()
1022         fn := f(NFC, s)
1023         b.SetBytes(int64(len(s)))
1024         b.StartTimer()
1025         for i := 0; i < b.N; i++ {
1026                 fn()
1027         }
1028 }
1029
1030 var (
1031         smallNoChange = []byte("nörmalization")
1032         smallChange   = []byte("No\u0308rmalization")
1033         ascii         = strings.Repeat("There is nothing to change here! ", 500)
1034 )
1035
1036 func lowerBench(f Form, in []byte) func() {
1037         // Use package strings instead of bytes as it doesn't allocate memory
1038         // if there aren't any changes.
1039         s := string(in)
1040         return func() {
1041                 strings.ToLower(s)
1042         }
1043 }
1044
1045 func BenchmarkLowerCaseNoChange(b *testing.B) {
1046         doSingle(b, lowerBench, smallNoChange)
1047 }
1048 func BenchmarkLowerCaseChange(b *testing.B) {
1049         doSingle(b, lowerBench, smallChange)
1050 }
1051
1052 func quickSpanBench(f Form, in []byte) func() {
1053         return func() {
1054                 f.QuickSpan(in)
1055         }
1056 }
1057
1058 func BenchmarkQuickSpanChangeNFC(b *testing.B) {
1059         doSingle(b, quickSpanBench, smallNoChange)
1060 }
1061
1062 func BenchmarkBytesNoChangeNFC(b *testing.B) {
1063         doSingle(b, bytesBench, smallNoChange)
1064 }
1065 func BenchmarkBytesChangeNFC(b *testing.B) {
1066         doSingle(b, bytesBench, smallChange)
1067 }
1068
1069 func BenchmarkAppendNoChangeNFC(b *testing.B) {
1070         doSingle(b, appendBench, smallNoChange)
1071 }
1072 func BenchmarkAppendChangeNFC(b *testing.B) {
1073         doSingle(b, appendBench, smallChange)
1074 }
1075 func BenchmarkAppendLargeNFC(b *testing.B) {
1076         doSingle(b, appendBench, txt_all_bytes)
1077 }
1078
1079 func BenchmarkIterNoChangeNFC(b *testing.B) {
1080         doSingle(b, iterBench, smallNoChange)
1081 }
1082 func BenchmarkIterChangeNFC(b *testing.B) {
1083         doSingle(b, iterBench, smallChange)
1084 }
1085 func BenchmarkIterLargeNFC(b *testing.B) {
1086         doSingle(b, iterBench, txt_all_bytes)
1087 }
1088
1089 func BenchmarkTransformNoChangeNFC(b *testing.B) {
1090         doSingle(b, transformBench, smallNoChange)
1091 }
1092 func BenchmarkTransformChangeNFC(b *testing.B) {
1093         doSingle(b, transformBench, smallChange)
1094 }
1095 func BenchmarkTransformLargeNFC(b *testing.B) {
1096         doSingle(b, transformBench, txt_all_bytes)
1097 }
1098
1099 func BenchmarkNormalizeAsciiNFC(b *testing.B) {
1100         doFormBenchmark(b, NFC, NFC, ascii)
1101 }
1102 func BenchmarkNormalizeAsciiNFD(b *testing.B) {
1103         doFormBenchmark(b, NFC, NFD, ascii)
1104 }
1105 func BenchmarkNormalizeAsciiNFKC(b *testing.B) {
1106         doFormBenchmark(b, NFC, NFKC, ascii)
1107 }
1108 func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
1109         doFormBenchmark(b, NFC, NFKD, ascii)
1110 }
1111
1112 func BenchmarkNormalizeNFC2NFC(b *testing.B) {
1113         doFormBenchmark(b, NFC, NFC, txt_all)
1114 }
1115 func BenchmarkNormalizeNFC2NFD(b *testing.B) {
1116         doFormBenchmark(b, NFC, NFD, txt_all)
1117 }
1118 func BenchmarkNormalizeNFD2NFC(b *testing.B) {
1119         doFormBenchmark(b, NFD, NFC, txt_all)
1120 }
1121 func BenchmarkNormalizeNFD2NFD(b *testing.B) {
1122         doFormBenchmark(b, NFD, NFD, txt_all)
1123 }
1124
1125 // Hangul is often special-cased, so we test it separately.
1126 func BenchmarkNormalizeHangulNFC2NFC(b *testing.B) {
1127         doFormBenchmark(b, NFC, NFC, txt_kr)
1128 }
1129 func BenchmarkNormalizeHangulNFC2NFD(b *testing.B) {
1130         doFormBenchmark(b, NFC, NFD, txt_kr)
1131 }
1132 func BenchmarkNormalizeHangulNFD2NFC(b *testing.B) {
1133         doFormBenchmark(b, NFD, NFC, txt_kr)
1134 }
1135 func BenchmarkNormalizeHangulNFD2NFD(b *testing.B) {
1136         doFormBenchmark(b, NFD, NFD, txt_kr)
1137 }
1138
1139 var forms = []Form{NFC, NFD, NFKC, NFKD}
1140
1141 func doTextBenchmark(b *testing.B, s string) {
1142         b.StopTimer()
1143         in := []byte(s)
1144         bm := []func(){}
1145         for _, f := range forms {
1146                 bm = appendBenchmarks(bm, f, in)
1147         }
1148         b.SetBytes(int64(len(s) * len(bm)))
1149         b.StartTimer()
1150         for i := 0; i < b.N; i++ {
1151                 for _, f := range bm {
1152                         f()
1153                 }
1154         }
1155 }
1156
1157 func BenchmarkCanonicalOrdering(b *testing.B) {
1158         doTextBenchmark(b, txt_canon)
1159 }
1160 func BenchmarkExtendedLatin(b *testing.B) {
1161         doTextBenchmark(b, txt_vn)
1162 }
1163 func BenchmarkMiscTwoByteUtf8(b *testing.B) {
1164         doTextBenchmark(b, twoByteUtf8)
1165 }
1166 func BenchmarkMiscThreeByteUtf8(b *testing.B) {
1167         doTextBenchmark(b, threeByteUtf8)
1168 }
1169 func BenchmarkHangul(b *testing.B) {
1170         doTextBenchmark(b, txt_kr)
1171 }
1172 func BenchmarkJapanese(b *testing.B) {
1173         doTextBenchmark(b, txt_jp)
1174 }
1175 func BenchmarkChinese(b *testing.B) {
1176         doTextBenchmark(b, txt_cn)
1177 }
1178 func BenchmarkOverflow(b *testing.B) {
1179         doTextBenchmark(b, overflow)
1180 }
1181
1182 var overflow = string(bytes.Repeat([]byte("\u035D"), 4096)) + "\u035B"
1183
1184 // Tests sampled from the Canonical ordering tests (Part 2) of
1185 // http://unicode.org/Public/UNIDATA/NormalizationTest.txt
1186 const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062
1187 \u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062
1188 \u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062
1189 \u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062 
1190 \u0061\u059A\u0316\u302A\u0339       \u0061\u0341\u0315\u0300\u05AE\u0062
1191 \u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062
1192 \u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062
1193 \u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062
1194 \u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062
1195 \u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062
1196 \u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062
1197 \u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062
1198 \u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062
1199 \u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062
1200 \u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062
1201 \u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062
1202 \u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062
1203 \u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062`
1204
1205 // Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
1206 const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả. 
1207 Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ 
1208 nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc 
1209 một giấy phép khác có các điều khoản tương tự như giấy phép này
1210 cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào
1211 trên đây cũng có thể được miễn bỏ nếu bạn được sự cho phép của
1212 người sở hữu bản quyền. Phạm vi công chúng — Khi tác phẩm hoặc
1213 bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
1214 chúng theo quy định của pháp luật thì tình trạng của nó không 
1215 bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
1216
1217 // Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
1218 const txt_ru = `При обязательном соблюдении следующих условий:
1219 Attribution — Вы должны атрибутировать произведение (указывать
1220 автора и источник) в порядке, предусмотренном автором или
1221 лицензиаром (но только так, чтобы никоим образом не подразумевалось,
1222 что они поддерживают вас или использование вами данного произведения).
1223 Υπό τις ακόλουθες προϋποθέσεις:`
1224
1225 // Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
1226 const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με τον
1227 τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια
1228 (χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή
1229 τη χρήση του έργου από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε,
1230 τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα
1231 μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή
1232 παρόμοια άδεια.`
1233
1234 // Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
1235 const txt_ar = `بموجب الشروط التالية نسب المصنف — يجب عليك أن
1236 تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من
1237 الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
1238 المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة
1239 من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد
1240 لهذا الترخيص.`
1241
1242 // Taken from http://creativecommons.org/licenses/by-sa/1.0/il/
1243 const txt_il = `בכפוף לתנאים הבאים: ייחוס — עליך לייחס את היצירה (לתת קרדיט) באופן
1244 המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך
1245 שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה — אם תחליט/י לשנות,
1246 לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך
1247 החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.`
1248
1249 const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il
1250
1251 // Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/
1252 const txt_kr = `다음과 같은 조건을 따라야 합니다: 저작자표시
1253 (Attribution) — 저작자나 이용허락자가 정한 방법으로 저작물의
1254 원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의
1255 이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다). 
1256 동일조건변경허락 — 이 저작물을 이용하여 만든 이차적 저작물에는 본
1257 라이선스와 동일한 라이선스를 적용해야 합니다.`
1258
1259 // Taken from http://creativecommons.org/licenses/by-sa/3.0/th/
1260 const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา — คุณต้องแสดงที่
1261 มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่
1262 ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่
1263 คุณนำงานไปใช้) อนุญาตแบบเดียวกัน — หากคุณดัดแปลง เปลี่ยนรูป หรื
1264 อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื
1265 อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น`
1266
1267 const threeByteUtf8 = txt_th
1268
1269 // Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/
1270 const txt_jp = `あなたの従うべき条件は以下の通りです。
1271 表示 — あなたは原著作者のクレジットを表示しなければなりません。
1272 継承 — もしあなたがこの作品を改変、変形または加工した場合、
1273 あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ
1274 頒布することができます。`
1275
1276 // http://creativecommons.org/licenses/by-sa/2.5/cn/
1277 const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、
1278 广播或通过信息网络传播本作品 创作演绎作品
1279 对本作品进行商业性使用 惟须遵守下列条件:
1280 署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。
1281 相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作,
1282 您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。`
1283
1284 const txt_cjk = txt_cn + txt_jp + txt_kr
1285 const txt_all = txt_vn + twoByteUtf8 + threeByteUtf8 + txt_cjk
1286
1287 var txt_all_bytes = []byte(txt_all)