avro_turf 1.19.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +20 -11
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +5 -2
  5. data/Rakefile +2 -1
  6. data/avro_turf.gemspec +16 -16
  7. data/lib/avro_turf/cached_confluent_schema_registry.rb +9 -8
  8. data/lib/avro_turf/cached_schema_registry.rb +3 -1
  9. data/lib/avro_turf/confluent_schema_registry.rb +23 -17
  10. data/lib/avro_turf/core_ext/date.rb +2 -0
  11. data/lib/avro_turf/core_ext/enumerable.rb +2 -0
  12. data/lib/avro_turf/core_ext/false_class.rb +2 -0
  13. data/lib/avro_turf/core_ext/hash.rb +4 -2
  14. data/lib/avro_turf/core_ext/nil_class.rb +2 -0
  15. data/lib/avro_turf/core_ext/numeric.rb +2 -0
  16. data/lib/avro_turf/core_ext/string.rb +2 -0
  17. data/lib/avro_turf/core_ext/symbol.rb +2 -0
  18. data/lib/avro_turf/core_ext/time.rb +2 -0
  19. data/lib/avro_turf/core_ext/true_class.rb +2 -0
  20. data/lib/avro_turf/core_ext.rb +12 -10
  21. data/lib/avro_turf/disk_cache.rb +13 -12
  22. data/lib/avro_turf/in_memory_cache.rb +2 -0
  23. data/lib/avro_turf/messaging.rb +22 -14
  24. data/lib/avro_turf/mutable_schema_store.rb +25 -4
  25. data/lib/avro_turf/schema_registry.rb +3 -1
  26. data/lib/avro_turf/schema_store.rb +3 -2
  27. data/lib/avro_turf/schema_to_avro_patch.rb +14 -12
  28. data/lib/avro_turf/test/fake_confluent_schema_registry_server.rb +24 -23
  29. data/lib/avro_turf/test/fake_prefixed_confluent_schema_registry_server.rb +12 -10
  30. data/lib/avro_turf/test/fake_schema_registry_server.rb +3 -1
  31. data/lib/avro_turf/version.rb +3 -1
  32. data/lib/avro_turf.rb +15 -13
  33. data/perf/encoding_size.rb +4 -2
  34. data/perf/encoding_speed.rb +4 -2
  35. data/spec/avro_turf_spec.rb +24 -23
  36. data/spec/cached_confluent_schema_registry_spec.rb +9 -7
  37. data/spec/confluent_schema_registry_spec.rb +31 -10
  38. data/spec/core_ext/date_spec.rb +2 -0
  39. data/spec/core_ext/enumerable_spec.rb +2 -0
  40. data/spec/core_ext/false_class_spec.rb +2 -0
  41. data/spec/core_ext/hash_spec.rb +3 -1
  42. data/spec/core_ext/nil_class_spec.rb +2 -0
  43. data/spec/core_ext/numeric_spec.rb +2 -0
  44. data/spec/core_ext/string_spec.rb +2 -0
  45. data/spec/core_ext/symbol_spec.rb +2 -0
  46. data/spec/core_ext/time_spec.rb +2 -0
  47. data/spec/core_ext/true_class_spec.rb +2 -0
  48. data/spec/disk_cached_confluent_schema_registry_spec.rb +23 -21
  49. data/spec/messaging_spec.rb +124 -99
  50. data/spec/mutable_schema_store_spec.rb +134 -0
  51. data/spec/schema_store_spec.rb +23 -21
  52. data/spec/schema_to_avro_patch_spec.rb +8 -7
  53. data/spec/spec_helper.rb +9 -9
  54. data/spec/support/authorized_fake_confluent_schema_registry_server.rb +4 -2
  55. data/spec/support/authorized_fake_prefixed_confluent_schema_registry_server.rb +4 -2
  56. data/spec/support/confluent_schema_registry_context.rb +32 -30
  57. data/spec/test/fake_confluent_schema_registry_server_spec.rb +97 -94
  58. metadata +5 -26
