rdkafka 0.13.0 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/workflows/ci.yml +57 -0
  5. data/.gitignore +4 -0
  6. data/.rspec +1 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/CHANGELOG.md +155 -111
  10. data/{LICENSE → MIT-LICENSE} +2 -1
  11. data/README.md +60 -39
  12. data/certs/cert_chain.pem +26 -0
  13. data/docker-compose.yml +18 -15
  14. data/ext/README.md +1 -1
  15. data/ext/Rakefile +43 -26
  16. data/lib/rdkafka/abstract_handle.rb +40 -26
  17. data/lib/rdkafka/admin/acl_binding_result.rb +51 -0
  18. data/lib/rdkafka/admin/create_acl_handle.rb +28 -0
  19. data/lib/rdkafka/admin/create_acl_report.rb +24 -0
  20. data/lib/rdkafka/admin/create_partitions_handle.rb +27 -0
  21. data/lib/rdkafka/admin/create_partitions_report.rb +6 -0
  22. data/lib/rdkafka/admin/delete_acl_handle.rb +30 -0
  23. data/lib/rdkafka/admin/delete_acl_report.rb +23 -0
  24. data/lib/rdkafka/admin/delete_groups_handle.rb +28 -0
  25. data/lib/rdkafka/admin/delete_groups_report.rb +24 -0
  26. data/lib/rdkafka/admin/describe_acl_handle.rb +30 -0
  27. data/lib/rdkafka/admin/describe_acl_report.rb +23 -0
  28. data/lib/rdkafka/admin.rb +449 -7
  29. data/lib/rdkafka/bindings.rb +133 -7
  30. data/lib/rdkafka/callbacks.rb +196 -1
  31. data/lib/rdkafka/config.rb +53 -19
  32. data/lib/rdkafka/consumer/headers.rb +2 -4
  33. data/lib/rdkafka/consumer/topic_partition_list.rb +11 -8
  34. data/lib/rdkafka/consumer.rb +164 -74
  35. data/lib/rdkafka/helpers/time.rb +14 -0
  36. data/lib/rdkafka/metadata.rb +22 -1
  37. data/lib/rdkafka/native_kafka.rb +6 -1
  38. data/lib/rdkafka/producer/delivery_handle.rb +12 -1
  39. data/lib/rdkafka/producer/delivery_report.rb +16 -3
  40. data/lib/rdkafka/producer.rb +121 -13
  41. data/lib/rdkafka/version.rb +3 -3
  42. data/lib/rdkafka.rb +21 -1
  43. data/rdkafka.gemspec +19 -5
  44. data/renovate.json +6 -0
  45. data/spec/rdkafka/abstract_handle_spec.rb +0 -2
  46. data/spec/rdkafka/admin/create_acl_handle_spec.rb +56 -0
  47. data/spec/rdkafka/admin/create_acl_report_spec.rb +18 -0
  48. data/spec/rdkafka/admin/create_topic_handle_spec.rb +0 -2
  49. data/spec/rdkafka/admin/create_topic_report_spec.rb +0 -2
  50. data/spec/rdkafka/admin/delete_acl_handle_spec.rb +85 -0
  51. data/spec/rdkafka/admin/delete_acl_report_spec.rb +72 -0
  52. data/spec/rdkafka/admin/delete_topic_handle_spec.rb +0 -2
  53. data/spec/rdkafka/admin/delete_topic_report_spec.rb +0 -2
  54. data/spec/rdkafka/admin/describe_acl_handle_spec.rb +85 -0
  55. data/spec/rdkafka/admin/describe_acl_report_spec.rb +73 -0
  56. data/spec/rdkafka/admin_spec.rb +205 -2
  57. data/spec/rdkafka/bindings_spec.rb +0 -1
  58. data/spec/rdkafka/callbacks_spec.rb +0 -2
  59. data/spec/rdkafka/config_spec.rb +8 -2
  60. data/spec/rdkafka/consumer/headers_spec.rb +0 -2
  61. data/spec/rdkafka/consumer/message_spec.rb +0 -2
  62. data/spec/rdkafka/consumer/partition_spec.rb +0 -2
  63. data/spec/rdkafka/consumer/topic_partition_list_spec.rb +19 -2
  64. data/spec/rdkafka/consumer_spec.rb +232 -39
  65. data/spec/rdkafka/error_spec.rb +0 -2
  66. data/spec/rdkafka/metadata_spec.rb +2 -3
  67. data/spec/rdkafka/native_kafka_spec.rb +2 -3
  68. data/spec/rdkafka/producer/delivery_handle_spec.rb +0 -2
  69. data/spec/rdkafka/producer/delivery_report_spec.rb +4 -2
  70. data/spec/rdkafka/producer_spec.rb +183 -3
  71. data/spec/spec_helper.rb +3 -1
  72. data.tar.gz.sig +0 -0
  73. metadata +78 -14
  74. metadata.gz.sig +0 -0
  75. data/.semaphore/semaphore.yml +0 -27
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Rdkafka::Admin::DescribeAclHandle do
6
+ let(:response) { Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR }
7
+ let(:resource_name) {"acl-test-topic"}
8
+ let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
9
+ let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
10
+ let(:principal) {"User:anonymous"}
11
+ let(:host) {"*"}
12
+ let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
13
+ let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
14
+ let(:describe_acl_ptr) {FFI::Pointer::NULL}
15
+
16
+ subject do
17
+ error_buffer = FFI::MemoryPointer.from_string(" " * 256)
18
+ describe_acl_ptr = Rdkafka::Bindings.rd_kafka_AclBinding_new(
19
+ resource_type,
20
+ FFI::MemoryPointer.from_string(resource_name),
21
+ resource_pattern_type,
22
+ FFI::MemoryPointer.from_string(principal),
23
+ FFI::MemoryPointer.from_string(host),
24
+ operation,
25
+ permission_type,
26
+ error_buffer,
27
+ 256
28
+ )
29
+ if describe_acl_ptr.null?
30
+ raise Rdkafka::Config::ConfigError.new(error_buffer.read_string)
31
+ end
32
+ pointer_array = [describe_acl_ptr]
33
+ describe_acls_array_ptr = FFI::MemoryPointer.new(:pointer)
34
+ describe_acls_array_ptr.write_array_of_pointer(pointer_array)
35
+ Rdkafka::Admin::DescribeAclHandle.new.tap do |handle|
36
+ handle[:pending] = pending_handle
37
+ handle[:response] = response
38
+ handle[:response_string] = FFI::MemoryPointer.from_string("")
39
+ handle[:acls] = describe_acls_array_ptr
40
+ handle[:acls_count] = 1
41
+ end
42
+ end
43
+
44
+ after do
45
+ if describe_acl_ptr != FFI::Pointer::NULL
46
+ Rdkafka::Bindings.rd_kafka_AclBinding_destroy(describe_acl_ptr)
47
+ end
48
+ end
49
+
50
+ describe "#wait" do
51
+ let(:pending_handle) { true }
52
+
53
+ it "should wait until the timeout and then raise an error" do
54
+ expect {
55
+ subject.wait(max_wait_timeout: 0.1)
56
+ }.to raise_error Rdkafka::Admin::DescribeAclHandle::WaitTimeoutError, /describe acl/
57
+ end
58
+
59
+ context "when not pending anymore and no error" do
60
+ let(:pending_handle) { false }
61
+
62
+ it "should return a describe acl report" do
63
+ report = subject.wait
64
+
65
+ expect(report.acls.length).to eq(1)
66
+ end
67
+
68
+ it "should wait without a timeout" do
69
+ report = subject.wait(max_wait_timeout: nil)
70
+
71
+ expect(report.acls[0].matching_acl_resource_name).to eq("acl-test-topic")
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#raise_error" do
77
+ let(:pending_handle) { false }
78
+
79
+ it "should raise the appropriate error" do
80
+ expect {
81
+ subject.raise_error
82
+ }.to raise_exception(Rdkafka::RdkafkaError, /Success \(no_error\)/)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Rdkafka::Admin::DescribeAclReport do
6
+
7
+ let(:resource_name) {"acl-test-topic"}
8
+ let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
9
+ let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
10
+ let(:principal) {"User:anonymous"}
11
+ let(:host) {"*"}
12
+ let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
13
+ let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
14
+ let(:describe_acl_ptr) {FFI::Pointer::NULL}
15
+
16
+ subject do
17
+ error_buffer = FFI::MemoryPointer.from_string(" " * 256)
18
+ describe_acl_ptr = Rdkafka::Bindings.rd_kafka_AclBinding_new(
19
+ resource_type,
20
+ FFI::MemoryPointer.from_string(resource_name),
21
+ resource_pattern_type,
22
+ FFI::MemoryPointer.from_string(principal),
23
+ FFI::MemoryPointer.from_string(host),
24
+ operation,
25
+ permission_type,
26
+ error_buffer,
27
+ 256
28
+ )
29
+ if describe_acl_ptr.null?
30
+ raise Rdkafka::Config::ConfigError.new(error_buffer.read_string)
31
+ end
32
+ pointer_array = [describe_acl_ptr]
33
+ describe_acls_array_ptr = FFI::MemoryPointer.new(:pointer)
34
+ describe_acls_array_ptr.write_array_of_pointer(pointer_array)
35
+ Rdkafka::Admin::DescribeAclReport.new(acls: describe_acls_array_ptr, acls_count: 1)
36
+ end
37
+
38
+ after do
39
+ if describe_acl_ptr != FFI::Pointer::NULL
40
+ Rdkafka::Bindings.rd_kafka_AclBinding_destroy(describe_acl_ptr)
41
+ end
42
+ end
43
+
44
+
45
+ it "should get matching acl resource type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC" do
46
+ expect(subject.acls[0].matching_acl_resource_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC)
47
+ end
48
+
49
+ it "should get matching acl resource name as acl-test-topic" do
50
+ expect(subject.acls[0].matching_acl_resource_name).to eq(resource_name)
51
+ end
52
+
53
+ it "should get matching acl resource pattern type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL" do
54
+ expect(subject.acls[0].matching_acl_resource_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
55
+ expect(subject.acls[0].matching_acl_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
56
+ end
57
+
58
+ it "should get matching acl principal as User:anonymous" do
59
+ expect(subject.acls[0].matching_acl_principal).to eq("User:anonymous")
60
+ end
61
+
62
+ it "should get matching acl host as * " do
63
+ expect(subject.acls[0].matching_acl_host).to eq("*")
64
+ end
65
+
66
+ it "should get matching acl operation as Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ" do
67
+ expect(subject.acls[0].matching_acl_operation).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ)
68
+ end
69
+
70
+ it "should get matching acl permission_type as Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW" do
71
+ expect(subject.acls[0].matching_acl_permission_type).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW)
72
+ end
73
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
3
  require "ostruct"
