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