github.com/hamba/avro@v1.8.0/decoder_union_test.go (about) 1 package avro_test 2 3 import ( 4 "bytes" 5 "math/big" 6 "testing" 7 "time" 8 9 "github.com/hamba/avro" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 func TestDecoder_UnionInvalidType(t *testing.T) { 14 defer ConfigTeardown() 15 16 data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F} 17 schema := `["null", "string"]` 18 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 19 assert.NoError(t, err) 20 21 var str string 22 err = dec.Decode(&str) 23 24 assert.Error(t, err) 25 } 26 27 func TestDecoder_UnionMap(t *testing.T) { 28 defer ConfigTeardown() 29 30 data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F} 31 schema := `["null", "string"]` 32 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 33 34 var got map[string]interface{} 35 err := dec.Decode(&got) 36 37 assert.NoError(t, err) 38 assert.Equal(t, map[string]interface{}{"string": "foo"}, got) 39 } 40 41 func TestDecoder_UnionMapNamed(t *testing.T) { 42 defer ConfigTeardown() 43 44 data := []byte{0x02, 0x02} 45 schema := `["null", {"type":"enum", "name": "test", "symbols": ["foo", "bar"]}]` 46 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 47 48 var got map[string]interface{} 49 err := dec.Decode(&got) 50 51 assert.NoError(t, err) 52 assert.Equal(t, map[string]interface{}{"test": "bar"}, got) 53 } 54 55 func TestDecoder_UnionMapNull(t *testing.T) { 56 defer ConfigTeardown() 57 58 data := []byte{0x00} 59 schema := `["null", "string"]` 60 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 61 62 var got map[string]interface{} 63 err := dec.Decode(&got) 64 65 assert.NoError(t, err) 66 assert.Equal(t, map[string]interface{}(nil), got) 67 } 68 69 func TestDecoder_UnionMapWithTime(t *testing.T) { 70 defer ConfigTeardown() 71 72 data := []byte{0x02, 0x80, 0xCD, 0xB7, 0xA2, 0xEE, 0xC7, 0xCD, 0x05} 73 schema := `["null", {"type": "long", "logicalType": "timestamp-micros"}]` 74 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 75 76 var got map[string]interface{} 77 err := dec.Decode(&got) 78 79 assert.NoError(t, err) 80 assert.Equal(t, time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC), got["long.timestamp-micros"]) 81 } 82 83 func TestDecoder_UnionMapWithDuration(t *testing.T) { 84 defer ConfigTeardown() 85 86 data := []byte{0x02, 0xAA, 0xB4, 0xDE, 0x75} 87 schema := `["null", {"type": "int", "logicalType": "time-millis"}]` 88 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 89 90 var got map[string]interface{} 91 err := dec.Decode(&got) 92 93 assert.NoError(t, err) 94 assert.Equal(t, 123456789*time.Millisecond, got["int.time-millis"]) 95 } 96 97 func TestDecoder_UnionMapWithDecimal(t *testing.T) { 98 defer ConfigTeardown() 99 100 t.Run("low scale", func(t *testing.T) { 101 data := []byte{0x02, 0x6, 0x00, 0x87, 0x78} 102 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 2}]` 103 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 104 105 var got map[string]interface{} 106 err := dec.Decode(&got) 107 108 assert.NoError(t, err) 109 assert.Equal(t, big.NewRat(1734, 5), got["bytes.decimal"]) 110 }) 111 112 t.Run("high scale", func(t *testing.T) { 113 data := []byte{0x2, 0x22, 0x65, 0xea, 0x55, 0xc, 0x11, 0x8, 0xf7, 0xc3, 0xb8, 0xec, 0x53, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0} 114 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 77, "scale": 38}]` 115 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 116 117 var got map[string]interface{} 118 err := dec.Decode(&got) 119 120 assert.NoError(t, err) 121 assert.Equal(t, big.NewRat(1734, 5), got["bytes.decimal"]) 122 }) 123 } 124 125 func TestDecoder_UnionMapInvalidSchema(t *testing.T) { 126 defer ConfigTeardown() 127 128 data := []byte{0x04} 129 schema := `["null", "string"]` 130 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 131 132 var got map[string]interface{} 133 err := dec.Decode(&got) 134 135 assert.Error(t, err) 136 } 137 138 func TestDecoder_UnionMapInvalidMap(t *testing.T) { 139 defer ConfigTeardown() 140 141 data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F} 142 schema := `["null", "string"]` 143 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 144 145 var got map[string]string 146 err := dec.Decode(&got) 147 148 assert.Error(t, err) 149 } 150 151 func TestDecoder_UnionPtr(t *testing.T) { 152 defer ConfigTeardown() 153 154 data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F} 155 schema := `["null", "string"]` 156 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 157 158 var got *string 159 err := dec.Decode(&got) 160 161 want := "foo" 162 assert.NoError(t, err) 163 assert.Equal(t, &want, got) 164 } 165 166 func TestDecoder_UnionPtrReversed(t *testing.T) { 167 defer ConfigTeardown() 168 169 data := []byte{0x00, 0x06, 0x66, 0x6F, 0x6F} 170 schema := `["string", "null"]` 171 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 172 173 var got *string 174 err := dec.Decode(&got) 175 176 want := "foo" 177 assert.NoError(t, err) 178 assert.Equal(t, &want, got) 179 } 180 181 func TestDecoder_UnionPtrReuseInstance(t *testing.T) { 182 defer ConfigTeardown() 183 184 avro.Register("test", &TestRecord{}) 185 186 data := []byte{0x02, 0x36, 0x06, 0x66, 0x6F, 0x6F} 187 schema := `["null", {"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}]` 188 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 189 190 got := &TestRecord{} 191 err := dec.Decode(&got) 192 193 assert.NoError(t, err) 194 assert.IsType(t, &TestRecord{}, got) 195 assert.Equal(t, int64(27), got.A) 196 assert.Equal(t, "foo", got.B) 197 } 198 199 func TestDecoder_UnionPtrNull(t *testing.T) { 200 defer ConfigTeardown() 201 202 data := []byte{0x00} 203 schema := `["null", "string"]` 204 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 205 206 var got *string 207 err := dec.Decode(&got) 208 209 assert.NoError(t, err) 210 assert.Nil(t, got) 211 } 212 213 func TestDecoder_UnionPtrReversedNull(t *testing.T) { 214 defer ConfigTeardown() 215 216 data := []byte{0x02} 217 schema := `["string", "null"]` 218 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 219 220 var got *string 221 err := dec.Decode(&got) 222 223 assert.NoError(t, err) 224 assert.Nil(t, got) 225 } 226 227 func TestDecoder_UnionPtrInvalidSchema(t *testing.T) { 228 defer ConfigTeardown() 229 230 data := []byte{0x04} 231 schema := `["null", "string"]` 232 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 233 234 var got *string 235 err := dec.Decode(&got) 236 237 assert.Error(t, err) 238 } 239 240 func TestDecoder_UnionPtrNotNullable(t *testing.T) { 241 defer ConfigTeardown() 242 243 data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F} 244 schema := `["null", "string", "int"]` 245 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 246 247 var got *string 248 err := dec.Decode(&got) 249 250 assert.Error(t, err) 251 } 252 253 func TestDecoder_UnionInterface(t *testing.T) { 254 defer ConfigTeardown() 255 256 data := []byte{0x02, 0x36} 257 schema := `["null", "int"]` 258 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 259 260 var got interface{} 261 err := dec.Decode(&got) 262 263 assert.NoError(t, err) 264 assert.Equal(t, 27, got) 265 } 266 267 func TestDecoder_UnionInterfaceInRecord(t *testing.T) { 268 defer ConfigTeardown() 269 270 data := []byte{0x02, 0x36} 271 schema := `{ 272 "type": "record", 273 "name": "test", 274 "fields" : [ 275 {"name": "a", "type": ["null", "int"]} 276 ] 277 }` 278 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 279 280 got := &TestUnion{} 281 err := dec.Decode(&got) 282 283 assert.NoError(t, err) 284 assert.Equal(t, 27, got.A) 285 } 286 287 func TestDecoder_UnionInterfaceInMap(t *testing.T) { 288 defer ConfigTeardown() 289 290 avro.Register("map:int", map[string]int{}) 291 292 data := []byte{0x01, 0x0c, 0x06, 0x66, 0x6f, 0x6f, 0x00, 0x36, 0x00} 293 schema := `{"type": "map", "values": ["int", "string"]}` 294 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 295 296 var got map[string]interface{} 297 err := dec.Decode(&got) 298 299 assert.NoError(t, err) 300 assert.Equal(t, map[string]interface{}{"foo": 27}, got) 301 } 302 303 func TestDecoder_UnionInterfaceInMapWithBool(t *testing.T) { 304 defer ConfigTeardown() 305 306 data := []byte{0x01, 0x0c, 0x06, 0x66, 0x6F, 0x6F, 0x02, 0x01, 0x00} 307 schema := `{"type":"map", "values": ["null", "boolean"]}` 308 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 309 310 var got map[string]interface{} 311 err := dec.Decode(&got) 312 313 assert.NoError(t, err) 314 assert.Equal(t, map[string]interface{}{"foo": true}, got) 315 } 316 317 func TestDecoder_UnionInterfaceMap(t *testing.T) { 318 defer ConfigTeardown() 319 320 avro.Register("map:int", map[string]int{}) 321 322 data := []byte{0x02, 0x01, 0x0a, 0x06, 0x66, 0x6f, 0x6f, 0x36, 0x00} 323 schema := `["int", {"type": "map", "values": "int"}]` 324 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 325 326 var got interface{} 327 err := dec.Decode(&got) 328 329 assert.NoError(t, err) 330 assert.Equal(t, map[string]int{"foo": 27}, got) 331 } 332 333 func TestDecoder_UnionInterfaceMapNamed(t *testing.T) { 334 defer ConfigTeardown() 335 336 avro.Register("map:test", map[string]string{}) 337 338 data := []byte{0x02, 0x01, 0x0a, 0x06, 0x66, 0x6f, 0x6f, 0x02, 0x00} 339 schema := `["int", {"type": "map", "values": {"type":"enum", "name": "test", "symbols": ["A", "B"]}}]` 340 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 341 342 var got interface{} 343 err := dec.Decode(&got) 344 345 assert.NoError(t, err) 346 assert.Equal(t, map[string]string{"foo": "B"}, got) 347 } 348 349 func TestDecoder_UnionInterfaceArray(t *testing.T) { 350 defer ConfigTeardown() 351 352 avro.Register("array:int", []int{}) 353 354 data := []byte{0x02, 0x01, 0x02, 0x36, 0x00} 355 schema := `["int", {"type": "array", "items": "int"}]` 356 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 357 358 var got interface{} 359 err := dec.Decode(&got) 360 361 assert.NoError(t, err) 362 assert.Equal(t, []int{27}, got) 363 } 364 365 func TestDecoder_UnionInterfaceArrayNamed(t *testing.T) { 366 defer ConfigTeardown() 367 368 avro.Register("array:test", []string{}) 369 370 data := []byte{0x02, 0x01, 0x02, 0x02, 0x00} 371 schema := `["int", {"type": "array", "items": {"type":"enum", "name": "test", "symbols": ["A", "B"]}}]` 372 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 373 374 var got interface{} 375 err := dec.Decode(&got) 376 377 assert.NoError(t, err) 378 assert.Equal(t, []string{"B"}, got) 379 } 380 381 func TestDecoder_UnionInterfaceNull(t *testing.T) { 382 defer ConfigTeardown() 383 384 data := []byte{0x00} 385 schema := `["null", "string"]` 386 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 387 388 var got interface{} 389 err := dec.Decode(&got) 390 391 assert.NoError(t, err) 392 assert.Equal(t, nil, got) 393 } 394 395 func TestDecoder_UnionInterfaceNamed(t *testing.T) { 396 defer ConfigTeardown() 397 398 avro.Register("test", "") 399 400 data := []byte{0x02, 0x02} 401 schema := `["null", {"type":"enum", "name": "test", "symbols": ["A", "B"]}]` 402 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 403 404 var got interface{} 405 err := dec.Decode(&got) 406 407 assert.NoError(t, err) 408 assert.Equal(t, "B", got) 409 } 410 411 func TestDecoder_UnionInterfaceRecord(t *testing.T) { 412 defer ConfigTeardown() 413 414 avro.Register("test", &TestRecord{}) 415 416 data := []byte{0x02, 0x36, 0x06, 0x66, 0x6F, 0x6F} 417 schema := `["int", {"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}]` 418 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 419 420 var got interface{} 421 err := dec.Decode(&got) 422 423 assert.NoError(t, err) 424 assert.IsType(t, &TestRecord{}, got) 425 rec := got.(*TestRecord) 426 assert.Equal(t, int64(27), rec.A) 427 assert.Equal(t, "foo", rec.B) 428 } 429 430 func TestDecoder_UnionInterfaceRecordNotReused(t *testing.T) { 431 defer ConfigTeardown() 432 433 avro.Register("test", &TestRecord{}) 434 435 data := []byte{0x02, 0x36, 0x06, 0x66, 0x6F, 0x6F} 436 schema := `["int", {"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}]` 437 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 438 439 var got interface{} = "" 440 err := dec.Decode(&got) 441 442 assert.NoError(t, err) 443 assert.IsType(t, &TestRecord{}, got) 444 rec := got.(*TestRecord) 445 assert.Equal(t, int64(27), rec.A) 446 assert.Equal(t, "foo", rec.B) 447 } 448 449 func TestDecoder_UnionInterfaceUnresolvableType(t *testing.T) { 450 defer ConfigTeardown() 451 452 data := []byte{0x02, 0x36, 0x06, 0x66, 0x6F, 0x6F} 453 schema := `["int", {"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}]` 454 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 455 456 var got interface{} 457 err := dec.Decode(&got) 458 459 assert.NoError(t, err) 460 assert.IsType(t, map[string]interface{}{}, got) 461 m := got.(map[string]interface{}) 462 assert.IsType(t, map[string]interface{}{}, m["test"]) 463 assert.Equal(t, int64(27), m["test"].(map[string]interface{})["a"]) 464 assert.Equal(t, "foo", m["test"].(map[string]interface{})["b"]) 465 } 466 467 func TestDecoder_UnionInterfaceWithTime(t *testing.T) { 468 defer ConfigTeardown() 469 470 data := []byte{0x02, 0x80, 0xCD, 0xB7, 0xA2, 0xEE, 0xC7, 0xCD, 0x05} 471 schema := `["null", {"type": "long", "logicalType": "timestamp-micros"}]` 472 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 473 474 var got interface{} 475 err := dec.Decode(&got) 476 477 assert.NoError(t, err) 478 assert.Equal(t, time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC), got) 479 } 480 481 func TestDecoder_UnionInterfaceWithDuration(t *testing.T) { 482 defer ConfigTeardown() 483 484 data := []byte{0x02, 0xAA, 0xB4, 0xDE, 0x75} 485 schema := `["null", {"type": "int", "logicalType": "time-millis"}]` 486 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 487 488 var got interface{} 489 err := dec.Decode(&got) 490 491 assert.NoError(t, err) 492 assert.Equal(t, 123456789*time.Millisecond, got) 493 } 494 495 func TestDecoder_UnionInterfaceWithDecimal(t *testing.T) { 496 defer ConfigTeardown() 497 498 t.Run("low scale", func(t *testing.T) { 499 data := []byte{0x02, 0x6, 0x00, 0x87, 0x78} 500 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 2}]` 501 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 502 503 var got interface{} 504 err := dec.Decode(&got) 505 506 assert.NoError(t, err) 507 assert.Equal(t, big.NewRat(1734, 5), got) 508 }) 509 510 t.Run("high scale", func(t *testing.T) { 511 data := []byte{0x2, 0x22, 0x65, 0xea, 0x55, 0xc, 0x11, 0x8, 0xf7, 0xc3, 0xb8, 0xec, 0x53, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0} 512 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 77, "scale": 38}]` 513 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 514 515 var got interface{} 516 err := dec.Decode(&got) 517 518 assert.NoError(t, err) 519 assert.Equal(t, big.NewRat(1734, 5), got) 520 }) 521 } 522 523 func TestDecoder_UnionInterfaceWithDecimal_Negative(t *testing.T) { 524 defer ConfigTeardown() 525 526 t.Run("low scale", func(t *testing.T) { 527 data := []byte{0x02, 0x6, 0xFF, 0x78, 0x88} 528 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 2}]` 529 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 530 531 var got interface{} 532 err := dec.Decode(&got) 533 534 assert.NoError(t, err) 535 assert.Equal(t, big.NewRat(-1734, 5), got) 536 }) 537 t.Run("high scale", func(t *testing.T) { 538 data := []byte{0x2, 0x22, 0x9a, 0x15, 0xaa, 0xf3, 0xee, 0xf7, 0x8, 0x3c, 0x47, 0x13, 0xac, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0} 539 schema := `["null", {"type": "bytes", "logicalType": "decimal", "precision": 77, "scale": 38}]` 540 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 541 542 var got interface{} 543 err := dec.Decode(&got) 544 545 assert.NoError(t, err) 546 assert.Equal(t, big.NewRat(-1734, 5), got) 547 }) 548 } 549 550 func TestDecoder_UnionInterfaceUnresolvableTypeWithError(t *testing.T) { 551 defer ConfigTeardown() 552 553 avro.DefaultConfig = avro.Config{UnionResolutionError: true}.Freeze() 554 555 data := []byte{0x02, 0x36, 0x06, 0x66, 0x6F, 0x6F} 556 schema := `["int", {"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}]` 557 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 558 559 var got interface{} 560 err := dec.Decode(&got) 561 562 assert.Error(t, err) 563 } 564 565 func TestDecoder_UnionInterfaceInvalidSchema(t *testing.T) { 566 defer ConfigTeardown() 567 568 data := []byte{0x04} 569 schema := `["null", "int"]` 570 dec, _ := avro.NewDecoder(schema, bytes.NewReader(data)) 571 572 var got interface{} 573 err := dec.Decode(&got) 574 575 assert.Error(t, err) 576 }