public void CatchesAndLogsSynchronousExceptionsThrownByTransmitterWhenPausingTransmission()
 {
     var policy = new ErrorHandlingTransmissionPolicy();
     var exception = CreateException(statusCode: 408);
     var transmitter = new StubTransmitter { OnApplyPolicies = () => { throw exception; } };
     CatchesAndLogsExceptionThrownByTransmitter(policy, transmitter, exception);
 }
        public void IfIndexMoreThanNumberOfItemsInTransmissionIgnoreError()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            // Index is 0-based
            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 1,
                errorCodes: new[] { "408" },
                indexStartWith: 1);

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        public void DoesNotSendTransmissionForUnsupportedCodes()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 50,
                itemsAccepted: 45,
                errorCodes: new[] { "400", "402", "502", "409", "417" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        public void InitializeStoresTransmitterForUseByChildClasses()
        {
            var transmitter = new StubTransmitter();
            var policy = new TestableTransmissionPolicy();

            policy.Initialize(transmitter);

            Assert.Same(transmitter, policy.Transmitter);
        }
            public void StopsTransmissionSendingAndBuffering()
            {
                var transmitter = new StubTransmitter();
                
                var applicationLifecycle = new StubApplicationLifecycle();
                var policy = new ApplicationLifecycleTransmissionPolicy(applicationLifecycle);
                policy.Initialize(transmitter);

                applicationLifecycle.OnStopping(ApplicationStoppingEventArgs.Empty);

                Assert.Equal(0, policy.MaxSenderCapacity);
                Assert.Equal(0, policy.MaxBufferCapacity);
            }
 public void CatchesAndLogsSynchronousExceptionsThrownByTransmitterWhenResumingTransmission()
 {
     var policy = new TestableErrorHandlingTransmissionPolicy { BackOffTime = TimeSpan.FromMilliseconds(1) };
     var exception = CreateException(statusCode: 408);
     var transmitter = new StubTransmitter();
     transmitter.OnApplyPolicies = () =>
     {
         if (policy.MaxSenderCapacity == null)
         {
             throw exception;
         }
     };
     CatchesAndLogsExceptionThrownByTransmitter(policy, transmitter, exception);
 }
            public void SerializesTelemetryOnSameThreadBecauseItAssumesItIsAlreadyOnThreadPool()
            {
                int serializationThreadId = -1;
                var transmitter = new StubTransmitter();
                transmitter.OnEnqueue = t => 
                {
                    serializationThreadId = Thread.CurrentThread.ManagedThreadId;
                };

                var serializer = new TelemetrySerializer(transmitter);
                serializer.Serialize(new[] { new StubTelemetry() });

                Assert.Equal(serializationThreadId, Thread.CurrentThread.ManagedThreadId);
            }
        public void ApplyInvokesApplyPoliciesAsyncOfTransmitter()
        {
            bool policiesApplied = false;
            var transmitter = new StubTransmitter
            {
                OnApplyPolicies = () => { policiesApplied = true; }
            };

            var policy = new StubTransmissionPolicy();
            policy.Initialize(transmitter);

            policy.Apply();

            Assert.True(policiesApplied);
        }
            public void DoesNotRetrySuccessfulTransmission()
            {
                Transmission enqueuedTransmission = null;
                var transmitter = new StubTransmitter();
                transmitter.OnEnqueue = transmission =>
                {
                    enqueuedTransmission = transmission;
                };

                var policy = new ErrorHandlingTransmissionPolicy();
                policy.Initialize(transmitter);

                var successfulTransmission = new StubTransmission();
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(successfulTransmission));

                Assert.Null(enqueuedTransmission);
                Assert.Equal(0, policy.ConsecutiveErrors);
            }
            public void StopsTransmissionSendingWhenTransmissionTimesOut()
            {
                var policyApplied = new AutoResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    policyApplied.Set();
                };

                var policy = new TestableErrorHandlingTransmissionPolicy();
                policy.Initialize(transmitter);

                policy.BackOffTime = TimeSpan.FromSeconds(10);
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission(), CreateException(statusCode: 408)));
                
                Assert.True(policyApplied.WaitOne(100));
                Assert.Equal(0, policy.MaxSenderCapacity);
            }
            public void AssertUnsupportedResponseCodeDoesntChangeCapacity()
            {
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    throw new Exception("Apply shouldn't be called because unsupported response code was passed");
                };

                var policy = new ThrottlingTransmissionPolicy();
                policy.Initialize(transmitter);

                transmitter.OnTransmissionSent(
                    new TransmissionProcessedEventArgs(
                        new StubTransmission(),
                    CreateThrottledResponse(ResponseCodeUnsupported, 1)));

                Assert.Null(policy.MaxSenderCapacity);
                Assert.Null(policy.MaxBufferCapacity);
                Assert.Null(policy.MaxStorageCapacity);
            }
            public void AssertIfDateParseErrorCausesDefaultDelay()
            {
                var policyApplied = new AutoResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    policyApplied.Set();
                };

                var policy = new ThrottlingTransmissionPolicy();
                policy.Initialize(transmitter);

                transmitter.OnTransmissionSent(
                    new TransmissionProcessedEventArgs(
                        new StubTransmission(),
                    CreateThrottledResponse(ResponseCodeTooManyRequests, "no one can parse me! :)")));

                Assert.True(policyApplied.WaitOne(100));
                Assert.Null(policy.MaxSenderCapacity);
                Assert.Null(policy.MaxBufferCapacity);
                Assert.Null(policy.MaxStorageCapacity);
            }
            private static void CatchesAndLogsExceptionThrownByTransmitter(ErrorHandlingTransmissionPolicy policy, StubTransmitter transmitter, Exception exception)
            {
                policy.Initialize(transmitter);

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

                    transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission(), CreateException(statusCode: 408)));

                    EventWrittenEventArgs error = listener.Messages.First(args => args.EventId == 23);
                    Assert.Contains(exception.Message, (string)error.Payload[1], StringComparison.Ordinal);
                }
            }
            private void PositiveTest(int responseCode, int? expectedSenderCapacity, int? expectedBufferCapacity, int? expectedStorageCapacity)
            {
                const int RetryAfterSeconds = 2;
                string retryAfter = DateTime.Now.ToUniversalTime().AddSeconds(RetryAfterSeconds).ToString("R", CultureInfo.InvariantCulture);
                const int WaitForTheFirstApplyAsync = 100;
                int waitForTheSecondApplyAsync = (RetryAfterSeconds * 1000) /*to miliseconds*/ +
                    500 /**magic number to wait for other code before/after 
                         * timer which calls 2nd ApplyAsync
                         **/;

                var policyApplied = new AutoResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    policyApplied.Set();
                };

                var policy = new ThrottlingTransmissionPolicy();
                policy.Initialize(transmitter);

                transmitter.OnTransmissionSent(
                    new TransmissionProcessedEventArgs(
                        new StubTransmission(),
                    CreateThrottledResponse(responseCode, retryAfter)));

                Assert.True(policyApplied.WaitOne(WaitForTheFirstApplyAsync));
                
                Assert.Equal(expectedSenderCapacity, policy.MaxSenderCapacity);
                Assert.Equal(expectedBufferCapacity, policy.MaxBufferCapacity);
                Assert.Equal(expectedStorageCapacity, policy.MaxStorageCapacity);

                Assert.True(policyApplied.WaitOne(waitForTheSecondApplyAsync));

                // Check that it resets after retry-after interval
                Assert.Null(policy.MaxSenderCapacity);
                Assert.Null(policy.MaxBufferCapacity);
                Assert.Null(policy.MaxStorageCapacity);
            }
            public void RetryAfterOlderThanNow()
            {
                // An old date
                string retryAfterDateString = DateTime.Now.AddMinutes(-1).ToString("R", CultureInfo.InvariantCulture);

                var policyApplied = new AutoResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    policyApplied.Set();
                };

                var policy = new ThrottlingTransmissionPolicy();
                policy.Initialize(transmitter);

                transmitter.OnTransmissionSent(
                    new TransmissionProcessedEventArgs(
                        new StubTransmission(),
                    CreateThrottledResponse(ResponseCodeTooManyRequests, retryAfterDateString)));

                Assert.True(policyApplied.WaitOne(100));
                Assert.Null(policy.MaxSenderCapacity);
                Assert.Null(policy.MaxBufferCapacity);
                Assert.Null(policy.MaxStorageCapacity);
            }
            public void AsksTransmitterToApplyPoliciesWhenNetworkAvailabilityChanges()
            {
                bool policiesApplied = false;
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () => 
                {
                    policiesApplied = true;
                };

                var network = new StubNetwork();
                var policy = new NetworkAvailabilityTransmissionPolicy(network);
                policy.Initialize(transmitter);

                network.OnStatusChanged(EventArgs.Empty);

                Assert.True(policiesApplied);
            }
        public void IfResponseIsBadJsonWeDoNotIncreaseErrorCount()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = "[,]";

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        public void NewTransmissionCreatedByIndexesFromResponse()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry>
                {
                    new EventTelemetry("1"),
                    new EventTelemetry("2"),
                    new EventTelemetry("3"),
                };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 3,
                itemsAccepted: 1,
                errorCodes: new[] { "439", "439" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            string[] newItems = JsonSerializer
                .Deserialize(enqueuedTransmissions[0].Content)
                .Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            Assert.Equal(2, newItems.Length);
            Assert.True(newItems[0].Contains("\"name\":\"1\""));
            Assert.True(newItems[1].Contains("\"name\":\"2\""));
        }
        public void IfItemIsRejectedOnlyThisItemIsUploadedBack()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 1,
                errorCodes: new[] { "429" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(1, enqueuedTransmissions.Count);
        }
     public void EnqueuesTransmissionWithExpectedProperties()
     {
         Transmission transmission = null;
         var transmitter = new StubTransmitter();
         transmitter.OnEnqueue = t =>
         {
             transmission = t;
         };
 
         var serializer = new TelemetrySerializer(transmitter) { EndpointAddress = new Uri("http://expected.uri") };
         serializer.Serialize(new[] { new StubTelemetry() });
 
         Assert.Equal(serializer.EndpointAddress, transmission.EndpointAddress);
         Assert.Equal("application/x-json-stream", transmission.ContentType);
         Assert.Equal("gzip", transmission.ContentEncoding);
         Assert.Equal(string.Empty, Unzip(transmission.Content));
     }
            public void RetriesFailedTransmissionIfItsNumberOfAttemptsDidNotReachMaximum()
            {
                Transmission enqueuedTransmission = null;
                var transmitter = new StubTransmitter();
                transmitter.OnEnqueue = transmission =>
                {
                    enqueuedTransmission = transmission;
                };

                var policy = new ErrorHandlingTransmissionPolicy();
                policy.Initialize(transmitter);

                var failedTransmission = new StubTransmission();
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(failedTransmission, CreateException(statusCode: 408)));

                Assert.Same(failedTransmission, enqueuedTransmission);
            }
            public void DoesNotContinueAsyncOperationsOnCapturedSynchronizationContextToImprovePerformance()
            {
                var transmitter = new StubTransmitter() { OnEnqueue = transmission => TaskEx.Run(() => { }) };
                var serializer = new TelemetrySerializer(transmitter);

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

                    serializer.Serialize(new[] { new StubTelemetry() });
                }

                Assert.False(postedBack);
            }
        public void IfNumberOfRecievedItemsEqualsToNumberOfAcceptedErrorsListIsIgnored()
        {
            var transmitter = new StubTransmitter();

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 2,
                errorCodes: new[] { "408", "408" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
        }
            public void AppliesTransmissionPoliciesToBeginSendingStoredTelemetry()
            {
                var transmissionPoliciesApplied = new ManualResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnApplyPolicies = () =>
                {
                    transmissionPoliciesApplied.Set();
                };
                var channel = new ServerTelemetryChannel { Transmitter = transmitter };
                channel.Initialize(TelemetryConfiguration.CreateDefault());

                var initializedConfiguration = new TelemetryConfiguration();
                channel.Initialize(initializedConfiguration);

                Assert.True(transmissionPoliciesApplied.WaitOne(1000));
            }
            public void RetriesFailedTransmissionInfinitely()
            {
                Transmission enqueuedTransmission = null;
                var transmitter = new StubTransmitter();
                transmitter.OnEnqueue = transmission =>
                {
                    enqueuedTransmission = transmission;
                };

                var policy = new TestableErrorHandlingTransmissionPolicy();
                policy.BackOffTime = TimeSpan.FromMilliseconds(10);
                policy.Initialize(transmitter);

                var failedTransmission = new StubTransmission();
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(failedTransmission, CreateException(statusCode: 408)));
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(failedTransmission, CreateException(statusCode: 408)));
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(failedTransmission, CreateException(statusCode: 408)));
                Assert.Same(failedTransmission, enqueuedTransmission);
            }
            public void CannotParseRetryAfterWritesToEventSource()
            {
                const string UnparsableDate = "no one can parse me! :)";

                var transmitter = new StubTransmitter();
                var policy = new ThrottlingTransmissionPolicy();
                policy.Initialize(transmitter);

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

                    transmitter.OnTransmissionSent(
                        new TransmissionProcessedEventArgs(
                            new StubTransmission(),
                        CreateThrottledResponse(ResponseCodeTooManyRequests, UnparsableDate)));

                    EventWrittenEventArgs trace = listener.Messages.First(args => args.EventId == 24);
                    Assert.Equal(UnparsableDate, (string)trace.Payload[0]);
                }
            }
            public void KeepsTransmissionSenderPausedWhenAdditionalTransmissionsFail()
            {
                var transmitter = new StubTransmitter();
                var policy = new TestableErrorHandlingTransmissionPolicy();
                policy.Initialize(transmitter);
                
                policy.BackOffTime = TimeSpan.FromMilliseconds(10);
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission(), CreateException(statusCode: 408)));
                
                policy.BackOffTime = TimeSpan.FromMilliseconds(50);
                transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(new StubTransmission(), CreateException(statusCode: 408)));

                Thread.Sleep(TimeSpan.FromMilliseconds(30));

                Assert.Equal(0, policy.MaxSenderCapacity);
            }
            public void InitializeCallsTransmitterInitialize()
            {
                var transmitterInitialized = new ManualResetEvent(false);
                var transmitter = new StubTransmitter();
                transmitter.OnInitialize = () =>
                {
                    transmitterInitialized.Set();
                };
                var channel = new ServerTelemetryChannel { Transmitter = transmitter };

                var initializedConfiguration = new TelemetryConfiguration();
                channel.Initialize(initializedConfiguration);

                Assert.True(transmitterInitialized.WaitOne(1000));
            }
        public void IfMultipleItemsAreRejectedNumberOfErrorsIsIncreasedByOne()
        {
            // Number of errors determine backoff timeout.
            // When we get several bad items in one batch we want to increase errors by 1 only since it is one attempt to access Breeze

            var transmitter = new StubTransmitter();

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 100,
                itemsAccepted: 95,
                errorCodes: new[] { "500", "500", "503", "503", "429" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(1, policy.ConsecutiveErrors);
        }