public void When_keep_alive_with_unconfigured_mediator_status_is_received_it_must_disconnect()
        {
            // Arrange
            using (var testRunner = new CirceUsbLoopbackTestRunner())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.MediatorUnconfigured)
                    {
                        testRunner.SignalSucceeded();
                    }
                };

                testRunner.MediatorStatusCode = KnownMediatorStatusCode.MediatorUnconfigured;

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
            }
        }
        public void When_keep_alive_with_incorrect_version_is_received_it_must_disconnect()
        {
            // Arrange
            using (var testRunner = new CirceUsbLoopbackTestRunner())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.ProtocolVersionMismatch)
                    {
                        testRunner.SignalSucceeded();
                    }
                };

                testRunner.ProtocolVersion = new Version(99, 88, 77);

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
            }
        }
        public void When_keep_alive_operation_is_received_it_must_raise_event_for_mediator_status_change()
        {
            // Arrange
            const int mediatorStatusCode = 5;

            using (var testRunner = new CirceUsbLoopbackTestRunner())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.Connection.Send(new KeepAliveOperation(KeepAliveOperation.CurrentProtocolVersion,
                            mediatorStatusCode));
                    }
                };

                testRunner.RemoteSessionManager.DeviceTracker.MediatorStatusChanged += (s, e) =>
                {
                    if (e.Argument == mediatorStatusCode)
                    {
                        testRunner.SignalSucceeded();
                    }
                };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
            }
        }
        public void When_connection_becomes_idle_it_must_reconnect()
        {
            // Arrange
            var seenLogout = new FreshBoolean(false);

            using (var testRunner = new CirceUsbLoopbackTestRunner())
            {
                testRunner.OperationReceived += (s, e) =>
                {
                    var logoutOperation = e.Operation as LogoutOperation;
                    if (logoutOperation != null)
                    {
                        seenLogout.Value = true;
                    }
                };

                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        if (seenLogout.Value)
                        {
                            testRunner.SignalSucceeded();
                        }
                    }
                };

                testRunner.RunTimeout = TimeSpan.FromSeconds(5);

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
            }
        }
        public void When_connection_becomes_idle_it_must_send_logout_operation()
        {
            // Arrange
            using (var testRunner = new CirceUsbLoopbackTestRunner<LogoutOperation>())
            {
                testRunner.OperationReceived += (s, e) =>
                {
                    var logoutOperation = e.Operation as LogoutOperation;
                    if (logoutOperation != null)
                    {
                        testRunner.SignalSucceeded(logoutOperation);
                    }
                };

                testRunner.RunTimeout = TimeSpan.FromSeconds(3);

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                testRunner.Result.Should().NotBeNull();
            }
        }
        public void When_visualize_is_requested_it_must_send_operation()
        {
            var destinations = new[] { new WirelessNetworkAddress("AABBCC"), new WirelessNetworkAddress("DDEEFF") };
            VisualizeFieldSet visualizeFieldSet = new VisualizeFieldSetBuilder()
                .WithCurrentCompetitorNumber(123)
                .WithNextCompetitorNumber(125)
                .WithPrimaryTimerIsActive(true)
                .WithPrimaryTimerValue(25.Seconds().And(993.Milliseconds()))
                .WithSecondaryTimerValue(16.Seconds().And(123.Milliseconds()))
                .WithCurrentFaultCount(5)
                .WithCurrentRefusalCount(10)
                .WithElimination(true)
                .WithPreviousPlacement(23)
                .Build();

            // Arrange
            using (var testRunner = new CirceUsbLoopbackTestRunner<VisualizeOperation>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.RemoteSessionManager.VisualizeAsync(destinations, visualizeFieldSet);
                    }
                };

                testRunner.OperationReceived += (s, e) =>
                {
                    var visualizeOperation = e.Operation as VisualizeOperation;
                    if (visualizeOperation != null)
                    {
                        testRunner.SignalSucceeded(visualizeOperation);
                    }
                };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                VisualizeOperation operationNotNull = testRunner.Result.ShouldNotBeNull();
                operationNotNull.DestinationAddresses.Should().Equal(destinations);
                operationNotNull.CurrentCompetitorNumber.Should().Be(visualizeFieldSet.CurrentCompetitorNumber);
                operationNotNull.NextCompetitorNumber.Should().Be(visualizeFieldSet.NextCompetitorNumber);
                operationNotNull.StartTimer.Should().Be(visualizeFieldSet.StartPrimaryTimer);
                operationNotNull.PrimaryTimerValue.Should().Be(visualizeFieldSet.PrimaryTimerValue);
                operationNotNull.SecondaryTimerValue.Should().Be(visualizeFieldSet.SecondaryTimerValue);
                operationNotNull.FaultCount.Should().Be(visualizeFieldSet.CurrentFaultCount);
                operationNotNull.RefusalCount.Should().Be(visualizeFieldSet.CurrentRefusalCount);
                operationNotNull.Eliminated.Should().Be(visualizeFieldSet.CurrentIsEliminated);
                operationNotNull.PreviousPlacement.Should().Be(visualizeFieldSet.PreviousPlacement);
            }
        }
        public void When_clock_synchronization_is_requested_it_must_send_operation()
        {
            // Arrange
            using (var testRunner = new CirceUsbLoopbackTestRunner<SynchronizeClocksOperation>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.RemoteSessionManager.SynchronizeClocksAsync();
                    }
                };

                testRunner.OperationReceived += (s, e) =>
                {
                    var synchronizeClocksOperation = e.Operation as SynchronizeClocksOperation;
                    if (synchronizeClocksOperation != null)
                    {
                        testRunner.SignalSucceeded(synchronizeClocksOperation);
                    }
                };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                testRunner.Result.Should().NotBeNull();
            }
        }
        public void When_network_setup_is_requested_it_must_send_operation()
        {
            // Arrange
            var deviceAddress = new WirelessNetworkAddress("AABBCC");
            const bool setMembership = true;
            const DeviceRoles roles = DeviceRoles.Keypad;

            using (var testRunner = new CirceUsbLoopbackTestRunner<NetworkSetupOperation>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.RemoteSessionManager.NetworkSetupAsync(deviceAddress, setMembership, roles);
                    }
                };

                testRunner.OperationReceived += (s, e) =>
                {
                    var networkSetupOperation = e.Operation as NetworkSetupOperation;
                    if (networkSetupOperation != null)
                    {
                        testRunner.SignalSucceeded(networkSetupOperation);
                    }
                };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                NetworkSetupOperation operationNotNull = testRunner.Result.ShouldNotBeNull();
                operationNotNull.DestinationAddress.Should().Be(deviceAddress);
                operationNotNull.SetMembership.Should().Be(setMembership);
                operationNotNull.Roles.Should().Be(roles);
            }
        }
        public void When_alert_is_requested_it_must_send_operation()
        {
            // Arrange
            var deviceAddress = new WirelessNetworkAddress("AABBCC");

            using (var testRunner = new CirceUsbLoopbackTestRunner<AlertOperation>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.RemoteSessionManager.AlertAsync(deviceAddress);
                    }
                };

                testRunner.OperationReceived += (s, e) =>
                {
                    var alertOperation = e.Operation as AlertOperation;
                    if (alertOperation != null)
                    {
                        testRunner.SignalSucceeded(alertOperation);
                    }
                };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                AlertOperation operationNotNull = testRunner.Result.ShouldNotBeNull();
                operationNotNull.DestinationAddress.Should().Be(deviceAddress);
            }
        }
        public void When_notify_action_operation_is_received_it_must_raise_event_for_action()
        {
            // Arrange
            var deviceAddress = new WirelessNetworkAddress("AABBCC");
            const RawDeviceKeys inputKeys = RawDeviceKeys.Key1OrPlaySoundA;
            TimeSpan sensorTime = TimeSpan.FromMilliseconds(3456);

            using (var testRunner = new CirceUsbLoopbackTestRunner<DeviceAction>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.Connection.Send(new NotifyActionOperation(deviceAddress)
                        {
                            InputKeys = inputKeys,
                            SensorTime = sensorTime
                        });
                    }
                };

                testRunner.RemoteSessionManager.DeviceActionReceived +=
                    (s, e) => { testRunner.SignalSucceeded(e.Argument); };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                DeviceAction deviceActionNotNull = testRunner.Result.ShouldNotBeNull();
                deviceActionNotNull.DeviceAddress.Should().Be(deviceAddress);
                deviceActionNotNull.InputKeys.Should().Be(inputKeys);
                deviceActionNotNull.SensorTime.Should().Be(sensorTime);
            }
        }
        public void When_notify_status_operation_is_received_twice_it_must_raise_event_for_changed_device()
        {
            // Arrange
            var deviceAddress = new WirelessNetworkAddress("AABBCC");
            const bool getMembership = true;
            const DeviceCapabilities capabilities =
                DeviceCapabilities.ControlKeypad | DeviceCapabilities.NumericKeypad | DeviceCapabilities.StartSensor |
                    DeviceCapabilities.FinishSensor | DeviceCapabilities.IntermediateSensor;
            const DeviceRoles roles = DeviceRoles.StartTimer | DeviceRoles.FinishTimer;
            const int signalStrength = 99;
            const int batteryStatus = 83;
            const bool isAligned = true;
            const ClockSynchronizationStatus clockSynchronization = ClockSynchronizationStatus.RequiresSync;

            using (var testRunner = new CirceUsbLoopbackTestRunner<DeviceStatus>())
            {
                testRunner.RemoteSessionManager.ConnectionStateChanged += (s, e) =>
                {
                    if (e.State == ControllerConnectionState.Connected)
                    {
                        testRunner.Connection.Send(new NotifyStatusOperation(deviceAddress, getMembership,
                            capabilities, roles, 25));

                        testRunner.Connection.Send(new NotifyStatusOperation(deviceAddress, getMembership,
                            capabilities, roles, signalStrength)
                        {
                            BatteryStatus = batteryStatus,
                            IsAligned = isAligned,
                            ClockSynchronization = clockSynchronization
                        });
                    }
                };

                testRunner.RemoteSessionManager.DeviceTracker.DeviceChanged +=
                    (s, e) => { testRunner.SignalSucceeded(e.Argument); };

                // Act
                bool succeeded = testRunner.Start();

                // Assert
                succeeded.Should().Be(true, "<USB loopback cable must be connected and COM port must be correct.>");
                DeviceStatus deviceStatusNotNull = testRunner.Result.ShouldNotBeNull();
                deviceStatusNotNull.DeviceAddress.Should().Be(deviceAddress);
                deviceStatusNotNull.IsInNetwork.Should().Be(getMembership);
                deviceStatusNotNull.Capabilities.Should().Be(capabilities);
                deviceStatusNotNull.Roles.Should().Be(roles);
                deviceStatusNotNull.SignalStrength.Should().Be(signalStrength);
                deviceStatusNotNull.BatteryStatus.Should().Be(batteryStatus);
                deviceStatusNotNull.IsAligned.Should().Be(isAligned);
                deviceStatusNotNull.ClockSynchronization.Should().Be(clockSynchronization);
            }
        }