rdkafka 0.13.0 → 0.15.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.
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