encode_array_test.go (10417B)
1 package gojay 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 type TestEncodingArrStrings []string 11 12 func (t TestEncodingArrStrings) MarshalJSONArray(enc *Encoder) { 13 for _, e := range t { 14 enc.AddString(e) 15 } 16 } 17 func (t TestEncodingArrStrings) IsNil() bool { 18 return len(t) == 0 19 } 20 21 type TestEncodingArr []*TestEncoding 22 23 func (t TestEncodingArr) MarshalJSONArray(enc *Encoder) { 24 for _, e := range t { 25 enc.AddObject(e) 26 } 27 } 28 func (t TestEncodingArr) IsNil() bool { 29 return t == nil 30 } 31 32 type testEncodingArrInterfaces []interface{} 33 34 func (t testEncodingArrInterfaces) MarshalJSONArray(enc *Encoder) { 35 for _, e := range t { 36 enc.AddInterface(e) 37 } 38 } 39 func (t testEncodingArrInterfaces) IsNil() bool { 40 return t == nil 41 } 42 43 func TestEncoderArrayMarshalAPI(t *testing.T) { 44 t.Run("array-objects", func(t *testing.T) { 45 v := &TestEncodingArr{ 46 &TestEncoding{ 47 test: "hello world", 48 test2: "漢字", 49 testInt: 1, 50 testBool: true, 51 testInterface: 1, 52 sub: &SubObject{ 53 test1: 10, 54 test2: "hello world", 55 test3: 1.23543, 56 testBool: true, 57 sub: &SubObject{ 58 test1: 10, 59 testBool: false, 60 test2: "hello world", 61 }, 62 }, 63 }, 64 &TestEncoding{ 65 test: "hello world", 66 test2: "漢字", 67 testInt: 1, 68 testBool: true, 69 sub: &SubObject{ 70 test1: 10, 71 test2: "hello world", 72 test3: 1.23543, 73 testBool: true, 74 sub: &SubObject{ 75 test1: 10, 76 testBool: false, 77 test2: "hello world", 78 }, 79 }, 80 }, 81 nil, 82 } 83 r, err := Marshal(v) 84 assert.Nil(t, err, "Error should be nil") 85 assert.Equal( 86 t, 87 `[{"test":"hello world","test2":"漢字","testInt":1,"testBool":true,`+ 88 `"testArr":[],"testF64":0,"testF32":0,"testInterface":1,"sub":{"test1":10,"test2":"hello world",`+ 89 `"test3":1.23543,"testBool":true,"sub":{"test1":10,"test2":"hello world",`+ 90 `"test3":0,"testBool":false,"sub":{}}}},{"test":"hello world","test2":"漢字","testInt":1,`+ 91 `"testBool":true,"testArr":[],"testF64":0,"testF32":0,"sub":{"test1":10,"test2":"hello world","test3":1.23543,`+ 92 `"testBool":true,"sub":{"test1":10,"test2":"hello world","test3":0,"testBool":false,"sub":{}}}},{}]`, 93 string(r), 94 "Result of marshalling is different as the one expected") 95 }) 96 t.Run("array-interfaces", func(t *testing.T) { 97 v := &testEncodingArrInterfaces{ 98 1, 99 int64(1), 100 int32(1), 101 int16(1), 102 int8(1), 103 uint64(1), 104 uint32(1), 105 uint16(1), 106 uint8(1), 107 float64(1.31), 108 float32(1.31), 109 &TestEncodingArr{}, 110 &TestEncodingArrStrings{}, 111 true, 112 false, 113 "test", 114 &TestEncoding{ 115 test: "hello world", 116 test2: "foobar", 117 testInt: 1, 118 testBool: true, 119 }, 120 } 121 r, err := MarshalJSONArray(v) 122 assert.Nil(t, err, "Error should be nil") 123 assert.Equal( 124 t, 125 `[1,1,1,1,1,1,1,1,1.31,1.31,[],[],true,false,"test",{"test":"hello world","test2":"foobar","testInt":1,"testBool":true,"testArr":[],"testF64":0,"testF32":0,"sub":{}}]`, 126 string(r), 127 "Result of marshalling is different as the one expected") 128 }) 129 } 130 131 func TestEncoderArrayEncodeAPI(t *testing.T) { 132 t.Run("array-interfaces", func(t *testing.T) { 133 v := &testEncodingArrInterfaces{ 134 1, 135 int64(1), 136 int32(1), 137 int16(1), 138 int8(1), 139 uint64(1), 140 uint32(1), 141 uint16(1), 142 uint8(1), 143 float64(1.31), 144 // float32(1.31), 145 &TestEncodingArr{}, 146 true, 147 "test", 148 &TestEncoding{ 149 test: "hello world", 150 test2: "foobar", 151 testInt: 1, 152 testBool: true, 153 }, 154 } 155 builder := &strings.Builder{} 156 enc := BorrowEncoder(builder) 157 defer enc.Release() 158 err := enc.EncodeArray(v) 159 assert.Nil(t, err, "Error should be nil") 160 assert.Equal( 161 t, 162 `[1,1,1,1,1,1,1,1,1.31,[],true,"test",{"test":"hello world","test2":"foobar","testInt":1,"testBool":true,"testArr":[],"testF64":0,"testF32":0,"sub":{}}]`, 163 builder.String(), 164 "Result of marshalling is different as the one expected") 165 }) 166 167 t.Run("array-interfaces-write-error", func(t *testing.T) { 168 v := &testEncodingArrInterfaces{} 169 w := TestWriterError("") 170 enc := BorrowEncoder(w) 171 defer enc.Release() 172 err := enc.EncodeArray(v) 173 assert.NotNil(t, err, "err should not be nil") 174 }) 175 } 176 177 // Array add with omit key tests 178 179 type TestEncodingIntOmitEmpty []int 180 181 func (t TestEncodingIntOmitEmpty) MarshalJSONArray(enc *Encoder) { 182 for _, e := range t { 183 enc.AddIntOmitEmpty(e) 184 } 185 } 186 func (t TestEncodingIntOmitEmpty) IsNil() bool { 187 return t == nil 188 } 189 190 type TestEncodingStringOmitEmpty []string 191 192 func (t TestEncodingStringOmitEmpty) MarshalJSONArray(enc *Encoder) { 193 for _, e := range t { 194 enc.AddStringOmitEmpty(e) 195 } 196 } 197 func (t TestEncodingStringOmitEmpty) IsNil() bool { 198 return t == nil 199 } 200 201 type TestEncodingFloatOmitEmpty []float64 202 203 func (t TestEncodingFloatOmitEmpty) MarshalJSONArray(enc *Encoder) { 204 for _, e := range t { 205 enc.AddFloatOmitEmpty(e) 206 } 207 } 208 func (t TestEncodingFloatOmitEmpty) IsNil() bool { 209 return t == nil 210 } 211 212 type TestEncodingFloat32OmitEmpty []float32 213 214 func (t TestEncodingFloat32OmitEmpty) MarshalJSONArray(enc *Encoder) { 215 for _, e := range t { 216 enc.AddFloat32OmitEmpty(e) 217 } 218 } 219 func (t TestEncodingFloat32OmitEmpty) IsNil() bool { 220 return t == nil 221 } 222 223 type TestEncodingBoolOmitEmpty []bool 224 225 func (t TestEncodingBoolOmitEmpty) MarshalJSONArray(enc *Encoder) { 226 for _, e := range t { 227 enc.AddBoolOmitEmpty(e) 228 } 229 } 230 func (t TestEncodingBoolOmitEmpty) IsNil() bool { 231 return len(t) == 0 232 } 233 234 type TestEncodingArrOmitEmpty []TestEncodingBoolOmitEmpty 235 236 func (t TestEncodingArrOmitEmpty) MarshalJSONArray(enc *Encoder) { 237 for _, e := range t { 238 enc.AddArrayOmitEmpty(e) 239 } 240 } 241 func (t TestEncodingArrOmitEmpty) IsNil() bool { 242 return len(t) == 0 243 } 244 245 type TestObjEmpty struct { 246 empty bool 247 } 248 249 func (t *TestObjEmpty) MarshalJSONObject(enc *Encoder) { 250 } 251 252 func (t *TestObjEmpty) IsNil() bool { 253 return !t.empty 254 } 255 256 type TestEncodingObjOmitEmpty []*TestObjEmpty 257 258 func (t TestEncodingObjOmitEmpty) MarshalJSONArray(enc *Encoder) { 259 for _, e := range t { 260 enc.AddObjectOmitEmpty(e) 261 } 262 } 263 func (t TestEncodingObjOmitEmpty) IsNil() bool { 264 return t == nil 265 } 266 267 func TestEncoderArrayOmitEmpty(t *testing.T) { 268 t.Run("omit-int", func(t *testing.T) { 269 intArr := TestEncodingIntOmitEmpty{0, 1, 0, 1} 270 b, err := Marshal(intArr) 271 assert.Nil(t, err, "err must be nil") 272 assert.Equal(t, `[1,1]`, string(b), "string(b) must be equal to `[1,1]`") 273 }) 274 t.Run("omit-float", func(t *testing.T) { 275 floatArr := TestEncodingFloatOmitEmpty{0, 1, 0, 1} 276 b, err := Marshal(floatArr) 277 assert.Nil(t, err, "err must be nil") 278 assert.Equal(t, `[1,1]`, string(b), "string(b) must be equal to `[1,1]`") 279 }) 280 t.Run("omit-float32", func(t *testing.T) { 281 float32Arr := TestEncodingFloat32OmitEmpty{0, 1, 0, 1} 282 b, err := Marshal(float32Arr) 283 assert.Nil(t, err, "err must be nil") 284 assert.Equal(t, `[1,1]`, string(b), "string(b) must be equal to `[1,1]`") 285 }) 286 t.Run("omit-string", func(t *testing.T) { 287 stringArr := TestEncodingStringOmitEmpty{"", "hello", "", "world"} 288 b, err := Marshal(stringArr) 289 assert.Nil(t, err, "err must be nil") 290 assert.Equal(t, `["hello","world"]`, string(b), "string(b) must be equal to `[\"hello\",\"world\"]`") 291 }) 292 t.Run("omit-bool", func(t *testing.T) { 293 boolArr := TestEncodingBoolOmitEmpty{false, true, false, true} 294 b, err := Marshal(boolArr) 295 assert.Nil(t, err, "err must be nil") 296 assert.Equal(t, `[true,true]`, string(b), "string(b) must be equal to `[true,true]`") 297 }) 298 t.Run("omit-arr", func(t *testing.T) { 299 arrArr := TestEncodingArrOmitEmpty{TestEncodingBoolOmitEmpty{true}, nil, TestEncodingBoolOmitEmpty{true}, nil} 300 b, err := Marshal(arrArr) 301 assert.Nil(t, err, "err must be nil") 302 assert.Equal(t, `[[true],[true]]`, string(b), "string(b) must be equal to `[[true],[true]]`") 303 }) 304 t.Run("omit-obj", func(t *testing.T) { 305 objArr := TestEncodingObjOmitEmpty{&TestObjEmpty{true}, &TestObjEmpty{false}, &TestObjEmpty{true}, &TestObjEmpty{false}} 306 b, err := Marshal(objArr) 307 assert.Nil(t, err, "err must be nil") 308 assert.Equal(t, `[{},{}]`, string(b), "string(b) must be equal to `[{},{}]`") 309 }) 310 } 311 312 func TestEncoderArrErrors(t *testing.T) { 313 t.Run("add-interface-error", func(t *testing.T) { 314 builder := &strings.Builder{} 315 enc := NewEncoder(builder) 316 enc.AddInterface(nil) 317 assert.Nil(t, enc.err, "enc.Err() should not be nil") 318 assert.Equal(t, "", builder.String(), "builder.String() should not be ''") 319 }) 320 t.Run("array-pooled-error", func(t *testing.T) { 321 v := &testEncodingArrInterfaces{} 322 enc := BorrowEncoder(nil) 323 enc.Release() 324 defer func() { 325 err := recover() 326 assert.NotNil(t, err, "err shouldnt be nil") 327 assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError") 328 assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError") 329 }() 330 _ = enc.EncodeArray(v) 331 assert.True(t, false, "should not be called as it should have panicked") 332 }) 333 } 334 335 func TestEncoderArrayFunc(t *testing.T) { 336 var f EncodeArrayFunc 337 assert.True(t, f.IsNil()) 338 } 339 340 func TestEncodeArrayNullEmpty(t *testing.T) { 341 var testCases = []struct { 342 name, baseJSON, expectedJSON string 343 }{ 344 { 345 name: "basic 1st elem", 346 baseJSON: "[", 347 expectedJSON: `[null,["foo"]`, 348 }, 349 { 350 name: "basic 1st elem", 351 baseJSON: `["test"`, 352 expectedJSON: `["test",null,["foo"]`, 353 }, 354 } 355 356 for _, testCase := range testCases { 357 t.Run(testCase.name, func(t *testing.T) { 358 var b strings.Builder 359 var enc = NewEncoder(&b) 360 enc.writeString(testCase.baseJSON) 361 enc.AddArrayNullEmpty(&TestEncodingArrStrings{}) 362 enc.ArrayNullEmpty(&TestEncodingArrStrings{"foo"}) 363 }) 364 } 365 } 366 367 func TestEncodeArrayKeyNullEmpty(t *testing.T) { 368 var testCases = []struct { 369 name, baseJSON, expectedJSON string 370 }{ 371 { 372 name: "basic 1st elem", 373 baseJSON: "{", 374 expectedJSON: `{"foo":null,"bar":["foo"]`, 375 }, 376 { 377 name: "basic 1st elem", 378 baseJSON: `{"test":"test"`, 379 expectedJSON: `{"test":"test","foo":null,"bar":["foo"]`, 380 }, 381 } 382 383 for _, testCase := range testCases { 384 t.Run(testCase.name, func(t *testing.T) { 385 var b strings.Builder 386 var enc = NewEncoder(&b) 387 enc.writeString(testCase.baseJSON) 388 enc.AddArrayKeyNullEmpty("foo", &TestEncodingArrStrings{}) 389 enc.ArrayKeyNullEmpty("bar", &TestEncodingArrStrings{"foo"}) 390 }) 391 } 392 }