github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/codec_default_internal_test.go (about)

     1  package avro
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"math"
     7  	"math/big"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  type testEnumTextUnmarshaler int
    15  
    16  func (m *testEnumTextUnmarshaler) UnmarshalText(data []byte) error {
    17  	switch string(data) {
    18  	case "foo":
    19  		*m = 0
    20  		return nil
    21  	case "bar":
    22  		*m = 1
    23  		return nil
    24  	default:
    25  		return errors.New("unknown symbol")
    26  	}
    27  }
    28  
    29  func ConfigTeardown() {
    30  	// Reset the caches
    31  	DefaultConfig = Config{}.Freeze()
    32  }
    33  
    34  func TestDecoder_InvalidDefault(t *testing.T) {
    35  	defer ConfigTeardown()
    36  
    37  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
    38  
    39  	schema := MustParse(`{
    40  		"type": "record",
    41  		"name": "test",
    42  		"fields" : [
    43  			{"name": "a", "type": "string"},
    44  			{"name": "b", "type": "boolean", "default": true}
    45  		]
    46  	}`)
    47  
    48  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
    49  	// alter default value to force encoding failure
    50  	schema.(*RecordSchema).fields[1].def = "invalid value"
    51  
    52  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
    53  
    54  	var got map[string]any
    55  	err := dec.Decode(&got)
    56  
    57  	require.Error(t, err)
    58  }
    59  
    60  func TestDecoder_IgnoreField(t *testing.T) {
    61  	defer ConfigTeardown()
    62  
    63  	// write schema
    64  	// `{
    65  	// // 	"type": "record",
    66  	// // 	"name": "test",
    67  	// // 	"fields" : [
    68  	// // 		{"name": "a", "type": "string"}
    69  	// // 	]
    70  	// // }`
    71  
    72  	// {"a": "foo"}
    73  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
    74  
    75  	schema := MustParse(`{
    76  		"type": "record",
    77  		"name": "test",
    78  		"fields" : [
    79  			{"name": "a", "type": "string"},
    80  			{"name": "b", "type": "float", "default": 10.45}
    81  		]
    82  	}`)
    83  
    84  	schema.(*RecordSchema).Fields()[0].action = FieldIgnore
    85  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
    86  
    87  	type TestRecord struct {
    88  		A string  `avro:"a"`
    89  		B float32 `avro:"b"`
    90  	}
    91  
    92  	var got TestRecord
    93  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
    94  
    95  	require.NoError(t, err)
    96  	assert.Equal(t, TestRecord{B: 10.45, A: ""}, got)
    97  }
    98  
    99  func TestDecoder_DefaultBool(t *testing.T) {
   100  	defer ConfigTeardown()
   101  
   102  	// write schema
   103  	// `{
   104  	// // 	"type": "record",
   105  	// // 	"name": "test",
   106  	// // 	"fields" : [
   107  	// // 		{"name": "a", "type": "string"}
   108  	// // 	]
   109  	// // }`
   110  
   111  	// {"a": "foo"}
   112  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   113  
   114  	schema := MustParse(`{
   115  		"type": "record",
   116  		"name": "test",
   117  		"fields" : [
   118  			{"name": "a", "type": "string"},
   119  			{"name": "b", "type": "boolean", "default": true}
   120  		]
   121  	}`)
   122  
   123  	// hack: set field action to force decode default behavior
   124  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   125  
   126  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   127  
   128  	type TestRecord struct {
   129  		A string `avro:"a"`
   130  		B bool   `avro:"b"`
   131  	}
   132  
   133  	var got TestRecord
   134  	err := dec.Decode(&got)
   135  
   136  	require.NoError(t, err)
   137  	assert.Equal(t, TestRecord{B: true, A: "foo"}, got)
   138  }
   139  
   140  func TestDecoder_DefaultInt(t *testing.T) {
   141  	defer ConfigTeardown()
   142  
   143  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   144  
   145  	schema := MustParse(`{
   146  		"type": "record",
   147  		"name": "test",
   148  		"fields" : [
   149  			{"name": "a", "type": "string"},
   150  			{"name": "b", "type": "int", "default": 1000}
   151  		]
   152  	}`)
   153  
   154  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   155  
   156  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   157  
   158  	type TestRecord struct {
   159  		A string `avro:"a"`
   160  		B int32  `avro:"b"`
   161  	}
   162  
   163  	var got TestRecord
   164  	err := dec.Decode(&got)
   165  
   166  	require.NoError(t, err)
   167  	assert.Equal(t, TestRecord{B: 1000, A: "foo"}, got)
   168  }
   169  
   170  func TestDecoder_DefaultLong(t *testing.T) {
   171  	defer ConfigTeardown()
   172  
   173  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   174  
   175  	schema := MustParse(`{
   176  		"type": "record",
   177  		"name": "test",
   178  		"fields" : [
   179  			{"name": "a", "type": "string"},
   180  			{"name": "b", "type": "long", "default": 1000}
   181  		]
   182  	}`)
   183  
   184  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   185  
   186  	type TestRecord struct {
   187  		A string `avro:"a"`
   188  		B int64  `avro:"b"`
   189  	}
   190  
   191  	var got TestRecord
   192  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   193  
   194  	require.NoError(t, err)
   195  	assert.Equal(t, TestRecord{B: 1000, A: "foo"}, got)
   196  }
   197  
   198  func TestDecoder_DefaultFloat(t *testing.T) {
   199  	defer ConfigTeardown()
   200  
   201  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   202  
   203  	schema := MustParse(`{
   204  		"type": "record",
   205  		"name": "test",
   206  		"fields" : [
   207  			{"name": "a", "type": "string"},
   208  			{"name": "b", "type": "float", "default": 10.45}
   209  		]
   210  	}`)
   211  
   212  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   213  
   214  	type TestRecord struct {
   215  		A string  `avro:"a"`
   216  		B float32 `avro:"b"`
   217  	}
   218  
   219  	var got TestRecord
   220  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   221  
   222  	require.NoError(t, err)
   223  	assert.Equal(t, TestRecord{B: 10.45, A: "foo"}, got)
   224  }
   225  
   226  func TestDecoder_DefaultDouble(t *testing.T) {
   227  	defer ConfigTeardown()
   228  
   229  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   230  
   231  	schema := MustParse(`{
   232  		"type": "record",
   233  		"name": "test",
   234  		"fields" : [
   235  			{"name": "a", "type": "string"},
   236  			{"name": "b", "type": "double", "default": 10.45}
   237  		]
   238  	}`)
   239  
   240  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   241  
   242  	type TestRecord struct {
   243  		A string  `avro:"a"`
   244  		B float64 `avro:"b"`
   245  	}
   246  
   247  	var got TestRecord
   248  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   249  
   250  	require.NoError(t, err)
   251  	assert.Equal(t, TestRecord{B: 10.45, A: "foo"}, got)
   252  }
   253  
   254  func TestDecoder_DefaultBytes(t *testing.T) {
   255  	defer ConfigTeardown()
   256  
   257  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   258  
   259  	schema := MustParse(`{
   260  		"type": "record",
   261  		"name": "test",
   262  		"fields" : [
   263  			{"name": "a", "type": "string"},
   264  			{"name": "b", "type": "bytes", "default": "value"}
   265  		]
   266  	}`)
   267  
   268  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   269  
   270  	type TestRecord struct {
   271  		A string `avro:"a"`
   272  		B []byte `avro:"b"`
   273  	}
   274  
   275  	var got TestRecord
   276  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   277  
   278  	require.NoError(t, err)
   279  	assert.Equal(t, TestRecord{B: []byte("value"), A: "foo"}, got)
   280  }
   281  
   282  func TestDecoder_DefaultString(t *testing.T) {
   283  	defer ConfigTeardown()
   284  
   285  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   286  
   287  	schema := MustParse(`{
   288  		"type": "record",
   289  		"name": "test",
   290  		"fields" : [
   291  			{"name": "a", "type": "string"},
   292  			{"name": "b", "type": "string", "default": "value"}
   293  		]
   294  	}`)
   295  
   296  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   297  
   298  	type TestRecord struct {
   299  		A string `avro:"a"`
   300  		B string `avro:"b"`
   301  	}
   302  
   303  	var got TestRecord
   304  	err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   305  
   306  	require.NoError(t, err)
   307  	assert.Equal(t, TestRecord{B: "value", A: "foo"}, got)
   308  }
   309  
   310  func TestDecoder_DefaultEnum(t *testing.T) {
   311  	defer ConfigTeardown()
   312  
   313  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   314  
   315  	schema := MustParse(`{
   316  		"type": "record",
   317  		"name": "test",
   318  		"fields" : [
   319  			{"name": "a", "type": "string"},
   320  			{
   321  				"name": "b",
   322  				"type": {
   323  					"type": "enum",
   324  					"name": "test.enum",
   325  					"symbols": ["foo", "bar"]
   326  				},
   327  			  	"default": "bar"
   328  			}
   329  		]
   330  	}`)
   331  
   332  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   333  
   334  	t.Run("simple", func(t *testing.T) {
   335  		type TestRecord struct {
   336  			A string `avro:"a"`
   337  			B string `avro:"b"`
   338  		}
   339  
   340  		var got TestRecord
   341  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   342  
   343  		require.NoError(t, err)
   344  		assert.Equal(t, TestRecord{B: "bar", A: "foo"}, got)
   345  
   346  	})
   347  
   348  	t.Run("TextUnmarshaler", func(t *testing.T) {
   349  		type TestRecord struct {
   350  			A string                  `avro:"a"`
   351  			B testEnumTextUnmarshaler `avro:"b"`
   352  		}
   353  
   354  		var got TestRecord
   355  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   356  
   357  		require.NoError(t, err)
   358  		assert.Equal(t, TestRecord{B: 1, A: "foo"}, got)
   359  	})
   360  
   361  	t.Run("TextUnmarshaler Ptr", func(t *testing.T) {
   362  		type TestRecord struct {
   363  			A string                   `avro:"a"`
   364  			B *testEnumTextUnmarshaler `avro:"b"`
   365  		}
   366  
   367  		var got TestRecord
   368  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   369  
   370  		require.NoError(t, err)
   371  		var v testEnumTextUnmarshaler = 1
   372  		assert.Equal(t, TestRecord{B: &v, A: "foo"}, got)
   373  	})
   374  }
   375  
   376  func TestDecoder_DefaultUnion(t *testing.T) {
   377  	defer ConfigTeardown()
   378  
   379  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   380  
   381  	t.Run("null default", func(t *testing.T) {
   382  		type TestRecord struct {
   383  			A string  `avro:"a"`
   384  			B *string `avro:"b"`
   385  		}
   386  
   387  		schema := MustParse(`{
   388  			"type": "record",
   389  			"name": "test",
   390  			"fields" : [
   391  				{"name": "a", "type": "string"},
   392  				{"name": "b", "type": ["null", "long"], "default": null}
   393  			]
   394  		}`)
   395  
   396  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   397  
   398  		var got TestRecord
   399  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   400  
   401  		require.NoError(t, err)
   402  		assert.Equal(t, TestRecord{B: nil, A: "foo"}, got)
   403  	})
   404  
   405  	t.Run("not null default", func(t *testing.T) {
   406  		type TestRecord struct {
   407  			A string `avro:"a"`
   408  			B any    `avro:"b"`
   409  		}
   410  
   411  		schema := MustParse(`{
   412  			"type": "record",
   413  			"name": "test",
   414  			"fields" : [
   415  				{"name": "a", "type": "string"},
   416  				{"name": "b", "type": ["string", "long"], "default": "bar"}
   417  			]
   418  		}`)
   419  
   420  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   421  
   422  		var got TestRecord
   423  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   424  
   425  		require.NoError(t, err)
   426  		assert.Equal(t, TestRecord{B: "bar", A: "foo"}, got)
   427  	})
   428  
   429  	t.Run("map receiver", func(t *testing.T) {
   430  		type TestRecord struct {
   431  			A string         `avro:"a"`
   432  			B map[string]any `avro:"b"`
   433  		}
   434  
   435  		schema := MustParse(`{
   436  			"type": "record",
   437  			"name": "test",
   438  			"fields" : [
   439  				{"name": "a", "type": "string"},
   440  				{"name": "b", "type": ["string", "long"], "default": "bar"}
   441  			]
   442  		}`)
   443  
   444  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   445  
   446  		var got TestRecord
   447  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   448  
   449  		require.NoError(t, err)
   450  		assert.Equal(t, TestRecord{B: map[string]any{"string": "bar"}, A: "foo"}, got)
   451  	})
   452  }
   453  
   454  func TestDecoder_DefaultArray(t *testing.T) {
   455  	defer ConfigTeardown()
   456  
   457  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   458  
   459  	schema := MustParse(`{
   460  		"type": "record",
   461  		"name": "test",
   462  		"fields" : [
   463  			{"name": "a", "type": "string"},
   464  			{
   465  				"name": "b",
   466  				"type": {
   467  					"type": "array", "items": "int"
   468  				},
   469  				"default":[1, 2, 3, 4]
   470  			}
   471  		]
   472  	}`)
   473  
   474  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   475  
   476  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   477  
   478  	type TestRecord struct {
   479  		A string  `avro:"a"`
   480  		B []int16 `avro:"b"`
   481  	}
   482  
   483  	var got TestRecord
   484  	err := dec.Decode(&got)
   485  
   486  	require.NoError(t, err)
   487  	assert.Equal(t, TestRecord{B: []int16{1, 2, 3, 4}, A: "foo"}, got)
   488  }
   489  
   490  func TestDecoder_DefaultMap(t *testing.T) {
   491  	defer ConfigTeardown()
   492  
   493  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   494  
   495  	schema := MustParse(`{
   496  		"type": "record",
   497  		"name": "test",
   498  		"fields" : [
   499  			{"name": "a", "type": "string"},
   500  			{
   501  				"name": "b",
   502  				"type": {
   503  					"type": "map", "values": "string"
   504  				},
   505  				"default": {"foo":"bar"}
   506  			}
   507  		]
   508  	}`)
   509  
   510  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   511  
   512  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   513  
   514  	type TestRecord struct {
   515  		A string            `avro:"a"`
   516  		B map[string]string `avro:"b"`
   517  	}
   518  
   519  	var got TestRecord
   520  	err := dec.Decode(&got)
   521  
   522  	require.NoError(t, err)
   523  	assert.Equal(t, TestRecord{B: map[string]string{"foo": "bar"}, A: "foo"}, got)
   524  }
   525  
   526  func TestDecoder_DefaultRecord(t *testing.T) {
   527  	defer ConfigTeardown()
   528  
   529  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   530  
   531  	schema := MustParse(`{
   532  		"type": "record",
   533  		"name": "test",
   534  		"fields" : [
   535  			{"name": "a", "type": "string"},
   536  			{
   537  				"name": "b",
   538  				"type": {
   539  					"type": "record",
   540  					"name": "test.record",
   541  					"fields" : [
   542  						{"name": "a", "type": "string"},
   543  						{"name": "b", "type": "string"}
   544  					]
   545  				},
   546  				"default": {"a":"foo", "b": "bar"}
   547  			}
   548  		]
   549  	}`)
   550  
   551  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   552  
   553  	t.Run("struct", func(t *testing.T) {
   554  		dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   555  
   556  		type subRecord struct {
   557  			A string `avro:"a"`
   558  			B string `avro:"b"`
   559  		}
   560  		type TestRecord struct {
   561  			A string    `avro:"a"`
   562  			B subRecord `avro:"b"`
   563  		}
   564  
   565  		var got TestRecord
   566  		err := dec.Decode(&got)
   567  
   568  		require.NoError(t, err)
   569  		assert.Equal(t, TestRecord{B: subRecord{A: "foo", B: "bar"}, A: "foo"}, got)
   570  	})
   571  
   572  	t.Run("map", func(t *testing.T) {
   573  		dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   574  
   575  		var got map[string]any
   576  		err := dec.Decode(&got)
   577  
   578  		require.NoError(t, err)
   579  		assert.Equal(t, map[string]any{"b": map[string]any{"a": "foo", "b": "bar"}, "a": "foo"}, got)
   580  	})
   581  }
   582  
   583  func TestDecoder_DefaultRef(t *testing.T) {
   584  	defer ConfigTeardown()
   585  
   586  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   587  
   588  	_ = MustParse(`{
   589  		"type": "record",
   590  		"name": "test.embed",
   591  		"fields" : [
   592  			{"name": "a", "type": "string"}
   593  		]
   594  	}`)
   595  
   596  	schema := MustParse(`{
   597  		"type": "record",
   598  		"name": "test",
   599  		"fields" : [
   600  			{"name": "a", "type": "string"},
   601  			{"name": "b", "type": "test.embed", "default": {"a": "foo"}}
   602  		]
   603  	}`)
   604  
   605  	schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   606  
   607  	dec := NewDecoderForSchema(schema, bytes.NewReader(data))
   608  
   609  	var got map[string]any
   610  	err := dec.Decode(&got)
   611  
   612  	require.NoError(t, err)
   613  	assert.Equal(t, map[string]any{"b": map[string]any{"a": "foo"}, "a": "foo"}, got)
   614  }
   615  
   616  func TestDecoder_DefaultFixed(t *testing.T) {
   617  	defer ConfigTeardown()
   618  
   619  	data := []byte{0x6, 0x66, 0x6f, 0x6f}
   620  
   621  	t.Run("array", func(t *testing.T) {
   622  		schema := MustParse(`{
   623  			"type": "record",
   624  			"name": "test",
   625  			"fields" : [
   626  				{"name": "a", "type": "string"},
   627  				{
   628  					"name": "b",
   629  					"type": {
   630  						"type": "fixed",
   631  						"name": "test.fixed",
   632  						"size": 3
   633  					}, 
   634  					"default": "foo"
   635  				}
   636  			]
   637  		}`)
   638  
   639  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   640  
   641  		type TestRecord struct {
   642  			A string  `avro:"a"`
   643  			B [3]byte `avro:"b"`
   644  		}
   645  
   646  		var got TestRecord
   647  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   648  
   649  		require.NoError(t, err)
   650  		assert.Equal(t, TestRecord{B: [3]byte{'f', 'o', 'o'}, A: "foo"}, got)
   651  	})
   652  
   653  	t.Run("uint64", func(t *testing.T) {
   654  		schema := MustParse(`{
   655  			"type": "record",
   656  			"name": "test",
   657  			"fields" : [
   658  				{"name": "a", "type": "string"},
   659  				{
   660  					"name": "b",
   661  					"type": {
   662  						"type": "fixed",
   663  						"name": "test.fixed",
   664  						"size": 8
   665  					}, 
   666  					"default": "\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff"
   667  				}
   668  			]
   669  		}`)
   670  
   671  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   672  
   673  		type TestRecord struct {
   674  			A string `avro:"a"`
   675  			B uint64 `avro:"b"`
   676  		}
   677  
   678  		var got TestRecord
   679  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   680  
   681  		require.NoError(t, err)
   682  		assert.Equal(t, TestRecord{B: uint64(math.MaxUint64), A: "foo"}, got)
   683  	})
   684  
   685  	t.Run("duration", func(t *testing.T) {
   686  		schema := MustParse(`{
   687  			"type": "record",
   688  			"name": "test",
   689  			"fields" : [
   690  				{"name": "a", "type": "string"},
   691  				{
   692  					"name": "b",
   693  					"type": {
   694  						"type": "fixed",
   695  						"name": "test.fixed",
   696  						"logicalType":"duration",
   697  						"size":12
   698  					}, 
   699  					"default": "\u000c\u0000\u0000\u0000\u0022\u0000\u0000\u0000\u0052\u00aa\u0008\u0000"
   700  				}
   701  			]
   702  		}`)
   703  
   704  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   705  
   706  		type TestRecord struct {
   707  			A string          `avro:"a"`
   708  			B LogicalDuration `avro:"b"`
   709  		}
   710  
   711  		var got TestRecord
   712  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   713  
   714  		require.NoError(t, err)
   715  
   716  		assert.Equal(t, uint32(12), got.B.Months)
   717  		assert.Equal(t, uint32(34), got.B.Days)
   718  		assert.Equal(t, uint32(567890), got.B.Milliseconds)
   719  		assert.Equal(t, "foo", got.A)
   720  	})
   721  
   722  	t.Run("rat", func(t *testing.T) {
   723  		schema := MustParse(`{
   724  			"type": "record",
   725  			"name": "test",
   726  			"fields" : [
   727  				{"name": "a", "type": "string"},
   728  				{
   729  					"name": "b",
   730  					"type": {
   731  						"type": "fixed",
   732  						"name": "test.fixed",
   733  						"size": 6,
   734  						"logicalType":"decimal",
   735  						"precision":4,
   736  						"scale":2
   737  					}, 
   738  					"default": "\u0000\u0000\u0000\u0000\u0087\u0078"
   739  				}
   740  			]
   741  		}`)
   742  		schema.(*RecordSchema).Fields()[1].action = FieldSetDefault
   743  
   744  		type TestRecord struct {
   745  			A string  `avro:"a"`
   746  			B big.Rat `avro:"b"`
   747  		}
   748  
   749  		var got TestRecord
   750  		err := NewDecoderForSchema(schema, bytes.NewReader(data)).Decode(&got)
   751  
   752  		require.NoError(t, err)
   753  		assert.Equal(t, big.NewRat(1734, 5), &got.B)
   754  		assert.Equal(t, "foo", got.A)
   755  	})
   756  }