github.com/hamba/avro@v1.8.0/schema_canonical_test.go (about)

     1  package avro_test
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  
     7  	"github.com/hamba/avro"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  // Test cases are taken from the reference implementation here:
    13  // https://github.com/apache/avro/blob/master/share/test/data/schema-tests.txt
    14  
    15  func TestSchema_Canonical(t *testing.T) {
    16  	tests := []struct {
    17  		input     string
    18  		canonical string
    19  	}{
    20  		{
    21  			input:     `"null"`,
    22  			canonical: `"null"`,
    23  		},
    24  		{
    25  			input:     `{"type":"null"}`,
    26  			canonical: `"null"`,
    27  		},
    28  		{
    29  			input:     `"boolean"`,
    30  			canonical: `"boolean"`,
    31  		},
    32  		{
    33  			input:     `{"type":"boolean"}`,
    34  			canonical: `"boolean"`,
    35  		},
    36  		{
    37  			input:     `"int"`,
    38  			canonical: `"int"`,
    39  		},
    40  		{
    41  			input:     `{"type":"int"}`,
    42  			canonical: `"int"`,
    43  		},
    44  		{
    45  			input:     `{"type":"int","logicalType":"date"}`,
    46  			canonical: `{"type":"int","logicalType":"date"}`,
    47  		},
    48  		{
    49  			input:     `{"type":"int","logicalType":"time-millis"}`,
    50  			canonical: `{"type":"int","logicalType":"time-millis"}`,
    51  		},
    52  		{
    53  			input:     `{"type":"int"}`,
    54  			canonical: `"int"`,
    55  		},
    56  		{
    57  			input:     `"long"`,
    58  			canonical: `"long"`,
    59  		},
    60  		{
    61  			input:     `{"type":"long"}`,
    62  			canonical: `"long"`,
    63  		},
    64  		{
    65  			input:     `{"type":"long","logicalType":"time-micros"}`,
    66  			canonical: `{"type":"long","logicalType":"time-micros"}`,
    67  		},
    68  		{
    69  			input:     `{"type":"long","logicalType":"timestamp-millis"}`,
    70  			canonical: `{"type":"long","logicalType":"timestamp-millis"}`,
    71  		},
    72  		{
    73  			input:     `{"type":"long","logicalType":"timestamp-millis"}`,
    74  			canonical: `{"type":"long","logicalType":"timestamp-millis"}`,
    75  		},
    76  		{
    77  			input:     `"float"`,
    78  			canonical: `"float"`,
    79  		},
    80  		{
    81  			input:     `{"type":"float"}`,
    82  			canonical: `"float"`,
    83  		},
    84  		{
    85  			input:     `"double"`,
    86  			canonical: `"double"`,
    87  		},
    88  		{
    89  			input:     `{"type":"double"}`,
    90  			canonical: `"double"`,
    91  		},
    92  		{
    93  			input:     `"bytes"`,
    94  			canonical: `"bytes"`,
    95  		},
    96  		{
    97  			input:     `{"type":"bytes"}`,
    98  			canonical: `"bytes"`,
    99  		},
   100  		{
   101  			input:     `{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}`,
   102  			canonical: `{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}`,
   103  		},
   104  		{
   105  			input:     `{"type":"bytes","logicalType":"decimal","precision":4,"scale":0}`,
   106  			canonical: `{"type":"bytes","logicalType":"decimal","precision":4}`,
   107  		},
   108  		{
   109  			input:     `"string"`,
   110  			canonical: `"string"`,
   111  		},
   112  		{
   113  			input:     `{"type":"string"}`,
   114  			canonical: `"string"`,
   115  		},
   116  		{
   117  			input:     `{"type":"string","logicalType":"uuid"}`,
   118  			canonical: `{"type":"string","logicalType":"uuid"}`,
   119  		},
   120  		{
   121  			input:     `[  ]`,
   122  			canonical: `[]`,
   123  		},
   124  		{
   125  			input:     `[ "int"  ]`,
   126  			canonical: `["int"]`,
   127  		},
   128  		{
   129  			input:     `[ "int" , {"type":"boolean"} ]`,
   130  			canonical: `["int","boolean"]`,
   131  		},
   132  		{
   133  			input:     `{"fields":[], "type":"error", "name":"foo"}`,
   134  			canonical: `{"name":"foo","type":"error","fields":[]}`,
   135  		},
   136  		{
   137  			input:     `{"fields":[], "type":"record", "name":"foo"}`,
   138  			canonical: `{"name":"foo","type":"record","fields":[]}`,
   139  		},
   140  		{
   141  			input:     `{"fields":[], "type":"record", "name":"foo", "namespace":"x.y"}`,
   142  			canonical: `{"name":"x.y.foo","type":"record","fields":[]}`,
   143  		},
   144  		{
   145  			input:     `{"fields":[], "type":"record", "name":"a.b.foo", "namespace":"x.y"}`,
   146  			canonical: `{"name":"a.b.foo","type":"record","fields":[]}`,
   147  		},
   148  		{
   149  			input:     `{"fields":[], "type":"record", "name":"foo", "doc":"Useful info"}`,
   150  			canonical: `{"name":"foo","type":"record","fields":[]}`,
   151  		},
   152  		{
   153  			input:     `{"fields":[], "type":"record", "name":"foo", "aliases":["foo","bar"]}`,
   154  			canonical: `{"name":"foo","type":"record","fields":[]}`,
   155  		},
   156  		{
   157  			input:     `{"fields":[], "type":"record", "name":"foo", "doc":"foo", "aliases":["foo","bar"]}`,
   158  			canonical: `{"name":"foo","type":"record","fields":[]}`,
   159  		},
   160  		{
   161  			input:     `{"fields":[{"type":{"type":"boolean"}, "name":"f1"}], "type":"record", "name":"foo"}`,
   162  			canonical: `{"name":"foo","type":"record","fields":[{"name":"f1","type":"boolean"}]}`,
   163  		},
   164  		{
   165  			input: `
   166  { "fields":[{"type":"boolean", "aliases":[], "name":"f1", "default":true},
   167             {"order":"descending","name":"f2","doc":"Hello","type":"int"}],
   168   "type":"record", "name":"foo"
   169  }`,
   170  			canonical: `{"name":"foo","type":"record","fields":[{"name":"f1","type":"boolean"},{"name":"f2","type":"int"}]}`,
   171  		},
   172  		{
   173  			input:     `{"type":"enum", "name":"foo", "symbols":["A1"]}`,
   174  			canonical: `{"name":"foo","type":"enum","symbols":["A1"]}`,
   175  		},
   176  		{
   177  			input:     `{"namespace":"x.y.z", "type":"enum", "name":"foo", "doc":"foo bar", "symbols":["A1", "A2"]}`,
   178  			canonical: `{"name":"x.y.z.foo","type":"enum","symbols":["A1","A2"]}`,
   179  		},
   180  		{
   181  			input:     `{"name":"foo","type":"fixed","size":15}`,
   182  			canonical: `{"name":"foo","type":"fixed","size":15}`,
   183  		},
   184  		{
   185  			input:     `{"name":"foo","type":"fixed","logicalType":"duration","size":12}`,
   186  			canonical: `{"name":"foo","type":"fixed","size":12,"logicalType":"duration"}`,
   187  		},
   188  		{
   189  			input:     `{"name":"foo","type":"fixed","logicalType":"decimal","size":12,"precision":4,"scale":2}`,
   190  			canonical: `{"name":"foo","type":"fixed","size":12,"logicalType":"decimal","precision":4,"scale":2}`,
   191  		},
   192  		{
   193  			input:     `{"name":"foo","type":"fixed","logicalType":"decimal","size":12,"precision":4,"scale":0}`,
   194  			canonical: `{"name":"foo","type":"fixed","size":12,"logicalType":"decimal","precision":4}`,
   195  		},
   196  		{
   197  			input:     `{"namespace":"x.y.z", "type":"fixed", "name":"foo", "doc":"foo bar", "size":32}`,
   198  			canonical: `{"name":"x.y.z.foo","type":"fixed","size":32}`,
   199  		},
   200  		{
   201  			input:     `{ "items":{"type":"null"}, "type":"array"}`,
   202  			canonical: `{"type":"array","items":"null"}`,
   203  		},
   204  		{
   205  			input:     `{ "values":"string", "type":"map"}`,
   206  			canonical: `{"type":"map","values":"string"}`,
   207  		},
   208  		{
   209  			input: `
   210  
   211   {"name":"PigValue","type":"record",
   212    "fields":[{"name":"value", "type":["null", "int", "long", "PigValue"]}]}
   213  `,
   214  			canonical: `{"name":"PigValue","type":"record","fields":[{"name":"value","type":["null","int","long","PigValue"]}]}`,
   215  		},
   216  		{
   217  			input: `{
   218  				"type":"record",
   219  				"namespace": "org.hamba.avro",
   220  				"name":"X",
   221    				"fields":[
   222  					{"name":"value", "type":{
   223  						"type":"record",
   224  						"name":"Y",
   225  						"fields":[
   226  							{"name":"value", "type":"string"}
   227  						]
   228  					}}
   229  				]
   230  			}`,
   231  			canonical: `{"name":"org.hamba.avro.X","type":"record","fields":[{"name":"value","type":{"name":"org.hamba.avro.Y","type":"record","fields":[{"name":"value","type":"string"}]}}]}`,
   232  		},
   233  		{
   234  			input: `{
   235  				"type":"record",
   236  				"namespace": "org.hamba.avro",
   237  				"name":"X",
   238    				"fields":[
   239  					{"name":"value", "type":{
   240  						"type":"enum",
   241  						"name":"Y",
   242  						"symbols":["TEST"]
   243  					}}
   244  				]
   245  			}`,
   246  			canonical: `{"name":"org.hamba.avro.X","type":"record","fields":[{"name":"value","type":{"name":"org.hamba.avro.Y","type":"enum","symbols":["TEST"]}}]}`,
   247  		},
   248  		{
   249  			input: `{
   250  				"type":"record",
   251  				"namespace": "org.hamba.avro",
   252  				"name":"X",
   253    				"fields":[
   254  					{"name":"value", "type":{
   255  						"type":"fixed",
   256  						"name":"Y",
   257  						"size":15
   258  					}}
   259  				]
   260  			}`,
   261  			canonical: `{"name":"org.hamba.avro.X","type":"record","fields":[{"name":"value","type":{"name":"org.hamba.avro.Y","type":"fixed","size":15}}]}`,
   262  		},
   263  	}
   264  
   265  	for i, test := range tests {
   266  		test := test
   267  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   268  			s, err := avro.Parse(test.input)
   269  
   270  			require.NoError(t, err)
   271  			assert.Equal(t, test.canonical, s.String())
   272  		})
   273  	}
   274  }