public async Task When_FreeSwitch_disconnects_it_completes_the_message_observables()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool disposed = true;
                bool messagesObservableCompleted = false;
                bool eventsObservableCompleted = false;

                listener.Connections.Subscribe(connection =>
                {
                    connected = true;
                    connection.Messages.Subscribe(_ => { }, () => messagesObservableCompleted = true);
                    connection.Events.Subscribe(_ => { }, () => eventsObservableCompleted = true);
                    connection.Disposed += (o, e) => disposed = true;
                });

                using (var client = new FakeFreeSwitchSocket(listener.Port))
                {
                    await Wait.Until(() => connected);
                    client.Dispose();

                    await Wait.Until(() => messagesObservableCompleted);
                    await Wait.Until(() => eventsObservableCompleted);

                    Assert.True(connected, "Expect a connection to have been made.");
                    Assert.True(disposed, "Expect the socket to have been disposed.");
                    Assert.True(messagesObservableCompleted, "Expect the BasicMessage observable to be completed");
                    Assert.True(eventsObservableCompleted, "Expect the EventMessage observable to be completed");
                }
            }
        }
        public async Task Channel_connect_errors_should_not_cause_subsequent_connections_to_fail()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled = false;
                bool firstConnectionReceived = false;
                bool secondConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                        {
                            freeSwitch.Dispose();
                            firstConnectionReceived = true;
                        });

                    await Wait.Until(() => firstConnectionReceived);
                    Assert.False(channelCallbackCalled);
                }

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(async _ =>
                        {
                            await freeSwitch.SendChannelDataEvent();
                            secondConnectionReceived = true;
                        });

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("linger") || m.StartsWith("event") || m.StartsWith("filter"))
                        .Subscribe(async _ =>
                        {
                            await freeSwitch.SendCommandReplyOk("sending OK for linger, event and filter commands");
                        });


                    await Wait.Until(() => secondConnectionReceived);
                    Assert.True(channelCallbackCalled);
                }
            }
        }
        public async Task Calling_Connect_on_a_OutboundSocket_that_was_disconnected_should_throw_OperationCanceledException()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                Exception ex = null;

                listener.Connections.Subscribe((socket) => ex = Record.Exception(() => socket.Connect().Wait()));

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ => freeSwitch.Dispose());

                    await Wait.Until(() => ex != null);
                    Assert.IsType<TaskCanceledException>(ex.InnerException);
                }
            }
        }
        public async Task Channel_listener_should_handle_where_FS_disconnects_before_channelData_event_received()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled = false;
                bool firstConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                        { 
                            firstConnectionReceived = true;
                            freeSwitch.Dispose();
                        });

                    await Wait.Until(() => firstConnectionReceived);
                    Assert.False(channelCallbackCalled);
                }
            }
        }
        public async Task Calling_Exit_on_a_disconnected_OutboundSocket_should_close_gracefully()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                EventMessage channelData = null;
                bool exited = false;

                listener.Connections.Subscribe(
                    async (socket) =>
                    {
                        channelData = await socket.Connect();
                        await socket.Exit();
                        exited = true;
                    });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                          .Subscribe(async _ =>
                              { 
                                  await freeSwitch.SendChannelDataEvent();
                                  await Task.Delay(500);
                                  freeSwitch.Dispose();
                              });

                    await Wait.Until(() => channelData != null);
                    await Wait.Until(() => exited);

                    Assert.True(exited);
                }
            }
        }