5
4
 
6
5
  describe Rdkafka::Admin do
@@ -10,6 +9,10 @@ describe Rdkafka::Admin do
10
9
  after do
11
10
  # Registry should always end up being empty
12
11
  expect(Rdkafka::Admin::CreateTopicHandle::REGISTRY).to be_empty
12
+ expect(Rdkafka::Admin::CreatePartitionsHandle::REGISTRY).to be_empty
13
+ expect(Rdkafka::Admin::DescribeAclHandle::REGISTRY).to be_empty
14
+ expect(Rdkafka::Admin::CreateAclHandle::REGISTRY).to be_empty
15
+ expect(Rdkafka::Admin::DeleteAclHandle::REGISTRY).to be_empty
13
16
  admin.close
14
17
  end
15
18
 
@@ -18,6 +21,15 @@ describe Rdkafka::Admin do
18
21
  let(:topic_replication_factor) { 1 }
19
22
  let(:topic_config) { {"cleanup.policy" => "compact", "min.cleanable.dirty.ratio" => 0.8} }
20
23
  let(:invalid_topic_config) { {"cleeeeenup.policee" => "campact"} }
24
+ let(:group_name) { "test-group-#{Random.new.rand(0..1_000_000)}" }
25
+
26
+ let(:resource_name) {"acl-test-topic"}
27
+ let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
28
+ let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
29
+ let(:principal) {"User:anonymous"}
30
+ let(:host) {"*"}
31
+ let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
32
+ let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
21
33
 
