avro_turf 1.19.0 → 1.20.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +20 -11
- data/CHANGELOG.md +12 -0
- data/Gemfile +5 -2
- data/Rakefile +2 -1
- data/avro_turf.gemspec +16 -17
- data/lib/avro_turf/cached_confluent_schema_registry.rb +9 -8
- data/lib/avro_turf/cached_schema_registry.rb +3 -1
- data/lib/avro_turf/confluent_schema_registry.rb +23 -17
- data/lib/avro_turf/core_ext/date.rb +2 -0
- data/lib/avro_turf/core_ext/enumerable.rb +2 -0
- data/lib/avro_turf/core_ext/false_class.rb +2 -0
- data/lib/avro_turf/core_ext/hash.rb +4 -2
- data/lib/avro_turf/core_ext/nil_class.rb +2 -0
- data/lib/avro_turf/core_ext/numeric.rb +2 -0
- data/lib/avro_turf/core_ext/string.rb +2 -0
- data/lib/avro_turf/core_ext/symbol.rb +2 -0
- data/lib/avro_turf/core_ext/time.rb +2 -0
- data/lib/avro_turf/core_ext/true_class.rb +2 -0
- data/lib/avro_turf/core_ext.rb +12 -10
- data/lib/avro_turf/disk_cache.rb +13 -12
- data/lib/avro_turf/in_memory_cache.rb +2 -0
- data/lib/avro_turf/messaging.rb +25 -15
- data/lib/avro_turf/mutable_schema_store.rb +25 -4
- data/lib/avro_turf/schema_registry.rb +3 -1
- data/lib/avro_turf/schema_store.rb +3 -2
- data/lib/avro_turf/schema_to_avro_patch.rb +14 -12
- data/lib/avro_turf/test/fake_confluent_schema_registry_server.rb +39 -37
- data/lib/avro_turf/test/fake_prefixed_confluent_schema_registry_server.rb +12 -10
- data/lib/avro_turf/test/fake_schema_registry_server.rb +3 -1
- data/lib/avro_turf/test/fake_server.rb +186 -0
- data/lib/avro_turf/version.rb +3 -1
- data/lib/avro_turf.rb +15 -13
- data/perf/encoding_size.rb +4 -2
- data/perf/encoding_speed.rb +4 -2
- data/spec/avro_turf_spec.rb +24 -23
- data/spec/cached_confluent_schema_registry_spec.rb +9 -7
- data/spec/confluent_schema_registry_spec.rb +31 -10
- data/spec/core_ext/date_spec.rb +2 -0
- data/spec/core_ext/enumerable_spec.rb +2 -0
- data/spec/core_ext/false_class_spec.rb +2 -0
- data/spec/core_ext/hash_spec.rb +3 -1
- data/spec/core_ext/nil_class_spec.rb +2 -0
- data/spec/core_ext/numeric_spec.rb +2 -0
- data/spec/core_ext/string_spec.rb +2 -0
- data/spec/core_ext/symbol_spec.rb +2 -0
- data/spec/core_ext/time_spec.rb +2 -0
- data/spec/core_ext/true_class_spec.rb +2 -0
- data/spec/disk_cached_confluent_schema_registry_spec.rb +23 -21
- data/spec/messaging_spec.rb +145 -99
- data/spec/mutable_schema_store_spec.rb +134 -0
- data/spec/schema_store_spec.rb +23 -21
- data/spec/schema_to_avro_patch_spec.rb +8 -7
- data/spec/spec_helper.rb +9 -9
- data/spec/support/authorized_fake_confluent_schema_registry_server.rb +4 -2
- data/spec/support/authorized_fake_prefixed_confluent_schema_registry_server.rb +4 -2
- data/spec/support/confluent_schema_registry_context.rb +32 -30
- data/spec/test/fake_confluent_schema_registry_server_http_contract_spec.rb +722 -0
- data/spec/test/fake_confluent_schema_registry_server_spec.rb +97 -94
- metadata +7 -40
data/spec/messaging_spec.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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) { {
|
|
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) { {
|
|
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
|
|
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(
|
|
95
|
-
registry.register(
|
|
96
|
+
registry.register("person", schema)
|
|
97
|
+
registry.register("people", schema)
|
|
96
98
|
end
|
|
97
99
|
|
|
98
|
-
it
|
|
99
|
-
data = avro.encode(message, subject:
|
|
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:
|
|
105
|
-
expect(avro.decode(data, schema_name:
|
|
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
|
|
109
|
-
expect { avro.encode(message, subject:
|
|
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
|
|
113
|
-
expect { avro.encode(city_message, schema_name:
|
|
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
|
|
118
|
-
data = avro.encode(message, schema_name:
|
|
119
|
-
expect(avro.decode(data, schema_name:
|
|
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
|
|
123
|
-
data = avro.encode(message, subject:
|
|
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
|
|
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(
|
|
135
|
-
registry.register(
|
|
136
|
+
registry.register("person", schema)
|
|
137
|
+
registry.register("people", schema)
|
|
136
138
|
end
|
|
137
139
|
|
|
138
|
-
it
|
|
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
|
|
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
|
|
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
|
|
160
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
159
161
|
|
|
160
|
-
it_behaves_like
|
|
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
|
|
177
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
176
178
|
|
|
177
|
-
it_behaves_like
|
|
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 = {
|
|
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 = {
|
|
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
|
|
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
|
|
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(
|
|
246
|
-
registry.register(
|
|
247
|
+
registry.register("person", schema)
|
|
248
|
+
registry.register("people", schema)
|
|
247
249
|
end
|
|
248
250
|
|
|
249
|
-
it
|
|
250
|
-
data = avro.encode(message, subject:
|
|
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:
|
|
258
|
-
expect(avro.decode_message(data, schema_name:
|
|
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
|
|
262
|
-
expect { avro.encode(message, subject:
|
|
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
|
|
266
|
-
data = avro.encode(message, subject:
|
|
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
|
|
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
|
|
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 = {
|
|
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 = {
|
|
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) { {
|
|
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) { {
|
|
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
|
|
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,39 @@ describe AvroTurf::Messaging do
|
|
|
361
363
|
|
|
362
364
|
let(:schema_id) { 234 }
|
|
363
365
|
|
|
364
|
-
context
|
|
366
|
+
context "using fetch_schema" do
|
|
365
367
|
subject { avro.fetch_schema(subject: subj, version: version) }
|
|
366
368
|
|
|
367
|
-
let(:subj) {
|
|
369
|
+
let(:subj) { "subject" }
|
|
368
370
|
|
|
369
|
-
let(:version) {
|
|
371
|
+
let(:version) { "version" }
|
|
370
372
|
|
|
371
|
-
let(:response) { {
|
|
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
|
|
379
|
+
it "gets schema from registry" do
|
|
378
380
|
expect(subject).to eq([schema, schema_id])
|
|
379
381
|
end
|
|
380
382
|
|
|
383
|
+
it "memoizes parsed schema" do
|
|
384
|
+
expect(registry).to receive(:subject_version).with(subj, version).twice.and_return(response)
|
|
385
|
+
expect(Avro::Schema).to receive(:parse).with(schema_json).once.and_return(schema)
|
|
386
|
+
|
|
387
|
+
first_result = avro.fetch_schema(subject: subj, version: version)
|
|
388
|
+
second_result = avro.fetch_schema(subject: subj, version: version)
|
|
389
|
+
|
|
390
|
+
expect(first_result).to eq([schema, schema_id])
|
|
391
|
+
expect(second_result).to eq([schema, schema_id])
|
|
392
|
+
end
|
|
393
|
+
|
|
381
394
|
context "with an incompatible schema type" do
|
|
382
|
-
let(:response) { {
|
|
383
|
-
let(:schema_type) {
|
|
395
|
+
let(:response) { {"id" => schema_id, "schema" => "blah", "schemaType" => schema_type} }
|
|
396
|
+
let(:schema_type) { "PROTOBUF" }
|
|
384
397
|
|
|
385
|
-
it
|
|
398
|
+
it "raises IncompatibleSchemaError" do
|
|
386
399
|
expect { subject }.to raise_error(
|
|
387
400
|
AvroTurf::IncompatibleSchemaError,
|
|
388
401
|
"The #{schema_type} schema for #{subj} is incompatible."
|
|
@@ -391,22 +404,32 @@ describe AvroTurf::Messaging do
|
|
|
391
404
|
end
|
|
392
405
|
end
|
|
393
406
|
|
|
394
|
-
context
|
|
407
|
+
context "using fetch_schema_by_id" do
|
|
395
408
|
subject { avro.fetch_schema_by_id(schema_id) }
|
|
396
409
|
|
|
397
410
|
before do
|
|
398
411
|
allow(registry).to receive(:fetch).with(schema_id).and_return(schema_json)
|
|
399
412
|
end
|
|
400
413
|
|
|
401
|
-
it
|
|
414
|
+
it "gets schema from registry" do
|
|
402
415
|
expect(subject).to eq([schema, schema_id])
|
|
403
416
|
end
|
|
417
|
+
|
|
418
|
+
it "memoizes schema in @schemas_by_id after first call" do
|
|
419
|
+
expect(registry).to receive(:fetch).with(schema_id).once.and_return(schema_json)
|
|
420
|
+
|
|
421
|
+
first_result = avro.fetch_schema_by_id(schema_id)
|
|
422
|
+
second_result = avro.fetch_schema_by_id(schema_id)
|
|
423
|
+
|
|
424
|
+
expect(first_result).to eq([schema, schema_id])
|
|
425
|
+
expect(second_result).to eq([schema, schema_id])
|
|
426
|
+
end
|
|
404
427
|
end
|
|
405
428
|
|
|
406
|
-
context
|
|
407
|
-
let(:subject_name) {
|
|
408
|
-
let(:schema_name) {
|
|
409
|
-
let(:namespace) {
|
|
429
|
+
context "using fetch_schema_by_body" do
|
|
430
|
+
let(:subject_name) { "city" }
|
|
431
|
+
let(:schema_name) { "city" }
|
|
432
|
+
let(:namespace) { "namespace" }
|
|
410
433
|
let(:city_schema_id) { 125 }
|
|
411
434
|
let(:city_schema_data) do
|
|
412
435
|
{
|
|
@@ -426,50 +449,50 @@ describe AvroTurf::Messaging do
|
|
|
426
449
|
allow(registry).to receive(:check).with(subject_name, city_schema).and_return(city_schema_data)
|
|
427
450
|
end
|
|
428
451
|
|
|
429
|
-
it
|
|
452
|
+
it "gets schema from registry" do
|
|
430
453
|
expect(fetch_schema_by_body).to eq([city_schema, city_schema_id])
|
|
431
454
|
end
|
|
432
455
|
end
|
|
433
456
|
|
|
434
|
-
context
|
|
435
|
-
let(:schema_name) {
|
|
457
|
+
context "using register_schema" do
|
|
458
|
+
let(:schema_name) { "schema_name" }
|
|
436
459
|
|
|
437
|
-
let(:namespace) {
|
|
460
|
+
let(:namespace) { "namespace" }
|
|
438
461
|
|
|
439
462
|
before do
|
|
440
463
|
allow(schema_store).to receive(:find).with(schema_name, namespace).and_return(schema)
|
|
441
464
|
end
|
|
442
465
|
|
|
443
|
-
context
|
|
466
|
+
context "when subject is not set" do
|
|
444
467
|
subject { avro.register_schema(schema_name: schema_name, namespace: namespace) }
|
|
445
468
|
|
|
446
469
|
before do
|
|
447
470
|
allow(registry).to receive(:register).with(schema.fullname, schema).and_return(schema_id)
|
|
448
471
|
end
|
|
449
472
|
|
|
450
|
-
it
|
|
473
|
+
it "registers schema in registry" do
|
|
451
474
|
expect(subject).to eq([schema, schema_id])
|
|
452
475
|
end
|
|
453
476
|
end
|
|
454
477
|
|
|
455
|
-
context
|
|
478
|
+
context "when subject is set" do
|
|
456
479
|
subject { avro.register_schema(schema_name: schema_name, namespace: namespace, subject: subj) }
|
|
457
480
|
|
|
458
|
-
let(:subj) {
|
|
481
|
+
let(:subj) { "subject" }
|
|
459
482
|
|
|
460
483
|
before do
|
|
461
484
|
allow(registry).to receive(:register).with(subj, schema).and_return(schema_id)
|
|
462
485
|
end
|
|
463
486
|
|
|
464
|
-
it
|
|
487
|
+
it "registers schema in registry" do
|
|
465
488
|
expect(subject).to eq([schema, schema_id])
|
|
466
489
|
end
|
|
467
490
|
end
|
|
468
491
|
end
|
|
469
492
|
end
|
|
470
493
|
|
|
471
|
-
context
|
|
472
|
-
let(:path_prefix) {
|
|
494
|
+
context "with a registry path prefix" do
|
|
495
|
+
let(:path_prefix) { "/prefix" }
|
|
473
496
|
|
|
474
497
|
let(:avro) {
|
|
475
498
|
AvroTurf::Messaging.new(
|
|
@@ -489,11 +512,11 @@ describe AvroTurf::Messaging do
|
|
|
489
512
|
end
|
|
490
513
|
|
|
491
514
|
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
492
|
-
it_behaves_like
|
|
493
|
-
it_behaves_like
|
|
515
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
516
|
+
it_behaves_like "encoding and decoding with the schema_id from registry"
|
|
494
517
|
end
|
|
495
518
|
|
|
496
|
-
context
|
|
519
|
+
context "with a connect timeout" do
|
|
497
520
|
let(:avro) {
|
|
498
521
|
AvroTurf::Messaging.new(
|
|
499
522
|
registry_url: registry_url,
|
|
@@ -507,16 +530,16 @@ describe AvroTurf::Messaging do
|
|
|
507
530
|
}
|
|
508
531
|
|
|
509
532
|
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
510
|
-
it_behaves_like
|
|
511
|
-
it_behaves_like
|
|
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"
|
|
512
535
|
|
|
513
|
-
it
|
|
536
|
+
it "passes the connect timeout setting to Excon" do
|
|
514
537
|
expect(Excon).to receive(:new).with(anything, hash_including(connect_timeout: 10)).and_call_original
|
|
515
538
|
avro
|
|
516
539
|
end
|
|
517
540
|
end
|
|
518
541
|
|
|
519
|
-
context
|
|
542
|
+
context "with a connect timeout" do
|
|
520
543
|
let(:avro) {
|
|
521
544
|
AvroTurf::Messaging.new(
|
|
522
545
|
registry_url: registry_url,
|
|
@@ -530,17 +553,17 @@ describe AvroTurf::Messaging do
|
|
|
530
553
|
}
|
|
531
554
|
|
|
532
555
|
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
533
|
-
it_behaves_like
|
|
534
|
-
it_behaves_like
|
|
556
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
557
|
+
it_behaves_like "encoding and decoding with the schema_id from registry"
|
|
535
558
|
|
|
536
|
-
it
|
|
559
|
+
it "passes the connect timeout setting to Excon" do
|
|
537
560
|
expect(Excon).to receive(:new).with(anything, hash_including(retry_limit: 5)).and_call_original
|
|
538
561
|
avro
|
|
539
562
|
end
|
|
540
563
|
end
|
|
541
564
|
|
|
542
|
-
context
|
|
543
|
-
let(:proxy_url) {
|
|
565
|
+
context "with a proxy" do
|
|
566
|
+
let(:proxy_url) { "http://proxy.example.com" }
|
|
544
567
|
let(:avro) {
|
|
545
568
|
AvroTurf::Messaging.new(
|
|
546
569
|
registry_url: registry_url,
|
|
@@ -554,18 +577,17 @@ describe AvroTurf::Messaging do
|
|
|
554
577
|
}
|
|
555
578
|
|
|
556
579
|
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
557
|
-
it_behaves_like
|
|
558
|
-
it_behaves_like
|
|
580
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
581
|
+
it_behaves_like "encoding and decoding with the schema_id from registry"
|
|
559
582
|
|
|
560
|
-
it
|
|
583
|
+
it "passes the proxy setting to Excon" do
|
|
561
584
|
expect(Excon).to receive(:new).with(anything, hash_including(proxy: proxy_url)).and_call_original
|
|
562
585
|
avro
|
|
563
586
|
end
|
|
564
587
|
end
|
|
565
588
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
let(:resolv_resolver) { Resolv.new([Resolv::Hosts.new, Resolv::DNS.new(nameserver: ['127.0.0.1', '127.0.0.1'])]) }
|
|
589
|
+
context "with a custom domain name resolver" do
|
|
590
|
+
let(:resolv_resolver) { Resolv.new([Resolv::Hosts.new, Resolv::DNS.new(nameserver: ["127.0.0.1", "127.0.0.1"])]) }
|
|
569
591
|
let(:avro) {
|
|
570
592
|
AvroTurf::Messaging.new(
|
|
571
593
|
registry_url: registry_url,
|
|
@@ -579,12 +601,36 @@ describe AvroTurf::Messaging do
|
|
|
579
601
|
}
|
|
580
602
|
|
|
581
603
|
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
582
|
-
it_behaves_like
|
|
583
|
-
it_behaves_like
|
|
604
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
605
|
+
it_behaves_like "encoding and decoding with the schema_id from registry"
|
|
584
606
|
|
|
585
|
-
it
|
|
607
|
+
it "passes the domain name resolver setting to Excon" do
|
|
586
608
|
expect(Excon).to receive(:new).with(anything, hash_including(resolv_resolver: resolv_resolver)).and_call_original
|
|
587
609
|
avro
|
|
588
610
|
end
|
|
589
611
|
end
|
|
612
|
+
|
|
613
|
+
context "with a cert chain" do
|
|
614
|
+
let(:client_chain) { "test client chain" }
|
|
615
|
+
let(:avro) {
|
|
616
|
+
AvroTurf::Messaging.new(
|
|
617
|
+
registry_url: registry_url,
|
|
618
|
+
schemas_path: "spec/schemas",
|
|
619
|
+
logger: logger,
|
|
620
|
+
client_cert: client_cert,
|
|
621
|
+
client_chain: client_chain,
|
|
622
|
+
client_key: client_key,
|
|
623
|
+
client_key_pass: client_key_pass
|
|
624
|
+
)
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
it_behaves_like "encoding and decoding with the schema from schema store"
|
|
628
|
+
it_behaves_like "encoding and decoding with the schema from registry"
|
|
629
|
+
it_behaves_like "encoding and decoding with the schema_id from registry"
|
|
630
|
+
|
|
631
|
+
it "passes the client chain to Excon" do
|
|
632
|
+
expect(Excon).to receive(:new).with(anything, hash_including(client_chain: client_chain)).and_call_original
|
|
633
|
+
avro
|
|
634
|
+
end
|
|
635
|
+
end
|
|
590
636
|
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
|