1
1
#include < string>
2
2
#include < algorithm>
3
3
#include < cstring>
4
+ #include < cstdarg>
4
5
#include < cppkafka/mocking/api.h>
5
6
#include < cppkafka/mocking/producer_mock.h>
7
+ #include < cppkafka/mocking/consumer_mock.h>
6
8
#include < cppkafka/mocking/kafka_cluster_registry.h>
7
9
8
10
using std::string;
9
11
using std::copy;
12
+ using std::vector;
10
13
using std::strlen;
14
+ using std::move;
11
15
using std::make_shared;
16
+ using std::unique_ptr;
17
+
18
+ using std::chrono::milliseconds;
12
19
13
20
using namespace cppkafka ::mocking;
14
21
using namespace cppkafka ::mocking::detail;
@@ -205,6 +212,25 @@ rd_kafka_topic_partition_list_add(rd_kafka_topic_partition_list_t* toppar_list,
205
212
return output;
206
213
}
207
214
215
+ // rd_kafka_topic_t
216
+
217
+ rd_kafka_topic_t * rd_kafka_topic_new (rd_kafka_t * rk, const char * topic,
218
+ rd_kafka_topic_conf_t * conf) {
219
+ return reinterpret_cast <rd_kafka_topic_t *>(new TopicHandle (topic, nullptr ));
220
+ }
221
+
222
+ const char * rd_kafka_topic_name (const rd_kafka_topic_t * rkt) {
223
+ return reinterpret_cast <const TopicHandle*>(rkt)->get_topic ().c_str ();
224
+ }
225
+
226
+ void rd_kafka_topic_destroy (rd_kafka_topic_t * rkt) {
227
+ delete reinterpret_cast <TopicHandle*>(rkt);
228
+ }
229
+
230
+ int rd_kafka_topic_partition_available (const rd_kafka_topic_t * rkt, int32_t partition) {
231
+ return 1 ;
232
+ }
233
+
208
234
// rd_kafka_t
209
235
210
236
rd_kafka_t * rd_kafka_new (rd_kafka_type_t type, rd_kafka_conf_t *conf_ptr,
@@ -219,5 +245,195 @@ rd_kafka_t* rd_kafka_new(rd_kafka_type_t type, rd_kafka_conf_t *conf_ptr,
219
245
return new rd_kafka_t (new ProducerMock (conf, make_shared<EventProcessor>(),
220
246
move (cluster)));
221
247
}
248
+ else if (type == RD_KAFKA_CONSUMER) {
249
+ if (!conf.has_key (" group.id" )) {
250
+ const string error = " Local: Unknown topic" ;
251
+ if (error.size () < errstr_size) {
252
+ copy (error.begin (), error.end (), errstr);
253
+ errstr[error.size ()] = 0 ;
254
+ }
255
+ return nullptr ;
256
+ }
257
+ return new rd_kafka_t (new ConsumerMock (conf, make_shared<EventProcessor>(),
258
+ move (cluster)));
259
+ }
222
260
return nullptr ;
223
261
}
262
+
263
+ void rd_kafka_destroy (rd_kafka_t * rk) {
264
+ delete &rk->get_handle ();
265
+ }
266
+
267
+ int rd_kafka_brokers_add (rd_kafka_t * rk, const char * brokerlist) {
268
+ auto cluster = KafkaClusterRegistry::instance ().get_cluster (brokerlist);
269
+ if (cluster) {
270
+ rk->get_handle ().set_cluster (move (cluster));
271
+ }
272
+ return 1 ;
273
+ }
274
+
275
+ const char * rd_kafka_name (const rd_kafka_t * rk) {
276
+ return " cppkafka mock handle" ;
277
+ }
278
+
279
+ rd_kafka_message_t * rd_kafka_consumer_poll (rd_kafka_t * rk, int timeout_ms) {
280
+ auto & consumer = rk->get_handle <ConsumerMock>();
281
+ auto message_ptr = consumer.poll (milliseconds (timeout_ms));
282
+ if (!message_ptr) {
283
+ return nullptr ;
284
+ }
285
+ else {
286
+ return &message_ptr.release ()->get_message ();
287
+ }
288
+ }
289
+
290
+ void rd_kafka_message_destroy (rd_kafka_message_t * rkmessage) {
291
+ delete static_cast <MessageHandlePrivateData*>(rkmessage->_private )->get_owner ();
292
+ }
293
+
294
+ rd_kafka_resp_err_t rd_kafka_pause_partitions (rd_kafka_t * rk,
295
+ rd_kafka_topic_partition_list_t * partitions) {
296
+ const vector<TopicPartitionMock> topic_partitions = from_rdkafka_handle (*partitions);
297
+ auto & consumer = rk->get_handle <ConsumerMock>();
298
+ consumer.pause_partitions (topic_partitions);
299
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
300
+ }
301
+
302
+ rd_kafka_resp_err_t rd_kafka_resume_partitions (rd_kafka_t * rk,
303
+ rd_kafka_topic_partition_list_t * partitions) {
304
+ const vector<TopicPartitionMock> topic_partitions = from_rdkafka_handle (*partitions);
305
+ auto & consumer = rk->get_handle <ConsumerMock>();
306
+ consumer.resume_partitions (topic_partitions);
307
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
308
+ }
309
+
310
+ rd_kafka_resp_err_t rd_kafka_subscribe (rd_kafka_t * rk,
311
+ const rd_kafka_topic_partition_list_t * partitions) {
312
+ const vector<TopicPartitionMock> topic_partitions = from_rdkafka_handle (*partitions);
313
+ vector<string> topics;
314
+ for (const TopicPartitionMock& topic_partition : topic_partitions) {
315
+ topics.emplace_back (topic_partition.get_topic ());
316
+ }
317
+ auto & consumer = rk->get_handle <ConsumerMock>();
318
+ consumer.subscribe (topics);
319
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
320
+ }
321
+
322
+ rd_kafka_resp_err_t rd_kafka_unsubscribe (rd_kafka_t * rk) {
323
+ auto & consumer = rk->get_handle <ConsumerMock>();
324
+ consumer.unsubscribe ();
325
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
326
+ }
327
+
328
+ rd_kafka_resp_err_t rd_kafka_assign (rd_kafka_t * rk,
329
+ const rd_kafka_topic_partition_list_t * partitions) {
330
+ const vector<TopicPartitionMock> topic_partitions = from_rdkafka_handle (*partitions);
331
+ auto & consumer = rk->get_handle <ConsumerMock>();
332
+ consumer.assign (topic_partitions);
333
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
334
+ }
335
+
336
+ rd_kafka_resp_err_t rd_kafka_assignment (rd_kafka_t * rk,
337
+ rd_kafka_topic_partition_list_t ** partitions) {
338
+ auto & consumer = rk->get_handle <ConsumerMock>();
339
+ const vector<TopicPartitionMock> assignment = consumer.get_assignment ();
340
+ *partitions = to_rdkafka_handle (assignment).release ();
341
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
342
+ }
343
+
344
+ rd_kafka_resp_err_t rd_kafka_flush (rd_kafka_t * rk, int timeout_ms) {
345
+ if (rk->get_handle <ProducerMock>().flush (milliseconds (timeout_ms))) {
346
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
347
+ }
348
+ else {
349
+ return RD_KAFKA_RESP_ERR__TIMED_OUT;
350
+ }
351
+ }
352
+
353
+ int rd_kafka_poll (rd_kafka_t * rk, int timeout_ms) {
354
+ return rk->get_handle <ProducerMock>().poll (milliseconds (timeout_ms));
355
+ }
356
+
357
+ rd_kafka_resp_err_t rd_kafka_producev (rd_kafka_t * rk, ...) {
358
+ va_list args;
359
+ int vtype;
360
+ unique_ptr<TopicHandle> topic;
361
+ unsigned partition = RD_KAFKA_PARTITION_UA;
362
+ void * key_ptr = nullptr ;
363
+ size_t key_size = 0 ;
364
+ void * payload_ptr = nullptr ;
365
+ size_t payload_size = 0 ;
366
+ void * opaque = nullptr ;
367
+ MessageHandle::PointerOwnership ownership = MessageHandle::PointerOwnership::Unowned;
368
+ int64_t timestamp = 0 ;
369
+
370
+ va_start (args, rk);
371
+ while ((vtype = va_arg (args, int )) != RD_KAFKA_VTYPE_END) {
372
+ switch (vtype) {
373
+ case RD_KAFKA_VTYPE_TOPIC:
374
+ topic.reset (new TopicHandle (va_arg (args, const char *), nullptr ));
375
+ break ;
376
+ case RD_KAFKA_VTYPE_PARTITION:
377
+ partition = va_arg (args, int32_t );
378
+ break ;
379
+ case RD_KAFKA_VTYPE_VALUE:
380
+ payload_ptr = va_arg (args, void *);
381
+ payload_size = va_arg (args, size_t );
382
+ break ;
383
+ case RD_KAFKA_VTYPE_KEY:
384
+ key_ptr = va_arg (args, void *);
385
+ key_size = va_arg (args, size_t );
386
+ break ;
387
+ case RD_KAFKA_VTYPE_OPAQUE:
388
+ opaque = va_arg (args, void *);
389
+ break ;
390
+ case RD_KAFKA_VTYPE_MSGFLAGS:
391
+ if (va_arg (args, int ) == static_cast <int >(MessageHandle::PointerOwnership::Owned)) {
392
+ ownership = MessageHandle::PointerOwnership::Owned;
393
+ }
394
+ break ;
395
+ case RD_KAFKA_VTYPE_TIMESTAMP:
396
+ timestamp = va_arg (args, int64_t );
397
+ break ;
398
+ default :
399
+ return RD_KAFKA_RESP_ERR__INVALID_ARG;
400
+ }
401
+ }
402
+ va_end (args);
403
+
404
+ MessageHandlePrivateData private_data (RD_KAFKA_TIMESTAMP_CREATE_TIME, timestamp);
405
+ private_data.set_opaque (opaque);
406
+ rk->get_handle <ProducerMock>().produce (MessageHandle (
407
+ move (topic),
408
+ partition,
409
+ -1 , // offset
410
+ key_ptr, key_size,
411
+ payload_ptr, payload_size,
412
+ RD_KAFKA_RESP_ERR_NO_ERROR,
413
+ private_data,
414
+ ownership
415
+ ));
416
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
417
+ }
418
+
419
+ int rd_kafka_outq_len (rd_kafka_t * rk) {
420
+ return rk->get_handle <ProducerMock>().get_event_count ();
421
+ }
422
+
423
+ void * rd_kafka_opaque (const rd_kafka_t * rk) {
424
+ return rk->get_handle ().get_opaque ();
425
+ }
426
+
427
+ void rd_kafka_set_log_level (rd_kafka_t * /* rk*/ , int /* level*/ ) {
428
+
429
+ }
430
+
431
+ // misc
432
+
433
+ const char * rd_kafka_err2str (rd_kafka_resp_err_t err) {
434
+ return " cppkafka mock: error" ;
435
+ }
436
+
437
+ rd_kafka_resp_err_t rd_kafka_errno2err (int errnox) {
438
+ return RD_KAFKA_RESP_ERR_NO_ERROR;
439
+ }
0 commit comments