public async Task RunAndBlock_SetsLastError_WhenExceptionIsThrown()
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = @"TestScripts\Empty"
            };

            var factoryMock       = new Mock <IScriptHostFactory>();
            var scriptHostFactory = new TestScriptHostFactory()
            {
                Throw = true
            };
            var  hostManager = new ScriptHostManager(config, _settingsManager, scriptHostFactory);
            Task taskIgnore  = Task.Run(() => hostManager.RunAndBlock());

            // we expect a host exception immediately
            await Task.Delay(2000);

            Assert.Equal(ScriptHostState.Error, hostManager.State);
            Assert.False(hostManager.CanInvoke());
            Assert.NotNull(hostManager.LastError);
            Assert.Equal("Kaboom!", hostManager.LastError.Message);

            // now verify that if no error is thrown on the next iteration
            // the cached error is cleared
            scriptHostFactory.Throw = false;
            await TestHelpers.Await(() =>
            {
                return(hostManager.State == ScriptHostState.Running);
            });

            Assert.Null(hostManager.LastError);
            Assert.True(hostManager.CanInvoke());
            Assert.Equal(ScriptHostState.Running, hostManager.State);
        }
        public async Task RunAndBlock_ParseError_LogsError()
        {
            TestLoggerProvider        loggerProvider = new TestLoggerProvider();
            TestLoggerProviderFactory factory        = new TestLoggerProviderFactory(loggerProvider, includeDefaultLoggerProviders: false);

            string rootPath = Path.Combine(Environment.CurrentDirectory, "ScriptHostTests");

            if (!Directory.Exists(rootPath))
            {
                Directory.CreateDirectory(rootPath);
            }

            var configPath = Path.Combine(rootPath, "host.json");

            File.WriteAllText(configPath, @"{<unparseable>}");

            var config = new ScriptHostConfiguration()
            {
                RootScriptPath = rootPath
            };

            config.HostConfig.HostId = ID;

            var  scriptHostFactory = new TestScriptHostFactory();
            var  eventManagerMock  = new Mock <IScriptEventManager>();
            var  hostManager       = new ScriptHostManager(config, _settingsManager, scriptHostFactory, eventManagerMock.Object, loggerProviderFactory: factory);
            Task taskIgnore        = Task.Run(() => hostManager.RunAndBlock());

            await TestHelpers.Await(() => hostManager.State == ScriptHostState.Error, 3000, 50);

            Assert.Equal(ScriptHostState.Error, hostManager.State);

            hostManager.Stop();

            var ex = hostManager.LastError;

            Assert.True(ex is FormatException);
            var expectedMessage = $"Unable to parse host configuration file '{configPath}'.";

            Assert.Equal(expectedMessage, ex.Message);

            var logger     = loggerProvider.CreatedLoggers.Last();
            var logMessage = logger.GetLogMessages()[0];

            Assert.StartsWith("A ScriptHost error has occurred", logMessage.FormattedMessage);
            Assert.Equal(expectedMessage, logMessage.Exception.Message);
        }
        public async Task RunAndBlock_HostJsonValueError_LogsError()
        {
            // Try to load valid host.json file that has an out-of-range value.
            // Ensure that it's logged to ILogger

            string rootPath = Path.Combine(Environment.CurrentDirectory, @"TestScripts\OutOfRange");

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = rootPath
            };

            TestLoggerProvider provider = new TestLoggerProvider();
            var loggerProviderFactory   = new TestLoggerProviderFactory(provider, includeDefaultLoggerProviders: false);

            var  factoryMock       = new Mock <IScriptHostFactory>();
            var  scriptHostFactory = new TestScriptHostFactory();
            var  eventManagerMock  = new Mock <IScriptEventManager>();
            var  hostManager       = new ScriptHostManager(config, _settingsManager, scriptHostFactory, eventManagerMock.Object, loggerProviderFactory: loggerProviderFactory);
            Task taskIgnore        = Task.Run(() => hostManager.RunAndBlock());

            await TestHelpers.Await(() => hostManager.State == ScriptHostState.Error, 3000, 50);

            Assert.Equal(ScriptHostState.Error, hostManager.State);
            Assert.False(hostManager.CanInvoke());

            hostManager.Stop();
            var ex = hostManager.LastError;

            Assert.True(ex is ArgumentOutOfRangeException);

            string msg = "A ScriptHost error has occurred";

            var startupLogger = provider.CreatedLoggers.Last();
            var loggerMessage = startupLogger.GetLogMessages().First();

            Assert.Equal(msg, loggerMessage.FormattedMessage);
            Assert.Same(ex, loggerMessage.Exception);
        }
        public async Task RunAndBlock_SetsLastError_WhenExceptionIsThrown()
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = @"TestScripts\Empty"
            };

            var factoryMock = new Mock<IScriptHostFactory>();
            var scriptHostFactory = new TestScriptHostFactory()
            {
                Throw = true
            };
            var hostManager = new ScriptHostManager(config, _settingsManager, scriptHostFactory);
            Task taskIgnore = Task.Run(() => hostManager.RunAndBlock());

            // we expect a host exception immediately
            await Task.Delay(2000);

            Assert.Equal(ScriptHostState.Error, hostManager.State);
            Assert.False(hostManager.CanInvoke());
            Assert.NotNull(hostManager.LastError);
            Assert.Equal("Kaboom!", hostManager.LastError.Message);

            // now verify that if no error is thrown on the next iteration
            // the cached error is cleared
            scriptHostFactory.Throw = false;
            await TestHelpers.Await(() =>
            {
                return hostManager.State == ScriptHostState.Running;
            });

            Assert.Null(hostManager.LastError);
            Assert.True(hostManager.CanInvoke());
            Assert.Equal(ScriptHostState.Running, hostManager.State);
        }