示例#1
0
        public async Task SetupAsync()
        {
            ScriptPath       = Path.Combine(GetCSharpSamplePath(), BenchmarkTrigger, "run.csx");
            ScriptSource     = File.ReadAllText(ScriptPath);
            FunctionMetadata = new FunctionMetadata()
            {
                FunctionDirectory = Path.GetDirectoryName(ScriptPath),
                ScriptFile        = ScriptPath,
                Name     = BenchmarkTrigger,
                Language = DotNetScriptTypes.CSharp
            };

            Resolver           = new ScriptFunctionMetadataResolver(ScriptPath, Array.Empty <IScriptBindingProvider>(), NullLogger.Instance);
            CompilationService = new CSharpCompilationService(Resolver, OptimizationLevel.Release);

            ScriptCompilation = await CompilationService.GetFunctionCompilationAsync(FunctionMetadata);

            ScriptAssembly = await ScriptCompilation.EmitAsync(default);
示例#2
0
        public async Task GetFunctionTargetAsync_CompilationError_ReportsResults()
        {
            // Create the compilation exception we expect to throw
            var descriptor = new DiagnosticDescriptor(DotNetConstants.MissingFunctionEntryPointCompilationCode,
                                                      "Test compilation exception", "Test compilation error", "AzureFunctions", DiagnosticSeverity.Error, true);
            var exception = new CompilationErrorException("Test compilation exception", ImmutableArray.Create(Diagnostic.Create(descriptor, Location.None)));

            // Create the invoker dependencies and setup the appropriate method to throw the exception
            RunDependencies dependencies = CreateDependencies();

            dependencies.Compilation.Setup(c => c.GetEntryPointSignature(It.IsAny <IFunctionEntryPointResolver>(), It.IsAny <Assembly>()))
            .Throws(exception);
            dependencies.Compilation.Setup(c => c.EmitAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(DotNetCompilationResult.FromPath(typeof(DotNetFunctionInvokerTests).Assembly.Location));

            string functionName        = Guid.NewGuid().ToString();
            string rootFunctionsFolder = Path.Combine(Path.GetTempPath(), functionName);

            Directory.CreateDirectory(rootFunctionsFolder);

            // Create a dummy file to represent our function
            string filePath = Path.Combine(rootFunctionsFolder, Guid.NewGuid().ToString() + ".csx");

            File.WriteAllText(filePath, string.Empty);

            var metadata = new FunctionMetadata
            {
                ScriptFile        = filePath,
                FunctionDirectory = Path.GetDirectoryName(filePath),
                Name     = functionName,
                Language = DotNetScriptTypes.CSharp
            };

            metadata.Bindings.Add(new BindingMetadata()
            {
                Name = "Test", Type = "ManualTrigger"
            });

            var invoker = new DotNetFunctionInvoker(dependencies.Host, metadata, new Collection <FunctionBinding>(), new Collection <FunctionBinding>(),
                                                    dependencies.EntrypointResolver.Object, dependencies.CompilationServiceFactory.Object, dependencies.LoggerFactory, dependencies.MetricsLogger,
                                                    new Collection <IScriptBindingProvider>());

            // Send file change notification to trigger a reload
            var fileEventArgs = new FileSystemEventArgs(WatcherChangeTypes.Changed, Path.GetTempPath(), Path.Combine(Path.GetFileName(rootFunctionsFolder), Path.GetFileName(filePath)));

            dependencies.Host.EventManager.Publish(new FileEvent(EventSources.ScriptFiles, fileEventArgs));

            LogMessage[] logMessages    = null;
            var          loggerProvider = dependencies.LoggerProvider;
            await TestHelpers.Await(() =>
            {
                logMessages = loggerProvider.GetAllLogMessages().ToArray();

                return(logMessages.Any(t => t.FormattedMessage.Contains("Compilation failed.")) &&
                       logMessages.Any(t => t.FormattedMessage.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode)));
            });

            // verify expected logs when the function target is retrieved
            // NOT on the invocation path
            dependencies.LoggerProvider.ClearAllLogMessages();
            await Assert.ThrowsAsync <CompilationErrorException>(async() =>
            {
                await invoker.GetFunctionTargetAsync();
            });

            Assert.Equal(3, logMessages.Length);
            Assert.Equal($"Script for function '{functionName}' changed. Reloading.", logMessages[0].FormattedMessage);
            Assert.Equal(LogLevel.Information, logMessages[0].Level);
            Assert.Equal("error AF001: Test compilation error", logMessages[1].FormattedMessage);
            Assert.Equal(LogLevel.Error, logMessages[1].Level);
            Assert.True(logMessages[1].State.Any(q => q.Key == ScriptConstants.LogPropertyIsUserLogKey));
            Assert.Equal("Compilation failed.", logMessages[2].FormattedMessage);
            Assert.Equal(LogLevel.Information, logMessages[2].Level);
            Assert.True(logMessages.All(p => p.State.Any(q => q.Key == ScriptConstants.LogPropertyPrimaryHostKey)));

            await TestHelpers.Await(() =>
            {
                logMessages = loggerProvider.GetAllLogMessages().ToArray();

                return(logMessages.Any(t => t.FormattedMessage.Contains("Function compilation error")) &&
                       logMessages.Any(t => t.FormattedMessage.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode)));
            });

            // now test the invoke path and verify that the compilation error
            // details are written
            loggerProvider.ClearAllLogMessages();
            await Assert.ThrowsAsync <CompilationErrorException>(async() =>
            {
                await invoker.GetFunctionTargetAsync(isInvocation: true);
            });

            logMessages = loggerProvider.GetAllLogMessages().ToArray();
            Assert.Equal(2, logMessages.Length);
            Assert.Equal("Function compilation error", logMessages[0].FormattedMessage);
            Assert.Equal(LogLevel.Error, logMessages[0].Level);
            Assert.Same("Test compilation exception", logMessages[0].Exception.Message);
            Assert.Equal("error AF001: Test compilation error", logMessages[1].FormattedMessage);
            Assert.Equal(LogLevel.Error, logMessages[1].Level);
            Assert.True(logMessages[1].State.Any(q => q.Key == ScriptConstants.LogPropertyIsUserLogKey));
            Assert.True(logMessages.All(p => !(p.State != null && p.State.Any(q => q.Key == ScriptConstants.LogPropertyPrimaryHostKey))));
        }
        public async Task ReloadScript_WithInvalidCompilationAndMissingMethod_ReportsResults()
        {
            // Create the compilation exception we expect to throw during the reload
            var descriptor = new DiagnosticDescriptor(DotNetConstants.MissingFunctionEntryPointCompilationCode,
                                                      "Test compilation exception", "Test compilation error", "AzureFunctions", DiagnosticSeverity.Error, true);
            var exception = new CompilationErrorException("Test compilation exception", ImmutableArray.Create(Diagnostic.Create(descriptor, Location.None)));

            // Create the invoker dependencies and setup the appropriate method to throw the exception
            RunDependencies dependencies = CreateDependencies();

            dependencies.Compilation.Setup(c => c.GetEntryPointSignature(It.IsAny <IFunctionEntryPointResolver>(), It.IsAny <Assembly>()))
            .Throws(exception);
            dependencies.Compilation.Setup(c => c.EmitAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(DotNetCompilationResult.FromPath(typeof(DotNetFunctionInvokerTests).Assembly.Location));

            string functionName        = Guid.NewGuid().ToString();
            string rootFunctionsFolder = Path.Combine(Path.GetTempPath(), functionName);

            Directory.CreateDirectory(rootFunctionsFolder);

            // Create a dummy file to represent our function
            string filePath = Path.Combine(rootFunctionsFolder, Guid.NewGuid().ToString() + ".csx");

            File.WriteAllText(filePath, string.Empty);

            var metadata = new FunctionMetadata
            {
                ScriptFile        = filePath,
                FunctionDirectory = Path.GetDirectoryName(filePath),
                Name       = functionName,
                ScriptType = ScriptType.CSharp
            };

            metadata.Bindings.Add(new BindingMetadata()
            {
                Name = "Test", Type = "ManualTrigger"
            });

            var invoker = new DotNetFunctionInvoker(dependencies.Host.Object, metadata, new Collection <Script.Binding.FunctionBinding>(),
                                                    new Collection <FunctionBinding>(), dependencies.EntrypointResolver.Object, dependencies.CompilationServiceFactory.Object);

            // Send file change notification to trigger a reload
            var fileEventArgs = new FileSystemEventArgs(WatcherChangeTypes.Changed, Path.GetTempPath(), Path.Combine(Path.GetFileName(rootFunctionsFolder), Path.GetFileName(filePath)));

            dependencies.Host.Object.EventManager.Publish(new FileEvent(EventSources.ScriptFiles, fileEventArgs));

            await TestHelpers.Await(() =>
            {
                IEnumerable <LogMessage> logMessages = dependencies.LoggerProvider.GetAllLogMessages();

                return(logMessages.Any(t => t.FormattedMessage.Contains("Compilation failed.")) &&
                       logMessages.Any(t => t.FormattedMessage.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode)));
            });

            dependencies.LoggerProvider.ClearAllLogMessages();

            CompilationErrorException resultException = await Assert.ThrowsAsync <CompilationErrorException>(() => invoker.GetFunctionTargetAsync());

            await TestHelpers.Await(() =>
            {
                IEnumerable <LogMessage> logMessages = dependencies.LoggerProvider.GetAllLogMessages();

                return(logMessages.Any(t => t.FormattedMessage.Contains("Function compilation error")) &&
                       logMessages.Any(t => t.FormattedMessage.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode)));
            });
        }