1 package ldvalue
2
3 import (
4 "encoding/json"
5 "fmt"
6 "testing"
7
8 "github.com/launchdarkly/go-jsonstream/v3/jreader"
9 "github.com/launchdarkly/go-jsonstream/v3/jwriter"
10
11 "github.com/stretchr/testify/assert"
12 )
13
14 type structWithOptionalBools struct {
15 B1 OptionalBool `json:"b1"`
16 B2 OptionalBool `json:"b2"`
17 B3 OptionalBool `json:"b3"`
18 }
19
20 type structWithOptionalInts struct {
21 N1 OptionalInt `json:"n1"`
22 N2 OptionalInt `json:"n2"`
23 N3 OptionalInt `json:"n3"`
24 }
25
26 type structWithOptionalStrings struct {
27 S1 OptionalString `json:"s1"`
28 S2 OptionalString `json:"s2"`
29 S3 OptionalString `json:"s3"`
30 }
31
32 func TestOptionalBoolJSONMarshalling(t *testing.T) {
33 testWithMarshaler := func(t *testing.T, marshal func(OptionalBool) ([]byte, error)) {
34 bytes, err := marshal(OptionalBool{})
35 assert.NoError(t, err)
36 assert.Equal(t, nullAsJSON, string(bytes))
37
38 bytes, err = marshal(NewOptionalBool(true))
39 assert.NoError(t, err)
40 assert.Equal(t, `true`, string(bytes))
41
42 bytes, err = marshal(NewOptionalBool(false))
43 assert.NoError(t, err)
44 assert.Equal(t, `false`, string(bytes))
45 }
46
47 t.Run("with json.Marshal", func(t *testing.T) {
48 testWithMarshaler(t, func(o OptionalBool) ([]byte, error) {
49 return json.Marshal(o)
50 })
51
52 swos := structWithOptionalBools{B1: NewOptionalBool(true), B2: NewOptionalBool(false)}
53 bytes, err := json.Marshal(swos)
54 assert.NoError(t, err)
55 assert.Equal(t, `{"b1":true,"b2":false,"b3":null}`, string(bytes))
56 })
57
58 t.Run("with WriteToJSONWriter", func(t *testing.T) {
59 testWithMarshaler(t, func(o OptionalBool) ([]byte, error) {
60 w := jwriter.NewWriter()
61 o.WriteToJSONWriter(&w)
62 return w.Bytes(), w.Error()
63 })
64 })
65 }
66
67 func TestOptionalIntJSONMarshalling(t *testing.T) {
68 testWithMarshaler := func(t *testing.T, marshal func(OptionalInt) ([]byte, error)) {
69 bytes, err := marshal(OptionalInt{})
70 assert.NoError(t, err)
71 assert.Equal(t, nullAsJSON, string(bytes))
72
73 bytes, err = marshal(NewOptionalInt(3))
74 assert.NoError(t, err)
75 assert.Equal(t, `3`, string(bytes))
76 }
77
78 t.Run("with json.Marshal", func(t *testing.T) {
79 testWithMarshaler(t, func(o OptionalInt) ([]byte, error) {
80 return json.Marshal(o)
81 })
82
83 swos := structWithOptionalInts{N1: NewOptionalInt(3)}
84 bytes, err := json.Marshal(swos)
85 assert.NoError(t, err)
86 assert.Equal(t, `{"n1":3,"n2":null,"n3":null}`, string(bytes))
87 })
88
89 t.Run("with WriteToJSONWriter", func(t *testing.T) {
90 testWithMarshaler(t, func(o OptionalInt) ([]byte, error) {
91 w := jwriter.NewWriter()
92 o.WriteToJSONWriter(&w)
93 return w.Bytes(), w.Error()
94 })
95 })
96 }
97
98 func TestOptionalStringJSONMarshalling(t *testing.T) {
99 testWithMarshaler := func(t *testing.T, marshal func(OptionalString) ([]byte, error)) {
100 bytes, err := marshal(OptionalString{})
101 assert.NoError(t, err)
102 assert.Equal(t, nullAsJSON, string(bytes))
103
104 bytes, err = marshal(NewOptionalString(`a "good" string`))
105 assert.NoError(t, err)
106 assert.Equal(t, `"a \"good\" string"`, string(bytes))
107 }
108
109 t.Run("with json.Marshal", func(t *testing.T) {
110 testWithMarshaler(t, func(o OptionalString) ([]byte, error) {
111 return json.Marshal(o)
112 })
113
114 swos := structWithOptionalStrings{S1: NewOptionalString("yes")}
115 bytes, err := json.Marshal(swos)
116 assert.NoError(t, err)
117 assert.Equal(t, `{"s1":"yes","s2":null,"s3":null}`, string(bytes))
118 })
119
120 t.Run("with WriteToJSONWriter", func(t *testing.T) {
121 testWithMarshaler(t, func(o OptionalString) ([]byte, error) {
122 w := jwriter.NewWriter()
123 o.WriteToJSONWriter(&w)
124 return w.Bytes(), w.Error()
125 })
126 })
127 }
128
129 func TestOptionalBoolJSONUnmarshalling(t *testing.T) {
130 testWithUnmarshaler := func(t *testing.T, unmarshal func([]byte, *OptionalBool) error) {
131 var o OptionalBool
132 err := unmarshal([]byte(nullAsJSON), &o)
133 assert.NoError(t, err)
134 assert.False(t, o.IsDefined())
135
136 err = unmarshal([]byte(`true`), &o)
137 assert.NoError(t, err)
138 assert.Equal(t, NewOptionalBool(true), o)
139
140 err = unmarshal([]byte(`false`), &o)
141 assert.NoError(t, err)
142 assert.Equal(t, NewOptionalBool(false), o)
143
144 err = unmarshal([]byte(`3`), &o)
145 assert.Error(t, err)
146 assert.IsType(t, &json.UnmarshalTypeError{}, err)
147
148 err = unmarshal([]byte(`x`), &o)
149 assert.Error(t, err)
150 assert.IsType(t, &json.SyntaxError{}, err)
151 }
152
153 t.Run("with json.Unmarshal", func(t *testing.T) {
154 testWithUnmarshaler(t, func(data []byte, o *OptionalBool) error {
155 return json.Unmarshal(data, o)
156 })
157
158 var swos structWithOptionalBools
159 err := json.Unmarshal([]byte(`{"b1":true,"b2":false,"b3":null}`), &swos)
160 assert.NoError(t, err)
161 assert.Equal(t, NewOptionalBool(true), swos.B1)
162 assert.Equal(t, NewOptionalBool(false), swos.B2)
163 assert.Equal(t, OptionalBool{}, swos.B3)
164 })
165
166 t.Run("with ReadFromJSONReader", func(t *testing.T) {
167 testWithUnmarshaler(t, func(data []byte, o *OptionalBool) error {
168 r := jreader.NewReader(data)
169 o.ReadFromJSONReader(&r)
170 return jreader.ToJSONError(r.Error(), o)
171 })
172 })
173 }
174
175 func TestOptionalIntJSONUnmarshalling(t *testing.T) {
176 var o OptionalInt
177 err := json.Unmarshal([]byte(nullAsJSON), &o)
178 assert.NoError(t, err)
179 assert.False(t, o.IsDefined())
180
181 err = json.Unmarshal([]byte(`3`), &o)
182 assert.NoError(t, err)
183 assert.Equal(t, NewOptionalInt(3), o)
184
185 err = json.Unmarshal([]byte(`true`), &o)
186 assert.Error(t, err)
187 assert.IsType(t, &json.UnmarshalTypeError{}, err)
188
189 err = json.Unmarshal([]byte(`x`), &o)
190 assert.Error(t, err)
191 assert.IsType(t, &json.SyntaxError{}, err)
192
193 var swos structWithOptionalInts
194 err = json.Unmarshal([]byte(`{"n1":3,"n3":null}`), &swos)
195 assert.NoError(t, err)
196 assert.Equal(t, NewOptionalInt(3), swos.N1)
197 assert.Equal(t, OptionalInt{}, swos.N2)
198 assert.Equal(t, OptionalInt{}, swos.N3)
199 }
200
201 func TestOptionalStringJSONUnmarshalling(t *testing.T) {
202 var o OptionalString
203 err := json.Unmarshal([]byte(nullAsJSON), &o)
204 assert.NoError(t, err)
205 assert.False(t, o.IsDefined())
206
207 err = json.Unmarshal([]byte(`"a \"good\" string"`), &o)
208 assert.NoError(t, err)
209 assert.True(t, o.IsDefined())
210 assert.Equal(t, `a "good" string`, o.StringValue())
211
212 err = json.Unmarshal([]byte("3"), &o)
213 assert.Error(t, err)
214 assert.IsType(t, &json.UnmarshalTypeError{}, err)
215
216 var swos structWithOptionalStrings
217 err = json.Unmarshal([]byte(`{"s1":"yes","s3":null}`), &swos)
218 assert.NoError(t, err)
219 assert.Equal(t, NewOptionalString("yes"), swos.S1)
220 assert.Equal(t, OptionalString{}, swos.S2)
221 assert.Equal(t, OptionalString{}, swos.S3)
222 }
223
224 func TestOptionalsJSONString(t *testing.T) {
225 for _, v := range []JSONStringer{
226 OptionalBool{},
227 NewOptionalBool(true),
228 NewOptionalBool(false),
229 OptionalInt{},
230 NewOptionalInt(1),
231 OptionalString{},
232 NewOptionalString(""),
233 NewOptionalString("a"),
234 } {
235 t.Run(fmt.Sprintf("%+v", v), func(t *testing.T) {
236 jsonBytes, _ := json.Marshal(v)
237 assert.Equal(t, string(jsonBytes), v.JSONString())
238 })
239 }
240 }
241
View as plain text