1
2
3
4
5 package json
6
7 import (
8 "math"
9 "reflect"
10 "testing"
11 )
12
13 func TestTokenStringAllocations(t *testing.T) {
14 if testing.CoverMode() != "" {
15 t.Skip("coverage mode breaks the compiler optimization this depends on")
16 }
17
18 tok := rawToken(`"hello"`)
19 var m map[string]bool
20 got := int(testing.AllocsPerRun(10, func() {
21
22
23 if m[tok.String()] {
24 panic("never executed")
25 }
26 }))
27 if got > 0 {
28 t.Errorf("Token.String allocated %d times, want 0", got)
29 }
30 }
31
32 func TestTokenAccessors(t *testing.T) {
33 type token struct {
34 Bool bool
35 String string
36 Float float64
37 Int int64
38 Uint uint64
39 Kind Kind
40 }
41
42 tests := []struct {
43 in Token
44 want token
45 }{
46 {Token{}, token{String: "<invalid json.Token>"}},
47 {Null, token{String: "null", Kind: 'n'}},
48 {False, token{Bool: false, String: "false", Kind: 'f'}},
49 {True, token{Bool: true, String: "true", Kind: 't'}},
50 {Bool(false), token{Bool: false, String: "false", Kind: 'f'}},
51 {Bool(true), token{Bool: true, String: "true", Kind: 't'}},
52 {ObjectStart, token{String: "{", Kind: '{'}},
53 {ObjectEnd, token{String: "}", Kind: '}'}},
54 {ArrayStart, token{String: "[", Kind: '['}},
55 {ArrayEnd, token{String: "]", Kind: ']'}},
56 {String(""), token{String: "", Kind: '"'}},
57 {String("hello, world!"), token{String: "hello, world!", Kind: '"'}},
58 {rawToken(`"hello, world!"`), token{String: "hello, world!", Kind: '"'}},
59 {Float(0), token{String: "0", Float: 0, Int: 0, Uint: 0, Kind: '0'}},
60 {Float(math.Copysign(0, -1)), token{String: "-0", Float: math.Copysign(0, -1), Int: 0, Uint: 0, Kind: '0'}},
61 {Float(math.NaN()), token{String: "NaN", Float: math.NaN(), Int: 0, Uint: 0, Kind: '"'}},
62 {Float(math.Inf(+1)), token{String: "Infinity", Float: math.Inf(+1), Kind: '"'}},
63 {Float(math.Inf(-1)), token{String: "-Infinity", Float: math.Inf(-1), Kind: '"'}},
64 {Int(minInt64), token{String: "-9223372036854775808", Float: minInt64, Int: minInt64, Uint: minUint64, Kind: '0'}},
65 {Int(minInt64 + 1), token{String: "-9223372036854775807", Float: minInt64 + 1, Int: minInt64 + 1, Uint: minUint64, Kind: '0'}},
66 {Int(-1), token{String: "-1", Float: -1, Int: -1, Uint: minUint64, Kind: '0'}},
67 {Int(0), token{String: "0", Float: 0, Int: 0, Uint: 0, Kind: '0'}},
68 {Int(+1), token{String: "1", Float: +1, Int: +1, Uint: +1, Kind: '0'}},
69 {Int(maxInt64 - 1), token{String: "9223372036854775806", Float: maxInt64 - 1, Int: maxInt64 - 1, Uint: maxInt64 - 1, Kind: '0'}},
70 {Int(maxInt64), token{String: "9223372036854775807", Float: maxInt64, Int: maxInt64, Uint: maxInt64, Kind: '0'}},
71 {Uint(minUint64), token{String: "0", Kind: '0'}},
72 {Uint(minUint64 + 1), token{String: "1", Float: minUint64 + 1, Int: minUint64 + 1, Uint: minUint64 + 1, Kind: '0'}},
73 {Uint(maxUint64 - 1), token{String: "18446744073709551614", Float: maxUint64 - 1, Int: maxInt64, Uint: maxUint64 - 1, Kind: '0'}},
74 {Uint(maxUint64), token{String: "18446744073709551615", Float: maxUint64, Int: maxInt64, Uint: maxUint64, Kind: '0'}},
75 {rawToken(`-0`), token{String: "-0", Float: math.Copysign(0, -1), Int: 0, Uint: 0, Kind: '0'}},
76 {rawToken(`1e1000`), token{String: "1e1000", Float: math.MaxFloat64, Int: maxInt64, Uint: maxUint64, Kind: '0'}},
77 {rawToken(`-1e1000`), token{String: "-1e1000", Float: -math.MaxFloat64, Int: minInt64, Uint: minUint64, Kind: '0'}},
78 {rawToken(`0.1`), token{String: "0.1", Float: 0.1, Int: 0, Uint: 0, Kind: '0'}},
79 {rawToken(`0.5`), token{String: "0.5", Float: 0.5, Int: 0, Uint: 0, Kind: '0'}},
80 {rawToken(`0.9`), token{String: "0.9", Float: 0.9, Int: 0, Uint: 0, Kind: '0'}},
81 {rawToken(`1.1`), token{String: "1.1", Float: 1.1, Int: 1, Uint: 1, Kind: '0'}},
82 {rawToken(`-0.1`), token{String: "-0.1", Float: -0.1, Int: 0, Uint: 0, Kind: '0'}},
83 {rawToken(`-0.5`), token{String: "-0.5", Float: -0.5, Int: 0, Uint: 0, Kind: '0'}},
84 {rawToken(`-0.9`), token{String: "-0.9", Float: -0.9, Int: 0, Uint: 0, Kind: '0'}},
85 {rawToken(`-1.1`), token{String: "-1.1", Float: -1.1, Int: -1, Uint: 0, Kind: '0'}},
86 {rawToken(`99999999999999999999`), token{String: "99999999999999999999", Float: 1e20 - 1, Int: maxInt64, Uint: maxUint64, Kind: '0'}},
87 {rawToken(`-99999999999999999999`), token{String: "-99999999999999999999", Float: -1e20 - 1, Int: minInt64, Uint: minUint64, Kind: '0'}},
88 }
89
90 for _, tt := range tests {
91 t.Run("", func(t *testing.T) {
92 got := token{
93 Bool: func() bool {
94 defer func() { recover() }()
95 return tt.in.Bool()
96 }(),
97 String: tt.in.String(),
98 Float: func() float64 {
99 defer func() { recover() }()
100 return tt.in.Float()
101 }(),
102 Int: func() int64 {
103 defer func() { recover() }()
104 return tt.in.Int()
105 }(),
106 Uint: func() uint64 {
107 defer func() { recover() }()
108 return tt.in.Uint()
109 }(),
110 Kind: tt.in.Kind(),
111 }
112
113 if got.Bool != tt.want.Bool {
114 t.Errorf("Token(%s).Bool() = %v, want %v", tt.in, got.Bool, tt.want.Bool)
115 }
116 if got.String != tt.want.String {
117 t.Errorf("Token(%s).String() = %v, want %v", tt.in, got.String, tt.want.String)
118 }
119 if math.Float64bits(got.Float) != math.Float64bits(tt.want.Float) {
120 t.Errorf("Token(%s).Float() = %v, want %v", tt.in, got.Float, tt.want.Float)
121 }
122 if got.Int != tt.want.Int {
123 t.Errorf("Token(%s).Int() = %v, want %v", tt.in, got.Int, tt.want.Int)
124 }
125 if got.Uint != tt.want.Uint {
126 t.Errorf("Token(%s).Uint() = %v, want %v", tt.in, got.Uint, tt.want.Uint)
127 }
128 if got.Kind != tt.want.Kind {
129 t.Errorf("Token(%s).Kind() = %v, want %v", tt.in, got.Kind, tt.want.Kind)
130 }
131 })
132 }
133 }
134
135 func TestTokenClone(t *testing.T) {
136 tests := []struct {
137 in Token
138 wantExactRaw bool
139 }{
140 {Token{}, true},
141 {Null, true},
142 {False, true},
143 {True, true},
144 {ObjectStart, true},
145 {ObjectEnd, true},
146 {ArrayStart, true},
147 {ArrayEnd, true},
148 {String("hello, world!"), true},
149 {rawToken(`"hello, world!"`), false},
150 {Float(3.14159), true},
151 {rawToken(`3.14159`), false},
152 }
153
154 for _, tt := range tests {
155 t.Run("", func(t *testing.T) {
156 got := tt.in.Clone()
157 if !reflect.DeepEqual(got, tt.in) {
158 t.Errorf("Token(%s) == Token(%s).Clone() = false, want true", tt.in, tt.in)
159 }
160 gotExactRaw := got.raw == tt.in.raw
161 if gotExactRaw != tt.wantExactRaw {
162 t.Errorf("Token(%s).raw == Token(%s).Clone().raw = %v, want %v", tt.in, tt.in, gotExactRaw, tt.wantExactRaw)
163 }
164 })
165 }
166 }
167
View as plain text