public async Task WhenStartedTwiceThenSecondFails()
        {
            using var broker = new MiniMqttServer();
            using var sut    = new ConnectorBuilder().Build();

            await sut.ConnectAsync(HOST, broker.Port);

            Assert.Equal(1, broker.ConnectionCounter);

            await Assert.ThrowsAsync <InvalidOperationException>(() => sut.ConnectAsync(HOST, broker.Port));

            Assert.Equal(1, broker.ConnectionCounter);
        }
        public async Task WhenMessageReceivedThenForwardsToConsumers()
        {
            using var broker = new MiniMqttServer();

            var milestone = new SemaphoreSlim(0, 2);
            var consumers = new[]
            {
                new ConsumerStub {
                    ShouldHandle = false, Handler = _ => milestone.Release()
                },
                new ConsumerStub {
                    ShouldHandle = false, Handler = _ => milestone.Release()
                }
            };

            using var sut = new ConnectorBuilder()
                            .WithConsumers(consumers)
                            .Build();

            await sut.ConnectAsync(HOST, broker.Port);

            await broker.PublishAsync("boo", Encoding.ASCII.GetBytes("hoo"));

            Assert.True(await milestone.WaitAsync(TimeSpan.FromSeconds(5)));
            Assert.True(await milestone.WaitAsync(TimeSpan.FromSeconds(5)));

            Assert.All(consumers, c => Assert.Single(c.PacketsToHandle));
            Assert.All(consumers, c => Assert.Equal("boo", c.PacketsToHandle.First().Topic));
            Assert.All(consumers, c => Assert.Equal("hoo", Encoding.ASCII.GetString(c.PacketsToHandle.First().Payload)));
        }
        public async Task WhenMessageHandledThenForwardingLoopBreaks()
        {
            using var broker = new MiniMqttServer();

            var milestone   = new SemaphoreSlim(0, 2);
            var callCounter = 0;
            var consumers   = new[]
            {
                new ConsumerStub {
                    ShouldHandle = true, Handler = _ => milestone.Release()
                },
                new ConsumerStub {
                    ShouldHandle = true, Handler = _ => Interlocked.Increment(ref callCounter)
                }
            };

            using var sut = new ConnectorBuilder()
                            .WithConsumers(consumers)
                            .Build();

            await sut.ConnectAsync(HOST, broker.Port);

            await broker.PublishAsync("boo", Encoding.ASCII.GetBytes("hoo"));

            Assert.True(await milestone.WaitAsync(TimeSpan.FromSeconds(5)));

            // publish again, so if the first message was going to sent to the second subscriber
            // it would not be missed
            await broker.PublishAsync("boo", Encoding.ASCII.GetBytes("hoo"));

            Assert.True(await milestone.WaitAsync(TimeSpan.FromSeconds(5)));

            Assert.Equal(2, consumers[0].PacketsToHandle.Count());
            Assert.Equal(0, Volatile.Read(ref callCounter));
        }
        public async Task WhenStartedThenSubscribesForConsumers()
        {
            using var broker = new MiniMqttServer(PORT);

            var consumers = new[] {
                new ConsumerStub()
                {
                    Subscriptions = new[] { "foo", "boo" }
                },
                new ConsumerStub()
                {
                    Subscriptions = new[] { "moo", "shoo" }
                }
            };

            using var sut = new ConnectorBuilder()
                            .WithConsumers(consumers)
                            .Build();

            await sut.ConnectAsync(HOST, PORT);

            var expected = consumers.SelectMany(c => c.Subscriptions).OrderBy(s => s);

            Assert.Equal(expected, broker.Subscriptions.OrderBy(s => s));
            broker.Dispose();
        }
        public async Task WhenStartedThenConnectsToServer()
        {
            using var broker = new MiniMqttServer();
            using var sut    = new ConnectorBuilder().Build();

            await sut.ConnectAsync(HOST, broker.Port);

            Assert.Equal(1, broker.ConnectionCounter);
        }