22
34
  describe "#create_topic" do
23
35
  describe "called with invalid input" do
@@ -33,7 +45,7 @@ describe Rdkafka::Admin do
33
45
  }.to raise_exception { |ex|
34
46
  expect(ex).to be_a(Rdkafka::RdkafkaError)
35
47
  expect(ex.message).to match(/Broker: Invalid topic \(topic_exception\)/)
36
- expect(ex.broker_message).to match(/Topic name.*is illegal, it contains a character other than ASCII alphanumerics/)
48
+ expect(ex.broker_message).to match(/Topic name.*is invalid: .* contains one or more characters other than ASCII alphanumerics, '.', '_' and '-'/)
37
49
  }
38
50
  end
39
51
  end
@@ -201,4 +213,195 @@ describe Rdkafka::Admin do
201
213
  expect(delete_topic_report.result_name).to eq(topic_name)
202
214
  end
203
215
  end
216
+
217
+ describe "#ACL tests" do
218
+ let(:non_existing_resource_name) {"non-existing-topic"}
219
+ before do
220
+ #create topic for testing acl
221
+ create_topic_handle = admin.create_topic(resource_name, topic_partition_count, topic_replication_factor)
222
+ create_topic_report = create_topic_handle.wait(max_wait_timeout: 15.0)
223
+ end
224
+
225
+ after do
226
+ #delete acl
227
+ delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
228
+ delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
229
+
230
+ #delete topic that was created for testing acl
231
+ delete_topic_handle = admin.delete_topic(resource_name)
232
+ delete_topic_report = delete_topic_handle.wait(max_wait_timeout: 15.0)
233
+ end
234
+
235
+ describe "#create_acl" do
236
+ it "create acl for a topic that does not exist" do
237
+ # acl creation for resources that does not exist will still get created successfully.
238
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
239
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
240
+ expect(create_acl_report.rdkafka_response).to eq(0)
241
+ expect(create_acl_report.rdkafka_response_string).to eq("")
242
+
243
+ # delete the acl that was created for a non existing topic"
244
+ delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
245
+ delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
246
+ expect(delete_acl_handle[:response]).to eq(0)
247
+ expect(delete_acl_report.deleted_acls.size).to eq(1)
248
+ end
249
+
250
+ it "creates a acl for topic that was newly created" do
251
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
252
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
253
+ expect(create_acl_report.rdkafka_response).to eq(0)
254
+ expect(create_acl_report.rdkafka_response_string).to eq("")
255
+ end
256
+ end
257
+
258
+ describe "#describe_acl" do
259
+ it "describe acl of a topic that does not exist" do
260
+ describe_acl_handle = admin.describe_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
261
+ describe_acl_report = describe_acl_handle.wait(max_wait_timeout: 15.0)
262
+ expect(describe_acl_handle[:response]).to eq(0)
263
+ expect(describe_acl_report.acls.size).to eq(0)
264
+ end
265
+
266
+ it "create acls and describe the newly created acls" do
267
+ #create_acl
268
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_1", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
269
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
270
+ expect(create_acl_report.rdkafka_response).to eq(0)
271
+ expect(create_acl_report.rdkafka_response_string).to eq("")
272
+
273
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_2", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
274
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
275
+ expect(create_acl_report.rdkafka_response).to eq(0)
276
+ expect(create_acl_report.rdkafka_response_string).to eq("")
277
+
278
+ #describe_acl
279
+ describe_acl_handle = admin.describe_acl(resource_type: Rdkafka::Bindings::RD_KAFKA_RESOURCE_ANY, resource_name: nil, resource_pattern_type: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_ANY, principal: nil, host: nil, operation: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ANY, permission_type: Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ANY)
280
+ describe_acl_report = describe_acl_handle.wait(max_wait_timeout: 15.0)
281
+ expect(describe_acl_handle[:response]).to eq(0)
282
+ expect(describe_acl_report.acls.length).to eq(2)
283
+ end
284
+ end
285
+
286
+ describe "#delete_acl" do
287
+ it "delete acl of a topic that does not exist" do
288
+ delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
289
+ delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
290
+ expect(delete_acl_handle[:response]).to eq(0)
291
+ expect(delete_acl_report.deleted_acls.size).to eq(0)
292
+ end
293
+
294
+ it "create an acl and delete the newly created acl" do
295
+ #create_acl
296
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_1", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
297
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
298
+ expect(create_acl_report.rdkafka_response).to eq(0)
299
+ expect(create_acl_report.rdkafka_response_string).to eq("")
300
+
301
+ create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_2", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
302
+ create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
303
+ expect(create_acl_report.rdkafka_response).to eq(0)
304
+ expect(create_acl_report.rdkafka_response_string).to eq("")
305
+
306
+ #delete_acl - resource_name nil - to delete all acls with any resource name and matching all other filters.
307
+ delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: nil, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
308
+ delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
309
+ expect(delete_acl_handle[:response]).to eq(0)
310
+ expect(delete_acl_report.deleted_acls.length).to eq(2)
311
+
312
+ end
313
+ end
314
+ end
315
+
316
+ describe('Group tests') do
317
+ describe "#delete_group" do
318
+ describe("with an existing group") do
319
+ let(:consumer_config) { rdkafka_consumer_config('group.id': group_name) }
320
+ let(:producer_config) { rdkafka_producer_config }
321
+ let(:producer) { producer_config.producer }
322
+ let(:consumer) { consumer_config.consumer }
323
+
324
+ before do
325
+ # Create a topic, post a message to it, consume it and commit offsets, this will create a group that we can then delete.
326
+ admin.create_topic(topic_name, topic_partition_count, topic_replication_factor).wait(max_wait_timeout: 15.0)
327
+
328
+ producer.produce(topic: topic_name, payload: "test", key: "test").wait(max_wait_timeout: 15.0)
329
+
330
+ consumer.subscribe(topic_name)
331
+ wait_for_assignment(consumer)
332
+ message = consumer.poll(100)
333
+
334
+ expect(message).to_not be_nil
335
+
336
+ consumer.commit
337
+ consumer.close
338
+ end
339
+
340
+ after do
341
+ producer.close
342
+ consumer.close
343
+ end
344
+
345
+ it "deletes the group" do
346
+ delete_group_handle = admin.delete_group(group_name)
347
+ report = delete_group_handle.wait(max_wait_timeout: 15.0)
348
+
349
+ expect(report.result_name).to eql(group_name)
350
+ end
351
+ end
352
+
353
+ describe "called with invalid input" do
354
+ describe "with the name of a group that does not exist" do
355
+ it "raises an exception" do
356
+ delete_group_handle = admin.delete_group(group_name)
357
+
358
+ expect {
359
+ delete_group_handle.wait(max_wait_timeout: 15.0)
360
+ }.to raise_exception { |ex|
361
+ expect(ex).to be_a(Rdkafka::RdkafkaError)
362
+ expect(ex.message).to match(/Broker: The group id does not exist \(group_id_not_found\)/)
363
+ }
364
+ end
365
+ end
366
+ end
367
+
368
+ end
369
+ end
370
+
371
+ describe '#create_partitions' do
372
+ let(:metadata) { admin.metadata(topic_name).topics.first }
373
+
374
+ context 'when topic does not exist' do
375
+ it 'expect to fail due to unknown partition' do
376
+ expect { admin.create_partitions(topic_name, 10).wait }.to raise_error(Rdkafka::RdkafkaError, /unknown_topic_or_part/)
377
+ end
378
+ end
379
+
380
+ context 'when topic already has the desired number of partitions' do
381
+ before { admin.create_topic(topic_name, 2, 1).wait }
382
+
383
+ it 'expect not to change number of partitions' do
384
+ expect { admin.create_partitions(topic_name, 2).wait }.to raise_error(Rdkafka::RdkafkaError, /invalid_partitions/)
385
+ expect(metadata[:partition_count]).to eq(2)
386
+ end
387
+ end
388
+
389
+ context 'when topic has more than the requested number of partitions' do
390
+ before { admin.create_topic(topic_name, 5, 1).wait }
391
+
392
+ it 'expect not to change number of partitions' do
393
+ expect { admin.create_partitions(topic_name, 2).wait }.to raise_error(Rdkafka::RdkafkaError, /invalid_partitions/)
394
+ expect(metadata[:partition_count]).to eq(5)
395
+ end
396
+ end
397
+
398
+ context 'when topic has less then desired number of partitions' do
399
+ before { admin.create_topic(topic_name, 1, 1).wait }
400
+
401
+ it 'expect to change number of partitions' do
402
+ admin.create_partitions(topic_name, 10).wait
403
+ expect(metadata[:partition_count]).to eq(10)
404
+ end
405
+ end
406
+ end
204
407
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
3
  require 'zlib'
