github.com/segmentio/encoding@v0.4.0/json/parse_test.go (about) 1 package json 2 3 import ( 4 "bytes" 5 "strings" 6 "testing" 7 ) 8 9 func TestParseString(t *testing.T) { 10 tests := []struct { 11 in string 12 out string 13 ext string 14 err string 15 }{ 16 {`""`, `""`, ``, ``}, 17 {`"1234567890"`, `"1234567890"`, ``, ``}, 18 {`"Hello World!"`, `"Hello World!"`, ``, ``}, 19 {`"Hello\"World!"`, `"Hello\"World!"`, ``, ``}, 20 {`"\\"`, `"\\"`, ``, ``}, 21 {`"\u0061\u0062\u0063"`, `"\u0061\u0062\u0063"`, ``, ``}, 22 {`"\u0"`, ``, ``, `json: unicode code point must have at least 4 characters: 0"`}, 23 } 24 25 d := decoder{} 26 for _, test := range tests { 27 t.Run(test.in, func(t *testing.T) { 28 out, ext, _, err := d.parseString([]byte(test.in)) 29 30 if test.err == "" { 31 if err != nil { 32 t.Errorf("%s => %s", test.in, err) 33 return 34 } 35 } else { 36 if s := err.Error(); s != test.err { 37 t.Error("invalid error") 38 t.Logf("expected: %s", test.err) 39 t.Logf("found: %s", s) 40 } 41 } 42 43 if s := string(out); s != test.out { 44 t.Error("invalid output") 45 t.Logf("expected: %s", test.out) 46 t.Logf("found: %s", s) 47 } 48 49 if s := string(ext); s != test.ext { 50 t.Error("invalid extra bytes") 51 t.Logf("expected: %s", test.ext) 52 t.Logf("found: %s", s) 53 } 54 }) 55 } 56 } 57 58 func TestParseStringUnquote(t *testing.T) { 59 tests := []struct { 60 in string 61 out string 62 ext string 63 }{ 64 {`""`, ``, ``}, 65 {`"1234567890"`, `1234567890`, ``}, 66 {`"Hello World!"`, `Hello World!`, ``}, 67 {`"Hello\"World!"`, `Hello"World!`, ``}, 68 {`"\\"`, `\`, ``}, 69 {`"\u0061\u0062\u0063"`, `abc`, ``}, 70 } 71 72 d := decoder{} 73 for _, test := range tests { 74 t.Run(test.in, func(t *testing.T) { 75 out, ext, _, err := d.parseStringUnquote([]byte(test.in), nil) 76 77 if err != nil { 78 t.Errorf("%s => %s", test.in, err) 79 return 80 } 81 82 if s := string(out); s != test.out { 83 t.Error("invalid output") 84 t.Logf("expected: %s", test.out) 85 t.Logf("found: %s", s) 86 } 87 88 if s := string(ext); s != test.ext { 89 t.Error("invalid extra bytes") 90 t.Logf("expected: %s", test.ext) 91 t.Logf("found: %s", s) 92 } 93 }) 94 } 95 } 96 97 func TestAppendToLower(t *testing.T) { 98 tests := []string{ 99 "", 100 "A", 101 "a", 102 "__segment_internal", 103 "someFieldWithALongBName", 104 "Hello World!", 105 "Hello\"World!", 106 "Hello\\World!", 107 "Hello\nWorld!", 108 "Hello\rWorld!", 109 "Hello\tWorld!", 110 "Hello\bWorld!", 111 "Hello\fWorld!", 112 "你好", 113 "<", 114 ">", 115 "&", 116 "\u001944", 117 "\u00c2e>", 118 "\u00c2V?", 119 "\u000e=8", 120 "\u001944\u00c2e>\u00c2V?\u000e=8", 121 "ir\u001bQJ\u007f\u0007y\u0015)", 122 } 123 124 for _, test := range tests { 125 s1 := strings.ToLower(test) 126 s2 := string(appendToLower(nil, []byte(test))) 127 128 if s1 != s2 { 129 t.Error("lowercase values mismatch") 130 t.Log("expected:", s1) 131 t.Log("found: ", s2) 132 } 133 } 134 } 135 136 func BenchmarkParseString(b *testing.B) { 137 s := []byte(`"__segment_internal"`) 138 139 d := decoder{} 140 for i := 0; i != b.N; i++ { 141 d.parseString(s) 142 } 143 } 144 145 func BenchmarkToLower(b *testing.B) { 146 s := []byte("someFieldWithALongName") 147 148 for i := 0; i != b.N; i++ { 149 bytes.ToLower(s) 150 } 151 } 152 153 func BenchmarkAppendToLower(b *testing.B) { 154 a := []byte(nil) 155 s := []byte("someFieldWithALongName") 156 157 for i := 0; i != b.N; i++ { 158 a = appendToLower(a[:0], s) 159 } 160 } 161 162 var benchmarkHasPrefixString = []byte("some random string") 163 var benchmarkHasPrefixResult = false 164 165 func BenchmarkHasPrefix(b *testing.B) { 166 for i := 0; i < b.N; i++ { 167 benchmarkHasPrefixResult = hasPrefix(benchmarkHasPrefixString, "null") 168 } 169 } 170 171 func BenchmarkHasNullPrefix(b *testing.B) { 172 for i := 0; i < b.N; i++ { 173 benchmarkHasPrefixResult = hasNullPrefix(benchmarkHasPrefixString) 174 } 175 } 176 177 func BenchmarkHasTruePrefix(b *testing.B) { 178 for i := 0; i < b.N; i++ { 179 benchmarkHasPrefixResult = hasTruePrefix(benchmarkHasPrefixString) 180 } 181 } 182 183 func BenchmarkHasFalsePrefix(b *testing.B) { 184 for i := 0; i < b.N; i++ { 185 benchmarkHasPrefixResult = hasFalsePrefix(benchmarkHasPrefixString) 186 } 187 } 188 189 func BenchmarkParseStringEscapeNone(b *testing.B) { 190 var j = []byte(`"` + strings.Repeat(`a`, 1000) + `"`) 191 var s string 192 b.SetBytes(int64(len(j))) 193 194 for i := 0; i < b.N; i++ { 195 if err := Unmarshal(j, &s); err != nil { 196 b.Fatal(err) 197 } 198 s = "" 199 } 200 } 201 202 func BenchmarkParseStringEscapeOne(b *testing.B) { 203 var j = []byte(`"` + strings.Repeat(`a`, 998) + `\n"`) 204 var s string 205 b.SetBytes(int64(len(j))) 206 207 for i := 0; i < b.N; i++ { 208 if err := Unmarshal(j, &s); err != nil { 209 b.Fatal(err) 210 } 211 s = "" 212 } 213 } 214 215 func BenchmarkParseStringEscapeAll(b *testing.B) { 216 var j = []byte(`"` + strings.Repeat(`\`, 1000) + `"`) 217 var s string 218 b.SetBytes(int64(len(j))) 219 220 for i := 0; i < b.N; i++ { 221 if err := Unmarshal(j, &s); err != nil { 222 b.Fatal(err) 223 } 224 s = "" 225 } 226 }