github.com/hamba/avro@v1.8.0/schema_compatibility_test.go (about) 1 package avro_test 2 3 import ( 4 "testing" 5 6 "github.com/hamba/avro" 7 "github.com/stretchr/testify/assert" 8 ) 9 10 func TestNewSchemaCompatibility(t *testing.T) { 11 sc := avro.NewSchemaCompatibility() 12 13 assert.IsType(t, &avro.SchemaCompatibility{}, sc) 14 } 15 16 func TestSchemaCompatibility_Compatible(t *testing.T) { 17 tests := []struct { 18 name string 19 reader string 20 writer string 21 wantErr bool 22 }{ 23 { 24 name: "Primitive Matching", 25 reader: `"int"`, 26 writer: `"int"`, 27 wantErr: false, 28 }, 29 { 30 name: "Int Promote Long", 31 reader: `"long"`, 32 writer: `"int"`, 33 wantErr: false, 34 }, 35 { 36 name: "Int Promote Float", 37 reader: `"float"`, 38 writer: `"int"`, 39 wantErr: false, 40 }, 41 { 42 name: "Int Promote Double", 43 reader: `"double"`, 44 writer: `"int"`, 45 wantErr: false, 46 }, 47 { 48 name: "Long Promote Float", 49 reader: `"float"`, 50 writer: `"long"`, 51 wantErr: false, 52 }, 53 { 54 name: "Long Promote Double", 55 reader: `"double"`, 56 writer: `"long"`, 57 wantErr: false, 58 }, 59 { 60 name: "Float Promote Double", 61 reader: `"double"`, 62 writer: `"float"`, 63 wantErr: false, 64 }, 65 { 66 name: "String Promote Bytes", 67 reader: `"bytes"`, 68 writer: `"string"`, 69 wantErr: false, 70 }, 71 { 72 name: "Bytes Promote String", 73 reader: `"string"`, 74 writer: `"bytes"`, 75 wantErr: false, 76 }, 77 { 78 name: "Union Match", 79 reader: `["int", "long", "string"]`, 80 writer: `["string", "int", "long"]`, 81 wantErr: false, 82 }, 83 { 84 name: "Union Reader Missing Schema", 85 reader: `["int", "string"]`, 86 writer: `["string", "int", "long"]`, 87 wantErr: true, 88 }, 89 { 90 name: "Union Writer Missing Schema", 91 reader: `["int", "long", "string"]`, 92 writer: `["string", "int"]`, 93 wantErr: false, 94 }, 95 { 96 name: "Union Writer Not Union", 97 reader: `["int", "long", "string"]`, 98 writer: `"int"`, 99 wantErr: false, 100 }, 101 { 102 name: "Union Writer Not Union With Error", 103 reader: `["string"]`, 104 writer: `"int"`, 105 wantErr: true, 106 }, 107 { 108 name: "Union Reader Not Union", 109 reader: `"int"`, 110 writer: `["int"]`, 111 wantErr: false, 112 }, 113 { 114 name: "Union Reader Not Union With Error", 115 reader: `"int"`, 116 writer: `["string", "int", "long"]`, 117 wantErr: true, 118 }, 119 { 120 name: "Array Match", 121 reader: `{"type":"array", "items": "int"}`, 122 writer: `{"type":"array", "items": "int"}`, 123 wantErr: false, 124 }, 125 { 126 name: "Array Items Mismatch", 127 reader: `{"type":"array", "items": "int"}`, 128 writer: `{"type":"array", "items": "string"}`, 129 wantErr: true, 130 }, 131 { 132 name: "Map Match", 133 reader: `{"type":"map", "values": "int"}`, 134 writer: `{"type":"map", "values": "int"}`, 135 wantErr: false, 136 }, 137 { 138 name: "Map Items Mismatch", 139 reader: `{"type":"map", "values": "int"}`, 140 writer: `{"type":"map", "values": "string"}`, 141 wantErr: true, 142 }, 143 { 144 name: "Fixed Match", 145 reader: `{"type":"fixed", "name":"test", "namespace": "org.hamba.avro", "size": 12}`, 146 writer: `{"type":"fixed", "name":"test", "namespace": "org.hamba.avro", "size": 12}`, 147 wantErr: false, 148 }, 149 { 150 name: "Fixed Name Mismatch", 151 reader: `{"type":"fixed", "name":"test1", "namespace": "org.hamba.avro", "size": 12}`, 152 writer: `{"type":"fixed", "name":"test", "namespace": "org.hamba.avro", "size": 12}`, 153 wantErr: true, 154 }, 155 { 156 name: "Fixed Size Mismatch", 157 reader: `{"type":"fixed", "name":"test", "namespace": "org.hamba.avro", "size": 13}`, 158 writer: `{"type":"fixed", "name":"test", "namespace": "org.hamba.avro", "size": 12}`, 159 wantErr: true, 160 }, 161 { 162 name: "Enum Match", 163 reader: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 164 writer: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 165 wantErr: false, 166 }, 167 { 168 name: "Enum Name Mismatch", 169 reader: `{"type":"enum", "name":"test1", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 170 writer: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 171 wantErr: true, 172 }, 173 { 174 name: "Enum Reader Missing Symbol", 175 reader: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1"]}`, 176 writer: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 177 wantErr: true, 178 }, 179 { 180 name: "Enum Writer Missing Symbol", 181 reader: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1", "TEST2"]}`, 182 writer: `{"type":"enum", "name":"test", "namespace": "org.hamba.avro", "symbols":["TEST1"]}`, 183 wantErr: false, 184 }, 185 { 186 name: "Record Match", 187 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}, {"name": "b", "type": "string"}]}`, 188 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "string"}, {"name": "a", "type": "int"}]}`, 189 wantErr: false, 190 }, 191 { 192 name: "Record Name Mismatch", 193 reader: `{"type":"record", "name":"test1", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int", "default": 1}, {"name": "b", "type": "string"}]}`, 194 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "string", "default": "b"}, {"name": "a", "type": "int"}]}`, 195 wantErr: true, 196 }, 197 { 198 name: "Record Schema Mismatch", 199 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "string"}, {"name": "b", "type": "string"}]}`, 200 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "string"}, {"name": "a", "type": "int"}]}`, 201 wantErr: true, 202 }, 203 { 204 name: "Record Reader Field Missing", 205 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}]}`, 206 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "string"}, {"name": "a", "type": "int"}]}`, 207 wantErr: false, 208 }, 209 { 210 name: "Record Writer Field Missing With Default", 211 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}, {"name": "b", "type": "string", "default": "test"}]}`, 212 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}]}`, 213 wantErr: false, 214 }, 215 { 216 name: "Record Writer Field Missing Without Default", 217 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}, {"name": "b", "type": "string"}]}`, 218 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "int"}]}`, 219 wantErr: true, 220 }, 221 { 222 name: "Ref Dereference", 223 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": {"type":"record", "name":"test1", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "int"}]}}, {"name": "b", "type": "test1"}]}`, 224 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": {"type":"record", "name":"test1", "namespace": "org.hamba.avro", "fields":[{"name": "b", "type": "int"}]}}, {"name": "b", "type": "test"}]}`, 225 wantErr: true, 226 }, 227 { 228 name: "Breaks Recursion", 229 reader: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "test"}]}`, 230 writer: `{"type":"record", "name":"test", "namespace": "org.hamba.avro", "fields":[{"name": "a", "type": "test"}]}`, 231 wantErr: false, 232 }, 233 } 234 235 for _, tt := range tests { 236 t.Run(tt.name, func(t *testing.T) { 237 r := avro.MustParse(tt.reader) 238 w := avro.MustParse(tt.writer) 239 sc := avro.NewSchemaCompatibility() 240 241 err := sc.Compatible(r, w) 242 243 if tt.wantErr { 244 assert.Error(t, err) 245 return 246 } 247 248 assert.NoError(t, err) 249 }) 250 } 251 } 252 253 func TestSchemaCompatibility_CompatibleUsesCacheWithNoError(t *testing.T) { 254 reader := `"int"` 255 writer := `"int"` 256 257 r := avro.MustParse(reader) 258 w := avro.MustParse(writer) 259 sc := avro.NewSchemaCompatibility() 260 261 _ = sc.Compatible(r, w) 262 263 err := sc.Compatible(r, w) 264 265 assert.NoError(t, err) 266 } 267 268 func TestSchemaCompatibility_CompatibleUsesCacheWithError(t *testing.T) { 269 reader := `"int"` 270 writer := `"string"` 271 272 r := avro.MustParse(reader) 273 w := avro.MustParse(writer) 274 sc := avro.NewSchemaCompatibility() 275 276 _ = sc.Compatible(r, w) 277 278 err := sc.Compatible(r, w) 279 280 assert.Error(t, err) 281 }