5
4
 
6
5
  describe Rdkafka::Bindings do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Callbacks do
6
4
 
7
5
  # The code in the call back functions is 100% covered by other specs. Due to
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Config do
6
4
  context "logger" do
7
5
  it "should have a default logger" do
@@ -115,6 +113,14 @@ describe Rdkafka::Config do
115
113
  consumer.close
116
114
  end
117
115
 
116
+ it "should create a consumer with consumer_poll_set set to false" do
117
+ config = rdkafka_consumer_config
118
+ config.consumer_poll_set = false
119
+ consumer = config.consumer
120
+ expect(consumer).to be_a Rdkafka::Consumer
121
+ consumer.close
122
+ end
123
+
118
124
  it "should raise an error when creating a consumer with invalid config" do
119
125
  config = Rdkafka::Config.new('invalid.key' => 'value')
120
126
  expect {
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Consumer::Headers do
6
4
  let(:headers) do
7
5
  { # Note String keys!
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Consumer::Message do
6
4
  let(:native_client) { new_native_client }
7
5
  let(:native_topic) { new_native_topic(native_client: native_client) }
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Consumer::Partition do
6
4
  let(:offset) { 100 }
7
5
  let(:err) { 0 }
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
4
-
5
3
  describe Rdkafka::Consumer::TopicPartitionList do
6
4
  it "should create a new list and add unassigned topics" do
7
5
  list = Rdkafka::Consumer::TopicPartitionList.new
@@ -221,5 +219,24 @@ describe Rdkafka::Consumer::TopicPartitionList do
221
219
 
222
220
  expect(list).to eq other
223
221
  end
222
+
223
+ it "should create a native list with timetamp offsets if offsets are Time" do
224
+ list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
225
+ list.add_topic_and_partitions_with_offsets("topic", 0 => Time.at(1505069646, 250_000))
226
+ end
227
+
228
+ tpl = list.to_native_tpl
229
+
230
+ compare_list = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
231
+ list.add_topic_and_partitions_with_offsets(
232
+ "topic",
233
+ 0 => (Time.at(1505069646, 250_000).to_f * 1000).floor
234
+ )
235
+ end
236
+
237
+ native_list = Rdkafka::Consumer::TopicPartitionList.from_native_tpl(tpl)
238
+
239
+ expect(native_list).to eq compare_list
240
+ end
224
241
  end
225
242
  end