public void Send_one_messages()
        {
            var slice1 = new BufferSlice(new byte[65535], 0, 65535);
            var encoder1 = new MicroMessageEncoder(new DataContractMessageSerializer());
            var decoder1 = new MicroMessageDecoder(new DataContractMessageSerializer());
            var slice2 = new BufferSlice(new byte[65535], 0, 65535);
            var encoder2 = new MicroMessageEncoder(new DataContractMessageSerializer());
            var decoder2 = new MicroMessageDecoder(new DataContractMessageSerializer());
            var evt = new ManualResetEvent(false);
            string actual = null;
            var sut2 = new TcpChannel(slice2, encoder2, decoder2);
            sut2.MessageReceived += (channel, message) =>
            {
                actual = message.ToString();
                evt.Set();
            };
            sut2.Assign(_helper.Server);

            var sut1 = new TcpChannel(slice1, encoder1, decoder1);
            sut1.MessageReceived += (channel, message) => { };
            sut1.Assign(_helper.Client);
            sut1.Send("Hello".PadRight(1000));

            evt.WaitOne(500).Should().BeTrue();
            actual.Should().StartWith("Hello");
        }
        public void assign_without_subscribing_on_MessageReceived_means_that_messages_can_get_lost()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = Substitute.For<IMessageDecoder>();

            var sut = new TcpChannel(slice, encoder, decoder);
            Action actual = () => sut.Assign(_helper.Client);

            actual.ShouldThrow<InvalidOperationException>();
        }
        public void initialize_own_buffer()
        {
            var buffer = new byte[10];

            var sut = new BufferSlice(buffer, 0, 10);

            Assert.Same(buffer, sut.Buffer);
            sut.Offset.Should().Be(0);
            sut.Capacity.Should().Be(10);
            sut.Buffer.Should().BeEquivalentTo(buffer);
        }
        public void Assign_should_work_after_subscription()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = Substitute.For<IMessageDecoder>();
            object expected;

            var sut = new TcpChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            sut.Assign(_helper.Client);

        }
        public void should_listen_on_the_decoder_event()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = new FakeDecoder();
            object expected = null;

            var sut = new TcpChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            decoder.MessageReceived("Hello");

            expected.Should().Be("Hello");
        }
        public void assign_without_subscribing_on_MessageReceived_means_that_messages_can_get_lost()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = Substitute.For<IMessageDecoder>();
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);

            var sut = CreateClientChannel(slice, encoder, decoder);
            Action actual = () => sut.Assign(_helper.Client);

            actual.ShouldThrow<InvalidOperationException>();
        }
        public void send_message()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = new FakeEncoder();
            var decoder = new FakeDecoder();
            object expected = null;

            var sut = new TcpChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            sut.Assign(_helper.Client);
            sut.Send("Hello world");

            
        }
        public void Assign_should_work_after_subscription()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = Substitute.For<IMessageDecoder>();
            object expected;
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);

            var sut = CreateClientChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            sut.Assign(_helper.Client);

        }
        public void should_listen_on_the_decoder_event()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = Substitute.For<IMessageEncoder>();
            var decoder = new FakeDecoder();
            object expected = null;
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);

            var sut = CreateClientChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            decoder.MessageReceived("Hello");

            expected.Should().Be("Hello");
        }
        public void can_clear_even_without_shit_being_used()
        {
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Clear();
            sut.Prepare(msg);
            sut.Send(buffer);

            var field = sut.GetType().GetField("_bodyStream", BindingFlags.Instance | BindingFlags.NonPublic);
            ((Stream)field.GetValue(sut)).CanWrite.Should().BeTrue();
        }
        public void dont_close_our_internal_stream_as_we_reuse_it()
        {
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.Clear();

            var field = sut.GetType().GetField("_bodyStream", BindingFlags.Instance | BindingFlags.NonPublic);
            ((Stream) field.GetValue(sut)).CanWrite.Should().BeTrue();
        }
        public void partial_send__continue_sending_rest_of_the_buffer_before_doing_anything_else()
        {
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.OnSendCompleted(10);
            sut.Send(buffer);

            buffer.Offset.Should().Be(10);
            buffer.Count.Should().Be(2 + MicroMessageEncoder.FixedHeaderLength + "string".Length + msg.Length - 10, "2 for the header length");
        }
        public void codec_a_string_message()
        {
            object receivedMessage = null;
            var encoderSlice = new BufferSlice(new byte[65535], 0, 65535);
            var serializer = new DataContractMessageSerializer();
            var encoder = new MicroMessageEncoder(serializer, encoderSlice);
            var decoder = new MicroMessageDecoder(serializer) {MessageReceived = o => receivedMessage = o};
            var expected = "Hello world";
            var encoderArgs = new SocketBufferFake();
            
            encoder.Prepare(expected);
            encoder.Send(encoderArgs);
            encoderArgs.BytesTransferred = encoderArgs.Count;
            decoder.ProcessReadBytes(encoderArgs);

            receivedMessage.Should().Be(expected);
        }
        public void codec_a_custom_type()
        {
            object receivedMessage = null;
            var encoderSlice = new BufferSlice(new byte[65535], 0, 65535);
            var serializer = new DataContractMessageSerializer();
            var encoder = new MicroMessageEncoder(serializer, encoderSlice);
            var decoder = new MicroMessageDecoder(serializer) { MessageReceived = o => receivedMessage = o };
            var expected = new CustomType {Name = "Arne"};
            var encoderArgs = new SocketBufferFake();

            encoder.Prepare(expected);
            encoder.Send(encoderArgs);
            encoderArgs.BytesTransferred = encoderArgs.Count;
            decoder.ProcessReadBytes(encoderArgs);

            receivedMessage.Should().BeOfType<CustomType>();
            receivedMessage.As<CustomType>().Name.Should().Be(expected.Name);
        }
        public void close_external_Stream_as_we_take_over_ownership_from_the_dev()
        {
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = new MemoryStream();
            var text = Encoding.ASCII.GetBytes("Hello world");
            msg.Write(text, 0, text.Length);
            msg.Position = 0;
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.Clear();

            var field = sut.GetType().GetField("_bodyStream", BindingFlags.Instance | BindingFlags.NonPublic);
            if (field == null) throw new ArgumentNullException("field");
            var value = ((Stream)field.GetValue(sut));
            value.Should().BeNull();
        }
        public void codec_a_byte_buffer()
        {
            object receivedMessage = null;
            var encoderSlice = new BufferSlice(new byte[65535], 0, 65535);
            var serializer = new DataContractMessageSerializer();
            var encoder = new MicroMessageEncoder(serializer, encoderSlice);
            var decoder = new MicroMessageDecoder(serializer) { MessageReceived = o => receivedMessage = o };
            var expected = new byte[] {1, 2, 3, 4, 5, 6, 7};
            var encoderArgs = new SocketBufferFake();

            encoder.Prepare(expected);
            encoder.Send(encoderArgs);
            encoderArgs.BytesTransferred = encoderArgs.Count;
            decoder.ProcessReadBytes(encoderArgs);

            var ms = (MemoryStream) receivedMessage;
            var buf = ms.GetBuffer();
            expected.Should().BeSubsetOf(buf);
            ms.Length.Should().Be(expected.Length);
        }
        public void codec_a_stream()
        {
            object receivedMessage = null;
            var encoderSlice = new BufferSlice(new byte[65535], 0, 65535);
            var serializer = new DataContractMessageSerializer();
            var encoder = new MicroMessageEncoder(serializer, encoderSlice);
            var decoder = new MicroMessageDecoder(serializer) {MessageReceived = o => receivedMessage = o};
            var expected = "Hello world";
            var stream = new MemoryStream(Encoding.ASCII.GetBytes(expected));
            stream.SetLength(expected.Length);
            var encoderArgs = new SocketBufferFake();

            encoder.Prepare(stream);
            encoder.Send(encoderArgs);
            encoderArgs.BytesTransferred = encoderArgs.Count;
            decoder.ProcessReadBytes(encoderArgs);

            var reader = new StreamReader((Stream) receivedMessage);
            var msg = reader.ReadToEnd();
            msg.Should().Be(expected);
        }
        public void write_a_complete_string_message_directly()
        {
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);

            var headerLen = MicroMessageEncoder.FixedHeaderLength + "string".Length;
            buffer.Buffer[0].Should().Be((byte)headerLen);
            buffer.Buffer[2].Should().Be(1, "first version");
            BitConverter.ToInt32(buffer.Buffer, 3).Should().Be(msg.Length);
            buffer.Buffer[7].Should().Be((byte)"string".Length);
            Encoding.ASCII.GetString(buffer.Buffer, 8, "string".Length).Should().Be("string");
            Encoding.ASCII.GetString(buffer.Buffer, MicroMessageEncoder.FixedHeaderLength + "string".Length + 2, msg.Length)
                .Should()
                .Be(msg);
        }
        public void write_a_complete_string_message_directly()
        {
            var contentType = "text/plain;type=System.String";
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);

            var headerLen = MicroMessageEncoder.FixedHeaderLength + contentType.Length;
            BitConverter.ToInt16(buffer.Buffer, 0).Should().Be((short)headerLen);
            buffer.Buffer[2].Should().Be(1, "first version");
            BitConverter.ToInt32(buffer.Buffer, 3).Should().Be(msg.Length);
            buffer.Buffer[7].Should().Be((byte)contentType.Length);
            Encoding.ASCII.GetString(buffer.Buffer, 8, contentType.Length).Should().Be(contentType);
            Encoding.ASCII.GetString(buffer.Buffer, 2 + MicroMessageEncoder.FixedHeaderLength + contentType.Length, msg.Length)
                .Should()
                .Be(msg);
        }
        public void Send_500_messages()
        {
            var slice1 = new BufferSlice(new byte[65535], 0, 65535);
            var encoder1 = new MicroMessageEncoder(new DataContractMessageSerializer());
            var decoder1 = new MicroMessageDecoder(new DataContractMessageSerializer());
            var slice2 = new BufferSlice(new byte[65535], 0, 65535);
            var encoder2 = new MicroMessageEncoder(new DataContractMessageSerializer());
            var decoder2 = new MicroMessageDecoder(new DataContractMessageSerializer());
            var evt = new ManualResetEvent(false);
            var messages = new List<object>();
            var sut1 = new TcpChannel(slice1, encoder1, decoder1);
            sut1.MessageReceived += (channel, message) => { };
            sut1.Assign(_helper.Client);
            var sut2 = new TcpChannel(slice2, encoder2, decoder2);
            sut2.MessageReceived += (channel, message) =>
            {
                messages.Add(message);
                if (messages.Count == 500) evt.Set();
            };
            sut2.Assign(_helper.Server);

            for (int i = 0; i < 500; i++)
            {
                sut1.Send("Hello" + i + "".PadRight(1000));
            }

            sut1.Send("Hello world");

            evt.WaitOne(500).Should().BeTrue();
            for (int i = 0; i < 500; i++)
            {
                messages[i].ToString().Should().StartWith("Hello" + i);
            }
        }
        public void reset_after_each_successful_message()
        {
            var contentType = "text/plain;type=System.String";
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[520], 0, 520);
            var msg = "Hello world";
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.OnSendCompleted(13);
            sut.Send(buffer);
            sut.OnSendCompleted(2 + MicroMessageEncoder.FixedHeaderLength + contentType.Length + msg.Length - 13);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.OnSendCompleted(5);
            sut.Send(buffer);
            

            buffer.Offset.Should().Be(5);
            buffer.Count.Should().Be(2 + MicroMessageEncoder.FixedHeaderLength + contentType.Length + msg.Length - 5);
        }
        public void send_message()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = new StringEncoder();
            var decoder = new StringDecoder();
            object expected = null;

            var sut = CreateClientChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => expected = message;
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);
            sut.Assign(_helper.Client);
            sut.Send("Hello world");

            var buf = new byte[65535];
            var tmp = stream.Read(buf, 0, 65535);
            var actual = Encoding.ASCII.GetString(buf, 4, tmp-4); // string encoder have a length header.
            actual.Should().Be("Hello world");
        }
        public void Receive_one_message()
        {
            var slice1 = new BufferSlice(new byte[65535], 0, 65535);
            var encoder1 = new StringEncoder();
            var decoder1 = new StringDecoder();
            var expected = "Hello".PadRight(5000);
            var outBuffer = new byte[expected.Length + 4];
            BitConverter2.GetBytes(expected.Length, outBuffer, 0);
            Encoding.UTF8.GetBytes(expected, 0, expected.Length, outBuffer, 4);
            object actual = null;
            var evt = new ManualResetEvent(false);
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);

            var sut1 = CreateClientChannel(slice1, encoder1, decoder1);
            sut1.MessageReceived = (channel, message) =>
            {
                actual = message;
                evt.Set();
            };
            sut1.Assign(_helper.Client);
            stream.Write(outBuffer);

            evt.WaitOne(500).Should().BeTrue();
            actual.Should().Be(expected);
        }
        public void too_small_buffer_requires_multiple_sends()
        {
            var contentType = "text/plain;type=System.String";
            var serializer = new StringSerializer();
            var slice = new BufferSlice(new byte[520], 0, 520);
            var msg = "Hello world".PadRight(520);
            var buffer = new SocketBufferFake();

            var sut = new MicroMessageEncoder(serializer, slice);
            sut.Prepare(msg);
            sut.Send(buffer);
            sut.OnSendCompleted(520).Should().BeFalse();
            sut.Send(buffer);

            buffer.Offset.Should().Be(0);
            // headerlength + fixed header length + content type length + content type - sent in first batch
            buffer.Count.Should().Be(2 + MicroMessageEncoder.FixedHeaderLength + contentType.Length + msg.Length - 520);
        }
        public void send_close_message()
        {
            var slice = new BufferSlice(new byte[65535], 0, 65535);
            var encoder = new StringEncoder();
            var decoder = new StringDecoder();

            var sut = CreateClientChannel(slice, encoder, decoder);
            sut.MessageReceived += (channel, message) => { };
            var stream = new SslStream(new NetworkStream(_helper.Server));
            stream.BeginAuthenticateAsServer(_certificate, OnAuthenticated, stream);
            sut.Assign(_helper.Client);

            Assert.True(sut.IsConnected);

            sut.Close();

            Assert.False(sut.IsConnected);
        }