github.com/hamba/avro@v1.8.0/reader_generic_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 TestReader_ReadNext(t *testing.T) {
    14  	tests := []struct {
    15  		name    string
    16  		data    []byte
    17  		schema  string
    18  		want    interface{}
    19  		wantErr bool
    20  	}{
    21  
    22  		{
    23  			name:    "Bool",
    24  			data:    []byte{0x01},
    25  			schema:  "boolean",
    26  			want:    true,
    27  			wantErr: false,
    28  		},
    29  		{
    30  			name:    "Int",
    31  			data:    []byte{0x36},
    32  			schema:  "int",
    33  			want:    27,
    34  			wantErr: false,
    35  		},
    36  		{
    37  			name:    "Int Date",
    38  			data:    []byte{0xAE, 0x9D, 0x02},
    39  			schema:  `{"type":"int","logicalType":"date"}`,
    40  			want:    time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC),
    41  			wantErr: false,
    42  		},
    43  		{
    44  			name:    "Int Time-Millis",
    45  			data:    []byte{0xAA, 0xB4, 0xDE, 0x75},
    46  			schema:  `{"type":"int","logicalType":"time-millis"}`,
    47  			want:    123456789 * time.Millisecond,
    48  			wantErr: false,
    49  		},
    50  		{
    51  			name:    "Long",
    52  			data:    []byte{0x36},
    53  			schema:  "long",
    54  			want:    int64(27),
    55  			wantErr: false,
    56  		},
    57  		{
    58  			name:    "Long Time-Micros",
    59  			data:    []byte{0x86, 0xEA, 0xC8, 0xE9, 0x97, 0x07},
    60  			schema:  `{"type":"long","logicalType":"time-micros"}`,
    61  			want:    123456789123 * time.Microsecond,
    62  			wantErr: false,
    63  		},
    64  		{
    65  			name:    "Long Timestamp-Millis",
    66  			data:    []byte{0x90, 0xB2, 0xAE, 0xC3, 0xEC, 0x5B},
    67  			schema:  `{"type":"long","logicalType":"timestamp-millis"}`,
    68  			want:    time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC),
    69  			wantErr: false,
    70  		},
    71  		{
    72  			name:    "Long Timestamp-Micros",
    73  			data:    []byte{0x80, 0xCD, 0xB7, 0xA2, 0xEE, 0xC7, 0xCD, 0x05},
    74  			schema:  `{"type":"long","logicalType":"timestamp-micros"}`,
    75  			want:    time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC),
    76  			wantErr: false,
    77  		},
    78  		{
    79  			name:    "Float",
    80  			data:    []byte{0x33, 0x33, 0x93, 0x3F},
    81  			schema:  "float",
    82  			want:    float32(1.15),
    83  			wantErr: false,
    84  		},
    85  		{
    86  			name:    "Double",
    87  			data:    []byte{0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF2, 0x3F},
    88  			schema:  "double",
    89  			want:    float64(1.15),
    90  			wantErr: false,
    91  		},
    92  		{
    93  			name:    "String",
    94  			data:    []byte{0x06, 0x66, 0x6F, 0x6F},
    95  			schema:  "string",
    96  			want:    "foo",
    97  			wantErr: false,
    98  		},
    99  		{
   100  			name:    "Bytes",
   101  			data:    []byte{0x08, 0xEC, 0xAB, 0x44, 0x00},
   102  			schema:  "bytes",
   103  			want:    []byte{0xEC, 0xAB, 0x44, 0x00},
   104  			wantErr: false,
   105  		},
   106  		{
   107  			name:    "Bytes Decimal",
   108  			data:    []byte{0x6, 0x00, 0x87, 0x78},
   109  			schema:  `{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}`,
   110  			want:    big.NewRat(1734, 5),
   111  			wantErr: false,
   112  		},
   113  		{
   114  			name:    "Record",
   115  			data:    []byte{0x36, 0x06, 0x66, 0x6f, 0x6f},
   116  			schema:  `{"type": "record", "name": "test", "fields" : [{"name": "a", "type": "long"}, {"name": "b", "type": "string"}]}`,
   117  			want:    map[string]interface{}{"a": int64(27), "b": "foo"},
   118  			wantErr: false,
   119  		},
   120  		{
   121  			name:    "Ref",
   122  			data:    []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x36, 0x06, 0x66, 0x6f, 0x6f},
   123  			schema:  `{"type":"record","name":"parent","fields":[{"name":"a","type":{"type":"record","name":"test","fields":[{"name":"a","type":"long"},{"name":"b","type":"string"}]}},{"name":"b","type":"test"}]}`,
   124  			want:    map[string]interface{}{"a": map[string]interface{}{"a": int64(27), "b": "foo"}, "b": map[string]interface{}{"a": int64(27), "b": "foo"}},
   125  			wantErr: false,
   126  		},
   127  		{
   128  			name:    "Array",
   129  			data:    []byte{0x04, 0x36, 0x38, 0x0},
   130  			schema:  `{"type":"array", "items": "int"}`,
   131  			want:    []interface{}{27, 28},
   132  			wantErr: false,
   133  		},
   134  		{
   135  			name:    "Map",
   136  			data:    []byte{0x02, 0x06, 0x66, 0x6F, 0x6F, 0x06, 0x66, 0x6F, 0x6F, 0x00},
   137  			schema:  `{"type":"map", "values": "string"}`,
   138  			want:    map[string]interface{}{"foo": "foo"},
   139  			wantErr: false,
   140  		},
   141  		{
   142  			name:    "Enum",
   143  			data:    []byte{0x02},
   144  			schema:  `{"type":"enum", "name": "test", "symbols": ["foo", "bar"]}`,
   145  			want:    "bar",
   146  			wantErr: false,
   147  		},
   148  		{
   149  			name:    "Enum Invalid Symbol",
   150  			data:    []byte{0x04},
   151  			schema:  `{"type":"enum", "name": "test", "symbols": ["foo", "bar"]}`,
   152  			want:    nil,
   153  			wantErr: true,
   154  		},
   155  		{
   156  			name:    "Union",
   157  			data:    []byte{0x02, 0x06, 0x66, 0x6F, 0x6F},
   158  			schema:  `["null", "string"]`,
   159  			want:    map[string]interface{}{"string": "foo"},
   160  			wantErr: false,
   161  		},
   162  		{
   163  			name:    "Union Nil",
   164  			data:    []byte{0x00},
   165  			schema:  `["null", "string"]`,
   166  			want:    nil,
   167  			wantErr: false,
   168  		},
   169  		{
   170  			name:    "Union Named",
   171  			data:    []byte{0x02, 0x02},
   172  			schema:  `["null", {"type":"enum", "name": "test", "symbols": ["foo", "bar"]}]`,
   173  			want:    map[string]interface{}{"test": "bar"},
   174  			wantErr: false,
   175  		},
   176  		{
   177  			name:    "Union Invalid Schema",
   178  			data:    []byte{0x04},
   179  			schema:  `["null", "string"]`,
   180  			want:    nil,
   181  			wantErr: true,
   182  		},
   183  		{
   184  			name:    "Fixed",
   185  			data:    []byte{0x66, 0x6F, 0x6F, 0x66, 0x6F, 0x6F},
   186  			schema:  `{"type":"fixed", "name": "test", "size": 6}`,
   187  			want:    []byte{'f', 'o', 'o', 'f', 'o', 'o'},
   188  			wantErr: false,
   189  		},
   190  		{
   191  			name:    "Fixed Decimal",
   192  			data:    []byte{0x00, 0x00, 0x00, 0x00, 0x87, 0x78},
   193  			schema:  `{"type":"fixed", "name": "test", "size": 6,"logicalType":"decimal","precision":4,"scale":2}`,
   194  			want:    big.NewRat(1734, 5),
   195  			wantErr: false,
   196  		},
   197  	}
   198  
   199  	for _, tt := range tests {
   200  		t.Run(tt.name, func(t *testing.T) {
   201  			schema := avro.MustParse(tt.schema)
   202  			r := avro.NewReader(bytes.NewReader(tt.data), 10)
   203  
   204  			got := r.ReadNext(schema)
   205  
   206  			if tt.wantErr {
   207  				assert.Error(t, r.Error)
   208  				return
   209  			}
   210  
   211  			assert.NoError(t, r.Error)
   212  			assert.Equal(t, tt.want, got)
   213  		})
   214  	}
   215  }
   216  
   217  func TestReader_ReadNextUnsupportedType(t *testing.T) {
   218  	schema := avro.NewPrimitiveSchema(avro.Type("test"), nil)
   219  	r := avro.NewReader(bytes.NewReader([]byte{0x01}), 10)
   220  
   221  	_ = r.ReadNext(schema)
   222  
   223  	assert.Error(t, r.Error)
   224  }