public async Task When_flushing_should_use_parallel_sends()
        {
            // this test aims at simulating the consumers that are slow enough to fill parallelism of reporter
            // it asserts that no progress is done till one of them finishes
            const int max = RawDataReporter.MaxParallelConsumers;

            var payloads  = new ConcurrentQueue <byte[]>();
            var tcs       = new TaskCompletionSource <object>();
            var semaphore = new SemaphoreSlim(0, max);

            var counter = 0;

            Task Report(byte[] payload, CancellationToken cancellationToken)
            {
                var value = ReadValues(payload)[0];

                if (value < max)
                {
                    payloads.Enqueue(payload);
                    semaphore.Release();
                    return(tcs.Task);
                }

                payloads.Enqueue(payload);
                Interlocked.Increment(ref counter);
                return(Task.FromResult(0));
            }

            var reporter = new RawDataReporter(Report, buffer, WriteEntriesValues, flushSize: 1, maxFlushSize: 1, maxSpinningTime: TimeSpan.MaxValue);

            reporter.Start();

            for (var i = 0; i < max; i++)
            {
                buffer.TryWrite(i);
            }

            // additional write
            buffer.TryWrite(max);

            for (var i = 0; i < max; i++)
            {
                await semaphore.WaitAsync();
            }

            // no new reports scheduled before previous complete
            Assert.AreEqual(0, counter);

            // complete all the reports
            tcs.SetResult("");

            await reporter.Stop();

            // should have run the additional one
            Assert.AreEqual(1, counter);

            Assert.AreEqual(max + 1, payloads.Count);
        }
        public async Task When_stopped()
        {
            var reporter = new RawDataReporter(sender.ReportPayload, buffer, WriteEntriesValues, int.MaxValue, TimeSpan.MaxValue);

            reporter.Start();
            buffer.TryWrite(1);
            buffer.TryWrite(2);

            await reporter.Stop();

            AssertValues(new long[] { 1, 2 });
        }
        public async Task When_flush_size_is_reached_only_maximum_number_is_flushed()
        {
            var reporter = new RawDataReporter(sender.ReportPayload, buffer, WriteEntriesValues, 4, TimeSpan.MaxValue);

            reporter.Start();
            buffer.TryWrite(1);
            buffer.TryWrite(2);
            buffer.TryWrite(3);
            buffer.TryWrite(4);

            AssertValues(new long[] { 1, 2 }, new long[] { 3, 4 });

            await reporter.Stop();
        }
        public async Task When_max_spinning_time_is_reached()
        {
            var maxSpinningTime = TimeSpan.FromMilliseconds(100);

            var reporter = new RawDataReporter(sender.ReportPayload, buffer, WriteEntriesValues, int.MaxValue, maxSpinningTime);

            reporter.Start();
            buffer.TryWrite(1);
            buffer.TryWrite(2);
            await Task.Delay(maxSpinningTime.Add(TimeSpan.FromMilliseconds(200)));

            AssertValues(new long[] { 1, 2 });

            await reporter.Stop();
        }
        public async Task When_highthrouput_endpoint_shuts_down()
        {
            const int testSize = 10000;
            var       queue    = new ConcurrentQueue <byte[]>();

            Task Send(byte[] data, CancellationToken cancellationToken)
            {
                queue.Enqueue(data);
                return(Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken)); // delay to make it realistically long
            }

            var reporter = new RawDataReporter(Send, buffer, WriteEntriesValues);

            reporter.Start();

            // write values
            for (var i = 0; i < testSize; i++)
            {
                while (buffer.TryWrite(i) == false)
                {
                    // spin till it's written
                }
            }

            await reporter.Stop();

            var values = new HashSet <long>();

            foreach (var current in queue.ToArray().Select(ReadValues))
            {
                foreach (var v in current)
                {
                    values.Add(v);
                }
            }

            Assert.AreEqual(testSize, values.Count);
        }