github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_encoder_iface_test.go (about) 1 package jzon 2 3 import ( 4 "fmt" 5 "math/rand" 6 "reflect" 7 "strconv" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestValEncoder_Iface_Error(t *testing.T) { 14 t.Run("chain error", func(t *testing.T) { 15 t.Run("", func(t *testing.T) { 16 testStreamerChainError(t, func(s *Streamer) { 17 (*ifaceValEncoder)(nil).Encode(nil, s, nil) 18 }) 19 }) 20 }) 21 } 22 23 type testBarface interface { 24 Bar() (string, error) 25 } 26 27 type testBarfaceImpl struct { 28 s string 29 e error 30 } 31 32 func (i testBarfaceImpl) Bar() (string, error) { 33 return i.s, i.e 34 } 35 36 type testBarfaceImpl2 struct { 37 s string 38 e error 39 } 40 41 func (i *testBarfaceImpl2) Bar() (string, error) { 42 return i.s, i.e 43 } 44 45 type testBarfaceEncoder struct{} 46 47 func (t testBarfaceEncoder) Encode(o interface{}, s *Streamer, opts *EncOpts) { 48 if s.Error != nil { 49 return 50 } 51 if o == nil { 52 s.Null() 53 return 54 } 55 bface, ok := o.(testBarface) 56 if !ok { 57 panic("should not reach") 58 } else { 59 b, err := bface.Bar() 60 if err != nil { 61 s.Error = err 62 return 63 } 64 s.String(b) 65 } 66 } 67 68 func TestValEncoder_Iface_NonPointerReceiver(t *testing.T) { 69 cfg := NewEncoderConfig(&EncoderOption{ 70 IfaceEncoders: []IfaceValEncoderConfig{{ 71 Type: reflect.TypeOf((*testBarface)(nil)).Elem(), 72 Encoder: testBarfaceEncoder{}, 73 }}, 74 }) 75 t.Run("non pointer", func(t *testing.T) { 76 t.Run("no error", func(t *testing.T) { 77 m := require.New(t) 78 s := strconv.Itoa(rand.Int()) 79 b, err := cfg.Marshal(testBarfaceImpl{ 80 s: s, 81 }) 82 m.NoError(err) 83 m.Equal(strconv.Quote(s), string(b)) 84 }) 85 }) 86 t.Run("pointer", func(t *testing.T) { 87 t.Run("nil", func(t *testing.T) { 88 m := require.New(t) 89 b, err := cfg.Marshal((*testBarfaceImpl)(nil)) 90 m.NoError(err) 91 m.Equal("null", string(b)) 92 }) 93 t.Run("no error", func(t *testing.T) { 94 m := require.New(t) 95 s := strconv.Itoa(rand.Int()) 96 b, err := cfg.Marshal(&testBarfaceImpl{ 97 s: s, 98 }) 99 m.NoError(err) 100 m.Equal(strconv.Quote(s), string(b)) 101 }) 102 }) 103 t.Run("pointer of pointer", func(t *testing.T) { 104 t.Run("nil", func(t *testing.T) { 105 m := require.New(t) 106 b, err := cfg.Marshal((**testBarfaceImpl)(nil)) 107 m.NoError(err) 108 m.Equal("null", string(b)) 109 }) 110 t.Run("pointer of nil", func(t *testing.T) { 111 m := require.New(t) 112 ptr := (*testBarfaceImpl)(nil) 113 b, err := cfg.Marshal(&ptr) 114 m.NoError(err) 115 m.Equal("null", string(b)) 116 }) 117 t.Run("no error", func(t *testing.T) { 118 m := require.New(t) 119 s := strconv.Itoa(rand.Int()) 120 ptr := &testBarfaceImpl{ 121 s: s, 122 } 123 b, err := cfg.Marshal(&ptr) 124 m.NoError(err) 125 m.Equal(strconv.Quote(s), string(b)) 126 }) 127 t.Run("error", func(t *testing.T) { 128 // TODO 129 }) 130 }) 131 } 132 133 func TestValEncoder_Iface_PointerReceiver(t *testing.T) { 134 cfg := NewEncoderConfig(&EncoderOption{ 135 IfaceEncoders: []IfaceValEncoderConfig{{ 136 Type: reflect.TypeOf((*testBarface)(nil)).Elem(), 137 Encoder: testBarfaceEncoder{}, 138 }}, 139 }) 140 t.Run("non pointer", func(t *testing.T) { 141 t.Run("no error", func(t *testing.T) { 142 m := require.New(t) 143 b, err := cfg.Marshal(testBarfaceImpl2{}) 144 m.NoError(err) 145 m.Equal("{}", string(b)) 146 }) 147 }) 148 t.Run("pointer", func(t *testing.T) { 149 t.Run("nil", func(t *testing.T) { 150 m := require.New(t) 151 b, err := cfg.Marshal((*testBarfaceImpl2)(nil)) 152 m.NoError(err) 153 m.Equal("null", string(b)) 154 }) 155 t.Run("no error", func(t *testing.T) { 156 m := require.New(t) 157 s := strconv.Itoa(rand.Int()) 158 b, err := cfg.Marshal(&testBarfaceImpl2{ 159 s: s, 160 }) 161 m.NoError(err) 162 m.Equal(strconv.Quote(s), string(b)) 163 }) 164 }) 165 t.Run("pointer of pointer", func(t *testing.T) { 166 t.Run("nil", func(t *testing.T) { 167 m := require.New(t) 168 b, err := cfg.Marshal((**testBarfaceImpl2)(nil)) 169 m.NoError(err) 170 m.Equal("null", string(b)) 171 }) 172 t.Run("pointer of nil", func(t *testing.T) { 173 m := require.New(t) 174 ptr := (*testBarfaceImpl2)(nil) 175 b, err := cfg.Marshal(&ptr) 176 m.NoError(err) 177 m.Equal("null", string(b)) 178 }) 179 t.Run("no error", func(t *testing.T) { 180 m := require.New(t) 181 s := strconv.Itoa(rand.Int()) 182 ptr := &testBarfaceImpl2{ 183 s: s, 184 } 185 b, err := cfg.Marshal(&ptr) 186 m.NoError(err) 187 m.Equal(strconv.Quote(s), string(b)) 188 }) 189 t.Run("error", func(t *testing.T) { 190 // TODO 191 }) 192 }) 193 t.Run("struct member", func(t *testing.T) { 194 t.Run("value", func(t *testing.T) { 195 type st struct { 196 A testBarfaceImpl2 197 } 198 t.Run("value", func(t *testing.T) { 199 m := require.New(t) 200 s := strconv.Itoa(rand.Int()) 201 b, err := cfg.Marshal(st{ 202 A: testBarfaceImpl2{ 203 s: s, 204 }, 205 }) 206 m.NoError(err) 207 m.Equal(`{"A":"`+s+`"}`, string(b)) 208 }) 209 t.Run("ptr", func(t *testing.T) { 210 m := require.New(t) 211 s := strconv.Itoa(rand.Int()) 212 b, err := cfg.Marshal(&st{ 213 A: testBarfaceImpl2{ 214 s: s, 215 }, 216 }) 217 m.NoError(err) 218 m.Equal(`{"A":"`+s+`"}`, string(b)) 219 }) 220 }) 221 t.Run("pointer", func(t *testing.T) { 222 type st struct { 223 A *testBarfaceImpl2 224 } 225 t.Run("nil", func(t *testing.T) { 226 m := require.New(t) 227 b, err := cfg.Marshal(&st{}) 228 m.NoError(err) 229 m.Equal(`{"A":null}`, string(b)) 230 }) 231 }) 232 }) 233 } 234 235 func TestValEncoder_Iface_Dynamic(t *testing.T) { 236 cfg := NewEncoderConfig(&EncoderOption{ 237 IfaceEncoders: []IfaceValEncoderConfig{{ 238 Type: reflect.TypeOf((*testBarface)(nil)).Elem(), 239 Encoder: testBarfaceEncoder{}, 240 }}, 241 }) 242 t.Run("iface nil", func(t *testing.T) { 243 m := require.New(t) 244 var i testBarface 245 b, err := cfg.Marshal(&i) 246 m.NoError(err) 247 m.Equal("null", string(b)) 248 }) 249 t.Run("iface", func(t *testing.T) { 250 m := require.New(t) 251 s := strconv.Itoa(rand.Int()) 252 var i testBarface = testBarfaceImpl{ 253 s: s, 254 } 255 b, err := cfg.Marshal(&i) 256 m.NoError(err) 257 m.Equal(strconv.Quote(s), string(b)) 258 }) 259 t.Run("iface 2", func(t *testing.T) { 260 m := require.New(t) 261 s := strconv.Itoa(rand.Int()) 262 var i testBarface = &testBarfaceImpl2{ 263 s: s, 264 } 265 b, err := cfg.Marshal(&i) 266 m.NoError(err) 267 m.Equal(strconv.Quote(s), string(b)) 268 }) 269 } 270 271 type testMapBarface map[int]int 272 273 func (m testMapBarface) Bar() (string, error) { 274 s := fmt.Sprintf("%d", len(m)) 275 return s, nil 276 } 277 278 func TestValEncoder_Iface_Direct(t *testing.T) { 279 cfg := NewEncoderConfig(&EncoderOption{ 280 IfaceEncoders: []IfaceValEncoderConfig{{ 281 Type: reflect.TypeOf((*testBarface)(nil)).Elem(), 282 Encoder: testBarfaceEncoder{}, 283 }}, 284 }) 285 t.Run("value", func(t *testing.T) { 286 t.Run("nil", func(t *testing.T) { 287 m := require.New(t) 288 b, err := cfg.Marshal(testMapBarface(nil)) 289 m.NoError(err) 290 m.Equal(`"0"`, string(b)) 291 }) 292 t.Run("non nil", func(t *testing.T) { 293 m := require.New(t) 294 b, err := cfg.Marshal(testMapBarface{ 295 1: 2, 296 }) 297 m.NoError(err) 298 m.Equal(`"1"`, string(b)) 299 }) 300 }) 301 t.Run("pointer", func(t *testing.T) { 302 t.Run("nil", func(t *testing.T) { 303 m := require.New(t) 304 b, err := cfg.Marshal((*testMapBarface)(nil)) 305 m.NoError(err) 306 m.Equal(`null`, string(b)) 307 }) 308 t.Run("non nil", func(t *testing.T) { 309 m := require.New(t) 310 var i testMapBarface 311 b, err := cfg.Marshal(&i) 312 m.NoError(err) 313 m.Equal(`"0"`, string(b)) 314 }) 315 t.Run("non nil 2", func(t *testing.T) { 316 m := require.New(t) 317 b, err := cfg.Marshal(&testMapBarface{ 318 1: 2, 319 }) 320 m.NoError(err) 321 m.Equal(`"1"`, string(b)) 322 }) 323 }) 324 t.Run("struct member", func(t *testing.T) { 325 type st struct { 326 A testMapBarface 327 } 328 m := require.New(t) 329 b, err := cfg.Marshal(&st{}) 330 m.NoError(err) 331 m.Equal(`{"A":"0"}`, string(b)) 332 }) 333 t.Run("value of iface", func(t *testing.T) { 334 t.Run("value", func(t *testing.T) { 335 var bar testBarface = testMapBarface{ 336 1: 2, 337 } 338 m := require.New(t) 339 b, err := cfg.Marshal(bar) 340 m.NoError(err) 341 m.Equal(`"1"`, string(b)) 342 }) 343 t.Run("pointer", func(t *testing.T) { 344 var bar testBarface = &testMapBarface{ 345 1: 2, 346 } 347 m := require.New(t) 348 b, err := cfg.Marshal(bar) 349 m.NoError(err) 350 m.Equal(`"1"`, string(b)) 351 }) 352 }) 353 t.Run("pointer of iface", func(t *testing.T) { 354 t.Run("nil", func(t *testing.T) { 355 var bar testBarface 356 m := require.New(t) 357 b, err := cfg.Marshal(&bar) 358 m.NoError(err) 359 m.Equal(`null`, string(b)) 360 }) 361 t.Run("value", func(t *testing.T) { 362 var bar testBarface = testMapBarface{ 363 1: 2, 364 } 365 m := require.New(t) 366 b, err := cfg.Marshal(&bar) 367 m.NoError(err) 368 m.Equal(`"1"`, string(b)) 369 }) 370 t.Run("pointer", func(t *testing.T) { 371 var bar testBarface = &testMapBarface{ 372 1: 2, 373 } 374 m := require.New(t) 375 b, err := cfg.Marshal(&bar) 376 m.NoError(err) 377 m.Equal(`"1"`, string(b)) 378 }) 379 }) 380 } 381 382 func TestValEncoder_Iface_OmitEmpty(t *testing.T) { 383 cfg := NewEncoderConfig(&EncoderOption{ 384 IfaceEncoders: []IfaceValEncoderConfig{{ 385 Type: reflect.TypeOf((*testBarface)(nil)).Elem(), 386 Encoder: testBarfaceEncoder{}, 387 }}, 388 }) 389 t.Run("", func(t *testing.T) { 390 type st struct { 391 A testBarfaceImpl `json:",omitempty"` 392 } 393 m := require.New(t) 394 s := strconv.Itoa(rand.Int()) 395 b, err := cfg.Marshal(st{ 396 A: testBarfaceImpl{ 397 s: s, 398 }, 399 }) 400 m.NoError(err) 401 m.Equal(`{"A":"`+s+`"}`, string(b)) 402 }) 403 }