1package json
2
3import (
4	"testing"
5	"unicode"
6)
7
8var enc = Encoder{}
9
10func TestAppendBytes(t *testing.T) {
11	for _, tt := range encodeStringTests {
12		b := enc.AppendBytes([]byte{}, []byte(tt.in))
13		if got, want := string(b), tt.out; got != want {
14			t.Errorf("appendBytes(%q) = %#q, want %#q", tt.in, got, want)
15		}
16	}
17}
18
19func TestAppendHex(t *testing.T) {
20	for _, tt := range encodeHexTests {
21		b := enc.AppendHex([]byte{}, []byte{tt.in})
22		if got, want := string(b), tt.out; got != want {
23			t.Errorf("appendHex(%x) = %s, want %s", tt.in, got, want)
24		}
25	}
26}
27
28func TestStringBytes(t *testing.T) {
29	t.Parallel()
30	// Test that encodeState.stringBytes and encodeState.string use the same encoding.
31	var r []rune
32	for i := '\u0000'; i <= unicode.MaxRune; i++ {
33		r = append(r, i)
34	}
35	s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
36
37	encStr := string(enc.AppendString([]byte{}, s))
38	encBytes := string(enc.AppendBytes([]byte{}, []byte(s)))
39
40	if encStr != encBytes {
41		i := 0
42		for i < len(encStr) && i < len(encBytes) && encStr[i] == encBytes[i] {
43			i++
44		}
45		encStr = encStr[i:]
46		encBytes = encBytes[i:]
47		i = 0
48		for i < len(encStr) && i < len(encBytes) && encStr[len(encStr)-i-1] == encBytes[len(encBytes)-i-1] {
49			i++
50		}
51		encStr = encStr[:len(encStr)-i]
52		encBytes = encBytes[:len(encBytes)-i]
53
54		if len(encStr) > 20 {
55			encStr = encStr[:20] + "..."
56		}
57		if len(encBytes) > 20 {
58			encBytes = encBytes[:20] + "..."
59		}
60
61		t.Errorf("encodings differ at %#q vs %#q", encStr, encBytes)
62	}
63}
64
65func BenchmarkAppendBytes(b *testing.B) {
66	tests := map[string]string{
67		"NoEncoding":       `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
68		"EncodingFirst":    `"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
69		"EncodingMiddle":   `aaaaaaaaaaaaaaaaaaaaaaaaa"aaaaaaaaaaaaaaaaaaaaaaaa`,
70		"EncodingLast":     `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
71		"MultiBytesFirst":  `❤️aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
72		"MultiBytesMiddle": `aaaaaaaaaaaaaaaaaaaaaaaaa❤️aaaaaaaaaaaaaaaaaaaaaaaa`,
73		"MultiBytesLast":   `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa❤️`,
74	}
75	for name, str := range tests {
76		byt := []byte(str)
77		b.Run(name, func(b *testing.B) {
78			buf := make([]byte, 0, 100)
79			for i := 0; i < b.N; i++ {
80				_ = enc.AppendBytes(buf, byt)
81			}
82		})
83	}
84}
85