1
2
3
4
5
6
7 package jsonopts_test
8
9 import (
10 "reflect"
11 "testing"
12
13 "encoding/json/internal/jsonflags"
14 . "encoding/json/internal/jsonopts"
15 "encoding/json/jsontext"
16 "encoding/json/v2"
17 )
18
19 func makeFlags(f ...jsonflags.Bools) (fs jsonflags.Flags) {
20 for _, f := range f {
21 fs.Set(f)
22 }
23 return fs
24 }
25
26 func TestJoin(t *testing.T) {
27 tests := []struct {
28 in Options
29 excludeCoders bool
30 want *Struct
31 }{{
32 in: jsonflags.AllowInvalidUTF8 | 1,
33 want: &Struct{Flags: makeFlags(jsonflags.AllowInvalidUTF8 | 1)},
34 }, {
35 in: jsonflags.Multiline | 0,
36 want: &Struct{
37 Flags: makeFlags(jsonflags.AllowInvalidUTF8|1, jsonflags.Multiline|0)},
38 }, {
39 in: Indent("\t"),
40 want: &Struct{
41 Flags: makeFlags(jsonflags.AllowInvalidUTF8 | jsonflags.Multiline | jsonflags.Indent | 1),
42 CoderValues: CoderValues{Indent: "\t"},
43 },
44 }, {
45 in: &Struct{
46 Flags: makeFlags(jsonflags.Multiline|jsonflags.EscapeForJS|0, jsonflags.AllowInvalidUTF8|1),
47 },
48 want: &Struct{
49 Flags: makeFlags(jsonflags.AllowInvalidUTF8|jsonflags.Indent|1, jsonflags.Multiline|jsonflags.EscapeForJS|0),
50 CoderValues: CoderValues{Indent: "\t"},
51 },
52 }, {
53 in: &DefaultOptionsV1,
54 want: func() *Struct {
55 v1 := DefaultOptionsV1
56 v1.Flags.Set(jsonflags.Indent | 1)
57 v1.Flags.Set(jsonflags.Multiline | 0)
58 v1.Indent = "\t"
59 return &v1
60 }(),
61 }, {
62 in: &DefaultOptionsV2,
63 want: func() *Struct {
64 v2 := DefaultOptionsV2
65 v2.Flags.Set(jsonflags.Indent | 1)
66 v2.Flags.Set(jsonflags.Multiline | 0)
67 v2.Indent = "\t"
68 return &v2
69 }(),
70 }, {
71 in: jsonflags.Deterministic | jsonflags.AllowInvalidUTF8 | 1, excludeCoders: true,
72 want: func() *Struct {
73 v2 := DefaultOptionsV2
74 v2.Flags.Set(jsonflags.Deterministic | 1)
75 v2.Flags.Set(jsonflags.Indent | 1)
76 v2.Flags.Set(jsonflags.Multiline | 0)
77 v2.Indent = "\t"
78 return &v2
79 }(),
80 }, {
81 in: jsontext.WithIndentPrefix(" "), excludeCoders: true,
82 want: func() *Struct {
83 v2 := DefaultOptionsV2
84 v2.Flags.Set(jsonflags.Deterministic | 1)
85 v2.Flags.Set(jsonflags.Indent | 1)
86 v2.Flags.Set(jsonflags.Multiline | 0)
87 v2.Indent = "\t"
88 return &v2
89 }(),
90 }, {
91 in: jsontext.WithIndentPrefix(" "), excludeCoders: false,
92 want: func() *Struct {
93 v2 := DefaultOptionsV2
94 v2.Flags.Set(jsonflags.Deterministic | 1)
95 v2.Flags.Set(jsonflags.Indent | 1)
96 v2.Flags.Set(jsonflags.IndentPrefix | 1)
97 v2.Flags.Set(jsonflags.Multiline | 1)
98 v2.Indent = "\t"
99 v2.IndentPrefix = " "
100 return &v2
101 }(),
102 }, {
103 in: &Struct{
104 Flags: jsonflags.Flags{
105 Presence: uint64(jsonflags.Deterministic | jsonflags.Indent | jsonflags.IndentPrefix),
106 Values: uint64(jsonflags.Indent | jsonflags.IndentPrefix),
107 },
108 CoderValues: CoderValues{Indent: " ", IndentPrefix: " "},
109 },
110 excludeCoders: true,
111 want: func() *Struct {
112 v2 := DefaultOptionsV2
113 v2.Flags.Set(jsonflags.Indent | 1)
114 v2.Flags.Set(jsonflags.IndentPrefix | 1)
115 v2.Flags.Set(jsonflags.Multiline | 1)
116 v2.Indent = "\t"
117 v2.IndentPrefix = " "
118 return &v2
119 }(),
120 }, {
121 in: &Struct{
122 Flags: jsonflags.Flags{
123 Presence: uint64(jsonflags.Deterministic | jsonflags.Indent | jsonflags.IndentPrefix),
124 Values: uint64(jsonflags.Indent | jsonflags.IndentPrefix),
125 },
126 CoderValues: CoderValues{Indent: " ", IndentPrefix: " "},
127 },
128 excludeCoders: false,
129 want: func() *Struct {
130 v2 := DefaultOptionsV2
131 v2.Flags.Set(jsonflags.Indent | 1)
132 v2.Flags.Set(jsonflags.IndentPrefix | 1)
133 v2.Flags.Set(jsonflags.Multiline | 1)
134 v2.Indent = " "
135 v2.IndentPrefix = " "
136 return &v2
137 }(),
138 }}
139 got := new(Struct)
140 for i, tt := range tests {
141 if tt.excludeCoders {
142 got.JoinWithoutCoderOptions(tt.in)
143 } else {
144 got.Join(tt.in)
145 }
146 if !reflect.DeepEqual(got, tt.want) {
147 t.Fatalf("%d: Join:\n\tgot: %+v\n\twant: %+v", i, got, tt.want)
148 }
149 }
150 }
151
152 func TestGet(t *testing.T) {
153 opts := &Struct{
154 Flags: makeFlags(jsonflags.Indent|jsonflags.Deterministic|jsonflags.Marshalers|1, jsonflags.Multiline|0),
155 CoderValues: CoderValues{Indent: "\t"},
156 ArshalValues: ArshalValues{Marshalers: new(json.Marshalers)},
157 }
158 if v, ok := json.GetOption(nil, jsontext.AllowDuplicateNames); v || ok {
159 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (false, false)", v, ok)
160 }
161 if v, ok := json.GetOption(jsonflags.AllowInvalidUTF8|0, jsontext.AllowDuplicateNames); v || ok {
162 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (false, false)", v, ok)
163 }
164 if v, ok := json.GetOption(jsonflags.AllowDuplicateNames|0, jsontext.AllowDuplicateNames); v || !ok {
165 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (false, true)", v, ok)
166 }
167 if v, ok := json.GetOption(jsonflags.AllowDuplicateNames|1, jsontext.AllowDuplicateNames); !v || !ok {
168 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (true, true)", v, ok)
169 }
170 if v, ok := json.GetOption(Indent(""), jsontext.AllowDuplicateNames); v || ok {
171 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (false, false)", v, ok)
172 }
173 if v, ok := json.GetOption(Indent(" "), jsontext.WithIndent); v != " " || !ok {
174 t.Errorf(`GetOption(..., WithIndent) = (%q, %v), want (" ", true)`, v, ok)
175 }
176 if v, ok := json.GetOption(jsonflags.AllowDuplicateNames|1, jsontext.WithIndent); v != "" || ok {
177 t.Errorf(`GetOption(..., WithIndent) = (%q, %v), want ("", false)`, v, ok)
178 }
179 if v, ok := json.GetOption(opts, jsontext.AllowDuplicateNames); v || ok {
180 t.Errorf("GetOption(..., AllowDuplicateNames) = (%v, %v), want (false, false)", v, ok)
181 }
182 if v, ok := json.GetOption(opts, json.Deterministic); !v || !ok {
183 t.Errorf("GetOption(..., Deterministic) = (%v, %v), want (true, true)", v, ok)
184 }
185 if v, ok := json.GetOption(opts, jsontext.Multiline); v || !ok {
186 t.Errorf("GetOption(..., Multiline) = (%v, %v), want (false, true)", v, ok)
187 }
188 if v, ok := json.GetOption(opts, jsontext.AllowInvalidUTF8); v || ok {
189 t.Errorf("GetOption(..., AllowInvalidUTF8) = (%v, %v), want (false, false)", v, ok)
190 }
191 if v, ok := json.GetOption(opts, jsontext.WithIndent); v != "\t" || !ok {
192 t.Errorf(`GetOption(..., WithIndent) = (%q, %v), want ("\t", true)`, v, ok)
193 }
194 if v, ok := json.GetOption(opts, jsontext.WithIndentPrefix); v != "" || ok {
195 t.Errorf(`GetOption(..., WithIndentPrefix) = (%q, %v), want ("", false)`, v, ok)
196 }
197 if v, ok := json.GetOption(opts, json.WithMarshalers); v == nil || !ok {
198 t.Errorf(`GetOption(..., WithMarshalers) = (%v, %v), want (non-nil, true)`, v, ok)
199 }
200 if v, ok := json.GetOption(opts, json.WithUnmarshalers); v != nil || ok {
201 t.Errorf(`GetOption(..., WithUnmarshalers) = (%v, %v), want (nil, false)`, v, ok)
202 }
203 }
204
205 var sink struct {
206 Bool bool
207 String string
208 Marshalers *json.Marshalers
209 }
210
211 func BenchmarkGetBool(b *testing.B) {
212 b.ReportAllocs()
213 opts := json.DefaultOptionsV2()
214 for range b.N {
215 sink.Bool, sink.Bool = json.GetOption(opts, jsontext.AllowDuplicateNames)
216 }
217 }
218
219 func BenchmarkGetIndent(b *testing.B) {
220 b.ReportAllocs()
221 opts := json.DefaultOptionsV2()
222 for range b.N {
223 sink.String, sink.Bool = json.GetOption(opts, jsontext.WithIndent)
224 }
225 }
226
227 func BenchmarkGetMarshalers(b *testing.B) {
228 b.ReportAllocs()
229 opts := json.JoinOptions(json.DefaultOptionsV2(), json.WithMarshalers(nil))
230 for range b.N {
231 sink.Marshalers, sink.Bool = json.GetOption(opts, json.WithMarshalers)
232 }
233 }
234
View as plain text