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  }