public void ShouldDisposeWithoutExecptionThrown()
 {
     using (var server = new FakeTcpServer(8999))
     {
         Thread.Sleep(500);
     }
 }
 public void ShouldDisposeEvenWhenTryingToSendWithoutExceptionThrown()
 {
     using (var server = new FakeTcpServer(8999))
     {
         server.SendDataAsync("test");
         Thread.Sleep(500);
     }
 }
 public void ShouldDisposeWithoutExceptionThrown()
 {
     using (var server = new FakeTcpServer(8999))
     using (var socket = new KafkaTcpSocket(_log, _kafkaEndpoint))
     {
         var conn = new KafkaConnection(socket, log: _log);
         TaskTest.WaitFor(() => server.ConnectionEventcount > 0);
         using (conn) { }
     }
 }
        public void SendAsyncShouldWaitUntilClientIsConnected()
        {
            const int testData = 99;
            using (var server = new FakeTcpServer(8999))
            using (var client = new TcpClient())
            {
                server.SendDataAsync(testData.ToBytes());
                Thread.Sleep(1000);
                client.Connect(_fakeServerUrl.Host, _fakeServerUrl.Port);

                var buffer = new byte[4];
                client.GetStream().ReadAsync(buffer, 0, 4).Wait(TimeSpan.FromSeconds(5));
                
                Assert.That(buffer.ToInt32(), Is.EqualTo(testData));
            }
        }
        public void FakeShouldBeAbleToReconnect()
        {
            using (var server = new FakeTcpServer(8999))
            {
                byte[] received = null;
                server.OnBytesReceived += data => received = data;

                var t1 = new TcpClient();
                t1.Connect(_fakeServerUrl.Host, _fakeServerUrl.Port);
                TaskTest.WaitFor(() => server.ConnectionEventcount == 1);

                server.DropConnection();
                TaskTest.WaitFor(() => server.DisconnectionEventCount == 1);

                var t2 = new TcpClient();
                t2.Connect(_fakeServerUrl.Host, _fakeServerUrl.Port);
                TaskTest.WaitFor(() => server.ConnectionEventcount == 2);

                t2.GetStream().Write(99.ToBytes(), 0, 4);
                TaskTest.WaitFor(() => received != null);

                Assert.That(received.ToInt32(), Is.EqualTo(99));
            }
        }
        public void ReadShouldReconnectAfterLosingConnection()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var disconnects = 0;
                var connects = 0;
                server.OnClientConnected += () => Interlocked.Increment(ref connects);
                server.OnClientDisconnected += () => Interlocked.Increment(ref disconnects);
                var socket = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var resultTask = ReadFromSocketWithRetry(socket, 4);

                //wait till connected
                TaskTest.WaitFor(() => connects > 0);

                //drop connection
                server.DropConnection();
                TaskTest.WaitFor(() => disconnects > 0);
                Assert.That(disconnects, Is.EqualTo(1), "Server should have disconnected the client.");

                //wait for reconnection
                TaskTest.WaitFor(() => connects > 1);
                Assert.That(connects, Is.EqualTo(2), "Socket should have reconnected.");

                //send data and get result
                server.SendDataAsync(99.ToBytes());
                Assert.That(resultTask.Result.ToInt32(), Is.EqualTo(99), "Socket should have received the 4 bytes.");
            }

        }
        public void ReadShouldThrowServerDisconnectedExceptionWhenDisconnected()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var socket = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var resultTask = socket.ReadAsync(4);

                //wait till connected
                TaskTest.WaitFor(() => server.ConnectionEventcount > 0);

                server.DropConnection();

                TaskTest.WaitFor(() => server.DisconnectionEventCount > 0);

                resultTask.ContinueWith(t => resultTask = t).Wait(TimeSpan.FromSeconds(1));

                Assert.That(resultTask.IsFaulted, Is.True);
                Assert.That(resultTask.Exception.InnerException, Is.TypeOf<ServerDisconnectedException>());
            }

        }
        public void ReadShouldNotLoseDataFromStreamOverMultipleReads()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                const int firstMessage = 99;
                const string secondMessage = "testmessage";

                var payload = new KafkaMessagePacker()
                    .Pack(firstMessage)
                    .Pack(secondMessage, StringPrefixEncoding.None);

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                //send the combined payload
                server.SendDataAsync(payload.PayloadNoLength());

                var firstResponse = test.ReadAsync(4).Result.ToInt32();
                Assert.That(firstResponse, Is.EqualTo(firstMessage));

                var secondResponse = Encoding.ASCII.GetString(test.ReadAsync(secondMessage.Length).Result);
                Assert.That(secondResponse, Is.EqualTo(secondMessage));
            }
        }
        public void ReadShouldBeAbleToReceiveMoreThanOnceAsyncronously()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                const int firstMessage = 99;
                const int secondMessage = 100;

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                Console.WriteLine("Sending first message to receive...");
                server.SendDataAsync(firstMessage.ToBytes());
                var firstResponseTask = test.ReadAsync(4);

                Console.WriteLine("Sending second message to receive...");
                server.SendDataAsync(secondMessage.ToBytes());
                var secondResponseTask = test.ReadAsync(4);

                Assert.That(firstResponseTask.Result.ToInt32(), Is.EqualTo(firstMessage));
                Assert.That(secondResponseTask.Result.ToInt32(), Is.EqualTo(secondMessage));
            }
        }
        public void SendAsyncShouldTimeoutByThrowingResponseTimeoutException()
        {
            using (var server = new FakeTcpServer(8999))
            using (var socket = new KafkaTcpSocket(_log, _kafkaEndpoint))
            using (var conn = new KafkaConnection(socket, TimeSpan.FromMilliseconds(100), log: _log))
            {
                TaskTest.WaitFor(() => server.ConnectionEventcount > 0);
                Assert.That(server.ConnectionEventcount, Is.EqualTo(1));

                var taskResult = conn.SendAsync(new MetadataRequest());

                taskResult.ContinueWith(t => taskResult = t).Wait(TimeSpan.FromSeconds(1));

                Assert.That(taskResult.IsFaulted, Is.True);
                Assert.That(taskResult.Exception.InnerException, Is.TypeOf<ResponseTimeoutException>());
            }
        }
        public void WriteShouldHandleLargeVolumeSendAsynchronously()
        {
            var write = new List<int>();
            
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                server.OnBytesReceived += data => write.AddRange(data.Batch(4).Select(x => x.ToArray().ToInt32()));

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var tasks = Enumerable.Range(1, 10000)
                    .SelectMany(i => new[]
                    {
                        test.WriteAsync(i.ToBytes()),
                    }).ToArray();

                Task.WaitAll(tasks);
                
                Assert.That(write.OrderBy(x => x), Is.EqualTo(Enumerable.Range(1, 10000)));
            }
        }
        public void WriteAsyncShouldAllowMoreThanOneWrite()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                const int testData = 99;
                var results = new List<byte>();

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);
                server.OnBytesReceived += results.AddRange;

                Task.WaitAll(test.WriteAsync(testData.ToBytes()), test.WriteAsync(testData.ToBytes()));
                TaskTest.WaitFor(() => results.Count >= 8);
                Assert.That(results.Count, Is.EqualTo(8));
            }
        }
        public void ReadShouldLogDisconnectAndRecover()
        {
            var mockLog = _kernel.GetMock<IKafkaLog>();

            using (var server = new FakeTcpServer(8999))
            using (var socket = new KafkaTcpSocket(mockLog.Object, _kafkaEndpoint))
            using (var conn = new KafkaConnection(socket, log: mockLog.Object))
            {
                TaskTest.WaitFor(() => server.ConnectionEventcount > 0);
                Assert.That(server.ConnectionEventcount, Is.EqualTo(1));

                server.DropConnection();
                TaskTest.WaitFor(() => server.DisconnectionEventCount > 0);
                Assert.That(server.DisconnectionEventCount, Is.EqualTo(1));

				//Wait a while for the client to notice the disconnect and log
				Thread.Sleep(15);

                //should log an exception and keep going
                mockLog.Verify(x => x.ErrorFormat(It.IsAny<string>(), It.IsAny<Exception>()));

                TaskTest.WaitFor(() => server.ConnectionEventcount > 1);
                Assert.That(server.ConnectionEventcount, Is.EqualTo(2));
            }
        }
        public void SendAsyncShouldTimeoutMultipleMessagesAtATime()
        {
            using (var server = new FakeTcpServer(8999))
            using (var socket = new KafkaTcpSocket(_log, _kafkaEndpoint))
            using (var conn = new KafkaConnection(socket, TimeSpan.FromMilliseconds(100), log: _log))
            {
                TaskTest.WaitFor(() => server.ConnectionEventcount > 0);
                Assert.That(server.ConnectionEventcount, Is.EqualTo(1));

                var tasks = new[]
                    {
                        conn.SendAsync(new MetadataRequest()),
                        conn.SendAsync(new MetadataRequest()),
                        conn.SendAsync(new MetadataRequest())
                    };

                Task.WhenAll(tasks);

                TaskTest.WaitFor(() => tasks.Any(t => t.IsFaulted));
                foreach (var task in tasks)
                {
                    Assert.That(task.IsFaulted, Is.True);
                    Assert.That(task.Exception.InnerException, Is.TypeOf<ResponseTimeoutException>());
                }
            }
        }
        public void ReadShouldStackReadRequestsAndReturnOneAtATime()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var messages = new[] { "test1", "test2", "test3", "test4" };
                var expectedLength = "test1".Length;

                var payload = new KafkaMessagePacker().Pack(messages);

                var socket = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var tasks = messages.Select(x => socket.ReadAsync(x.Length)).ToArray();

                server.SendDataAsync(payload.Payload());

                Task.WaitAll(tasks);

                foreach (var task in tasks)
                {
                    Assert.That(task.Result.Length, Is.EqualTo(expectedLength));
                }
            }
        }
        public void ReadShouldCancelWhileAwaitingResponse()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var count = 0;
                var semaphore = new SemaphoreSlim(0);
                var token = new CancellationTokenSource();

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                test.ReadAsync(4, token.Token).ContinueWith(t =>
                    {
                        Interlocked.Increment(ref count);
                        Assert.That(t.IsCanceled, Is.True, "Task should be set to cancelled when disposed.");
                        semaphore.Release();
                    });

                Thread.Sleep(100);
                token.Cancel();

                semaphore.Wait(TimeSpan.FromSeconds(1));
                Assert.That(count, Is.EqualTo(1), "Read should have cancelled and incremented count.");
            }
        }
        public void WriteAsyncShouldSendData()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                const int testData = 99;
                int result = 0;

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);
                server.OnBytesReceived += data => result = data.ToInt32();

                test.WriteAsync(testData.ToBytes()).Wait(TimeSpan.FromSeconds(1));
                TaskTest.WaitFor(() => result > 0);
                Assert.That(result, Is.EqualTo(testData));
            }
        }
        public void ReadShouldBlockUntilAllBytesRequestedAreReceived()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var count = 0;

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var resultTask = test.ReadAsync(4).ContinueWith(t =>
                    {
                        Interlocked.Increment(ref count);
                        return t.Result;
                    });

                Console.WriteLine("Sending first 3 bytes...");
                var sendInitialBytes = server.SendDataAsync(new byte[] { 0, 0, 0 }).Wait(TimeSpan.FromSeconds(10));
                Assert.That(sendInitialBytes, Is.True, "First 3 bytes should have been sent.");

                Console.WriteLine("Ensuring task blocks...");
                var unblocked = resultTask.Wait(TimeSpan.FromMilliseconds(500));
                Assert.That(unblocked, Is.False, "Wait should return false.");
                Assert.That(resultTask.IsCompleted, Is.False, "Task should still be running, blocking.");
                Assert.That(count, Is.EqualTo(0), "Should still block even though bytes have been received.");

                Console.WriteLine("Sending last byte...");
                var sendLastByte = server.SendDataAsync(new byte[] { 0 }).Wait(TimeSpan.FromSeconds(10));
                Assert.That(sendLastByte, Is.True, "Last byte should have sent.");

                Console.WriteLine("Ensuring task unblocks...");
                resultTask.Wait(TimeSpan.FromMilliseconds(500));
                Assert.That(resultTask.IsCompleted, Is.True, "Task should have completed.");
                Assert.That(count, Is.EqualTo(1), "Task ContinueWith should have executed.");
                Assert.That(resultTask.Result.Length, Is.EqualTo(4), "Result of task should be 4 bytes.");
            }
        }
        public void WriteAndReadShouldBeAsynchronous()
        {
            var write = new List<int>();
            var read = new List<int>();
            var expected = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            using (var server = new FakeTcpServer(FakeServerPort))
            {
                server.OnBytesReceived += data => write.AddRange(data.Batch(4).Select(x => x.ToArray().ToInt32()));

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var tasks = Enumerable.Range(1, 10)
                    .SelectMany(i => new[]
                    {
                        test.WriteAsync(i.ToBytes()),
                        test.ReadAsync(4).ContinueWith(t => read.Add(t.Result.ToInt32())),
                        server.SendDataAsync(i.ToBytes())
                    }).ToArray();

                Task.WaitAll(tasks);
                Assert.That(write.OrderBy(x => x), Is.EqualTo(expected));
                Assert.That(read.OrderBy(x => x), Is.EqualTo(expected));
            }
        }
        public void ReadShouldBeAbleToReceiveMoreThanOnce()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                const int firstMessage = 99;
                const string secondMessage = "testmessage";

                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                Console.WriteLine("Sending first message to receive...");
                server.SendDataAsync(firstMessage.ToBytes());

                var firstResponse = test.ReadAsync(4).Result.ToInt32();
                Assert.That(firstResponse, Is.EqualTo(firstMessage));

                Console.WriteLine("Sending second message to receive...");
                server.SendDataAsync(secondMessage);

                var secondResponse = Encoding.ASCII.GetString(test.ReadAsync(secondMessage.Length).Result);
                Assert.That(secondResponse, Is.EqualTo(secondMessage));
            }
        }
        public void KafkaTcpSocketShouldDisposeEvenWhileAwaitingReadAndThrowException()
        {
            using (var server = new FakeTcpServer(FakeServerPort))
            {
                var test = new KafkaTcpSocket(new DefaultTraceLog(), _fakeServerUrl);

                var taskResult = test.ReadAsync(4);

                using (test) { }

                taskResult.ContinueWith(t => taskResult = t).Wait(TimeSpan.FromSeconds(1));

                Assert.That(taskResult.IsFaulted, Is.True);
                Assert.That(taskResult.Exception.InnerException, Is.TypeOf<ObjectDisposedException>());
            }
        }
        public void ReadShouldIgnoreMessageWithUnknownCorrelationId()
        {
            const int correlationId = 99;

            var mockLog = _kernel.GetMock<IKafkaLog>();

            using (var server = new FakeTcpServer(8999))
            using (var socket = new KafkaTcpSocket(mockLog.Object, _kafkaEndpoint))
            using (var conn = new KafkaConnection(socket, log: mockLog.Object))
            {
                //send correlation message
                server.SendDataAsync(CreateCorrelationMessage(correlationId)).Wait(TimeSpan.FromSeconds(5));

                //wait for connection
                TaskTest.WaitFor(() => server.ConnectionEventcount > 0);
                Assert.That(server.ConnectionEventcount, Is.EqualTo(1));

				Thread.Sleep(10);

                //should log a warning and keep going
                mockLog.Verify(x => x.WarnFormat(It.IsAny<string>(), It.Is<int>(o => o == correlationId)));
            }
        }