public void CallbackUri_ForcesStrategy(LocalServerCodeReceiver.CallbackUriChooserStrategy strategy, string expectedTemplate)
        {
            MockClock clock   = new MockClock(DateTime.UtcNow);
            TimeSpan  timeout = TimeSpan.FromMinutes(1);
            // Make the template that should be forced, fail on the listener check.
            Func <string, bool> listenerFails = u => u == expectedTemplate;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            var uri1 = chooser.GetUriTemplate(strategy);

            // Even after time out
            clock.UtcNow = clock.UtcNow.AddMinutes(2);

            var uri2 = chooser.GetUriTemplate(strategy);

            // Even if a failure is reported, it succeeded at least once
            // so the failure is transient.
            chooser.ReportFailure(expectedTemplate);

            var uri3 = chooser.GetUriTemplate(strategy);

            Assert.Equal(expectedTemplate, uri1);
            Assert.Equal(expectedTemplate, uri2);
            Assert.Equal(expectedTemplate, uri3);
        }
        public void CallbackUri_TimeoutPreferredForRetries()
        {
            MockClock           clock         = new MockClock(DateTime.UtcNow);
            TimeSpan            timeout       = TimeSpan.FromMinutes(1);
            Func <string, bool> listenerFails = u => u == CallbackUriTemplate127001;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            // Loopback IP failed so this one is localhost.
            var uri1 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            // Make localhost time out.
            clock.UtcNow = clock.UtcNow.AddMinutes(2);
            // This one should still be localhost, which was timed out
            // vs loopback which was failed. And they have the same amount of reuses.
            var uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            // Make it time out again.
            clock.UtcNow = clock.UtcNow.AddMinutes(2);
            // And now this should be loopback, it had less reuse.
            var uri3 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            Assert.Equal(CallbackUriTemplateLocalhost, uri1);
            Assert.Equal(CallbackUriTemplateLocalhost, uri2);

            Assert.Equal(CallbackUriTemplate127001, uri3);
        }
        public void CallbackUri_BothTimeout()
        {
            MockClock clock   = new MockClock(DateTime.UtcNow);
            TimeSpan  timeout = TimeSpan.FromMinutes(1);
            // All uris are good.
            Func <string, bool> listenerFails = u => false;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            // They should alternate based on the amount of reuse.
            var uri1 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            clock.UtcNow = clock.UtcNow.AddMinutes(2);
            var uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            clock.UtcNow = clock.UtcNow.AddMinutes(2);
            var uri3 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            clock.UtcNow = clock.UtcNow.AddMinutes(2);
            var uri4 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            clock.UtcNow = clock.UtcNow.AddMinutes(2);

            Assert.Equal(CallbackUriTemplate127001, uri1);
            Assert.Equal(CallbackUriTemplate127001, uri3);

            Assert.Equal(CallbackUriTemplateLocalhost, uri2);
            Assert.Equal(CallbackUriTemplateLocalhost, uri4);
        }
        public void CallbackUri_LoopbackReportedSuccess()
        {
            MockClock clock   = new MockClock(DateTime.UtcNow);
            TimeSpan  timeout = TimeSpan.FromMinutes(1);
            // All uris are good.
            Func <string, bool> listenerFails = u => false;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            var uri = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            chooser.ReportSuccess(CallbackUriTemplate127001);

            var uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            Assert.Equal(CallbackUriTemplate127001, uri2);

            // Even after time out
            clock.UtcNow = clock.UtcNow.AddMinutes(2);

            uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);
            Assert.Equal(CallbackUriTemplate127001, uri2);

            // Even if a failure is reported, it succeeded at least once
            // so the failure is transient.
            chooser.ReportFailure(CallbackUriTemplate127001);

            uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);
            Assert.Equal(CallbackUriTemplate127001, uri2);
        }
        public void CallbackUri_LoopbackListenerFails()
        {
            MockClock           clock         = new MockClock(DateTime.UtcNow);
            TimeSpan            timeout       = TimeSpan.FromMinutes(1);
            Func <string, bool> listenerFails = u => u == CallbackUriTemplate127001;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            var uri = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            Assert.Equal(CallbackUriTemplateLocalhost, uri);
        }
        public void CallbackUri_PrefersLoopback()
        {
            MockClock clock   = new MockClock(DateTime.UtcNow);
            TimeSpan  timeout = TimeSpan.FromMinutes(1);
            // All uris are good.
            Func <string, bool> listenerFails = u => false;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            var uri = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            Assert.Equal(CallbackUriTemplate127001, uri);
        }
        public void CallbackUri_LoopbackReportedFailure()
        {
            MockClock clock   = new MockClock(DateTime.UtcNow);
            TimeSpan  timeout = TimeSpan.FromMinutes(1);
            // All uris are good.
            Func <string, bool> listenerFails = u => false;

            var chooser = new LocalServerCodeReceiver.CallbackUriChooser(clock, timeout, listenerFails);

            // This one should be loopback.
            var uri = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            chooser.ReportFailure(CallbackUriTemplate127001);

            var uri2 = chooser.GetUriTemplate(LocalServerCodeReceiver.CallbackUriChooserStrategy.Default);

            Assert.Equal(CallbackUriTemplateLocalhost, uri2);
        }