public void BufferingTargetWrapperSyncTest1()
        {
            var myTarget = new MyTarget();
            var targetWrapper = new BufferingTargetWrapper
            {
                WrappedTarget = myTarget,
                BufferSize = 10,
            };

            myTarget.Initialize(null);
            targetWrapper.Initialize(null);

            int totalEvents = 100;

            var continuationHit = new bool[totalEvents];
            var lastException = new Exception[totalEvents];
            var continuationThread = new Thread[totalEvents];
            int hitCount = 0;

            CreateContinuationFunc createAsyncContinuation = 
                eventNumber =>
                    ex =>
                    {
                        lastException[eventNumber] = ex;
                        continuationThread[eventNumber] = Thread.CurrentThread;
                        continuationHit[eventNumber] = true;
                        Interlocked.Increment(ref hitCount);
                    };

            // write 9 events - they will all be buffered and no final continuation will be reached
            int eventCounter = 0;
            for (int i = 0; i < 9; ++i)
            {
                targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            }

            Assert.AreEqual(0, hitCount);
            Assert.AreEqual(0, myTarget.WriteCount);

            // write one more event - everything will be flushed
            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            Assert.AreEqual(10, hitCount);
            Assert.AreEqual(1, myTarget.BufferedWriteCount);
            Assert.AreEqual(10, myTarget.BufferedTotalEvents);
            Assert.AreEqual(10, myTarget.WriteCount);
            for (int i = 0; i < hitCount; ++i)
            {
                Assert.AreSame(Thread.CurrentThread, continuationThread[i]);
                Assert.IsNull(lastException[i]);
            }

            // write 9 more events - they will all be buffered and no final continuation will be reached
            for (int i = 0; i < 9; ++i)
            {
                targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            }

            // no change
            Assert.AreEqual(10, hitCount);
            Assert.AreEqual(1, myTarget.BufferedWriteCount);
            Assert.AreEqual(10, myTarget.BufferedTotalEvents);
            Assert.AreEqual(10, myTarget.WriteCount);

            Exception flushException = null;
            var flushHit = new ManualResetEvent(false);

            targetWrapper.Flush(
                ex =>
                    {
                        flushException = ex;
                        flushHit.Set();
                    });

            Thread.Sleep(1000);

            flushHit.WaitOne();
            Assert.IsNull(flushException);

            // make sure remaining events were written
            Assert.AreEqual(19, hitCount);
            Assert.AreEqual(2, myTarget.BufferedWriteCount);
            Assert.AreEqual(19, myTarget.BufferedTotalEvents);
            Assert.AreEqual(19, myTarget.WriteCount);
            Assert.AreEqual(1, myTarget.FlushCount);

            // flushes happen on the same thread
            for (int i = 10; i < hitCount; ++i)
            {
                Assert.IsNotNull(continuationThread[i]);
                Assert.AreSame(Thread.CurrentThread, continuationThread[i], "Invalid thread #" + i);
                Assert.IsNull(lastException[i]);
            }

            // flush again - should just invoke Flush() on the wrapped target
            flushHit.Reset();
            targetWrapper.Flush(
                ex =>
                {
                    flushException = ex;
                    flushHit.Set();
                });

            flushHit.WaitOne();
            Assert.AreEqual(19, hitCount);
            Assert.AreEqual(2, myTarget.BufferedWriteCount);
            Assert.AreEqual(19, myTarget.BufferedTotalEvents);
            Assert.AreEqual(19, myTarget.WriteCount);
            Assert.AreEqual(2, myTarget.FlushCount);

            targetWrapper.Close();
            myTarget.Close();
        }
        public void BufferingTargetWrapperSyncWithTimedFlushSlidingTest()
        {
            var myTarget = new MyTarget();
            var targetWrapper = new BufferingTargetWrapper
            {
                WrappedTarget = myTarget,
                BufferSize = 10,
                FlushTimeout = 400,
            };

            myTarget.Initialize(null);
            targetWrapper.Initialize(null);

            int totalEvents = 100;

            var continuationHit = new bool[totalEvents];
            var lastException = new Exception[totalEvents];
            var continuationThread = new Thread[totalEvents];
            int hitCount = 0;

            CreateContinuationFunc createAsyncContinuation =
                eventNumber =>
                    ex =>
                    {
                        lastException[eventNumber] = ex;
                        continuationThread[eventNumber] = Thread.CurrentThread;
                        continuationHit[eventNumber] = true;
                        Interlocked.Increment(ref hitCount);
                    };

            int eventCounter = 0;
            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            Thread.Sleep(300);

            Assert.AreEqual(0, hitCount);
            Assert.AreEqual(0, myTarget.WriteCount);

            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            Thread.Sleep(300);

            Assert.AreEqual(0, hitCount);
            Assert.AreEqual(0, myTarget.WriteCount);

            Thread.Sleep(200);
            Assert.AreEqual(2, hitCount);
            Assert.AreEqual(2, myTarget.WriteCount);
        }
        public void BufferingTargetWrapperSyncWithTimedFlushTest()
        {
            var myTarget = new MyTarget();
            var targetWrapper = new BufferingTargetWrapper
            {
                WrappedTarget = myTarget,
                BufferSize = 10,
                FlushTimeout = 1000,
            };

            myTarget.Initialize(null);
            targetWrapper.Initialize(null);

            int totalEvents = 100;

            var continuationHit = new bool[totalEvents];
            var lastException = new Exception[totalEvents];
            var continuationThread = new Thread[totalEvents];
            int hitCount = 0;

            CreateContinuationFunc createAsyncContinuation =
                eventNumber =>
                    ex =>
                    {
                        lastException[eventNumber] = ex;
                        continuationThread[eventNumber] = Thread.CurrentThread;
                        continuationHit[eventNumber] = true;
                        Interlocked.Increment(ref hitCount);
                    };

            // write 9 events - they will all be buffered and no final continuation will be reached
            int eventCounter = 0;
            for (int i = 0; i < 9; ++i)
            {
                targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            }

            Assert.AreEqual(0, hitCount);
            Assert.AreEqual(0, myTarget.WriteCount);

            // sleep 2 seconds, this will trigger the timer and flush all events
            Thread.Sleep(2000);
            Assert.AreEqual(9, hitCount);
            Assert.AreEqual(1, myTarget.BufferedWriteCount);
            Assert.AreEqual(9, myTarget.BufferedTotalEvents);
            Assert.AreEqual(9, myTarget.WriteCount);
            for (int i = 0; i < hitCount; ++i)
            {
                Assert.AreNotSame(Thread.CurrentThread, continuationThread[i]);
                Assert.IsNull(lastException[i]);
            }

            // write 11 more events, 10 will be hit immediately because the buffer will fill up
            // 1 will be pending
            for (int i = 0; i < 11; ++i)
            {
                targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            }

            Assert.AreEqual(19, hitCount);
            Assert.AreEqual(2, myTarget.BufferedWriteCount);
            Assert.AreEqual(19, myTarget.BufferedTotalEvents);
            Assert.AreEqual(19, myTarget.WriteCount);

            // sleep 2 seonds and the last remaining one will be flushed
            Thread.Sleep(2000);
            Assert.AreEqual(20, hitCount);
            Assert.AreEqual(3, myTarget.BufferedWriteCount);
            Assert.AreEqual(20, myTarget.BufferedTotalEvents);
            Assert.AreEqual(20, myTarget.WriteCount);
        }
        public void WhenWrappedTargetThrowsExceptionThisIsHandled()
        {
            var myTarget = new MyTarget { ThrowException = true };
            var bufferingTargetWrapper = new BufferingTargetWrapper
                                             {
                                                 WrappedTarget = myTarget,
                                                 FlushTimeout = -1
                                             };

            InitializeTargets(myTarget, bufferingTargetWrapper);

            bufferingTargetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(_ => { }));

            var flushHit = new ManualResetEvent(false);
            bufferingTargetWrapper.Flush(ex => flushHit.Set());
            flushHit.WaitOne();

            Assert.Equal(1, myTarget.FlushCount);
        }
        public void BufferingTargetWrapperSyncWithTimedFlushNonSlidingTest()
        {
            var myTarget = new MyTarget();
            var targetWrapper = new BufferingTargetWrapper
            {
                WrappedTarget = myTarget,
                BufferSize = 10,
                FlushTimeout = 400,
                SlidingTimeout = false,
            };

            InitializeTargets(myTarget, targetWrapper);

            const int totalEvents = 100;

            var continuationHit = new bool[totalEvents];
            var lastException = new Exception[totalEvents];
            var continuationThread = new Thread[totalEvents];
            var hitCount = 0;

            var resetEvent = new ManualResetEvent(false);
            CreateContinuationFunc createAsyncContinuation =
                eventNumber =>
                    ex =>
                    {
                        lastException[eventNumber] = ex;
                        continuationThread[eventNumber] = Thread.CurrentThread;
                        continuationHit[eventNumber] = true;
                        Interlocked.Increment(ref hitCount);
                        if (eventNumber > 0)
                        {
                            resetEvent.Set();
                        }
                    };

            var eventCounter = 0;
            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));

            Assert.Equal(0, hitCount);
            Assert.Equal(0, myTarget.WriteCount);

            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            Assert.True(resetEvent.WaitOne(5000));

            Assert.Equal(2, hitCount);
            Assert.Equal(2, myTarget.WriteCount);
        }
        public void BufferingTargetWithFallbackGroupAndFirstTargetFails_Write_SecondTargetWritesEvents()
        {
            var myTarget = new MyTarget { FailCounter = 1 };
            var myTarget2 = new MyTarget();
            var fallbackGroup = new FallbackGroupTarget(myTarget, myTarget2);
            var targetWrapper = new BufferingTargetWrapper
            {
                WrappedTarget = fallbackGroup,
                BufferSize = 10,
            };

            InitializeTargets(myTarget, targetWrapper, myTarget2, fallbackGroup);

            const int totalEvents = 100;

            var continuationHit = new bool[totalEvents];
            var lastException = new Exception[totalEvents];
            var continuationThread = new Thread[totalEvents];

            CreateContinuationFunc createAsyncContinuation =
                eventNumber =>
                    ex =>
                    {
                        lastException[eventNumber] = ex;
                        continuationThread[eventNumber] = Thread.CurrentThread;
                        continuationHit[eventNumber] = true;
                    };

            // write 9 events - they will all be buffered and no final continuation will be reached
            var eventCounter = 0;
            for (var i = 0; i < 9; ++i)
            {
                targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            }

            Assert.Equal(0, myTarget.WriteCount);

            // write one more event - everything will be flushed
            targetWrapper.WriteAsyncLogEvent(new LogEventInfo().WithContinuation(createAsyncContinuation(eventCounter++)));
            Assert.Equal(1, myTarget.WriteCount);
            Assert.Equal(10, myTarget2.WriteCount);

            targetWrapper.Close();
            myTarget.Close();
        }