1 // Copyright 2013 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 json 6 7 import ( 8 "bytes" 9 "strings" 10 "testing" 11 "unicode/utf8" 12 ) 13 14 var foldTests = []struct { 15 fn func(s, t []byte) bool 16 s, t string 17 want bool 18 }{ 19 {equalFoldRight, "", "", true}, 20 {equalFoldRight, "a", "a", true}, 21 {equalFoldRight, "", "a", false}, 22 {equalFoldRight, "a", "", false}, 23 {equalFoldRight, "a", "A", true}, 24 {equalFoldRight, "AB", "ab", true}, 25 {equalFoldRight, "AB", "ac", false}, 26 {equalFoldRight, "sbkKc", "bKc", true}, 27 {equalFoldRight, "SbKkc", "bKc", true}, 28 {equalFoldRight, "SbKkc", "bKK", false}, 29 {equalFoldRight, "e", "", false}, 30 {equalFoldRight, "s", "S", true}, 31 32 {simpleLetterEqualFold, "", "", true}, 33 {simpleLetterEqualFold, "abc", "abc", true}, 34 {simpleLetterEqualFold, "abc", "ABC", true}, 35 {simpleLetterEqualFold, "abc", "ABCD", false}, 36 {simpleLetterEqualFold, "abc", "xxx", false}, 37 38 {asciiEqualFold, "a_B", "A_b", true}, 39 {asciiEqualFold, "aa@", "aa`", false}, // verify 0x40 and 0x60 aren't case-equivalent 40 } 41 42 func TestFold(t *testing.T) { 43 for i, tt := range foldTests { 44 if got := tt.fn([]byte(tt.s), []byte(tt.t)); got != tt.want { 45 t.Errorf("%d. %q, %q = %v; want %v", i, tt.s, tt.t, got, tt.want) 46 } 47 truth := strings.EqualFold(tt.s, tt.t) 48 if truth != tt.want { 49 t.Errorf("strings.EqualFold doesn't agree with case %d", i) 50 } 51 } 52 } 53 54 func TestFoldAgainstUnicode(t *testing.T) { 55 const bufSize = 5 56 buf1 := make([]byte, 0, bufSize) 57 buf2 := make([]byte, 0, bufSize) 58 var runes []rune 59 for i := 0x20; i <= 0x7f; i++ { 60 runes = append(runes, rune(i)) 61 } 62 runes = append(runes, kelvin, smallLongEss) 63 64 funcs := []struct { 65 name string 66 fold func(s, t []byte) bool 67 letter bool // must be ASCII letter 68 simple bool // must be simple ASCII letter (not 'S' or 'K') 69 }{ 70 { 71 name: "equalFoldRight", 72 fold: equalFoldRight, 73 }, 74 { 75 name: "asciiEqualFold", 76 fold: asciiEqualFold, 77 simple: true, 78 }, 79 { 80 name: "simpleLetterEqualFold", 81 fold: simpleLetterEqualFold, 82 simple: true, 83 letter: true, 84 }, 85 } 86 87 for _, ff := range funcs { 88 for _, r := range runes { 89 if r >= utf8.RuneSelf { 90 continue 91 } 92 if ff.letter && !isASCIILetter(byte(r)) { 93 continue 94 } 95 if ff.simple && (r == 's' || r == 'S' || r == 'k' || r == 'K') { 96 continue 97 } 98 for _, r2 := range runes { 99 buf1 := append(buf1[:0], 'x') 100 buf2 := append(buf2[:0], 'x') 101 buf1 = buf1[:1+utf8.EncodeRune(buf1[1:bufSize], r)] 102 buf2 = buf2[:1+utf8.EncodeRune(buf2[1:bufSize], r2)] 103 buf1 = append(buf1, 'x') 104 buf2 = append(buf2, 'x') 105 want := bytes.EqualFold(buf1, buf2) 106 if got := ff.fold(buf1, buf2); got != want { 107 t.Errorf("%s(%q, %q) = %v; want %v", ff.name, buf1, buf2, got, want) 108 } 109 } 110 } 111 } 112 } 113 114 func isASCIILetter(b byte) bool { 115 return ('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') 116 } 117