@@ -1,5 +1,7 @@
1
- require 'webmock/rspec'
2
- require 'avro_turf/messaging'
1
+ # frozen_string_literal: true
2
+
3
+ require "webmock/rspec"
4
+ require "avro_turf/messaging"
3
5
 
4
6
  describe AvroTurf::Messaging do
5
7
  let(:registry_url) { "http://registry.example.com" }
@@ -19,7 +21,7 @@ describe AvroTurf::Messaging do
19
21
  )
20
22
  }
21
23
 
22
- let(:message) { { "full_name" => "John Doe" } }
24
+ let(:message) { {"full_name" => "John Doe"} }
23
25
  let(:schema_json) do
24
26
  <<-AVSC
25
27
  {
@@ -35,7 +37,7 @@ describe AvroTurf::Messaging do
35
37
  AVSC
36
38
  end
37
39
 
38
- let(:city_message) { { "name" => "Paris" } }
40
+ let(:city_message) { {"name" => "Paris"} }
39
41
  let(:city_schema_json) do
40
42
  <<-AVSC
41
43
  {
@@ -88,39 +90,39 @@ describe AvroTurf::Messaging do
88
90
  end
89
91
  end
90
92
 
91
- shared_examples_for 'encoding and decoding with the schema from registry' do
93
+ shared_examples_for "encoding and decoding with the schema from registry" do
92
94
  before do
93
95
  registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger, path_prefix: path_prefix)
94
- registry.register('person', schema)
95
- registry.register('people', schema)
96
+ registry.register("person", schema)
97
+ registry.register("people", schema)
96
98
  end
97
99
 
98
- it 'encodes and decodes messages' do
99
- data = avro.encode(message, subject: 'person', version: 1)
100
+ it "encodes and decodes messages" do
101
+ data = avro.encode(message, subject: "person", version: 1)
100
102
  expect(avro.decode(data)).to eq message
101
103
  end
102
104
 
103
105
  it "allows specifying a reader's schema by subject and version" do
104
- data = avro.encode(message, subject: 'person', version: 1)
105
- expect(avro.decode(data, schema_name: 'person')).to eq message
106
+ data = avro.encode(message, subject: "person", version: 1)
107
+ expect(avro.decode(data, schema_name: "person")).to eq message
106
108
  end
107
109
 
108
- it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
109
- expect { avro.encode(message, subject: 'missing', version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
110
+ it "raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry" do
111
+ expect { avro.encode(message, subject: "missing", version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
110
112
  end
111
113
 
112
- it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry and register_schemas false' do
113
- expect { avro.encode(city_message, schema_name: 'city', register_schemas: false) }.
114
- to raise_error(AvroTurf::SchemaNotFoundError, "Schema with structure: #{city_schema} not found on registry")
114
+ it "raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry and register_schemas false" do
115
+ expect { avro.encode(city_message, schema_name: "city", register_schemas: false) }
116
+ .to raise_error(AvroTurf::SchemaNotFoundError, "Schema with structure: #{city_schema} not found on registry")
115
117
  end
116
118
 
117
- it 'encodes with register_schemas false when the schema exists on the registry' do
118
- data = avro.encode(message, schema_name: 'person', register_schemas: false)
119
- expect(avro.decode(data, schema_name: 'person')).to eq message
119
+ it "encodes with register_schemas false when the schema exists on the registry" do
120
+ data = avro.encode(message, schema_name: "person", register_schemas: false)
121
+ expect(avro.decode(data, schema_name: "person")).to eq message
120
122
  end
121
123
 
122
- it 'caches parsed schemas for decoding' do
123
- data = avro.encode(message, subject: 'person', version: 1)
124
+ it "caches parsed schemas for decoding" do
125
+ data = avro.encode(message, subject: "person", version: 1)
124
126
  avro.decode(data)
125
127
  allow(Avro::Schema).to receive(:parse).and_call_original
126
128
  expect(avro.decode(data)).to eq message
@@ -128,23 +130,23 @@ describe AvroTurf::Messaging do
128
130
  end
129
131
  end
130
132
 
131
- shared_examples_for 'encoding and decoding with the schema_id from registry' do
133
+ shared_examples_for "encoding and decoding with the schema_id from registry" do
132
134
  before do
133
135
  registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger, path_prefix: path_prefix)
134
- registry.register('person', schema)
135
- registry.register('people', schema)
136
+ registry.register("person", schema)
137
+ registry.register("people", schema)
136
138
  end
137
139
 
138
- it 'encodes and decodes messages' do
140
+ it "encodes and decodes messages" do
139
141
  data = avro.encode(message, schema_id: 0)
140
142
  expect(avro.decode(data)).to eq message
141
143
  end
142
144
 
143
- it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
145
+ it "raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry" do
144
146
  expect { avro.encode(message, schema_id: 5) }.to raise_error(AvroTurf::SchemaNotFoundError)
145
147
  end
146
148
 
147
- it 'caches parsed schemas for decoding' do
149
+ it "caches parsed schemas for decoding" do
148
150
  data = avro.encode(message, schema_id: 0)
149
151
  avro.decode(data)
150
152
  allow(Avro::Schema).to receive(:parse).and_call_original
@@ -155,9 +157,9 @@ describe AvroTurf::Messaging do
155
157
 
156
158
  it_behaves_like "encoding and decoding with the schema from schema store"
157
159
 
158
- it_behaves_like 'encoding and decoding with the schema from registry'
160
+ it_behaves_like "encoding and decoding with the schema from registry"
159
161
 
160
- it_behaves_like 'encoding and decoding with the schema_id from registry'
162
+ it_behaves_like "encoding and decoding with the schema_id from registry"
161
163
 
162
164
  context "with a provided registry" do
163
165
  let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
@@ -172,20 +174,20 @@ describe AvroTurf::Messaging do
172
174
 
173
175
  it_behaves_like "encoding and decoding with the schema from schema store"
174
176
 
175
- it_behaves_like 'encoding and decoding with the schema from registry'
177
+ it_behaves_like "encoding and decoding with the schema from registry"
176
178
 
177
- it_behaves_like 'encoding and decoding with the schema_id from registry'
179
+ it_behaves_like "encoding and decoding with the schema_id from registry"
178
180
 
179
181
  it "uses the provided registry" do
180
182
  allow(registry).to receive(:register).and_call_original
181
- message = { "full_name" => "John Doe" }
183
+ message = {"full_name" => "John Doe"}
182
184
  avro.encode(message, schema_name: "person")
183
185
  expect(registry).to have_received(:register).with("person", anything)
184
186
  end
185
187
 
186
188
  it "allows specifying a schema registry subject" do
187
189
  allow(registry).to receive(:register).and_call_original
188
- message = { "full_name" => "John Doe" }
190
+ message = {"full_name" => "John Doe"}
189
191
  avro.encode(message, schema_name: "person", subject: "people")
190
192
  expect(registry).to have_received(:register).with("people", anything)
191
193
  end
@@ -211,7 +213,7 @@ describe AvroTurf::Messaging do
211
213
  end
212
214
  end
213
215
 
214
- describe 'decoding with #decode_message' do
216
+ describe "decoding with #decode_message" do
215
217
  shared_examples_for "encoding and decoding with the schema from schema store" do
216
218
  it "encodes and decodes messages" do
217
219
  data = avro.encode(message, schema_name: "person")
@@ -239,31 +241,31 @@ describe AvroTurf::Messaging do
239
241
  end
240
242
  end
241
243
 
242
- shared_examples_for 'encoding and decoding with the schema from registry' do
244
+ shared_examples_for "encoding and decoding with the schema from registry" do
243
245
  before do
244
246
  registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
245
- registry.register('person', schema)
246
- registry.register('people', schema)
247
+ registry.register("person", schema)
248
+ registry.register("people", schema)
247
249
  end
248
250
 
249
- it 'encodes and decodes messages' do
250
- data = avro.encode(message, subject: 'person', version: 1)
251
+ it "encodes and decodes messages" do
252
+ data = avro.encode(message, subject: "person", version: 1)
251
253
  result = avro.decode_message(data)
252
254
  expect(result.message).to eq message
253
255
  expect(result.schema_id).to eq 0
254
256
  end
255
257
 
256
258
  it "allows specifying a reader's schema by subject and version" do
257
- data = avro.encode(message, subject: 'person', version: 1)
258
- expect(avro.decode_message(data, schema_name: 'person').message).to eq message
259
+ data = avro.encode(message, subject: "person", version: 1)
260
+ expect(avro.decode_message(data, schema_name: "person").message).to eq message
259
261
  end
260
262
 
261
- it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
262
- expect { avro.encode(message, subject: 'missing', version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
263
+ it "raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry" do
264
+ expect { avro.encode(message, subject: "missing", version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
263
265
  end
264
266
 
265
- it 'caches parsed schemas for decoding' do
266
- data = avro.encode(message, subject: 'person', version: 1)
267
+ it "caches parsed schemas for decoding" do
268
+ data = avro.encode(message, subject: "person", version: 1)
267
269
  avro.decode_message(data)
268
270
  allow(Avro::Schema).to receive(:parse).and_call_original
269
271
  expect(avro.decode_message(data).message).to eq message
@@ -273,7 +275,7 @@ describe AvroTurf::Messaging do
273
275
 
274
276
  it_behaves_like "encoding and decoding with the schema from schema store"
275
277
 
276
- it_behaves_like 'encoding and decoding with the schema from registry'
278
+ it_behaves_like "encoding and decoding with the schema from registry"
277
279
 
278
280
  context "with a provided registry" do
279
281
  let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
@@ -288,18 +290,18 @@ describe AvroTurf::Messaging do
288
290
 
289
291
  it_behaves_like "encoding and decoding with the schema from schema store"
290
292
 
291
- it_behaves_like 'encoding and decoding with the schema from registry'
293
+ it_behaves_like "encoding and decoding with the schema from registry"
292
294
 
293
295
  it "uses the provided registry" do
294
296
  allow(registry).to receive(:register).and_call_original
295
- message = { "full_name" => "John Doe" }
297
+ message = {"full_name" => "John Doe"}
296
298
  avro.encode(message, schema_name: "person")
297
299
  expect(registry).to have_received(:register).with("person", anything)
298
300
  end
299
301
 
300
302
  it "allows specifying a schema registry subject" do
301
303
  allow(registry).to receive(:register).and_call_original
302
- message = { "full_name" => "John Doe" }
304
+ message = {"full_name" => "John Doe"}
303
305
  avro.encode(message, schema_name: "person", subject: "people")
304
306
  expect(registry).to have_received(:register).with("people", anything)
305
307
  end
@@ -327,26 +329,26 @@ describe AvroTurf::Messaging do
327
329
  end
328
330
 
329
331
  context "validating" do
330
- subject(:encode){ avro.encode(message, schema_name: "person", validate: true) }
332
+ subject(:encode) { avro.encode(message, schema_name: "person", validate: true) }
331
333
 
332
334
  context "for correct message" do
333
335
  it { expect { encode }.not_to raise_error }
334
336
  end
335
337
 
336
338
  context "when message has wrong type" do
337
- let(:message) { { "full_name" => 123 } }
339
+ let(:message) { {"full_name" => 123} }
338
340
 
339
341
  it { expect { encode }.to raise_error(Avro::SchemaValidator::ValidationError, /\.full_name expected type string, got int/) }
340
342
  end
341
343
 
342
344
  context "when message contains extra fields (typo in key)" do
343
- let(:message) { { "fulll_name" => "John Doe" } }
345
+ let(:message) { {"fulll_name" => "John Doe"} }
344
346
 
345
347
  it { expect { encode }.to raise_error(Avro::SchemaValidator::ValidationError, /extra field 'fulll_name'/) }
346
348
  end
347
349
  end
348
350
 
349
- context 'fetching and registering schema' do
351
+ context "fetching and registering schema" do
350
352
  let(:schema_store) { AvroTurf::SchemaStore.new(path: "spec/schemas") }
351
353
 
352
354
  let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
@@ -361,28 +363,28 @@ describe AvroTurf::Messaging do
361
363
 
362
364
  let(:schema_id) { 234 }
363
365
 
364
- context 'using fetch_schema' do
366
+ context "using fetch_schema" do
365
367
  subject { avro.fetch_schema(subject: subj, version: version) }
366
368
 
367
- let(:subj) { 'subject' }
369
+ let(:subj) { "subject" }
368
370
 
369
- let(:version) { 'version' }
371
+ let(:version) { "version" }
370
372
 
371
- let(:response) { {'id' => schema_id, 'schema' => schema_json} }
373
+ let(:response) { {"id" => schema_id, "schema" => schema_json} }
372
374
 
373
375
  before do
374
376
  allow(registry).to receive(:subject_version).with(subj, version).and_return(response)
375
377
  end
376
378
 
377
- it 'gets schema from registry' do
379
+ it "gets schema from registry" do
378
380
  expect(subject).to eq([schema, schema_id])
379
381
  end
380
382
 
381
383
  context "with an incompatible schema type" do
382
- let(:response) { {'id' => schema_id, 'schema' => 'blah', 'schemaType' => schema_type } }
383
- let(:schema_type) { 'PROTOBUF' }
384
+ let(:response) { {"id" => schema_id, "schema" => "blah", "schemaType" => schema_type} }
385
+ let(:schema_type) { "PROTOBUF" }
384
386
 
385
- it 'raises IncompatibleSchemaError' do
387
+ it "raises IncompatibleSchemaError" do
386
388
  expect { subject }.to raise_error(
387
389
  AvroTurf::IncompatibleSchemaError,
388
390
  "The #{schema_type} schema for #{subj} is incompatible."
@@ -391,22 +393,22 @@ describe AvroTurf::Messaging do
391
393
  end
392
394
  end
393
395
 
394
- context 'using fetch_schema_by_id' do
396
+ context "using fetch_schema_by_id" do
395
397
  subject { avro.fetch_schema_by_id(schema_id) }
396
398
 
397
399
  before do
398
400
  allow(registry).to receive(:fetch).with(schema_id).and_return(schema_json)
399
401
  end
400
402
 
401
- it 'gets schema from registry' do
403
+ it "gets schema from registry" do
402
404
  expect(subject).to eq([schema, schema_id])
403
405
  end
404
406
  end
405
407
 
406
- context 'using fetch_schema_by_body' do
407
- let(:subject_name) { 'city' }
408
- let(:schema_name) { 'city' }
409
- let(:namespace) { 'namespace' }
408
+ context "using fetch_schema_by_body" do
409
+ let(:subject_name) { "city" }
410
+ let(:schema_name) { "city" }
411
+ let(:namespace) { "namespace" }
410
412
  let(:city_schema_id) { 125 }
411
413
  let(:city_schema_data) do
412
414
  {
@@ -426,50 +428,50 @@ describe AvroTurf::Messaging do
426
428
  allow(registry).to receive(:check).with(subject_name, city_schema).and_return(city_schema_data)
427
429
  end
428
430
 
429
- it 'gets schema from registry' do
431
+ it "gets schema from registry" do
430
432
  expect(fetch_schema_by_body).to eq([city_schema, city_schema_id])
431
433
  end
432
434
  end
433
435
 
434
- context 'using register_schema' do
435
- let(:schema_name) { 'schema_name' }
436
+ context "using register_schema" do
437
+ let(:schema_name) { "schema_name" }
436
438
 
437
- let(:namespace) { 'namespace' }
439
+ let(:namespace) { "namespace" }
438
440
 
439
441
  before do
440
442
  allow(schema_store).to receive(:find).with(schema_name, namespace).and_return(schema)
441
443
  end
442
444
 
443
- context 'when subject is not set' do
445
+ context "when subject is not set" do
444
446
  subject { avro.register_schema(schema_name: schema_name, namespace: namespace) }
445
447
 
446
448
  before do
447
449
  allow(registry).to receive(:register).with(schema.fullname, schema).and_return(schema_id)
448
450
  end
449
451
 
450
- it 'registers schema in registry' do
452
+ it "registers schema in registry" do
451
453
  expect(subject).to eq([schema, schema_id])
452
454
  end
453
455
  end
454
456
 
455
- context 'when subject is set' do
457
+ context "when subject is set" do
456
458
  subject { avro.register_schema(schema_name: schema_name, namespace: namespace, subject: subj) }
457
459
 
458
- let(:subj) { 'subject' }
460
+ let(:subj) { "subject" }
459
461
 
460
462
  before do
461
463
  allow(registry).to receive(:register).with(subj, schema).and_return(schema_id)
462
464
  end
463
465
 
464
- it 'registers schema in registry' do
466
+ it "registers schema in registry" do
465
467
  expect(subject).to eq([schema, schema_id])
466
468
  end
467
469
  end
468
470
  end
469
471
  end
470
472
 
471
- context 'with a registry path prefix' do
472
- let(:path_prefix) { '/prefix' }
473
+ context "with a registry path prefix" do
474
+ let(:path_prefix) { "/prefix" }
473
475
 
474
476
  let(:avro) {
475
477
  AvroTurf::Messaging.new(
@@ -489,11 +491,11 @@ describe AvroTurf::Messaging do
489
491
  end
490
492
 
491
493
  it_behaves_like "encoding and decoding with the schema from schema store"
492
- it_behaves_like 'encoding and decoding with the schema from registry'
493
- it_behaves_like 'encoding and decoding with the schema_id from registry'
494
+ it_behaves_like "encoding and decoding with the schema from registry"
495
+ it_behaves_like "encoding and decoding with the schema_id from registry"
494
496
  end
495
497
 
496
- context 'with a connect timeout' do
498
+ context "with a connect timeout" do
497
499
  let(:avro) {
498
500
  AvroTurf::Messaging.new(
499
501
  registry_url: registry_url,
@@ -507,16 +509,16 @@ describe AvroTurf::Messaging do
507
509
  }
508
510
 
509
511
  it_behaves_like "encoding and decoding with the schema from schema store"
510
- it_behaves_like 'encoding and decoding with the schema from registry'
511
- it_behaves_like 'encoding and decoding with the schema_id from registry'
512
+ it_behaves_like "encoding and decoding with the schema from registry"
513
+ it_behaves_like "encoding and decoding with the schema_id from registry"
512
514
 
513
- it 'passes the connect timeout setting to Excon' do
515
+ it "passes the connect timeout setting to Excon" do
514
516
  expect(Excon).to receive(:new).with(anything, hash_including(connect_timeout: 10)).and_call_original
515
517
  avro
516
518
  end
517
519
  end
518
520
 
519
- context 'with a connect timeout' do
521
+ context "with a connect timeout" do
520
522
  let(:avro) {
521
523
  AvroTurf::Messaging.new(
522
524
  registry_url: registry_url,
@@ -530,17 +532,17 @@ describe AvroTurf::Messaging do
530
532
  }
531
533
 
532
534
  it_behaves_like "encoding and decoding with the schema from schema store"
533
- it_behaves_like 'encoding and decoding with the schema from registry'
534
- it_behaves_like 'encoding and decoding with the schema_id from registry'
535
+ it_behaves_like "encoding and decoding with the schema from registry"
536
+ it_behaves_like "encoding and decoding with the schema_id from registry"
535
537
 
536
- it 'passes the connect timeout setting to Excon' do
538
+ it "passes the connect timeout setting to Excon" do
537
539
  expect(Excon).to receive(:new).with(anything, hash_including(retry_limit: 5)).and_call_original
538
540
  avro
539
541
  end
540
542
  end
541
543
 
542
- context 'with a proxy' do
543
- let(:proxy_url) { 'http://proxy.example.com' }
544
+ context "with a proxy" do
545
+ let(:proxy_url) { "http://proxy.example.com" }
544
546
  let(:avro) {
545
547
  AvroTurf::Messaging.new(
546
548
  registry_url: registry_url,
@@ -554,18 +556,17 @@ describe AvroTurf::Messaging do
554
556
  }
555
557
 
556
558
  it_behaves_like "encoding and decoding with the schema from schema store"
557
- it_behaves_like 'encoding and decoding with the schema from registry'
558
- it_behaves_like 'encoding and decoding with the schema_id from registry'
559
+ it_behaves_like "encoding and decoding with the schema from registry"
560
+ it_behaves_like "encoding and decoding with the schema_id from registry"
559
561
 
560
- it 'passes the proxy setting to Excon' do
562
+ it "passes the proxy setting to Excon" do
561
563
  expect(Excon).to receive(:new).with(anything, hash_including(proxy: proxy_url)).and_call_original
562
564
  avro
563
565
  end
564
566
  end
565
567
 
566
-
567
- context 'with a custom domain name resolver' do
568
- let(:resolv_resolver) { Resolv.new([Resolv::Hosts.new, Resolv::DNS.new(nameserver: ['127.0.0.1', '127.0.0.1'])]) }
568
+ context "with a custom domain name resolver" do
569
+ let(:resolv_resolver) { Resolv.new([Resolv::Hosts.new, Resolv::DNS.new(nameserver: ["127.0.0.1", "127.0.0.1"])]) }
569
570
  let(:avro) {
570
571
  AvroTurf::Messaging.new(
571
572
  registry_url: registry_url,
@@ -579,12 +580,36 @@ describe AvroTurf::Messaging do
579
580
  }
580
581
 
581
582
  it_behaves_like "encoding and decoding with the schema from schema store"
582
- it_behaves_like 'encoding and decoding with the schema from registry'
583
- it_behaves_like 'encoding and decoding with the schema_id from registry'
583
+ it_behaves_like "encoding and decoding with the schema from registry"
584
+ it_behaves_like "encoding and decoding with the schema_id from registry"
584
585
 
585
- it 'passes the domain name resolver setting to Excon' do
586
+ it "passes the domain name resolver setting to Excon" do
586
587
  expect(Excon).to receive(:new).with(anything, hash_including(resolv_resolver: resolv_resolver)).and_call_original
587
588
  avro
588
589
  end
589
590
  end
591
+
592
+ context "with a cert chain" do
593
+ let(:client_chain) { "test client chain" }
594
+ let(:avro) {
595
+ AvroTurf::Messaging.new(
596
+ registry_url: registry_url,
597
+ schemas_path: "spec/schemas",
598
+ logger: logger,
599
+ client_cert: client_cert,
600
+ client_chain: client_chain,
601
+ client_key: client_key,
602
+ client_key_pass: client_key_pass
603
+ )
604
+ }
605
+
606
+ it_behaves_like "encoding and decoding with the schema from schema store"
607
+ it_behaves_like "encoding and decoding with the schema from registry"
608
+ it_behaves_like "encoding and decoding with the schema_id from registry"
609
+
610
+ it "passes the client chain to Excon" do
611
+ expect(Excon).to receive(:new).with(anything, hash_including(client_chain: client_chain)).and_call_original
612
+ avro
613
+ end
614
+ end
590
615
  end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/mutable_schema_store"
4
+
5
+ describe AvroTurf::MutableSchemaStore do
6
+ let(:store) { AvroTurf::MutableSchemaStore.new(path: "spec/schemas") }
7
+
8
+ describe "#add_schema" do
9
+ it "adds a schema to the store" do
10
+ schema_hash = {
11
+ "name" => "person",
12
+ "namespace" => "test.people",
13
+ "type" => "record",
14
+ "fields" => [
15
+ {
16
+ "type" => "string",
17
+ "name" => "name"
18
+ }
19
+ ]
20
+ }
21
+
22
+ schema = store.add_schema(schema_hash)
23
+ expect(schema.fullname).to eq "test.people.person"
24
+ expect(store.schemas["test.people.person"]).to eq schema
25
+ end
26
+
27
+ # This test would fail under avro_turf <= v0.19.0
28
+ it "does NOT cache *nested* schemas in memory" do
29
+ schema_hash = {
30
+ "name" => "person",
31
+ "namespace" => "test",
32
+ "type" => "record",
33
+ "fields" => [
34
+ {
35
+ "name" => "address",
36
+ "type" => {
37
+ "name" => "address",
38
+ "type" => "record",
39
+ "fields" => [
40
+ {"name" => "addr1", "type" => "string"},
41
+ {"name" => "addr2", "type" => "string"},
42
+ {"name" => "city", "type" => "string"},
43
+ {"name" => "zip", "type" => "string"}
44
+ ]
45
+ }
46
+ }
47
+ ]
48
+ }
49
+
50
+ schema = store.add_schema(schema_hash)
51
+ expect(schema.fullname).to eq "test.person"
52
+ expect(store.schemas["test.person"]).to eq schema
53
+
54
+ expect { store.find("address", "test") }
55
+ .to raise_error(AvroTurf::SchemaNotFoundError)
56
+ end
57
+
58
+ # This test would fail under avro_turf <= v1.19.0
59
+ it "allows two different schemas to define nested sub-schemas with the same fullname" do
60
+ person_schema = {
61
+ "name" => "person",
62
+ "namespace" => "test",
63
+ "type" => "record",
64
+ "fields" => [
65
+ {
66
+ "name" => "location",
67
+ "type" => {
68
+ "name" => "location",
69
+ "type" => "record",
70
+ "fields" => [
71
+ {"name" => "city", "type" => "string"},
72
+ {"name" => "zipcode", "type" => "string"}
73
+ ]
74
+ }
75
+ }
76
+ ]
77
+ }
78
+
79
+ company_schema = {
80
+ "name" => "company",
81
+ "namespace" => "test",
82
+ "type" => "record",
83
+ "fields" => [
84
+ {
85
+ "name" => "headquarters",
86
+ "type" => {
87
+ "name" => "location",
88
+ "type" => "record",
89
+ "fields" => [
90
+ {"name" => "city", "type" => "string"},
91
+ {"name" => "postcode", "type" => "string"}
92
+ ]
93
+ }
94
+ }
95
+ ]
96
+ }
97
+
98
+ person = store.add_schema(person_schema)
99
+
100
+ # This should *NOT* raise the error:
101
+ # #<Avro::SchemaParseError: The name "test.location" is already in use.>
102
+ expect { store.add_schema(company_schema) }.not_to raise_error
103
+
104
+ company = store.schemas["test.company"]
105
+
106
+ person_location_field = person.fields_hash["location"]
107
+ expect(person_location_field.type.name).to eq("location")
108
+ expect(person_location_field.type.fields_hash).to include("zipcode")
109
+ expect(person_location_field.type.fields_hash).not_to include("postcode")
110
+
111
+ company_headquarters_field = company.fields_hash["headquarters"]
112
+ expect(company_headquarters_field.type.name).to eq("location")
113
+ expect(company_headquarters_field.type.fields_hash).to include("postcode")
114
+ expect(company_headquarters_field.type.fields_hash).not_to include("zipcode")
115
+ end
116
+ end
117
+
118
+ describe "#schemas" do
119
+ it "provides access to the internal schemas hash" do
120
+ expect(store.schemas).to be_a(Hash)
121
+ expect(store.schemas).to be_empty
122
+
123
+ schema_hash = {
124
+ "name" => "test",
125
+ "type" => "record",
126
+ "fields" => []
127
+ }
128
+
129
+ store.add_schema(schema_hash)
130
+ expect(store.schemas.size).to eq 1
131
+ expect(store.schemas["test"]).to be_a(Avro::Schema::RecordSchema)
132
+ end
133
+ end
134
+ end