public async Task ProducerShouldReportCorrectAmountOfAsyncRequests()
        {
            // var log = new ConsoleLog(); for (int i = 0; i < 100; i++) {
            var semaphore = new SemaphoreSlim(0);
            var routerProxy = new FakeBrokerRouter();
            //block the second call returning from send message async
            routerProxy.BrokerConn0.ProduceResponseFunction = async () =>
            {
                await semaphore.WaitAsync();
                return new ProduceResponse();
            };

            var router = routerProxy.Create();
            using (var producer = new Producer(router, maximumAsyncRequests: 1) { BatchSize = 1 })
            {
                var messages = new[] { new Message("1") };

                Assert.That(producer.AsyncCount, Is.EqualTo(0));

                var sendTask = producer.SendMessageAsync(BrokerRouterProxy.TestTopic, messages);

                await TaskTest.WaitFor(() => producer.AsyncCount > 0);
                Assert.That(producer.AsyncCount, Is.EqualTo(1), "One async operation should be sending.");

                semaphore.Release();
                sendTask.Wait(TimeSpan.FromMilliseconds(500));
                await Task.Delay(2);
                Assert.That(sendTask.IsCompleted, Is.True, "Send task should be marked as completed.");
                Assert.That(producer.AsyncCount, Is.EqualTo(0), "Async should now show zero count.");
                // } log.DebugFormat(i.ToString());
            }
        }
        public async void SendAsyncShouldGetAResultForEachPartitionSentTo()
        {
            using (var router = new BrokerRouter(new KafkaOptions(IntegrationConfig.IntegrationUri)))
            using (var producer = new Producer(router))
            {
                var messages = new[] { new Message("1"), new Message("2"), new Message("3") };
                var result = await producer.SendMessageAsync(IntegrationConfig.IntegrationTopic, messages);

                Assert.That(result.Count, Is.EqualTo(messages.Count()));
            }
        }
        public async void SendAsyncShouldGetOneResultForEachPartitionThroughBatching()
        {
            using (var router = new BrokerRouter(new KafkaOptions(IntegrationConfig.IntegrationUri)))
            using (var producer = new Producer(router))
            {
                var tasks = new[]
                {
                    producer.SendMessageAsync(IntegrationConfig.IntegrationTopic, new[] {new Message("1")}),
                    producer.SendMessageAsync(IntegrationConfig.IntegrationTopic, new[] {new Message("1")}),
                    producer.SendMessageAsync(IntegrationConfig.IntegrationTopic, new[] {new Message("1")}),
                };

                await Task.WhenAll(tasks);

                var result = tasks.SelectMany(x => x.Result).Distinct().ToList();

                Assert.That(result.Count, Is.EqualTo(tasks.Count()));
            }
        }
        public void EncodeMessageSetEncodesMultipleMessages()
        {
            //expected generated from python library
            var expected = new byte[]
                {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 45, 70, 24, 62, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 1, 48, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 16, 90, 65, 40, 168, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 1, 49, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 16, 195, 72, 121, 18, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 1, 50
                };

            var messages = new[]
                {
                    new Message("0", "1"),
                    new Message("1", "1"),
                    new Message("2", "1")
                };

            var result = Message.EncodeMessageSet(messages);

            Assert.That(expected, Is.EqualTo(result));
        }
        public async Task SendAsyncShouldBlockWhenMaximumAsyncQueueReached()
        {
            _log.InfoFormat("Start SendAsyncShouldBlockWhenMaximumAsyncQueueReached");
            int count = 0;
            var semaphore = new SemaphoreSlim(0);
            var routerProxy = new FakeBrokerRouter();
            //block the second call returning from send message async
            routerProxy.BrokerConn0.ProduceResponseFunction = async () => { await semaphore.WaitAsync(); return new ProduceResponse(); };

            var router = routerProxy.Create();
            using (var producer = new Producer(router, maximumAsyncRequests: 1) { BatchSize = 1 })
            {
                var messages = new[] { new Message("1") };

                Task.Run(async () =>
                {
                    var t = producer.SendMessageAsync(BrokerRouterProxy.TestTopic, messages);
                    Interlocked.Increment(ref count);
                    await t;

                    t = producer.SendMessageAsync(BrokerRouterProxy.TestTopic, messages);

                    Interlocked.Increment(ref count);
                    await t;
                });

                await TaskTest.WaitFor(() => producer.AsyncCount > 0);
                await TaskTest.WaitFor(() => count > 0);

                Assert.That(count, Is.EqualTo(1), "Only one SendMessageAsync should continue.");

                semaphore.Release();
                await TaskTest.WaitFor(() => count > 1);
                Assert.That(count, Is.EqualTo(2), "The second SendMessageAsync should continue after semaphore is released.");
            }
        }
        public async void ProducesShouldSendExpectedProduceRequestForEachCodecCombination(MessageCodec codec1, MessageCodec codec2, int expected)
        {
            var routerProxy = new FakeBrokerRouter();
            var producer = new Producer(routerProxy.Create()) { BatchSize = 100 };
            using (producer)
            {
                var calls = new[]
                {
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message(), new Message()}, codec: codec1),
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message(), new Message()}, codec: codec2)
                };

                await Task.WhenAll(calls);

                Assert.That(routerProxy.BrokerConn0.ProduceRequestCallCount, Is.EqualTo(expected));
                Assert.That(routerProxy.BrokerConn1.ProduceRequestCallCount, Is.EqualTo(expected));
            }
        }
        public async void ProducesShouldSendExpectedProduceRequestForEachAckLevelAndTimeoutCombination(short ack1, short ack2, int time1, int time2, int expected)
        {
            var routerProxy = new FakeBrokerRouter();
            var producer = new Producer(routerProxy.Create()) { BatchSize = 100 };
            using (producer)
            {
                var calls = new[]
                {
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message(), new Message()}, acks:ack1, timeout: TimeSpan.FromMilliseconds(time1)),
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message(), new Message()}, acks:ack2, timeout: TimeSpan.FromMilliseconds(time2))
                };

                await Task.WhenAll(calls);

                Assert.That(routerProxy.BrokerConn0.ProduceRequestCallCount, Is.EqualTo(expected));
                Assert.That(routerProxy.BrokerConn1.ProduceRequestCallCount, Is.EqualTo(expected));
            }
        }
        public async void ProducesShouldSendOneProduceRequestForEachBatchSize()
        {
            var routerProxy = new FakeBrokerRouter();
            var producer = new Producer(routerProxy.Create()) { BatchSize = 2 };
            using (producer)
            {
                var calls = new[]
                {
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message()}),
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message()}),
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message()}),
                    producer.SendMessageAsync(FakeBrokerRouter.TestTopic, new[] {new Message()})
                };

                await Task.WhenAll(calls);

                Assert.That(routerProxy.BrokerConn0.ProduceRequestCallCount, Is.EqualTo(2));
                Assert.That(routerProxy.BrokerConn1.ProduceRequestCallCount, Is.EqualTo(2));
            }
        }