Example #1
0
        public async Task EmptyHost_StartsSuccessfully()
        {
            string functionDir = Path.Combine(TestHelpers.FunctionsTestDirectory, "Functions", Guid.NewGuid().ToString());

            Directory.CreateDirectory(functionDir);

            // important for the repro that this directory does not exist
            string logDir = Path.Combine(TestHelpers.FunctionsTestDirectory, "Logs", Guid.NewGuid().ToString());

            JObject hostConfig = new JObject
            {
                { "id", "123456" }
            };

            File.WriteAllText(Path.Combine(functionDir, ScriptConstants.HostMetadataFileName), hostConfig.ToString());

            ScriptHostConfiguration config = new ScriptHostConfiguration
            {
                RootScriptPath  = functionDir,
                RootLogPath     = logDir,
                FileLoggingMode = FileLoggingMode.Always
            };

            var eventManagerMock          = new Mock <IScriptEventManager>();
            ScriptHostManager hostManager = new ScriptHostManager(config, eventManagerMock.Object);

            // start the host and wait for it to be running
            Task runTask = Task.Run(() => hostManager.RunAndBlock());
            await TestHelpers.Await(() => hostManager.State == ScriptHostState.Running, timeout : 10000);

            // exercise restart
            hostManager.RestartHost();
            Assert.Equal(ScriptHostState.Default, hostManager.State);
            await TestHelpers.Await(() => hostManager.State == ScriptHostState.Running, timeout : 10000);

            // stop the host fully
            hostManager.Stop();
            Assert.Equal(ScriptHostState.Default, hostManager.State);

            await Task.Delay(FileTraceWriter.LogFlushIntervalMs);

            string hostLogFilePath = Directory.EnumerateFiles(Path.Combine(logDir, "Host")).Single();
            string hostLogs        = File.ReadAllText(hostLogFilePath);

            Assert.Contains("Generating 0 job function(s)", hostLogs);
            Assert.Contains("No job functions found.", hostLogs);
            Assert.Contains("Job host started", hostLogs);
            Assert.Contains("Job host stopped", hostLogs);
        }
