internal Transmitter(
            TransmissionSender sender                 = null,
            TransmissionBuffer transmissionBuffer     = null,
            TransmissionStorage storage               = null,
            IEnumerable <TransmissionPolicy> policies = null,
            BackoffLogicManager backoffLogicManager   = null)
        {
            this.backoffLogicManager = backoffLogicManager ?? new BackoffLogicManager();
            this.Sender = sender ?? new TransmissionSender();
            this.Sender.TransmissionSent += this.HandleSenderTransmissionSentEvent;
            this.maxSenderCapacity        = this.Sender.Capacity;

            this.Buffer = transmissionBuffer ?? new TransmissionBuffer();
            this.Buffer.TransmissionDequeued += this.HandleBufferTransmissionDequeuedEvent;
            this.maxBufferCapacity            = this.Buffer.Capacity;

            this.Storage            = storage ?? new TransmissionStorage();
            this.maxStorageCapacity = this.Storage.Capacity;

            this.policies = policies ?? Enumerable.Empty <TransmissionPolicy>();
            foreach (TransmissionPolicy policy in this.policies)
            {
                policy.Initialize(this);
            }
        }
            public void MovesTransmissionsFromBufferToSenderWhenSenderCapacityIsGreaterThanZero()
            {
                var bufferedTransmission = new StubTransmission();
                var buffer = new TransmissionBuffer();

                buffer.Enqueue(() => bufferedTransmission);

                Transmission sentTransmission = null;
                var          sender           = new StubTransmissionSender();

                sender.OnEnqueue = getTransmission =>
                {
                    sentTransmission = getTransmission();
                    return(false);
                };

                var policy = new StubTransmissionPolicy {
                    MaxSenderCapacity = 0
                };

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer, policies: new[] { policy });

                policy.MaxSenderCapacity = 1;
                policy.Apply();

                Assert.Same(bufferedTransmission, sentTransmission);
            }
            public void CanBeSetToZeroToDsiableBufferingOfTransmissions()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 0
                };

                Assert.Equal(0, buffer.Capacity);
            }
            public void ReturnsTrueWhenNewTransmissionLengthDoesNotExceedBufferCapacity()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 1
                };

                Assert.True(buffer.Enqueue(() => new StubTransmission(new byte[1])));
            }
            public void ReturnsFalseWhenNewTransmissionLengthExceedsBufferCapacity()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 0
                };

                Assert.False(buffer.Enqueue(() => new StubTransmission(new byte[1])));
            }
            public void DoesNotMakesSpaceForNewTransmissionWhenBufferIsEmpty()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 0
                };

                buffer.Dequeue();
                Assert.False(buffer.Enqueue(() => new StubTransmission()));
            }
            public void ReflectsContentLengthOfTransmissionsAddedByEnqueueAsync()
            {
                Transmission transmission = new StubTransmission(new byte[42]);
                var          buffer       = new TransmissionBuffer();

                buffer.Enqueue(() => transmission);

                Assert.Equal(transmission.Content.Length, buffer.Size);
            }
            public void ReflectsContentLengthOfTransmissionsRemovedByDequeueAsync()
            {
                var buffer = new TransmissionBuffer();

                buffer.Enqueue(() => new StubTransmission(new byte[10]));
                buffer.Dequeue();

                Assert.Equal(0, buffer.Size);
            }
            public void MakesSpaceForOneNewTransmissionWhenOldTransmissionDequeuedSuccessfully()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 1
                };

                buffer.Enqueue(() => new StubTransmission());
                buffer.Dequeue();
                Assert.True(buffer.Enqueue(() => new StubTransmission()));
            }
            public void DoesNotCountNullTransmissionsReturnedFromEmptyStorageAgainstMaxNumber()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 1
                };

                buffer.Enqueue(() => null);

                Transmission transmission2 = new StubTransmission();

                Assert.True(buffer.Enqueue(() => transmission2));
            }
            public void DoesNotCountRejectedTransmissionsAgainstMaxNumber()
            {
                var buffer = new TransmissionBuffer {
                    Capacity = 0
                };

                buffer.Enqueue(() => new StubTransmission(new byte[1]));

                buffer.Capacity = 1;

                Assert.True(buffer.Enqueue(() => new StubTransmission(new byte[1])));
            }
 private static Transmitter CreateTransmitter(
     TransmissionSender sender = null, 
     TransmissionBuffer buffer = null, 
     TransmissionStorage storage = null, 
     IEnumerable<TransmissionPolicy> policies = null)
 {
     return new Transmitter(
         sender ?? new StubTransmissionSender(),
         buffer ?? new StubTransmissionBuffer(),
         storage ?? new StubTransmissionStorage(),
         policies);
 }
 private static Transmitter CreateTransmitter(
     TransmissionSender sender   = null,
     TransmissionBuffer buffer   = null,
     TransmissionStorage storage = null,
     IEnumerable <TransmissionPolicy> policies = null)
 {
     return(new Transmitter(
                sender ?? new StubTransmissionSender(),
                buffer ?? new StubTransmissionBuffer(),
                storage ?? new StubTransmissionStorage(),
                policies));
 }
            public void ReturnsOldestEnquedTransmission()
            {
                var buffer = new TransmissionBuffer();

                Transmission transmission1 = new StubTransmission();

                buffer.Enqueue(() => transmission1);

                Transmission transmission2 = new StubTransmission();

                buffer.Enqueue(() => transmission2);

                Assert.Same(transmission1, buffer.Dequeue());
                Assert.Same(transmission2, buffer.Dequeue());
            }
            public void DoesNotInvokeTransmissionGetterWhenMaxNumberOfTransmissionsIsExceededToKeepItStored()
            {
                bool transmissionGetterInvoked         = false;
                Func <Transmission> transmissionGetter = () =>
                {
                    transmissionGetterInvoked = true;
                    return(new StubTransmission(new byte[1]));
                };
                var buffer = new TransmissionBuffer {
                    Capacity = 0
                };

                buffer.Enqueue(transmissionGetter);

                Assert.False(transmissionGetterInvoked);
            }
            public void RaisedWhenDequeueFromEmptyBufferWasAttempted()
            {
                object eventSender = null;
                TransmissionProcessedEventArgs eventArgs = null;
                var buffer = new TransmissionBuffer();

                buffer.TransmissionDequeued += (sender, args) =>
                {
                    eventSender = sender;
                    eventArgs   = args;
                };

                buffer.Dequeue();

                Assert.Same(buffer, eventSender);
                Assert.Same(null, eventArgs.Transmission);
            }
            public void DoesNotContinueAsyncOperationsOnCapturedSynchronizationContextToImprovePerformance()
            {
                bool postedBack = false;

                using (var context = new StubSynchronizationContext())
                {
                    context.OnPost = (callback, state) =>
                    {
                        postedBack = true;
                        callback(state);
                    };

                    var buffer = new TransmissionBuffer();
                    buffer.Enqueue(() => new StubTransmission());
                }

                Assert.False(postedBack);
            }
            public void IsRaisedWhenTransmissionWasDequeuedSuccessfully()
            {
                object eventSender = null;
                TransmissionProcessedEventArgs eventArgs = null;
                var buffer = new TransmissionBuffer();

                buffer.TransmissionDequeued += (sender, args) =>
                {
                    eventSender = sender;
                    eventArgs   = args;
                };

                buffer.Enqueue(() => new StubTransmission());

                Transmission dequeuedTransmission = buffer.Dequeue();

                Assert.Same(buffer, eventSender);
                Assert.Same(dequeuedTransmission, eventArgs.Transmission);
            }
            public async Task LogsEventAfterMovingTransmissionsToStorage()
            {
                var sender = new StubTransmissionSender {
                    OnEnqueue = t => false
                };
                var buffer  = new TransmissionBuffer();
                var storage = new StubTransmissionStorage {
                    OnEnqueue = t => false
                };

                buffer.Enqueue(() => new StubTransmission());

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer, storage: storage);

                using (var listener = new TestEventListener())
                {
                    const long AllKeywords = -1;
                    listener.EnableEvents(TelemetryChannelEventSource.Log, EventLevel.LogAlways, (EventKeywords)AllKeywords);

                    await transmitter.MoveTransmissionsAndWaitForSender(default);
            public void EnqueueAndDequeueMethodsAreThreadSafe()
            {
                var buffer = new TransmissionBuffer();

                const int NumberOfThreads = 16;
                const int NumberOfIterations = 1000;
                var tasks = new Task[NumberOfThreads];
                for (int t = 0; t < NumberOfThreads; t++)
                {
                    tasks[t] = TaskEx.Run(() =>
                    {
                        for (int i = 0; i < NumberOfIterations; i++)
                        {
                            buffer.Enqueue(() => new StubTransmission());
                            buffer.Dequeue();
                        }
                    });
                }

                TaskEx.WhenAll(tasks).GetAwaiter().GetResult();
            }
            public void MovesOldestTransmissionFromBufferToSender()
            {
                Transmission sentTransmission = null;
                var          sender           = new StubTransmissionSender();

                sender.OnEnqueue = getTransmission =>
                {
                    sentTransmission = getTransmission();
                    return(false);
                };

                Transmission bufferedTransmission = new StubTransmission();
                var          buffer = new TransmissionBuffer();

                buffer.Enqueue(() => bufferedTransmission);

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer);

                sender.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission()));

                Assert.Same(bufferedTransmission, sentTransmission);
            }
            public void EnqueueAndDequeueMethodsAreThreadSafe()
            {
                var buffer = new TransmissionBuffer();

                const int NumberOfThreads    = 16;
                const int NumberOfIterations = 1000;
                var       tasks = new Task[NumberOfThreads];

                for (int t = 0; t < NumberOfThreads; t++)
                {
                    tasks[t] = TaskEx.Run(() =>
                    {
                        for (int i = 0; i < NumberOfIterations; i++)
                        {
                            buffer.Enqueue(() => new StubTransmission());
                            buffer.Dequeue();
                        }
                    });
                }

                TaskEx.WhenAll(tasks).GetAwaiter().GetResult();
            }
            public void MovesTransmissionsFromStorageToBufferWhenBufferCapacityIsGreaterThanZero()
            {
                var storedTransmission = new StubTransmission();

                var storage = new StubTransmissionStorage();

                storage.Enqueue(() => storedTransmission);

                var buffer = new TransmissionBuffer();

                var policy = new StubTransmissionPolicy();

                policy.MaxBufferCapacity = 0;

                Transmitter transmitter = CreateTransmitter(buffer: buffer, storage: storage, policies: new[] { policy });

                policy.MaxBufferCapacity = 1;
                policy.Apply();

                Transmission bufferedTransmission = buffer.Dequeue();

                Assert.Same(storedTransmission, bufferedTransmission);
            }
        internal Transmitter(
            TransmissionSender sender = null, 
            TransmissionBuffer transmissionBuffer = null, 
            TransmissionStorage storage = null, 
            IEnumerable<TransmissionPolicy> policies = null)
        { 
            this.Sender = sender ?? new TransmissionSender();
            this.Sender.TransmissionSent += this.HandleSenderTransmissionSentEvent;
            this.maxSenderCapacity = this.Sender.Capacity;

            this.Buffer = transmissionBuffer ?? new TransmissionBuffer();
            this.Buffer.TransmissionDequeued += this.HandleBufferTransmissionDequeuedEvent;
            this.maxBufferCapacity = this.Buffer.Capacity;

            this.Storage = storage ?? new TransmissionStorage();
            this.maxStorageCapacity = this.Storage.Capacity;

            this.policies = policies ?? Enumerable.Empty<TransmissionPolicy>();
            foreach (TransmissionPolicy policy in this.policies)
            {
                policy.Initialize(this);
            }
        }
            public void MovesTransmissionsFromBufferToStorageWhenBufferCapacityIsZero()
            {
                var storage = new StubTransmissionStorage {
                    Capacity = 1
                };

                var bufferedTransmission = new StubTransmission();
                var buffer = new TransmissionBuffer();

                storage.Enqueue(() => bufferedTransmission);

                var policy = new StubTransmissionPolicy();

                policy.MaxBufferCapacity = 1;

                Transmitter transmitter = CreateTransmitter(buffer: buffer, storage: storage, policies: new[] { policy });

                policy.MaxBufferCapacity = 0;
                policy.Apply();

                Transmission storedTransmission = storage.Dequeue();

                Assert.Same(bufferedTransmission, storedTransmission);
            }
            public async Task StoresTransmissionWhenSenderIsFull()
            {
                bool isInStorage = false;
                var  sender      = new StubTransmissionSender {
                    OnEnqueue = t => false
                };
                var buffer  = new TransmissionBuffer();
                var storage = new StubTransmissionStorage
                {
                    OnEnqueue = getTransmission =>
                    {
                        isInStorage = true;
                        return(true);
                    }
                };

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer, storage: storage);

                var transmission = new StubTransmission();
                var result       = await transmitter.FlushAsync(transmission, default);

                Assert.IsTrue(isInStorage);
                Assert.IsTrue(result);
            }
            public void DoesNotInvokeTransmissionGetterWhenMaxNumberOfTransmissionsIsExceededToKeepItStored()
            {
                bool transmissionGetterInvoked = false;
                Func<Transmission> transmissionGetter = () =>
                {
                    transmissionGetterInvoked = true;
                    return new StubTransmission(new byte[1]);
                };
                var buffer = new TransmissionBuffer { Capacity = 0 };

                buffer.Enqueue(transmissionGetter);

                Assert.False(transmissionGetterInvoked);
            }
 public void CanBeSetToZeroToDsiableBufferingOfTransmissions()
 {
     var buffer = new TransmissionBuffer { Capacity = 0 };
     Assert.Equal(0, buffer.Capacity);
 }
 public void MakesSpaceForOneNewTransmissionWhenOldTransmissionDequeuedSuccessfully()
 {
     var buffer = new TransmissionBuffer { Capacity = 1 };
     buffer.Enqueue(() => new StubTransmission());
     buffer.Dequeue();
     Assert.True(buffer.Enqueue(() => new StubTransmission()));
 }
            public void MovesOldestTransmissionFromBufferToSender()
            {
                Transmission sentTransmission = null;
                var sender = new StubTransmissionSender();
                sender.OnEnqueue = getTransmission =>
                {
                    sentTransmission = getTransmission();
                    return false;
                };

                Transmission bufferedTransmission = new StubTransmission();
                var buffer = new TransmissionBuffer();
                buffer.Enqueue(() => bufferedTransmission);

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer);

                sender.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission()));

                Assert.Same(bufferedTransmission, sentTransmission);
            }
            public void MovesTransmissionsFromBufferToStorageWhenBufferCapacityIsZero()
            {
                var storage = new StubTransmissionStorage { Capacity = 1 };

                var bufferedTransmission = new StubTransmission();
                var buffer = new TransmissionBuffer();
                storage.Enqueue(() => bufferedTransmission);
                
                var policy = new StubTransmissionPolicy();
                policy.MaxBufferCapacity = 1;

                Transmitter transmitter = CreateTransmitter(buffer: buffer, storage: storage, policies: new[] { policy });

                policy.MaxBufferCapacity = 0;
                policy.Apply();

                Transmission storedTransmission = storage.Dequeue();
                Assert.Same(bufferedTransmission, storedTransmission);
            }
            public void ReturnsOldestEnquedTransmission()
            {
                var buffer = new TransmissionBuffer();

                Transmission transmission1 = new StubTransmission();
                buffer.Enqueue(() => transmission1);

                Transmission transmission2 = new StubTransmission();
                buffer.Enqueue(() => transmission2);

                Assert.Same(transmission1, buffer.Dequeue());
                Assert.Same(transmission2, buffer.Dequeue());
            }
            public void DoesNotCountNullTransmissionsReturnedFromEmptyStorageAgainstMaxNumber()
            {
                var buffer = new TransmissionBuffer { Capacity = 1 };
                buffer.Enqueue(() => null);

                Transmission transmission2 = new StubTransmission();
                Assert.True(buffer.Enqueue(() => transmission2));
            }
            public void ReflectsContentLengthOfTransmissionsRemovedByDequeueAsync()
            {
                var buffer = new TransmissionBuffer();

                buffer.Enqueue(() => new StubTransmission(new byte[10]));
                buffer.Dequeue();

                Assert.Equal(0, buffer.Size);
            }
 public void StartsAtZero()
 {
     var buffer = new TransmissionBuffer();
     Assert.Equal(0, buffer.Size);
 }
            public void ReturnsNullWhenBufferIsEmpty()
            {
                var buffer = new TransmissionBuffer();

                Assert.Null(buffer.Dequeue());
            }
 public void DefaultValueIsAppropriateForMostApps()
 {
     var buffer = new TransmissionBuffer();
     Assert.Equal(1024 * 1024, buffer.Capacity);
 }
            public void IsRaisedWhenTransmissionWasDequeuedSuccessfully()
            {
                object eventSender = null;
                TransmissionProcessedEventArgs eventArgs = null;
                var buffer = new TransmissionBuffer();
                buffer.TransmissionDequeued += (sender, args) =>
                {
                    eventSender = sender;
                    eventArgs = args;
                };

                buffer.Enqueue(() => new StubTransmission());

                Transmission dequeuedTransmission = buffer.Dequeue();

                Assert.Same(buffer, eventSender);
                Assert.Same(dequeuedTransmission, eventArgs.Transmission);
            }
            public void RaisedWhenDequeueFromEmptyBufferWasAttempted()
            {
                object eventSender = null;
                TransmissionProcessedEventArgs eventArgs = null;
                var buffer = new TransmissionBuffer();
                buffer.TransmissionDequeued += (sender, args) =>
                {
                    eventSender = sender;
                    eventArgs = args;
                };

                buffer.Dequeue();

                Assert.Same(buffer, eventSender);
                Assert.Same(null, eventArgs.Transmission);
            }
            public void ThrowsArgumentOutOfRangeExceptionWhenValueIsLessThanZero()
            {
                var buffer = new TransmissionBuffer();

                Assert.Throws <ArgumentOutOfRangeException>(() => buffer.Capacity = -1);
            }
            public void DoesNotCountRejectedTransmissionsAgainstMaxNumber()
            {
                var buffer = new TransmissionBuffer { Capacity = 0 };
                buffer.Enqueue(() => new StubTransmission(new byte[1]));

                buffer.Capacity = 1;

                Assert.True(buffer.Enqueue(() => new StubTransmission(new byte[1])));
            }
            public void StartsAtZero()
            {
                var buffer = new TransmissionBuffer();

                Assert.Equal(0, buffer.Size);
            }
            public void DoesNotContinueAsyncOperationsOnCapturedSynchronizationContextToImprovePerformance()
            {
                bool postedBack = false;
                using (var context = new StubSynchronizationContext())
                {
                    context.OnPost = (callback, state) =>
                    {
                        postedBack = true;
                        callback(state);
                    };

                    var buffer = new TransmissionBuffer();
                    buffer.Enqueue(() => new StubTransmission());
                }

                Assert.False(postedBack);
            }
            public void ReflectsContentLengthOfTransmissionsAddedByEnqueueAsync()
            {
                Transmission transmission = new StubTransmission(new byte[42]);
                var buffer = new TransmissionBuffer();

                buffer.Enqueue(() => transmission);

                Assert.Equal(transmission.Content.Length, buffer.Size);
            }
            public void MovesTransmissionsFromStorageToBufferWhenBufferCapacityIsGreaterThanZero()
            {
                var storedTransmission = new StubTransmission();

                var storage = new StubTransmissionStorage();
                storage.Enqueue(() => storedTransmission);

                var buffer = new TransmissionBuffer();

                var policy = new StubTransmissionPolicy();
                policy.MaxBufferCapacity = 0;

                Transmitter transmitter = CreateTransmitter(buffer: buffer, storage: storage, policies: new[] { policy });

                policy.MaxBufferCapacity = 1;
                policy.Apply();

                Transmission bufferedTransmission = buffer.Dequeue();
                Assert.Same(storedTransmission, bufferedTransmission);
            }
 public void ReturnsTrueWhenNewTransmissionLengthDoesNotExceedBufferCapacity()
 {
     var buffer = new TransmissionBuffer { Capacity = 1 };
     Assert.True(buffer.Enqueue(() => new StubTransmission(new byte[1])));
 }
            public void MovesTransmissionsFromBufferToSenderWhenSenderCapacityIsGreaterThanZero()
            {
                var bufferedTransmission = new StubTransmission();
                var buffer = new TransmissionBuffer();
                buffer.Enqueue(() => bufferedTransmission);

                Transmission sentTransmission = null;
                var sender = new StubTransmissionSender();
                sender.OnEnqueue = getTransmission =>
                {
                    sentTransmission = getTransmission();
                    return false;
                };

                var policy = new StubTransmissionPolicy { MaxSenderCapacity = 0 };

                Transmitter transmitter = CreateTransmitter(sender: sender, buffer: buffer, policies: new[] { policy });

                policy.MaxSenderCapacity = 1;
                policy.Apply();

                Assert.Same(bufferedTransmission, sentTransmission);
            }
 public void DoesNotMakesSpaceForNewTransmissionWhenBufferIsEmpty()
 {
     var buffer = new TransmissionBuffer { Capacity = 0 };
     buffer.Dequeue();
     Assert.False(buffer.Enqueue(() => new StubTransmission()));
 }
 public void ReturnsNullWhenBufferIsEmpty()
 {
     var buffer = new TransmissionBuffer();
     Assert.Null(buffer.Dequeue());
 }
            public void DefaultValueIsAppropriateForMostApps()
            {
                var buffer = new TransmissionBuffer();

                Assert.Equal(1024 * 1024, buffer.Capacity);
            }
 public void ReturnsFalseWhenTransmissionGetterReturedNullIndicatingEmptyStorage()
 {
     var buffer = new TransmissionBuffer();
     Assert.False(buffer.Enqueue(() => null));
 }
            public void ReturnsFalseWhenTransmissionGetterReturedNullIndicatingEmptyStorage()
            {
                var buffer = new TransmissionBuffer();

                Assert.False(buffer.Enqueue(() => null));
            }
 public void ReturnsFalseWhenNewTransmissionLengthExceedsBufferCapacity()
 {
     var buffer = new TransmissionBuffer { Capacity = 0 };
     Assert.False(buffer.Enqueue(() => new StubTransmission(new byte[1])));
 }
 public void ThrowsArgumentOutOfRangeExceptionWhenValueIsLessThanZero()
 {
     var buffer = new TransmissionBuffer();
     Assert.Throws<ArgumentOutOfRangeException>(() => buffer.Capacity = -1);
 }