gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

decode_sqlnull_test.go (8868B)


      1 package gojay
      2 
      3 import (
      4 	"database/sql"
      5 	"strings"
      6 	"testing"
      7 
      8 	"github.com/stretchr/testify/assert"
      9 	"github.com/stretchr/testify/require"
     10 )
     11 
     12 func TestDecodeSQLNullString(t *testing.T) {
     13 	testCases := []struct {
     14 		name               string
     15 		json               string
     16 		expectedNullString sql.NullString
     17 		err                bool
     18 	}{
     19 		{
     20 			name:               "basic",
     21 			json:               `"test"`,
     22 			expectedNullString: sql.NullString{String: "test", Valid: true},
     23 		},
     24 		{
     25 			name:               "basic",
     26 			json:               `"test`,
     27 			expectedNullString: sql.NullString{String: "test", Valid: true},
     28 			err:                true,
     29 		},
     30 	}
     31 	for _, testCase := range testCases {
     32 		t.Run(testCase.name, func(t *testing.T) {
     33 			nullString := sql.NullString{}
     34 			dec := NewDecoder(strings.NewReader(testCase.json))
     35 			err := dec.DecodeSQLNullString(&nullString)
     36 			if testCase.err {
     37 				assert.NotNil(t, err)
     38 			} else {
     39 				assert.Nil(t, err)
     40 				assert.Equal(t, testCase.expectedNullString, nullString)
     41 			}
     42 		})
     43 	}
     44 	t.Run(
     45 		"should panic because decoder is pooled",
     46 		func(t *testing.T) {
     47 			dec := NewDecoder(nil)
     48 			dec.Release()
     49 			defer func() {
     50 				err := recover()
     51 				assert.NotNil(t, err, "err shouldnt be nil")
     52 				assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
     53 			}()
     54 			_ = dec.DecodeSQLNullString(&sql.NullString{})
     55 			assert.True(t, false, "should not be called as decoder should have panicked")
     56 		},
     57 	)
     58 }
     59 
     60 func TestDecodeSQLNullInt64(t *testing.T) {
     61 	testCases := []struct {
     62 		name              string
     63 		json              string
     64 		expectedNullInt64 sql.NullInt64
     65 		err               bool
     66 	}{
     67 		{
     68 			name:              "basic",
     69 			json:              `1`,
     70 			expectedNullInt64: sql.NullInt64{Int64: 1, Valid: true},
     71 		},
     72 		{
     73 			name:              "basic",
     74 			json:              `"test`,
     75 			expectedNullInt64: sql.NullInt64{Int64: 1, Valid: true},
     76 			err:               true,
     77 		},
     78 	}
     79 	for _, testCase := range testCases {
     80 		t.Run(testCase.name, func(t *testing.T) {
     81 			nullInt64 := sql.NullInt64{}
     82 			dec := NewDecoder(strings.NewReader(testCase.json))
     83 			err := dec.DecodeSQLNullInt64(&nullInt64)
     84 			if testCase.err {
     85 				assert.NotNil(t, err)
     86 			} else {
     87 				assert.Nil(t, err)
     88 				assert.Equal(t, testCase.expectedNullInt64, nullInt64)
     89 			}
     90 		})
     91 	}
     92 	t.Run(
     93 		"should panic because decoder is pooled",
     94 		func(t *testing.T) {
     95 			dec := NewDecoder(nil)
     96 			dec.Release()
     97 			defer func() {
     98 				err := recover()
     99 				assert.NotNil(t, err, "err shouldnt be nil")
    100 				assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
    101 			}()
    102 			_ = dec.DecodeSQLNullInt64(&sql.NullInt64{})
    103 			assert.True(t, false, "should not be called as decoder should have panicked")
    104 		},
    105 	)
    106 }
    107 
    108 func TestDecodeSQLNullFloat64(t *testing.T) {
    109 	testCases := []struct {
    110 		name                string
    111 		json                string
    112 		expectedNullFloat64 sql.NullFloat64
    113 		err                 bool
    114 	}{
    115 		{
    116 			name:                "basic",
    117 			json:                `1`,
    118 			expectedNullFloat64: sql.NullFloat64{Float64: 1, Valid: true},
    119 		},
    120 		{
    121 			name:                "basic",
    122 			json:                `"test`,
    123 			expectedNullFloat64: sql.NullFloat64{Float64: 1, Valid: true},
    124 			err:                 true,
    125 		},
    126 	}
    127 	for _, testCase := range testCases {
    128 		t.Run(testCase.name, func(t *testing.T) {
    129 			nullFloat64 := sql.NullFloat64{}
    130 			dec := NewDecoder(strings.NewReader(testCase.json))
    131 			err := dec.DecodeSQLNullFloat64(&nullFloat64)
    132 			if testCase.err {
    133 				assert.NotNil(t, err)
    134 			} else {
    135 				assert.Nil(t, err)
    136 				assert.Equal(t, testCase.expectedNullFloat64, nullFloat64)
    137 			}
    138 		})
    139 	}
    140 	t.Run(
    141 		"should panic because decoder is pooled",
    142 		func(t *testing.T) {
    143 			dec := NewDecoder(nil)
    144 			dec.Release()
    145 			defer func() {
    146 				err := recover()
    147 				assert.NotNil(t, err, "err shouldnt be nil")
    148 				assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
    149 			}()
    150 			_ = dec.DecodeSQLNullFloat64(&sql.NullFloat64{})
    151 			assert.True(t, false, "should not be called as decoder should have panicked")
    152 		},
    153 	)
    154 }
    155 
    156 func TestDecodeSQLNullBool(t *testing.T) {
    157 	testCases := []struct {
    158 		name             string
    159 		json             string
    160 		expectedNullBool sql.NullBool
    161 		err              bool
    162 	}{
    163 		{
    164 			name:             "basic",
    165 			json:             `true`,
    166 			expectedNullBool: sql.NullBool{Bool: true, Valid: true},
    167 		},
    168 		{
    169 			name:             "basic",
    170 			json:             `"&`,
    171 			expectedNullBool: sql.NullBool{Bool: true, Valid: true},
    172 			err:              true,
    173 		},
    174 	}
    175 	for _, testCase := range testCases {
    176 		t.Run(testCase.name, func(t *testing.T) {
    177 			nullBool := sql.NullBool{}
    178 			dec := NewDecoder(strings.NewReader(testCase.json))
    179 			err := dec.DecodeSQLNullBool(&nullBool)
    180 			if testCase.err {
    181 				assert.NotNil(t, err)
    182 			} else {
    183 				assert.Nil(t, err)
    184 				assert.Equal(t, testCase.expectedNullBool, nullBool)
    185 			}
    186 		})
    187 	}
    188 	t.Run(
    189 		"should panic because decoder is pooled",
    190 		func(t *testing.T) {
    191 			dec := NewDecoder(nil)
    192 			dec.Release()
    193 			defer func() {
    194 				err := recover()
    195 				assert.NotNil(t, err, "err shouldnt be nil")
    196 				assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
    197 			}()
    198 			_ = dec.DecodeSQLNullBool(&sql.NullBool{})
    199 			assert.True(t, false, "should not be called as decoder should have panicked")
    200 		},
    201 	)
    202 }
    203 
    204 type SQLDecodeObject struct {
    205 	S sql.NullString
    206 	F sql.NullFloat64
    207 	I sql.NullInt64
    208 	B sql.NullBool
    209 }
    210 
    211 func (s *SQLDecodeObject) UnmarshalJSONObject(dec *Decoder, k string) error {
    212 	switch k {
    213 	case "s":
    214 		return dec.AddSQLNullString(&s.S)
    215 	case "f":
    216 		return dec.AddSQLNullFloat64(&s.F)
    217 	case "i":
    218 		return dec.AddSQLNullInt64(&s.I)
    219 	case "b":
    220 		return dec.AddSQLNullBool(&s.B)
    221 	}
    222 	return nil
    223 }
    224 
    225 func (s *SQLDecodeObject) NKeys() int {
    226 	return 0
    227 }
    228 
    229 func TestDecodeSQLNullKeys(t *testing.T) {
    230 	var testCases = []struct {
    231 		name           string
    232 		json           string
    233 		expectedResult *SQLDecodeObject
    234 		err            bool
    235 	}{
    236 		{
    237 			name: "basic all valid",
    238 			json: `{
    239 				"s": "foo",
    240 				"f": 0.3,
    241 				"i": 3,
    242 				"b": true
    243 			}`,
    244 			expectedResult: &SQLDecodeObject{
    245 				S: sql.NullString{
    246 					String: "foo",
    247 					Valid:  true,
    248 				},
    249 				F: sql.NullFloat64{
    250 					Float64: 0.3,
    251 					Valid:   true,
    252 				},
    253 				I: sql.NullInt64{
    254 					Int64: 3,
    255 					Valid: true,
    256 				},
    257 				B: sql.NullBool{
    258 					Bool:  true,
    259 					Valid: true,
    260 				},
    261 			},
    262 		},
    263 		{
    264 			name: "string not valid",
    265 			json: `{
    266 				"s": null,
    267 				"f": 0.3,
    268 				"i": 3,
    269 				"b": true
    270 			}`,
    271 			expectedResult: &SQLDecodeObject{
    272 				S: sql.NullString{
    273 					Valid: false,
    274 				},
    275 				F: sql.NullFloat64{
    276 					Float64: 0.3,
    277 					Valid:   true,
    278 				},
    279 				I: sql.NullInt64{
    280 					Int64: 3,
    281 					Valid: true,
    282 				},
    283 				B: sql.NullBool{
    284 					Bool:  true,
    285 					Valid: true,
    286 				},
    287 			},
    288 		},
    289 		{
    290 			name: "string not valid, int not valid",
    291 			json: `{
    292 				"s": null,
    293 				"f": 0.3,
    294 				"i": null,
    295 				"b": true
    296 			}`,
    297 			expectedResult: &SQLDecodeObject{
    298 				S: sql.NullString{
    299 					Valid: false,
    300 				},
    301 				F: sql.NullFloat64{
    302 					Float64: 0.3,
    303 					Valid:   true,
    304 				},
    305 				I: sql.NullInt64{
    306 					Valid: false,
    307 				},
    308 				B: sql.NullBool{
    309 					Bool:  true,
    310 					Valid: true,
    311 				},
    312 			},
    313 		},
    314 		{
    315 			name: "keys absent",
    316 			json: `{
    317 				"f": 0.3,
    318 				"i": 3,
    319 				"b": true
    320 			}`,
    321 			expectedResult: &SQLDecodeObject{
    322 				S: sql.NullString{
    323 					Valid: false,
    324 				},
    325 				F: sql.NullFloat64{
    326 					Float64: 0.3,
    327 					Valid:   true,
    328 				},
    329 				I: sql.NullInt64{
    330 					Valid: true,
    331 					Int64: 3,
    332 				},
    333 				B: sql.NullBool{
    334 					Bool:  true,
    335 					Valid: true,
    336 				},
    337 			},
    338 		},
    339 		{
    340 			name: "keys all null",
    341 			json: `{
    342 				"s": null,
    343 				"f": null,
    344 				"i": null,
    345 				"b": null
    346 			}`,
    347 			expectedResult: &SQLDecodeObject{
    348 				S: sql.NullString{
    349 					Valid: false,
    350 				},
    351 				F: sql.NullFloat64{
    352 					Valid: false,
    353 				},
    354 				I: sql.NullInt64{
    355 					Valid: false,
    356 				},
    357 				B: sql.NullBool{
    358 					Valid: false,
    359 				},
    360 			},
    361 		},
    362 		{
    363 			name: "err string key",
    364 			json: `{
    365 				"s": "`,
    366 			err: true,
    367 		},
    368 		{
    369 			name: "err float key",
    370 			json: `{
    371 				"s": null,
    372 				"f": 1",
    373 				"i": null,
    374 				"b": null
    375 			}`,
    376 			err: true,
    377 		},
    378 		{
    379 			name: "err int key",
    380 			json: `{
    381 				"s": null,
    382 				"f": null,
    383 				"i": 1",
    384 				"b": null
    385 			}`,
    386 			err: true,
    387 		},
    388 		{
    389 			name: "err bool key",
    390 			json: `{
    391 				"s": null,
    392 				"f": null,
    393 				"i": null,
    394 				"b": tra
    395 			}`,
    396 			err: true,
    397 		},
    398 	}
    399 
    400 	for _, testCase := range testCases {
    401 		t.Run(testCase.name, func(t *testing.T) {
    402 			var o = &SQLDecodeObject{}
    403 			var dec = NewDecoder(strings.NewReader(testCase.json))
    404 			var err = dec.Decode(o)
    405 
    406 			if testCase.err {
    407 				require.NotNil(t, err)
    408 				return
    409 			}
    410 
    411 			require.Nil(t, err)
    412 			require.Equal(
    413 				t,
    414 				testCase.expectedResult,
    415 				o,
    416 			)
    417 		})
    418 	}
    419 
    420 }