mirror of
				https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka.git
				synced 2025-10-31 02:27:46 +00:00 
			
		
		
		
	Test suite fixes (#124)
* Move polling strategy adapter definition into test_utils.cpp * Use a random consumer group id in every test
This commit is contained in:
		| @@ -19,6 +19,7 @@ add_executable(cppkafka_tests | ||||
|     consumer_test.cpp | ||||
|     roundrobin_poll_test.cpp | ||||
|     headers_test.cpp | ||||
|     test_utils.cpp | ||||
|  | ||||
|     # Main file | ||||
|     test_main.cpp | ||||
|   | ||||
| @@ -35,7 +35,7 @@ static Configuration make_producer_config() { | ||||
|     return config; | ||||
| } | ||||
|  | ||||
| static Configuration make_consumer_config(const string& group_id = "consumer_test") { | ||||
| static Configuration make_consumer_config(const string& group_id = make_consumer_group_id()) { | ||||
|     Configuration config; | ||||
|     config.set("metadata.broker.list", KAFKA_TEST_INSTANCE); | ||||
|     config.set("enable.auto.commit", false); | ||||
| @@ -85,11 +85,12 @@ TEST_CASE("message consumption", "[consumer]") { | ||||
| TEST_CASE("consumer rebalance", "[consumer]") { | ||||
|     TopicPartitionList assignment1; | ||||
|     TopicPartitionList assignment2; | ||||
|     const string group_id = make_consumer_group_id(); | ||||
|     bool revocation_called = false; | ||||
|     int partition = 0; | ||||
|  | ||||
|     // Create a consumer and subscribe to the topic | ||||
|     Consumer consumer1(make_consumer_config()); | ||||
|     Consumer consumer1(make_consumer_config(group_id)); | ||||
|     consumer1.set_assignment_callback([&](const TopicPartitionList& topic_partitions) { | ||||
|         assignment1 = topic_partitions; | ||||
|     }); | ||||
| @@ -100,7 +101,7 @@ TEST_CASE("consumer rebalance", "[consumer]") { | ||||
|     ConsumerRunner runner1(consumer1, 1, KAFKA_NUM_PARTITIONS); | ||||
|  | ||||
|     // Create a second consumer and subscribe to the topic | ||||
|     Consumer consumer2(make_consumer_config()); | ||||
|     Consumer consumer2(make_consumer_config(group_id)); | ||||
|     consumer2.set_assignment_callback([&](const TopicPartitionList& topic_partitions) { | ||||
|         assignment2 = topic_partitions; | ||||
|     }); | ||||
|   | ||||
| @@ -42,7 +42,7 @@ static Configuration make_consumer_config() { | ||||
|     Configuration config = { | ||||
|         { "metadata.broker.list", KAFKA_TEST_INSTANCE }, | ||||
|         { "enable.auto.commit", false }, | ||||
|         { "group.id", "producer_test" }, | ||||
|         { "group.id", make_consumer_group_id() }, | ||||
|         { "api.version.request", true } | ||||
|     }; | ||||
|     return config; | ||||
|   | ||||
| @@ -7,13 +7,14 @@ | ||||
| #include <condition_variable> | ||||
| #include <catch.hpp> | ||||
| #include <memory> | ||||
| #include <iostream> | ||||
| #include <stdexcept> | ||||
| #include "cppkafka/cppkafka.h" | ||||
| #include "test_utils.h" | ||||
|  | ||||
| using std::vector; | ||||
| using std::move; | ||||
| using std::string; | ||||
| using std::exception; | ||||
| using std::thread; | ||||
| using std::set; | ||||
| using std::mutex; | ||||
| @@ -33,18 +34,18 @@ using namespace cppkafka; | ||||
| //                           Helper functions | ||||
| //================================================================================== | ||||
| static Configuration make_producer_config() { | ||||
|     Configuration config; | ||||
|     config.set("metadata.broker.list", KAFKA_TEST_INSTANCE); | ||||
|     Configuration config = {     | ||||
|         { "metadata.broker.list", KAFKA_TEST_INSTANCE }, | ||||
|     }; | ||||
|     return config; | ||||
| } | ||||
|  | ||||
| static Configuration make_consumer_config(const string& group_id = "rr_consumer_test") { | ||||
|     Configuration config; | ||||
|     config.set("metadata.broker.list", KAFKA_TEST_INSTANCE); | ||||
|     config.set("enable.auto.commit", true); | ||||
|     config.set("enable.auto.offset.store", true ); | ||||
|     config.set("auto.commit.interval.ms", 100); | ||||
|     config.set("group.id", group_id); | ||||
| static Configuration make_consumer_config(const string& group_id = make_consumer_group_id()) { | ||||
|     Configuration config = { | ||||
|         { "metadata.broker.list", KAFKA_TEST_INSTANCE }, | ||||
|         { "enable.auto.commit", false }, | ||||
|         { "group.id", group_id }, | ||||
|     }; | ||||
|     return config; | ||||
| } | ||||
|  | ||||
| @@ -63,44 +64,6 @@ static vector<int> make_roundrobin_partition_vector(int total_messages) { | ||||
| //                              TESTS | ||||
| //======================================================================== | ||||
|  | ||||
| TEST_CASE("serial consumer test", "[roundrobin consumer]") { | ||||
|     int messages_per_partition = 3; | ||||
|     int total_messages = KAFKA_NUM_PARTITIONS * messages_per_partition; | ||||
|  | ||||
|     // Create a consumer and subscribe to the topic | ||||
|     Consumer consumer(make_consumer_config()); | ||||
|     TopicPartitionList partitions; | ||||
|     for (int i = 0; i < KAFKA_NUM_PARTITIONS; partitions.emplace_back(KAFKA_TOPICS[0], i++)); | ||||
|     consumer.assign(partitions); | ||||
|      | ||||
|     // Start the runner with the original consumer | ||||
|     ConsumerRunner runner(consumer, total_messages, KAFKA_NUM_PARTITIONS); | ||||
|  | ||||
|     // Produce messages so we stop the consumer | ||||
|     Producer producer(make_producer_config()); | ||||
|     string payload = "Serial"; | ||||
|      | ||||
|     // push 3 messages in each partition | ||||
|     for (int i = 0; i < total_messages; ++i) { | ||||
|         producer.produce(MessageBuilder(KAFKA_TOPICS[0]).partition(i%KAFKA_NUM_PARTITIONS).payload(payload)); | ||||
|     } | ||||
|     producer.flush(); | ||||
|     runner.try_join(); | ||||
|      | ||||
|     // Check that we have all messages | ||||
|     REQUIRE(runner.get_messages().size() == total_messages); | ||||
|      | ||||
|     // messages should have sequential identical partition ids in groups of <messages_per_partition> | ||||
|     int expected_partition; | ||||
|     for (int i = 0; i < total_messages; ++i) { | ||||
|         if ((i % messages_per_partition) == 0) { | ||||
|             expected_partition = runner.get_messages()[i].get_partition(); | ||||
|         } | ||||
|         REQUIRE(runner.get_messages()[i].get_partition() == expected_partition); | ||||
|         REQUIRE((string)runner.get_messages()[i].get_payload() == payload); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("roundrobin consumer test", "[roundrobin consumer]") { | ||||
|     TopicPartitionList assignment; | ||||
|     int messages_per_partition = 3; | ||||
| @@ -119,9 +82,21 @@ TEST_CASE("roundrobin consumer test", "[roundrobin consumer]") { | ||||
|      | ||||
|     // push 3 messages in each partition | ||||
|     for (int i = 0; i < total_messages; ++i) { | ||||
|         producer.produce(MessageBuilder(KAFKA_TOPICS[0]).partition(i%KAFKA_NUM_PARTITIONS).payload(payload)); | ||||
|         producer.produce(MessageBuilder(KAFKA_TOPICS[0]) | ||||
|                             .partition(i % KAFKA_NUM_PARTITIONS) | ||||
|                             .payload(payload)); | ||||
|     } | ||||
|     for (int i = 0; i < 3; ++i) { | ||||
|         try { | ||||
|             producer.flush(); | ||||
|             break; | ||||
|         } | ||||
|         catch (const exception& ex) { | ||||
|             if (i == 2) { | ||||
|                 throw; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     producer.flush(); | ||||
|     runner.try_join(); | ||||
|      | ||||
|     // Check that we have all messages | ||||
|   | ||||
							
								
								
									
										94
									
								
								tests/test_utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								tests/test_utils.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| #include <cstdint> | ||||
| #include <iomanip> | ||||
| #include <limits> | ||||
| #include <sstream> | ||||
| #include <random> | ||||
| #include "test_utils.h" | ||||
|  | ||||
| using std::chrono::duration_cast; | ||||
| using std::chrono::milliseconds; | ||||
| using std::chrono::seconds; | ||||
| using std::chrono::system_clock; | ||||
| using std::hex; | ||||
| using std::move; | ||||
| using std::numeric_limits; | ||||
| using std::ostringstream; | ||||
| using std::random_device; | ||||
| using std::string; | ||||
| using std::uniform_int_distribution; | ||||
| using std::unique_ptr; | ||||
| using std::vector; | ||||
|  | ||||
| //================================================================================== | ||||
| //                           PollStrategyAdapter | ||||
| //================================================================================== | ||||
|  | ||||
| PollStrategyAdapter::PollStrategyAdapter(Configuration config) | ||||
|  : Consumer(config) { | ||||
| } | ||||
|  | ||||
| void PollStrategyAdapter::add_polling_strategy(unique_ptr<PollInterface> poll_strategy) { | ||||
|     strategy_ = move(poll_strategy); | ||||
| } | ||||
|  | ||||
| void PollStrategyAdapter::delete_polling_strategy() { | ||||
|     strategy_.reset(); | ||||
| } | ||||
|  | ||||
| Message PollStrategyAdapter::poll() { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll(); | ||||
|     } | ||||
|     return Consumer::poll(); | ||||
| } | ||||
|  | ||||
| Message PollStrategyAdapter::poll(milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll(timeout); | ||||
|     } | ||||
|     return Consumer::poll(timeout); | ||||
| } | ||||
|  | ||||
| vector<Message> PollStrategyAdapter::poll_batch(size_t max_batch_size) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll_batch(max_batch_size); | ||||
|     } | ||||
|     return Consumer::poll_batch(max_batch_size); | ||||
| } | ||||
|  | ||||
| vector<Message> PollStrategyAdapter::poll_batch(size_t max_batch_size, milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll_batch(max_batch_size, timeout); | ||||
|     } | ||||
|     return Consumer::poll_batch(max_batch_size, timeout); | ||||
| } | ||||
|  | ||||
| void PollStrategyAdapter::set_timeout(milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         strategy_->set_timeout(timeout); | ||||
|     } | ||||
|     else { | ||||
|         Consumer::set_timeout(timeout); | ||||
|     } | ||||
| } | ||||
|  | ||||
| milliseconds PollStrategyAdapter::get_timeout() { | ||||
|     if (strategy_) { | ||||
|         return strategy_->get_timeout(); | ||||
|     } | ||||
|     return Consumer::get_timeout(); | ||||
| } | ||||
|  | ||||
| // Misc | ||||
|  | ||||
| string make_consumer_group_id() { | ||||
|     ostringstream output; | ||||
|     output << hex; | ||||
|  | ||||
|     random_device rd; | ||||
|     uniform_int_distribution<uint64_t> distribution(0, numeric_limits<uint64_t>::max()); | ||||
|     const auto now = duration_cast<seconds>(system_clock::now().time_since_epoch()); | ||||
|     const auto random_number = distribution(rd); | ||||
|     output << now.count() << random_number; | ||||
|     return output.str(); | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| #ifndef CPPKAFKA_TEST_UTILS_H | ||||
| #define CPPKAFKA_TEST_UTILS_H | ||||
|  | ||||
| #include <string> | ||||
| #include <thread> | ||||
| #include <vector> | ||||
| #include "cppkafka/consumer.h" | ||||
| @@ -57,9 +58,14 @@ private: | ||||
|     std::unique_ptr<PollInterface> strategy_; | ||||
| }; | ||||
|  | ||||
| // Misc | ||||
|  | ||||
| std::string make_consumer_group_id(); | ||||
|  | ||||
| using PollConsumerRunner = BasicConsumerRunner<PollStrategyAdapter>; | ||||
| using ConsumerRunner = BasicConsumerRunner<Consumer>; | ||||
|  | ||||
|  | ||||
| #include "test_utils_impl.h" | ||||
|  | ||||
| #endif // CPPKAFKA_TEST_UTILS_H | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| #include <mutex> | ||||
| #include <chrono> | ||||
| #include <condition_variable> | ||||
| #include "test_utils.h" | ||||
| #include "cppkafka/utils/consumer_dispatcher.h" | ||||
|  | ||||
| using std::vector; | ||||
| @@ -45,7 +44,8 @@ BasicConsumerRunner<ConsumerType>::BasicConsumerRunner(ConsumerType& consumer, | ||||
|                 } | ||||
|             }, | ||||
|             // EOF callback | ||||
|             [&](typename BasicConsumerDispatcher<ConsumerType>::EndOfFile, const TopicPartition& topic_partition) { | ||||
|             [&](typename BasicConsumerDispatcher<ConsumerType>::EndOfFile, | ||||
|                 const TopicPartition& topic_partition) { | ||||
|                 if (number_eofs != partitions) { | ||||
|                     number_eofs++; | ||||
|                     if (number_eofs == partitions) { | ||||
| @@ -99,73 +99,4 @@ void BasicConsumerRunner<ConsumerType>::try_join() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| //================================================================================== | ||||
| //                           PollStrategyAdapter | ||||
| //================================================================================== | ||||
| inline | ||||
| PollStrategyAdapter::PollStrategyAdapter(Configuration config) | ||||
|  : Consumer(config) { | ||||
| } | ||||
|  | ||||
| inline | ||||
| void PollStrategyAdapter::add_polling_strategy(std::unique_ptr<PollInterface> poll_strategy) { | ||||
|     strategy_ = std::move(poll_strategy); | ||||
| } | ||||
|  | ||||
| inline | ||||
| void PollStrategyAdapter::delete_polling_strategy() { | ||||
|     strategy_.reset(); | ||||
| } | ||||
|  | ||||
| inline | ||||
| Message PollStrategyAdapter::poll() { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll(); | ||||
|     } | ||||
|     return Consumer::poll(); | ||||
| } | ||||
|  | ||||
| inline | ||||
| Message PollStrategyAdapter::poll(milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll(timeout); | ||||
|     } | ||||
|     return Consumer::poll(timeout); | ||||
| } | ||||
|  | ||||
| inline | ||||
| std::vector<Message> PollStrategyAdapter::poll_batch(size_t max_batch_size) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll_batch(max_batch_size); | ||||
|     } | ||||
|     return Consumer::poll_batch(max_batch_size); | ||||
| } | ||||
|  | ||||
| inline | ||||
| std::vector<Message> PollStrategyAdapter::poll_batch(size_t max_batch_size, | ||||
|                                                      milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         return strategy_->poll_batch(max_batch_size, timeout); | ||||
|     } | ||||
|     return Consumer::poll_batch(max_batch_size, timeout); | ||||
| } | ||||
|  | ||||
| inline | ||||
| void PollStrategyAdapter::set_timeout(milliseconds timeout) { | ||||
|     if (strategy_) { | ||||
|         strategy_->set_timeout(timeout); | ||||
|     } | ||||
|     else { | ||||
|         Consumer::set_timeout(timeout); | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline | ||||
| milliseconds PollStrategyAdapter::get_timeout() { | ||||
|     if (strategy_) { | ||||
|         return strategy_->get_timeout(); | ||||
|     } | ||||
|     return Consumer::get_timeout(); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Matias Fontanini
					Matias Fontanini