Example #2
0
        public async Task RenameFunctionAndRestart()
        {
            var oldDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestScripts/Node/TimerTrigger");
            var newDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestScripts/Node/MovedTrigger");

            CancellationTokenSource cts = new CancellationTokenSource();
            var fixture = new NodeEndToEndTests.TestFixture();
            await fixture.Host.StopAsync();

            var config = fixture.Host.ScriptConfig;

            var blob = fixture.TestOutputContainer.GetBlockBlobReference("testblob");

            ExceptionDispatchInfo exception = null;
            var mockEnvironment             = new Mock <IScriptHostEnvironment>();

            using (var eventManager = new ScriptEventManager())
                using (var manager = new ScriptHostManager(config, eventManager, mockEnvironment.Object))
                    using (var resetEvent = new ManualResetEventSlim())
                    {
                        mockEnvironment.Setup(e => e.RestartHost())
                        .Callback(() =>
                        {
                            resetEvent.Set();
                            manager.RestartHost();
                        });

                        // Background task to run while the main thread is pumping events at RunAndBlock().
                        Thread t = new Thread(_ =>
                        {
                            // don't start until the manager is running
                            TestHelpers.Await(() => manager.State == ScriptHostState.Running).Wait();

                            try
                            {
                                // Wait for initial execution.
                                TestHelpers.Await(async() =>
                                {
                                    bool exists = await blob.ExistsAsync();
                                    return(exists);
                                }, timeout: 10 * 1000).Wait();

                                // find __dirname from blob
                                string text;
                                using (var stream = new MemoryStream())
                                {
                                    blob.DownloadToStreamAsync(stream).Wait();
                                    text = System.Text.Encoding.UTF8.GetString(stream.ToArray());
                                }

                                Assert.Contains("TimerTrigger", text);

                                // rename directory & delete old blob
                                Directory.Move(oldDirectory, newDirectory);

                                resetEvent.Wait(TimeSpan.FromSeconds(10));

                                blob.DeleteIfExistsAsync();

                                // wait for newly executed
                                TestHelpers.Await(async() =>
                                {
                                    bool exists = await blob.ExistsAsync();
                                    return(exists);
                                }, timeout: 30 * 1000).Wait();

                                using (var stream = new MemoryStream())
                                {
                                    blob.DownloadToStreamAsync(stream).Wait();
                                    text = System.Text.Encoding.UTF8.GetString(stream.ToArray());
                                }

                                Assert.Contains("MovedTrigger", text);
                            }
                            catch (Exception ex)
                            {
                                exception = ExceptionDispatchInfo.Capture(ex);
                            }
                            finally
                            {
                                try
                                {
                                    Directory.Move(newDirectory, oldDirectory);
                                }
                                catch
                                {
                                }
                            }

                            cts.Cancel();
                        });
                        t.Start();

                        manager.RunAndBlock(cts.Token);

                        t.Join();

                        Assert.True(exception == null, exception?.SourceException?.ToString());
                    }
        }
        public async Task RenameFunctionAndRestart()
        {
            var oldDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestScripts/Node/TimerTrigger");
            var newDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestScripts/Node/MovedTrigger");

            var fixture = new NodeScriptHostTests.TestFixture(false);
            var config  = fixture.Host.ScriptConfig;

            config.OnConfigurationApplied = c =>
            {
                c.Functions = new Collection <string> {
                    "TimerTrigger", "MovedTrigger"
                };
            };

            var blob = fixture.TestOutputContainer.GetBlockBlobReference("testblob");
            await blob.DeleteIfExistsAsync();

            var mockEnvironment = new Mock <IScriptHostEnvironment>();

            using (var eventManager = new ScriptEventManager())
                using (var manager = new ScriptHostManager(config, eventManager, mockEnvironment.Object))
                    using (var resetEvent = new ManualResetEventSlim())
                    {
                        List <Exception> exceptions = new List <Exception>();

                        mockEnvironment.Setup(e => e.RestartHost())
                        .Callback(() =>
                        {
                            resetEvent.Set();
                            manager.RestartHost();
                        });

                        // Background task to run while the main thread is pumping events at RunAndBlock().
                        Thread backgroundThread = new Thread(_ =>
                        {
                            try
                            {
                                // don't start until the manager is running
                                TestHelpers.Await(() => manager.State == ScriptHostState.Running,
                                                  userMessageCallback: () => "Host did not start in time.").GetAwaiter().GetResult();

                                // Wait for initial execution.
                                TestHelpers.Await(async() =>
                                {
                                    bool exists = await blob.ExistsAsync();
                                    return(exists);
                                }, timeout: 10 * 1000,
                                                  userMessageCallback: () => $"Blob '{blob.Uri}' was not created by 'TimerTrigger' in time.").GetAwaiter().GetResult();

                                // find __dirname from blob
                                string text;
                                using (var stream = new MemoryStream())
                                {
                                    blob.DownloadToStreamAsync(stream).Wait();
                                    text = System.Text.Encoding.UTF8.GetString(stream.ToArray());
                                }

                                Assert.Contains("TimerTrigger", text);

                                // rename directory & delete old blob
                                Directory.Move(oldDirectory, newDirectory);

                                resetEvent.Wait(TimeSpan.FromSeconds(10));

                                blob.DeleteIfExistsAsync().GetAwaiter().GetResult();

                                // wait for newly executed
                                TestHelpers.Await(async() =>
                                {
                                    bool exists = await blob.ExistsAsync();
                                    return(exists);
                                }, timeout: 30 * 1000,
                                                  userMessageCallback: () => $"Blob '{blob.Uri}' was not created by 'MovedTrigger' in time.").GetAwaiter().GetResult();

                                using (var stream = new MemoryStream())
                                {
                                    blob.DownloadToStreamAsync(stream).Wait();
                                    text = System.Text.Encoding.UTF8.GetString(stream.ToArray());
                                }

                                Assert.Contains("MovedTrigger", text);

                                // The TimerTrigger can fire before the host is fully started. To be more
                                // reliably clean up the test, wait until it is running before calling Stop.
                                TestHelpers.Await(() => manager.State == ScriptHostState.Running).GetAwaiter().GetResult();
                            }
                            catch (Exception ex)
                            {
                                exceptions.Add(ex);
                            }
                            finally
                            {
                                try
                                {
                                    manager.Stop();
                                }
                                catch (Exception ex)
                                {
                                    exceptions.Add(ex);
                                }
                            }
                        });

                        try
                        {
                            backgroundThread.Start();
                            manager.RunAndBlock();
                            Assert.True(backgroundThread.Join(60000), "The background task did not complete in 60 seconds.");

                            string exceptionString = string.Join(Environment.NewLine, exceptions.Select(p => p.ToString()));
                            Assert.True(exceptions.Count() == 0, exceptionString);
                        }
                        finally
                        {
                            // Move the directory back after the host has stopped to prevent
                            // unnecessary host restarts
                            if (Directory.Exists(newDirectory))
                            {
                                Directory.Move(newDirectory, oldDirectory);
                            }
                        }
                    }
        }