github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/iterator_str_test.go (about) 1 package jzon 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "io" 8 "testing" 9 "unsafe" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 func runeToASCII(s string) string { 15 var ret string 16 for _, r := range []rune(s) { 17 if r < 128 { 18 ret += string(r) 19 } else { 20 ret += fmt.Sprintf("\\u%04x", r) 21 } 22 } 23 return ret 24 } 25 26 func testIteratorStr(t *testing.T, input string, ex error) { 27 var s string 28 err := json.Unmarshal([]byte(input), &s) 29 require.Equalf(t, ex == nil, err == nil, "json.Marshal\nexp:%v\ngot:%v", 30 ex, err) 31 withIterator(input, func(it *Iterator) { 32 s2, err := it.ReadString() 33 checkError(t, ex, err) 34 if ex == nil { 35 require.Equalf(t, s, s2, "exp: %s\ngot: %s", s, s2) 36 t.Logf("json: %s", s) 37 t.Logf("jzon: %s", s2) 38 } 39 }) 40 } 41 42 func TestIterator_Str_readU4(t *testing.T) { 43 origin := `中` 44 src := runeToASCII(`"` + origin + `"`) 45 t.Run("eof", func(t *testing.T) { 46 testIteratorStr(t, src[:3], io.EOF) 47 }) 48 t.Run("eof2", func(t *testing.T) { 49 testIteratorStr(t, src[:len(src)-1], io.EOF) 50 }) 51 t.Run("invalid_unicode", func(t *testing.T) { 52 testIteratorStr(t, `"\uG`, InvalidUnicodeCharError{}) 53 }) 54 t.Run("bytes", func(t *testing.T) { 55 t.Run("", func(t *testing.T) { 56 testIteratorStr(t, src, nil) 57 }) 58 t.Run("", func(t *testing.T) { 59 withIterator(src, func(it *Iterator) { 60 s, err := it.ReadString() 61 require.NoError(t, err) 62 require.Equal(t, origin, s) 63 }) 64 }) 65 }) 66 t.Run("reader", func(t *testing.T) { 67 withIterator("", func(it *Iterator) { 68 it.Reset(&stepByteReader{ 69 b: src, 70 }) 71 s, err := it.ReadString() 72 require.NoError(t, err) 73 require.Equal(t, origin, s) 74 }) 75 }) 76 } 77 78 func TestIterator_Str_readEscapedChar(t *testing.T) { 79 t.Run("eof", func(t *testing.T) { 80 testIteratorStr(t, `"\`, io.EOF) 81 }) 82 t.Run("control", func(t *testing.T) { 83 data := `"\n"` 84 t.Run("", func(t *testing.T) { 85 testIteratorStr(t, data, nil) 86 }) 87 t.Run("", func(t *testing.T) { 88 withIterator(data, func(it *Iterator) { 89 s, err := it.ReadString() 90 require.NoError(t, err) 91 require.Len(t, s, 1) 92 require.Equal(t, "\n", s) 93 }) 94 }) 95 }) 96 t.Run("invalid escape char", func(t *testing.T) { 97 testIteratorStr(t, `"\a"`, InvalidEscapeCharError{}) 98 }) 99 t.Run("unicode error 1", func(t *testing.T) { 100 testIteratorStr(t, `"\u0`, io.EOF) 101 }) 102 t.Run("surrogate err 1", func(t *testing.T) { 103 testIteratorStr(t, `"\ud800`, io.EOF) 104 }) 105 t.Run("surrogate incomplete", func(t *testing.T) { 106 data := `"\ud800"` 107 t.Run("", func(t *testing.T) { 108 testIteratorStr(t, data, nil) 109 }) 110 t.Run("", func(t *testing.T) { 111 withIterator(data, func(it *Iterator) { 112 s, err := it.ReadString() 113 require.NoError(t, err) 114 require.Equal(t, string(runeError), s) 115 }) 116 }) 117 }) 118 t.Run("surrogate err 2", func(t *testing.T) { 119 testIteratorStr(t, `"\ud800\`, io.EOF) 120 }) 121 t.Run("surrogate err 3", func(t *testing.T) { 122 testIteratorStr(t, `"\ud800\a`, InvalidEscapeCharError{}) 123 }) 124 t.Run("surrogate other escaped char", func(t *testing.T) { 125 data := `"\ud800\n"` 126 t.Run("", func(t *testing.T) { 127 testIteratorStr(t, data, nil) 128 }) 129 t.Run("", func(t *testing.T) { 130 withIterator(data, func(it *Iterator) { 131 s, err := it.ReadString() 132 require.NoError(t, err) 133 require.Equal(t, string(runeError)+"\n", s) 134 }) 135 }) 136 }) 137 t.Run("surrogate err 4", func(t *testing.T) { 138 testIteratorStr(t, `"\ud800\u`, io.EOF) 139 }) 140 t.Run("surrogate runeError", func(t *testing.T) { 141 data := `"\udc00\u0000"` 142 t.Run("", func(t *testing.T) { 143 testIteratorStr(t, data, nil) 144 }) 145 t.Run("", func(t *testing.T) { 146 withIterator(data, func(it *Iterator) { 147 s, err := it.ReadString() 148 require.NoError(t, err) 149 require.Equal(t, `"\ufffd\x00"`, fmt.Sprintf("%+q", s)) 150 }) 151 }) 152 }) 153 t.Run("surrogate", func(t *testing.T) { 154 data := `"\uD852\uDF62"` 155 t.Run("", func(t *testing.T) { 156 testIteratorStr(t, data, nil) 157 }) 158 t.Run("", func(t *testing.T) { 159 withIterator(data, func(it *Iterator) { 160 s, err := it.ReadString() 161 require.NoError(t, err) 162 require.Equal(t, "𤭢", s) 163 }) 164 }) 165 }) 166 t.Run("non surrogate", func(t *testing.T) { 167 s := `"\u4e2d"` // 中 168 t.Run("", func(t *testing.T) { 169 testIteratorStr(t, s, nil) 170 }) 171 t.Run("", func(t *testing.T) { 172 withIterator(s, func(it *Iterator) { 173 s, err := it.ReadString() 174 require.NoError(t, err) 175 require.Equal(t, "中", s) 176 }) 177 }) 178 }) 179 t.Run("surrogate consecutive", func(t *testing.T) { 180 data := `"\udc00\uD852\uDF62"` 181 t.Run("", func(t *testing.T) { 182 testIteratorStr(t, data, nil) 183 }) 184 withIterator(data, func(it *Iterator) { 185 s, err := it.ReadString() 186 require.NoError(t, err) 187 require.Equal(t, "\ufffd𤭢", s) 188 require.Equal(t, `"\ufffd\U00024b62"`, fmt.Sprintf("%+q", s)) 189 }) 190 }) 191 } 192 193 func TestIterator_Str_readStringAsSlice(t *testing.T) { 194 t.Run("reader error", func(t *testing.T) { 195 withIterator("", func(it *Iterator) { 196 e := errors.New("test") 197 it.Reset(&stepByteReader{ 198 err: e, 199 }) 200 _, err := it.ReadString() 201 require.Error(t, e, err) 202 }) 203 }) 204 t.Run("bad value type", func(t *testing.T) { 205 withIterator(`1`, func(it *Iterator) { 206 _, err := it.ReadString() 207 require.IsType(t, UnexpectedByteError{}, err) 208 }) 209 }) 210 t.Run("simple", func(t *testing.T) { 211 withIterator(`"abc123"`, func(it *Iterator) { 212 s, err := it.ReadString() 213 require.NoError(t, err) 214 require.Equal(t, "abc123", s) 215 _, err = it.NextValueType() 216 require.Equal(t, io.EOF, err) 217 }) 218 }) 219 t.Run("escape error", func(t *testing.T) { 220 withIterator(`"\`, func(it *Iterator) { 221 _, err := it.ReadString() 222 require.Equal(t, io.EOF, err) 223 }) 224 }) 225 t.Run("escape", func(t *testing.T) { 226 withIterator(`"\n"`, func(it *Iterator) { 227 s, err := it.ReadString() 228 require.NoError(t, err) 229 require.Equal(t, "\n", s) 230 }) 231 }) 232 t.Run("invalid string char", func(t *testing.T) { 233 withIterator("\"\x00\"", func(it *Iterator) { 234 _, err := it.ReadString() 235 require.IsType(t, InvalidStringCharError{}, err) 236 }) 237 }) 238 t.Run("reade err", func(t *testing.T) { 239 withIterator("", func(it *Iterator) { 240 it.Reset(&stepByteReader{ 241 b: `"\n`, 242 }) 243 _, err := it.ReadString() 244 require.Equal(t, io.EOF, err) 245 }) 246 }) 247 t.Run("reader", func(t *testing.T) { 248 withIterator("", func(it *Iterator) { 249 it.Reset(&stepByteReader{ 250 b: `"\n"`, 251 }) 252 s, err := it.ReadString() 253 require.NoError(t, err) 254 require.Len(t, s, 1) 255 require.Equal(t, "\n", s) 256 }) 257 }) 258 t.Run("reader 2", func(t *testing.T) { 259 withIterator("", func(it *Iterator) { 260 for step := 2; step < 6; step++ { 261 it.Reset(&stepByteReader{ 262 b: `"abc"`, 263 step: step, 264 }) 265 vt, err := it.NextValueType() 266 require.NoError(t, err) 267 require.Equal(t, StringValue, vt) 268 269 s, err := it.ReadString() 270 require.NoError(t, err) 271 require.Equal(t, "abc", s) 272 } 273 }) 274 }) 275 } 276 277 func TestIterator_Str_ReadStringAsSlice(t *testing.T) { 278 t.Run("not string", func(t *testing.T) { 279 withIterator("", func(it *Iterator) { 280 _, err := it.ReadStringAsSlice() 281 require.Equal(t, io.EOF, err) 282 }) 283 }) 284 t.Run("normal", func(t *testing.T) { 285 withIterator(`"abc"`, func(it *Iterator) { 286 ret, err := it.ReadStringAsSlice() 287 require.NoError(t, err) 288 require.Equal(t, []byte("abc"), ret) 289 }) 290 }) 291 } 292 293 func TestIterator_Str_ReadStringAndAppend(t *testing.T) { 294 t.Run("not string", func(t *testing.T) { 295 withIterator("", func(it *Iterator) { 296 _, err := it.ReadStringAndAppend(nil) 297 require.Equal(t, io.EOF, err) 298 }) 299 }) 300 t.Run("normal", func(t *testing.T) { 301 withIterator(`"abc"`, func(it *Iterator) { 302 buf := make([]byte, 0, 32) 303 ret, err := it.ReadStringAndAppend(buf) 304 require.NoError(t, err) 305 p1 := (*sliceHeader)(unsafe.Pointer(&buf)) 306 p2 := (*sliceHeader)(unsafe.Pointer(&ret)) 307 require.Equal(t, p1.Data, p2.Data) 308 require.Equal(t, p1.Cap, p2.Cap) 309 require.Equal(t, []byte("abc"), ret) 310 }) 311 }) 312 t.Run("error", func(t *testing.T) { 313 withIterator(`"`, func(it *Iterator) { 314 buf := make([]byte, 0, 32) 315 _, err := it.ReadStringAndAppend(buf) 316 require.Equal(t, io.EOF, err) 317 }) 318 }) 319 } 320 321 func TestIterator_Str_appendRune(t *testing.T) { 322 var b []byte 323 324 b = appendRune(b[:0], 0) 325 require.Equal(t, []byte{0}, b) 326 327 b = appendRune(b[:0], 1<<7) 328 require.Equal(t, []byte{0xc2, 0x80}, b) 329 330 b = appendRune(b[:0], maxRune+1) 331 require.Equal(t, []byte{0xef, 0xbf, 0xbd}, b) 332 333 b = appendRune(b[:0], surrogateMin) 334 require.Equal(t, []byte{0xef, 0xbf, 0xbd}, b) 335 336 b = appendRune(b[:0], surrogateMax) 337 require.Equal(t, []byte{0xef, 0xbf, 0xbd}, b) 338 339 b = appendRune(b[:0], rune3Max) 340 require.Equal(t, []byte{0xef, 0xbf, 0xbf}, b) 341 342 b = appendRune(b[:0], rune3Max+1) 343 require.Equal(t, []byte{0xf0, 0x90, 0x80, 0x80}, b) 344 }