public void ReceiveBytesFromRemoteEndpointWhenCommandIsSent()
        {
            byte[] buffer = Encoding.ASCII.GetBytes("TEST");
            Subject.Network.Command.Response.Device expected = new Subject.Network.Command.Response.Device(Subject.Network.Command.Status.Ok, 0, "TEST", "TEST", "TEST", Values.SignalStrength.Parse("0"), Values.LinkQuality.Parse("0"), Values.BatteryState.Parse("0"), TimeSpan.FromSeconds(1), 1, 1);
            A.CallTo(() => _responseParser.GetResponses("TEST")).Returns(new[] { expected });

            Subject<UdpReceiveResult> received = new Subject<UdpReceiveResult>();

            A.CallTo(() => _receiveSocket.Receive()).ReturnsLazily(call => received);
            A.CallTo(() => _sendSocket.Send(A<byte[]>.Ignored, A<int>.Ignored, RemoteEndpoint)).ReturnsLazily(call => Observable.Return(call.GetArgument<int>(1)));

            Subject.Network.Command.Endpoint.Instance instance = new Subject.Network.Command.Endpoint.Instance(_socketFactory, _responseParser, LocalEndpoint, RemoteEndpoint, TimeSpan.FromSeconds(10), UdpKey, _scheduler);

            instance.Open();

            Task<Subject.Network.Command.Response.Device> responseTask = instance.Send(new Subject.Network.Command.Request.GetDevice(0));

            _scheduler.AdvanceBy(1);

            A.CallTo(() => _receiveSocket.Receive()).MustHaveHappened();

            received.OnNext(new UdpReceiveResult(buffer, RemoteEndpoint));

            Assert.That(responseTask.Status, Is.EqualTo(TaskStatus.RanToCompletion));            
            Assert.That(responseTask.Result, Is.EqualTo(expected));
        }
        public void QueuedCommandsAreSentInSequence()
        {
            byte[] deviceResponse = Encoding.ASCII.GetBytes("DEVICE");
            Subject.Network.Command.Response.Device expectedDevice = new Subject.Network.Command.Response.Device(Subject.Network.Command.Status.Ok, 0, "TEST", "TEST", "TEST", Values.SignalStrength.Parse("0"), Values.LinkQuality.Parse("0"), Values.BatteryState.Parse("0"), TimeSpan.FromSeconds(1), 1, 1);
            A.CallTo(() => _responseParser.GetResponses("DEVICE")).Returns(new[] { expectedDevice });

            byte[] versionResponse = Encoding.ASCII.GetBytes("VERSION");
            Subject.Network.Command.Response.Version expectedVersion = new Subject.Network.Command.Response.Version(Subject.Network.Command.Status.Ok, "TEST", "TEST", "TEST");
            A.CallTo(() => _responseParser.GetResponses("VERSION")).Returns(new[] { expectedVersion });

            Subject<UdpReceiveResult> received = new Subject<UdpReceiveResult>();
            
            A.CallTo(() => _receiveSocket.Receive()).Returns(received);
            A.CallTo(() => _sendSocket.Send(A<byte[]>.Ignored, A<int>.Ignored, RemoteEndpoint)).ReturnsLazily(call => Observable.Return(call.GetArgument<int>(1)));

            Subject.Network.Command.Endpoint.Instance instance = new Subject.Network.Command.Endpoint.Instance(_socketFactory, _responseParser, LocalEndpoint, RemoteEndpoint, TimeSpan.FromSeconds(10), UdpKey, _scheduler);

            instance.Open();

            A.CallTo(() => _sendSocket.Send(A<byte[]>.That.Matches(bytes => bytes.Length > 0), A<int>.Ignored, RemoteEndpoint)).MustNotHaveHappened();
            
            Task<Subject.Network.Command.Response.Device> deviceTask = instance.Send(new Subject.Network.Command.Request.GetDevice(0));
            Task<Subject.Network.Command.Response.Version> versionTask = instance.Send(new Subject.Network.Command.Request.GetVersion());

            _scheduler.AdvanceBy(1);

            A.CallTo(() => _sendSocket.Send(A<byte[]>.That.Matches(bytes => bytes.Length > 0), A<int>.Ignored, RemoteEndpoint)).MustHaveHappened(Repeated.Exactly.Once);

            received.OnNext(new UdpReceiveResult(deviceResponse, RemoteEndpoint));

            Assert.That(deviceTask.Status, Is.EqualTo(TaskStatus.RanToCompletion));
            Assert.That(expectedDevice, Is.EqualTo(deviceTask.Result));

            _scheduler.AdvanceBy(1);

            A.CallTo(() => _sendSocket.Send(A<byte[]>.That.Matches(bytes => bytes.Length > 0), A<int>.Ignored, RemoteEndpoint)).MustHaveHappened(Repeated.Exactly.Twice);

            received.OnNext(new UdpReceiveResult(versionResponse, RemoteEndpoint));

            Assert.That(versionTask.Status, Is.EqualTo(TaskStatus.RanToCompletion));
            Assert.That(expectedVersion, Is.EqualTo(versionTask.Result));

            _scheduler.AdvanceBy(1);

            A.CallTo(() => _sendSocket.Send(A<byte[]>.That.Matches(bytes => bytes.Length > 0), A<int>.Ignored, RemoteEndpoint)).MustHaveHappened(Repeated.Exactly.Twice);

        }