public async Task MethodsStartStopAreIdempotent()
        {
            // Setup

            var log       = new LogToMemory();
            var messenger = CreateDefaultMockMessenger();

            var income = new List <string>();
            var socket = new WebSocketSubscriber(messenger.Object, log);

            socket.Subscribe(s => { income.Add(s); return(Task.FromResult(0)); });

            // Execute

            socket.Start();
            socket.Start();
            socket.Start();
            await Task.Delay(50);

            socket.Stop();
            socket.Stop();
            socket.Stop();
            socket.Dispose();
            socket.Dispose();
            socket.Dispose();

            // Check

            // Should receive all 'i': from 1 to 10
            Assert.True(income.Count > 0);

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }
        public async Task SubscriberCanBeRestartedMultipleTimes()
        {
            // Setup

            var log       = new LogToMemory();
            var messenger = CreateDefaultMockMessenger();

            var income = new List <string>();
            var socket = new WebSocketSubscriber(messenger.Object, log);

            socket.Subscribe(s => { income.Add(s); return(Task.FromResult(0)); });

            // Execute

            for (var i = 0; i < 10; i++)
            {
                messenger
                .Setup(m => m.GetResponseAsync(It.IsAny <CancellationToken>()))
                .Returns(Task.FromResult(i.ToString()));

                socket.Start();
                await Task.Delay(50);

                socket.Stop();
            }
            socket.Dispose();

            // Check

            // Should receive all 'i': from 1 to 10
            Assert.Equal(45, income.GroupBy(i => i).Select(g => Int32.Parse(g.Key)).Sum());

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }
        public async Task HeartbeatDoesNotRestartAfterStop()
        {
            // Setup

            var heartbeat = TimeSpan.FromMilliseconds(500);
            var waitTime  = TimeSpan.FromMilliseconds(1000);

            var log       = new LogToMemory();
            var messenger = CreateDefaultMockMessenger();
            var socket    = new WebSocketSubscriber(messenger.Object, log, heartbeat);

            // Execute

            socket.Start();
            await Task.Delay(TimeSpan.FromMilliseconds(50)); // give time to charge heartbeat

            socket.Stop();
            await Task.Delay(waitTime); // wait for possible heartbeat recharge

            socket.Dispose();

            // Check

            // 1 call Connect/Stop
            messenger.Verify(m => m.ConnectAsync(It.IsAny <CancellationToken>()), Times.Exactly(1));
            messenger.Verify(m => m.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(1));

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }
        public async Task StopCallInterruptsGetResponse()
        {
            // Setup

            var waitTime      = TimeSpan.FromMilliseconds(100);
            var controlTime   = TimeSpan.FromMilliseconds(300);
            var executionTime = TimeSpan.FromSeconds(10);
            var log           = new LogToMemory();

            var messenger = CreateDefaultMockMessenger();

            messenger
            .Setup(m => m.GetResponseAsync(It.IsAny <CancellationToken>()))
            .Returns <CancellationToken>(async token =>
            {
                await Task.Delay(executionTime, token);     // Emulate long connection
                return("");
            });
            var socket = new WebSocketSubscriber(messenger.Object, log);

            // Execute

            var watch = new Stopwatch();

            watch.Start();

            socket.Start();
            await Task.Delay(waitTime); // wait connection

            socket.Stop();
            socket.Dispose();

            watch.Stop();

            // Check

            // Connection must be interrupted
            Assert.True(watch.Elapsed < controlTime);

            // 1 call Connect/Stop
            messenger.Verify(m => m.ConnectAsync(It.IsAny <CancellationToken>()), Times.Exactly(1));
            messenger.Verify(m => m.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(1));

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }
        public async Task SimpleCycleExecutesCorrectly()
        {
            // Setup

            var log       = new LogToMemory();
            var messenger = CreateDefaultMockMessenger();
            var socket    = new WebSocketSubscriber(messenger.Object, log);

            // Execute

            socket.Start();
            await Task.Delay(TimeSpan.FromMilliseconds(100)); // wait cycle to perform

            socket.Stop();
            socket.Dispose();

            // Check

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }
        public async Task SubscriberRestartsWhenNoMessagesReceived()
        {
            // Setup

            var heartbeat     = TimeSpan.FromSeconds(1);
            var waitTime      = TimeSpan.FromSeconds(1.5);
            var executionTime = TimeSpan.FromSeconds(2);

            var log       = new LogToMemory();
            var messenger = CreateDefaultMockMessenger();

            messenger
            .Setup(m => m.GetResponseAsync(It.IsAny <CancellationToken>()))
            .Returns <CancellationToken>(async token =>
            {
                await Task.Delay(executionTime, token); return("");    // Emulate no messages for a long time
            });

            var socket = new WebSocketSubscriber(messenger.Object, log, heartbeat);

            // Execute

            socket.Start();
            await Task.Delay(waitTime); // wait cycle and restart to perform

            socket.Stop();
            socket.Dispose();

            // Check

            // Heartbeat restart causes 2 times connect/stop
            messenger.Verify(m => m.ConnectAsync(It.IsAny <CancellationToken>()), Times.Exactly(2));
            messenger.Verify(m => m.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(2));

            // Expecting no exceptions and no errors
            Assert.True(log.NoErrors());
        }