public async Task FunctionListener_DoesNotThrow_IfHandled() { HandlingTraceWriter trace = new HandlingTraceWriter(TraceLevel.Error, (te) => (te.Exception as RecoverableException).Handled = true); Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Throws(new Exception("listener")); var listener = new FunctionListener(badListener.Object, fd, trace, _loggerFactory); await listener.StartAsync(ct); string expectedMessage = "The listener for function 'testfunc' was unable to start."; // Validate TraceWriter Assert.Equal(expectedMessage, trace.Traces[0].Message); var traceEx = trace.Traces[0].Exception as FunctionException; Assert.Equal("testfunc", traceEx.MethodName); Assert.True(traceEx.Handled); // Validate Logger var logMessage = _loggerProvider.CreatedLoggers.Single().LogMessages.Single(); Assert.Equal(expectedMessage, logMessage.FormattedMessage); var loggerEx = logMessage.Exception as FunctionException; Assert.Equal("testfunc", loggerEx.MethodName); Assert.True(loggerEx.Handled); badListener.VerifyAll(); }
public async Task FunctionListener_DoesNotThrow_IfHandled() { ILoggerFactory handlingLoggerFactory = new LoggerFactory(); TestLoggerProvider handlingLoggerProvider = new TestLoggerProvider(null, (m) => (m.Exception as RecoverableException).Handled = true); handlingLoggerFactory.AddProvider(handlingLoggerProvider); Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Throws(new Exception("listener")); var listener = new FunctionListener(badListener.Object, fd, handlingLoggerFactory); await listener.StartAsync(ct); string expectedMessage = "The listener for function 'testfunc' was unable to start."; // Validate Logger var logMessage = handlingLoggerProvider.CreatedLoggers.Single().LogMessages.Single(); Assert.Equal(expectedMessage, logMessage.FormattedMessage); var loggerEx = logMessage.Exception as FunctionException; Assert.Equal("testfunc", loggerEx.MethodName); Assert.True(loggerEx.Handled); badListener.VerifyAll(); }
public async Task FunctionListener_DoesNotStop_IfNotStarted() { ILoggerFactory handlingLoggerFactory = new LoggerFactory(); TestLoggerProvider handlingLoggerProvider = new TestLoggerProvider(null, (m) => (m.Exception as RecoverableException).Handled = true); handlingLoggerFactory.AddProvider(handlingLoggerProvider); Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Throws(new Exception("listener")); var listener = new FunctionListener(badListener.Object, fd, handlingLoggerFactory); await listener.StartAsync(ct); // these should do nothing, as function listener had an exception on start await listener.StopAsync(ct); await listener.StopAsync(ct); await listener.StopAsync(ct); // ensure that badListener.StopAsync is not called on a disabled function listener badListener.VerifyAll(); }
public async Task FunctionListener_ConcurrentStartStop_ListenerIsStopped() { Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); var listener = new FunctionListener(badListener.Object, fd, _loggerFactory, allowPartialHostStartup: true, minRetryInterval: TimeSpan.FromMilliseconds(10), maxRetryInterval: TimeSpan.FromMilliseconds(100)); int count = 0; badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Returns(async() => { count++; if (count == 1) { // initiate the restart loop by falling on the first attemt throw new Exception("Listener Exploded!"); } else if (count == 2) { // while we're in the retry loop simulate a concurrent stop by // invoking stop ourselves await listener.StopAsync(ct); } else { // shouldn't get to here } }); bool stopCalled = false; badListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())) .Callback(() => stopCalled = true) .Returns(Task.CompletedTask); await listener.StartAsync(ct); await TestHelpers.Await(() => { return(Task.FromResult(stopCalled)); }, timeout : 4000, userMessageCallback : () => "Listener not stopped."); badListener.Verify(p => p.StartAsync(It.IsAny <CancellationToken>()), Times.Exactly(2)); badListener.Verify(p => p.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(1)); Assert.Collection(_loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage), p => Assert.Equal("The listener for function 'testfunc' was unable to start.", p), p => Assert.Equal("Retrying to start listener for function 'testfunc' (Attempt 1)", p), p => Assert.Equal("Listener successfully started for function 'testfunc' after 1 retries.", p), p => Assert.Equal("Listener for function 'testfunc' stopped. A stop was initiated while starting.", p)); // make sure the retry loop is not running await Task.Delay(1000); Assert.Equal(2, count); }
public async Task FunctionListener_RetriesOnListenerFailure_WhenPartialHostStartupEnabled() { Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); int failureCount = 0; badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Callback <CancellationToken>((ct) => { if (failureCount++ < 3) { throw new Exception("Listener Exploded!"); } }) .Returns(Task.CompletedTask); badListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var listener = new FunctionListener(badListener.Object, fd, _loggerFactory, allowPartialHostStartup: true, minRetryInterval: TimeSpan.FromMilliseconds(10), maxRetryInterval: TimeSpan.FromMilliseconds(100)); // we should return right away with the listener // attempting to restart in the background await listener.StartAsync(ct); string[] logs = null; await TestHelpers.Await(() => { logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray(); return(logs.Last() == "Listener successfully started for function 'testfunc' after 3 retries."); }); badListener.Verify(p => p.StartAsync(It.IsAny <CancellationToken>()), Times.Exactly(4)); var validators = new Action <string>[] { p => Assert.Equal("The listener for function 'testfunc' was unable to start.", p), p => Assert.Equal("Retrying to start listener for function 'testfunc' (Attempt 1)", p), p => Assert.Equal("The listener for function 'testfunc' was unable to start.", p), p => Assert.Equal("Retrying to start listener for function 'testfunc' (Attempt 2)", p), p => Assert.Equal("The listener for function 'testfunc' was unable to start.", p), p => Assert.Equal("Retrying to start listener for function 'testfunc' (Attempt 3)", p), p => Assert.Equal("Listener successfully started for function 'testfunc' after 3 retries.", p) }; Assert.Collection(logs, validators); await listener.StopAsync(ct); badListener.Verify(p => p.StopAsync(It.IsAny <CancellationToken>()), Times.Once()); }
public async Task FunctionListener_RunsStop_IfStarted() { Mock <IListener> goodListener = new Mock <IListener>(MockBehavior.Strict); goodListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Returns(Task.FromResult(false)); goodListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())) .Returns(Task.FromResult(false)); var listener = new FunctionListener(goodListener.Object, fd, _loggerFactory); await listener.StartAsync(ct); await listener.StopAsync(ct); Assert.Empty(_loggerProvider.CreatedLoggers.Single().LogMessages); goodListener.VerifyAll(); }
public async Task FunctionListener_RunsStop_IfStarted() { HandlingTraceWriter trace = new HandlingTraceWriter(TraceLevel.Error, (te) => (te.Exception as RecoverableException).Handled = true); Mock <IListener> goodListener = new Mock <IListener>(MockBehavior.Strict); goodListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Returns(Task.FromResult(false)); goodListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())) .Returns(Task.FromResult(false)); var listener = new FunctionListener(goodListener.Object, fd, trace, _loggerFactory); await listener.StartAsync(ct); await listener.StopAsync(ct); Assert.Empty(trace.Traces); Assert.Empty(_loggerProvider.CreatedLoggers.Single().LogMessages); goodListener.VerifyAll(); }
public async Task FunctionListener_DoesNotStop_IfNotStarted() { HandlingTraceWriter trace = new HandlingTraceWriter(TraceLevel.Error, (te) => (te.Exception as RecoverableException).Handled = true); Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Throws(new Exception("listener")); var listener = new FunctionListener(badListener.Object, fd, trace, _loggerFactory); await listener.StartAsync(ct); // these should do nothing, as function listener had an exception on start await listener.StopAsync(ct); await listener.StopAsync(ct); await listener.StopAsync(ct); // ensure that badListener.StopAsync is not called on a disabled function listener badListener.VerifyAll(); }
public async Task StopAsync_MultipleConcurrentRequests_InnerListenerStoppedOnce() { Mock <IListener> innerListener = new Mock <IListener>(MockBehavior.Strict); var functionListener = new FunctionListener(innerListener.Object, fd, _loggerFactory); innerListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); innerListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())).Returns(async() => await Task.Delay(100)); await functionListener.StartAsync(CancellationToken.None); List <Task> tasks = new List <Task>(); for (int i = 0; i < 10; i++) { tasks.Add(functionListener.StopAsync(CancellationToken.None)); } await Task.WhenAll(tasks); innerListener.Verify(p => p.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(1)); }
private async Task RetryStopTestHelper(Func <FunctionListener, Task> action) { Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Callback <CancellationToken>((ct) => { throw new Exception("Listener Exploded!"); }) .Returns(Task.CompletedTask); badListener.Setup(bl => bl.Dispose()); badListener.Setup(bl => bl.Cancel()); badListener.Setup(bl => bl.StopAsync(It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var listener = new FunctionListener(badListener.Object, fd, _loggerFactory, allowPartialHostStartup: true, minRetryInterval: TimeSpan.FromMilliseconds(10), maxRetryInterval: TimeSpan.FromMilliseconds(100)); await listener.StartAsync(ct); // wait until we're sure the retry task is running string[] logs = null; await TestHelpers.Await(() => { logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray(); return(logs.Any(p => p.Contains("Retrying to start listener"))); }); // initiate the action which should stop the retry task await action(listener); // take a count before and after a delay to make sure the // task is no longer running int prevRetryCount = _loggerProvider.GetAllLogMessages().Count(p => p.FormattedMessage.Contains("Retrying to start listener")); await Task.Delay(1000); int retryCount = _loggerProvider.GetAllLogMessages().Count(p => p.FormattedMessage.Contains("Retrying to start listener")); Assert.Equal(prevRetryCount, retryCount); }
public async Task FunctionListener_Throws_IfUnhandledListenerExceptionOnStartAsync() { var trace = new TestTraceWriter(TraceLevel.Error); Mock <IListener> badListener = new Mock <IListener>(MockBehavior.Strict); badListener.Setup(bl => bl.StartAsync(It.IsAny <CancellationToken>())) .Throws(new Exception("listener")); var listener = new FunctionListener(badListener.Object, fd, trace, _loggerFactory); var e = await Assert.ThrowsAsync <FunctionListenerException>(async() => await listener.StartAsync(ct)); // Validate TraceWriter var traceEx = trace.Traces[0].Exception as FunctionException; Assert.Equal("testfunc", traceEx.MethodName); Assert.False(traceEx.Handled); // Validate Logger var loggerEx = _loggerProvider.CreatedLoggers.Single().LogMessages.Single().Exception as FunctionException; Assert.Equal("testfunc", loggerEx.MethodName); Assert.False(loggerEx.Handled); badListener.VerifyAll(); }