github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/decoder_record_test.go (about) 1 package avro_test 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/hamba/avro/v2" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestDecoder_RecordStruct(t *testing.T) { 13 defer ConfigTeardown() 14 15 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 16 schema := `{ 17 "type": "record", 18 "name": "test", 19 "fields" : [ 20 {"name": "a", "type": "long"}, 21 {"name": "b", "type": "string"} 22 ] 23 }` 24 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 25 require.NoError(t, err) 26 27 var got TestRecord 28 err = dec.Decode(&got) 29 30 require.NoError(t, err) 31 assert.Equal(t, TestRecord{A: 27, B: "foo"}, got) 32 } 33 34 func TestDecoder_RecordStructPtr(t *testing.T) { 35 defer ConfigTeardown() 36 37 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 38 schema := `{ 39 "type": "record", 40 "name": "test", 41 "fields" : [ 42 {"name": "a", "type": "long"}, 43 {"name": "b", "type": "string"} 44 ] 45 }` 46 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 47 require.NoError(t, err) 48 49 got := &TestRecord{} 50 err = dec.Decode(&got) 51 52 require.NoError(t, err) 53 assert.Equal(t, &TestRecord{A: 27, B: "foo"}, got) 54 } 55 56 func TestDecoder_RecordStructPtrNil(t *testing.T) { 57 defer ConfigTeardown() 58 59 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 60 schema := `{ 61 "type": "record", 62 "name": "test", 63 "fields" : [ 64 {"name": "a", "type": "long"}, 65 {"name": "b", "type": "string"} 66 ] 67 }` 68 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 69 require.NoError(t, err) 70 71 var got *TestRecord 72 err = dec.Decode(&got) 73 74 require.NoError(t, err) 75 assert.Equal(t, &TestRecord{A: 27, B: "foo"}, got) 76 } 77 78 func TestDecoder_RecordStructWithFieldAlias(t *testing.T) { 79 defer ConfigTeardown() 80 81 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 82 schema := `{ 83 "type": "record", 84 "name": "test", 85 "fields" : [ 86 {"name": "c", "aliases": ["a"], "type": "long"}, 87 {"name": "b", "type": "string"} 88 ] 89 }` 90 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 91 assert.NoError(t, err) 92 93 var got TestRecord 94 err = dec.Decode(&got) 95 96 assert.NoError(t, err) 97 assert.Equal(t, TestRecord{A: 27, B: "foo"}, got) 98 } 99 100 func TestDecoder_RecordPartialStruct(t *testing.T) { 101 defer ConfigTeardown() 102 103 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 104 schema := `{ 105 "type": "record", 106 "name": "test", 107 "fields" : [ 108 {"name": "a", "type": "long"}, 109 {"name": "b", "type": "string"} 110 ] 111 }` 112 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 113 require.NoError(t, err) 114 115 var got TestPartialRecord 116 err = dec.Decode(&got) 117 118 require.NoError(t, err) 119 assert.Equal(t, TestPartialRecord{B: "foo"}, got) 120 } 121 122 func TestDecoder_RecordStructInvalidData(t *testing.T) { 123 defer ConfigTeardown() 124 125 data := []byte{0xE2, 0xA2, 0xF3, 0xAD, 0xAD, 0xAD, 0xE2, 0xA2, 0xF3, 0xAD, 0xAD, 0x06, 0x66, 0x6f, 0x6f} 126 schema := `{ 127 "type": "record", 128 "name": "test", 129 "fields" : [ 130 {"name": "a", "type": "long"}, 131 {"name": "b", "type": "string"} 132 ] 133 }` 134 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 135 require.NoError(t, err) 136 137 var got TestRecord 138 err = dec.Decode(&got) 139 140 assert.Error(t, err) 141 } 142 143 func TestDecoder_RecordEmbeddedStruct(t *testing.T) { 144 defer ConfigTeardown() 145 146 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x06, 0x62, 0x61, 0x72} 147 schema := `{ 148 "type": "record", 149 "name": "test", 150 "fields" : [ 151 {"name": "a", "type": "long"}, 152 {"name": "b", "type": "string"}, 153 {"name": "c", "type": "string"} 154 ] 155 }` 156 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 157 require.NoError(t, err) 158 159 var got TestEmbeddedRecord 160 err = dec.Decode(&got) 161 162 require.NoError(t, err) 163 assert.Equal(t, TestEmbeddedRecord{TestEmbed: TestEmbed{A: 27, B: "foo"}, C: "bar"}, got) 164 } 165 166 func TestDecoder_RecordEmbeddedPtrStruct(t *testing.T) { 167 defer ConfigTeardown() 168 169 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x06, 0x62, 0x61, 0x72} 170 schema := `{ 171 "type": "record", 172 "name": "test", 173 "fields" : [ 174 {"name": "a", "type": "long"}, 175 {"name": "b", "type": "string"}, 176 {"name": "c", "type": "string"} 177 ] 178 }` 179 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 180 require.NoError(t, err) 181 182 var got TestEmbeddedPtrRecord 183 err = dec.Decode(&got) 184 185 require.NoError(t, err) 186 assert.Equal(t, TestEmbeddedPtrRecord{TestEmbed: &TestEmbed{A: 27, B: "foo"}, C: "bar"}, got) 187 } 188 189 func TestDecoder_RecordEmbeddedPtrStructNew(t *testing.T) { 190 defer ConfigTeardown() 191 192 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x06, 0x62, 0x61, 0x72} 193 schema := `{ 194 "type": "record", 195 "name": "test", 196 "fields" : [ 197 {"name": "a", "type": "long"}, 198 {"name": "b", "type": "string"}, 199 {"name": "c", "type": "string"} 200 ] 201 }` 202 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 203 require.NoError(t, err) 204 205 var got TestEmbeddedPtrRecord 206 got.C = "nonzero" // non-zero value here triggers bug in allocating TestEmbed 207 err = dec.Decode(&got) 208 209 require.NoError(t, err) 210 assert.Equal(t, TestEmbeddedPtrRecord{TestEmbed: &TestEmbed{A: 27, B: "foo"}, C: "bar"}, got) 211 } 212 213 func TestDecoder_RecordEmbeddedIntStruct(t *testing.T) { 214 defer ConfigTeardown() 215 216 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x06, 0x62, 0x61, 0x72} 217 schema := `{ 218 "type": "record", 219 "name": "test", 220 "fields" : [ 221 {"name": "a", "type": "long"}, 222 {"name": "b", "type": "string"}, 223 {"name": "c", "type": "string"} 224 ] 225 }` 226 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 227 require.NoError(t, err) 228 229 var got TestEmbeddedIntRecord 230 err = dec.Decode(&got) 231 232 require.NoError(t, err) 233 assert.Equal(t, TestEmbeddedIntRecord{B: "foo"}, got) 234 } 235 236 func TestDecoder_RecordMap(t *testing.T) { 237 defer ConfigTeardown() 238 239 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 240 schema := `{ 241 "type": "record", 242 "name": "test", 243 "fields" : [ 244 {"name": "a", "type": "long"}, 245 {"name": "b", "type": "string"} 246 ] 247 }` 248 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 249 require.NoError(t, err) 250 251 var got map[string]any 252 err = dec.Decode(&got) 253 254 require.NoError(t, err) 255 assert.Equal(t, map[string]any{"a": int64(27), "b": "foo"}, got) 256 } 257 258 func TestDecoder_RecordMapInvalidKey(t *testing.T) { 259 defer ConfigTeardown() 260 261 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 262 schema := `{ 263 "type": "record", 264 "name": "test", 265 "fields" : [ 266 {"name": "a", "type": "long"}, 267 {"name": "b", "type": "string"} 268 ] 269 }` 270 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 271 require.NoError(t, err) 272 273 var got map[int]any 274 err = dec.Decode(&got) 275 276 assert.Error(t, err) 277 } 278 279 func TestDecoder_RecordMapInvalidElem(t *testing.T) { 280 defer ConfigTeardown() 281 282 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 283 schema := `{ 284 "type": "record", 285 "name": "test", 286 "fields" : [ 287 {"name": "a", "type": "long"}, 288 {"name": "b", "type": "string"} 289 ] 290 }` 291 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 292 require.NoError(t, err) 293 294 var got map[string]string 295 err = dec.Decode(&got) 296 297 assert.Error(t, err) 298 } 299 300 func TestDecoder_RecordMapInvalidData(t *testing.T) { 301 defer ConfigTeardown() 302 303 data := []byte{0xE2, 0xA2, 0xF3, 0xAD, 0xAD, 0xAD, 0xE2, 0xA2, 0xF3, 0xAD, 0xAD, 0x06, 0x66, 0x6f, 0x6f} 304 schema := `{ 305 "type": "record", 306 "name": "test", 307 "fields" : [ 308 {"name": "a", "type": "long"}, 309 {"name": "b", "type": "string"} 310 ] 311 }` 312 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 313 require.NoError(t, err) 314 315 var got map[string]any 316 err = dec.Decode(&got) 317 318 assert.Error(t, err) 319 } 320 321 func TestDecoder_RecordInterface(t *testing.T) { 322 defer ConfigTeardown() 323 324 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 325 schema := `{ 326 "type": "record", 327 "name": "test", 328 "fields" : [ 329 {"name": "a", "type": "long"}, 330 {"name": "b", "type": "string"} 331 ] 332 }` 333 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 334 require.NoError(t, err) 335 336 var got TestInterface = &TestRecord{} 337 err = dec.Decode(&got) 338 339 require.NoError(t, err) 340 assert.Equal(t, &TestRecord{A: 27, B: "foo"}, got) 341 } 342 343 func TestDecoder_RecordEmptyInterface(t *testing.T) { 344 defer ConfigTeardown() 345 346 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f} 347 schema := `{ 348 "type": "record", 349 "name": "test", 350 "fields" : [ 351 {"name": "a", "type": "long"}, 352 {"name": "b", "type": "string"} 353 ] 354 }` 355 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 356 require.NoError(t, err) 357 358 var got TestInterface 359 err = dec.Decode(&got) 360 361 assert.Error(t, err) 362 } 363 364 func TestDecoder_RefStruct(t *testing.T) { 365 defer ConfigTeardown() 366 367 data := []byte{0x36, 0x06, 0x66, 0x6f, 0x6f, 0x36, 0x06, 0x66, 0x6f, 0x6f} 368 schema := `{ 369 "type": "record", 370 "name": "parent", 371 "fields" : [ 372 {"name": "a", "type": { 373 "type": "record", 374 "name": "test", 375 "fields" : [ 376 {"name": "a", "type": "long"}, 377 {"name": "b", "type": "string"} 378 ]} 379 }, 380 {"name": "b", "type": "test"} 381 ] 382 }` 383 dec, err := avro.NewDecoder(schema, bytes.NewReader(data)) 384 require.NoError(t, err) 385 386 var got TestNestedRecord 387 err = dec.Decode(&got) 388 389 want := TestNestedRecord{ 390 A: TestRecord{A: 27, B: "foo"}, 391 B: TestRecord{A: 27, B: "foo"}, 392 } 393 require.NoError(t, err) 394 assert.Equal(t, want, got) 395 }