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  }