private static ImmutableArray<PackageReference> InitializeAssemblyRegistry(FunctionMetadata metadata)
        {
            var builder = ImmutableArray<PackageReference>.Empty.ToBuilder();
            string fileName = Path.Combine(Path.GetDirectoryName(metadata.Source), CSharpConstants.ProjectLockFileName);

            if (File.Exists(fileName))
            {
                var jobject = JObject.Parse(File.ReadAllText(fileName));

                var target = jobject.SelectTokens(string.Format(CultureInfo.InvariantCulture, "$.targets['{0}']", FrameworkTargetName)).FirstOrDefault();

                if (target != null)
                {
                    string nugetHome = PackageManager.GetNugetPackagesPath();

                    foreach (JProperty token in target)
                    {
                        var referenceNameParts = token.Name.Split('/');
                        if (referenceNameParts.Length != 2)
                        {
                            throw new FormatException(string.Format(CultureInfo.InvariantCulture, "The package name '{0}' is not correctly formatted.", token.Name));
                        }

                        var package = new PackageReference(referenceNameParts[0], referenceNameParts[1]);

                        var references = token.SelectTokens("$..compile").FirstOrDefault();
                        if (references != null)
                        {
                            foreach (JProperty reference in references)
                            {
                                if (!reference.Name.EndsWith(EmptyFolderFileMarker, StringComparison.Ordinal))
                                {
                                    string path = Path.Combine(nugetHome, token.Name, reference.Name);
                                    path = path.Replace('/', '\\');

                                    if (File.Exists(path))
                                    {
                                        package.Assemblies.Add(AssemblyName.GetAssemblyName(path), path);
                                    }
                                }
                            }
                        }

                        var frameworkAssemblies = token.SelectTokens("$..frameworkAssemblies").FirstOrDefault();
                        if (frameworkAssemblies != null)
                        {
                            foreach (var assembly in frameworkAssemblies)
                            {
                                string assemblyName = assembly.ToString();
                                package.FrameworkAssemblies.Add(new AssemblyName(assemblyName), assemblyName);
                            }
                        }

                        builder.Add(package);
                    }
                }
            }

            return builder.ToImmutableArray();
        }
        public void Generate_WithMultipleOutParameters()
        {
            string functionName = "FunctionWithOuts";
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();

            parameters.Add(new ParameterDescriptor("param1", typeof(string)));
            parameters.Add(new ParameterDescriptor("param2", typeof(string).MakeByRefType()) { Attributes = ParameterAttributes.Out });
            parameters.Add(new ParameterDescriptor("param3", typeof(string).MakeByRefType()) { Attributes = ParameterAttributes.Out });

            FunctionMetadata metadata = new FunctionMetadata();
            TestInvoker invoker = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor(functionName, invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod(functionName);
            ParameterInfo[] functionParams = method.GetParameters();

            // Verify that we have the correct number of parameters
            Assert.Equal(parameters.Count, functionParams.Length);

            // Verify that out parameters were correctly generated
            Assert.True(functionParams[1].IsOut);
            Assert.True(functionParams[2].IsOut);

            // Verify that the method is invocable
            method.Invoke(null, new object[] { "test", null, null });

            // verify our custom invoker was called
            Assert.Equal(1, invoker.InvokeCount);
        }
Пример #3
0
        public void Register(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            foreach (var binding in metadata.Bindings)
            {
                request.Metadata.Bindings.Add(binding.Name, new BindingInfo
                {
                    Direction = (BindingInfo.Types.Direction)binding.Direction,
                    Type      = binding.Type
                });
            }

            Send(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        public async Task FunctionDispatcherState_Default_DotNetFunctions()
        {
            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher();

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);
            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "func1",
                Language = "dotnet"
            };
            var functions = new List <FunctionMetadata>()
            {
                func1
            };
            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);

            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);

            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);
        }
Пример #5
0
        public void ValidateFunction_ThrowsOnDuplicateName()
        {
            var httpFunctions = new Dictionary <string, HttpTriggerAttribute>();
            var name          = "test";

            // first add an http function
            var metadata  = new FunctionMetadata();
            var function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, name, null, metadata, null, null, null, null);
            var attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get");

            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);

            ScriptHost.ValidateFunction(function.Object, httpFunctions);

            // add a proxy with same name
            metadata = new FunctionMetadata()
            {
                IsProxy = true
            };
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, name, null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get")
            {
                Route = "proxyRoute"
            };
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);

            var ex = Assert.Throws <InvalidOperationException>(() =>
            {
                ScriptHost.ValidateFunction(function.Object, httpFunctions);
            });

            Assert.Equal(string.Format($"The function or proxy name '{name}' must be unique within the function app.", name), ex.Message);
        }
        internal FunctionLoadRequest GetFunctionLoadRequest(FunctionMetadata metadata, ManagedDependencyOptions managedDependencyOptions)
        {
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.GetFunctionId(),
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty,
                    IsProxy    = false
                }
            };

            if (managedDependencyOptions != null && managedDependencyOptions.Enabled)
            {
                _workerChannelLogger?.LogDebug($"Adding dependency download request to {_workerConfig.Description.Language} language worker");
                request.ManagedDependencyEnabled = managedDependencyOptions.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }
            return(request);
        }
        internal void SendFunctionLoadRequest(FunctionMetadata metadata)
        {
            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            if (_managedDependencyOptions?.Value != null && _managedDependencyOptions.Value.Enabled)
            {
                _workerChannelLogger?.LogDebug($"Adding dependency download request to {_workerConfig.Language} language worker");
                request.ManagedDependencyEnabled = _managedDependencyOptions.Value.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new InvalidOperationException("functionMetadata");
            }

            functionDescriptor = null;

            // Default the trigger binding name if a name hasn't
            // been specified
            // TODO: Remove this logic and always require it to be explicitly
            // specified?
            foreach (var binding in functionMetadata.Bindings.Where(p => p.IsTrigger))
            {
                if (string.IsNullOrEmpty(binding.Name))
                {
                    if (binding.Type == BindingType.HttpTrigger)
                    {
                        binding.Name = DefaultHttpInputParameterName;
                    }
                    else
                    {
                        binding.Name = DefaultInputParameterName;
                    }
                }
            }

            // parse the bindings
            Collection<FunctionBinding> inputBindings = FunctionBinding.GetBindings(Config, functionMetadata.InputBindings, FileAccess.Read);
            Collection<FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, functionMetadata.OutputBindings, FileAccess.Write);

            BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
          
            string scriptFilePath = Path.Combine(Config.RootScriptPath, functionMetadata.Source);

            IFunctionInvoker invoker = null;

            try
            {
                invoker = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, inputBindings, outputBindings);

                Collection<CustomAttributeBuilder> methodAttributes = new Collection<CustomAttributeBuilder>();
                Collection<ParameterDescriptor> parameters = GetFunctionParameters(invoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);

                functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes);

                return true;
            }
            catch (Exception)
            {
                IDisposable disposableInvoker = invoker as IDisposable;
                if (disposableInvoker != null)
                {
                    disposableInvoker.Dispose();
                }

                throw;
            }
        }
        internal DotNetFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
            Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings,
            IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader,
            ICompilationServiceFactory compilationServiceFactory, ITraceWriterFactory traceWriterFactory = null)
            : base(host, functionMetadata, traceWriterFactory)
        {
            _metricsLogger = Host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader = assemblyLoader;
            _metadataResolver = new FunctionMetadataResolver(functionMetadata, host.ScriptConfig.BindingProviders, TraceWriter);
            _compilationService = compilationServiceFactory.CreateService(functionMetadata.ScriptType, _metadataResolver);
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _triggerInputName = functionMetadata.Bindings.FirstOrDefault(b => b.IsTrigger).Name;

            InitializeFileWatcher();

            _resultProcessor = CreateResultProcessor();

            _functionLoader = new FunctionLoader<MethodInfo>(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
Пример #10
0
        public async Task IsFunction_ReturnsExpectedResult()
        {
            var host = TestHelpers.GetDefaultHost(o =>
            {
                o.ScriptPath = TestHelpers.FunctionsTestDirectory;
                o.LogPath    = TestHelpers.GetHostLogFileDirectory().FullName;
            });
            await host.StartAsync();

            var scriptHost = host.GetScriptHost();

            var parameters = new Collection <ParameterDescriptor>();

            parameters.Add(new ParameterDescriptor("param1", typeof(string)));
            var metadata = new FunctionMetadata();
            var invoker  = new TestInvoker();
            var function = new FunctionDescriptor("TestFunction", invoker, metadata, parameters, null, null, null);

            scriptHost.Functions.Add(function);

            var errors = new Collection <string>();

            errors.Add("A really really bad error!");
            scriptHost.FunctionErrors.Add("ErrorFunction", errors);

            Assert.True(scriptHost.IsFunction("TestFunction"));
            Assert.True(scriptHost.IsFunction("ErrorFunction"));
            Assert.False(scriptHost.IsFunction("DoesNotExist"));
            Assert.False(scriptHost.IsFunction(string.Empty));
            Assert.False(scriptHost.IsFunction(null));
        }
Пример #11
0
        internal void SendFunctionLoadRequest(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        internal CSharpFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
            Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings,
            IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader)
            : base(host, functionMetadata)
        {
            _host = host;
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader = assemblyLoader;
            _metadataResolver = new FunctionMetadataResolver(functionMetadata, TraceWriter);
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _triggerInputName = GetTriggerInputName(functionMetadata);
            _metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();

            InitializeFileWatcherIfEnabled();
            _resultProcessor = CreateResultProcessor();

            _functionValueLoader = FunctionValueLoader.Create(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
 public FunctionAssemblyLoadContext(FunctionMetadata functionMetadata, Assembly functionAssembly, IFunctionMetadataResolver resolver, TraceWriter traceWriter)
 {
     _metadataResolver = resolver;
     _loadedAssemblies = ImmutableArray<Assembly>.Empty;
     _traceWriter = traceWriter;
     FunctionAssembly = functionAssembly;
     Metadata = functionMetadata;
 }
 public FunctionMetadataResolver(FunctionMetadata metadata, TraceWriter traceWriter)
 {
     _functionMetadata = metadata;
     _traceWriter = traceWriter;
     _packageAssemblyResolver = new PackageAssemblyResolver(metadata);
     _privateAssembliesPath = GetBinDirectory(metadata);
     _scriptResolver = ScriptMetadataResolver.Default.WithSearchPaths(_privateAssembliesPath);
 }
 internal ScriptFunctionInvoker(string scriptFilePath, ScriptHost host, FunctionMetadata functionMetadata, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
     : base(host, functionMetadata)
 {
     _scriptFilePath = scriptFilePath;
     _inputBindings = inputBindings;
     _outputBindings = outputBindings;
     _metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();
 }
 internal ScriptFunctionInvoker(string scriptFilePath, ScriptHost host, FunctionMetadata functionMetadata,
     Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings, ITraceWriterFactory traceWriterFactory = null)
     : base(host, functionMetadata, traceWriterFactory)
 {
     _scriptFilePath = scriptFilePath;
     _host = host;
     _inputBindings = inputBindings;
     _outputBindings = outputBindings;
 }
 public FunctionMetadataResolver(FunctionMetadata metadata, ICollection<ScriptBindingProvider> bindingProviders, TraceWriter traceWriter)
 {
     _functionMetadata = metadata;
     _traceWriter = traceWriter;
     _packageAssemblyResolver = new PackageAssemblyResolver(metadata);
     _privateAssembliesPath = GetBinDirectory(metadata);
     _scriptResolver = ScriptMetadataResolver.Default.WithSearchPaths(_privateAssembliesPath);
     _extensionSharedAssemblyProvider = new ExtensionSharedAssemblyProvider(bindingProviders);
 }
        public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
        {
            string code = GetFunctionSource(functionMetadata);
            Script<object> script = CSharpScript.Create(code, options: _metadataResolver.CreateScriptOptions(), assemblyLoader: AssemblyLoader.Value);

            Compilation compilation = GetScriptCompilation(script, functionMetadata);

            return new CSharpCompilation(compilation);
        }
        internal void SendFunctionLoadRequest(FunctionMetadata metadata)
        {
            _workerChannelLogger.LogDebug("Sending FunctionLoadRequest for function:{functionName} with functionId:{id}", metadata.Name, metadata.FunctionId);

            // send a load request for the registered function
            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = GetFunctionLoadRequest(metadata)
            });
        }
 internal PowerShellFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
     Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings, ITraceWriterFactory traceWriterFactory = null)
     : base(host, functionMetadata, traceWriterFactory)
 {
     _host = host;
     _scriptFilePath = functionMetadata.ScriptFile;
     _functionName = functionMetadata.Name;
     _inputBindings = inputBindings;
     _outputBindings = outputBindings;
 }
        public async Task FunctionDispatcherState_Initialized_RemainsInitializing(bool setException = false)
        {
            var mockRpcWorkerChannel = new Mock <IRpcWorkerChannel>();
            var tcs = new TaskCompletionSource <IRpcWorkerChannel>();
            Dictionary <string, TaskCompletionSource <IRpcWorkerChannel> > webhostLanguageWorkerChannels = new Dictionary <string, TaskCompletionSource <IRpcWorkerChannel> >();
            Mock <IWebHostRpcWorkerChannelManager> mockWebHostChannelManager = new Mock <IWebHostRpcWorkerChannelManager>();

            mockRpcWorkerChannel.Setup(a => a.StartWorkerProcessAsync(CancellationToken.None)).Returns(Task.FromResult(true));
            mockRpcWorkerChannel.Setup(a => a.SetupFunctionInvocationBuffers(It.IsAny <IEnumerable <FunctionMetadata> >()));
            mockRpcWorkerChannel.Setup(a => a.SendFunctionLoadRequests(It.IsAny <ManagedDependencyOptions>(), It.IsAny <TimeSpan?>()));
            webhostLanguageWorkerChannels.Add("java", tcs);
            mockWebHostChannelManager.Setup(a => a.GetChannels(It.IsAny <string>())).Returns(webhostLanguageWorkerChannels);
            mockWebHostChannelManager.Setup(a => a.ShutdownChannelIfExistsAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Exception>())).Returns(Task.FromResult(true));
            if (!setException)
            {
                tcs.SetResult(mockRpcWorkerChannel.Object);
            }
            else
            {
                tcs.SetException(new Exception());
            }

            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher(addWebhostChannel: true, mockwebHostLanguageWorkerChannelManager: mockWebHostChannelManager, runtime: RpcWorkerConstants.JavaLanguageWorkerName);

            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "func1",
                Language = "node"
            };
            var functions = new List <FunctionMetadata>()
            {
                func1
            };
            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Initializing, functionDispatcher.State);

            try
            {
                await WaitForFunctionDispactherStateInitialized(functionDispatcher);
            }
            catch (Exception)
            {
                // We don't care if this times out
            }

            if (!setException)
            {
                Assert.Equal(FunctionInvocationDispatcherState.Initialized, functionDispatcher.State);
            }
            else
            {
                Assert.Equal(FunctionInvocationDispatcherState.Initializing, functionDispatcher.State);
            }
        }
        public async Task Generate_EndToEnd()
        {
            // construct our TimerTrigger attribute ([TimerTrigger("00:00:02", RunOnStartup = true)])
            Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>();
            ParameterDescriptor parameter = new ParameterDescriptor("timerInfo", typeof(TimerInfo));
            ConstructorInfo ctorInfo = typeof(TimerTriggerAttribute).GetConstructor(new Type[] { typeof(string) });
            PropertyInfo runOnStartupProperty = typeof(TimerTriggerAttribute).GetProperty("RunOnStartup");
            CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(
                ctorInfo,
                new object[] { "00:00:02" },
                new PropertyInfo[] { runOnStartupProperty },
                new object[] { true });
            parameter.CustomAttributes.Add(attributeBuilder);
            parameters.Add(parameter);

            // create the FunctionDefinition
            FunctionMetadata metadata = new FunctionMetadata();
            TestInvoker invoker = new TestInvoker();
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", invoker, metadata, parameters);
            Collection<FunctionDescriptor> functions = new Collection<FunctionDescriptor>();
            functions.Add(function);

            // Get the Type Attributes (in this case, a TimeoutAttribute)
            ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration();
            scriptConfig.FunctionTimeout = TimeSpan.FromMinutes(5);
            Collection<CustomAttributeBuilder> typeAttributes = ScriptHost.CreateTypeAttributes(scriptConfig);

            // generate the Type
            Type functionType = FunctionGenerator.Generate("TestScriptHost", "TestFunctions", typeAttributes, functions);

            // verify the generated function
            MethodInfo method = functionType.GetMethod("TimerFunction");
            TimeoutAttribute timeoutAttribute = (TimeoutAttribute)functionType.GetCustomAttributes().Single();
            Assert.Equal(TimeSpan.FromMinutes(5), timeoutAttribute.Timeout);
            Assert.True(timeoutAttribute.ThrowOnTimeout);
            Assert.True(timeoutAttribute.TimeoutWhileDebugging);
            ParameterInfo triggerParameter = method.GetParameters()[0];
            TimerTriggerAttribute triggerAttribute = triggerParameter.GetCustomAttribute<TimerTriggerAttribute>();
            Assert.NotNull(triggerAttribute);

            // start the JobHost which will start running the timer function
            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator = new TypeLocator(functionType)
            };
            config.UseTimers();
            JobHost host = new JobHost(config);

            await host.StartAsync();
            await Task.Delay(3000);
            await host.StopAsync();

            // verify our custom invoker was called
            Assert.True(invoker.InvokeCount >= 2);
        }
        internal void SendFunctionLoadRequest(FunctionMetadata metadata, ManagedDependencyOptions managedDependencyOptions)
        {
            _functionLoadRequestResponseEvent = _metricsLogger.LatencyEvent(MetricEventNames.FunctionLoadRequestResponse);
            _workerChannelLogger.LogDebug("Sending FunctionLoadRequest for function:{functionName} with functionId:{id}", metadata.Name, metadata.FunctionId);

            // send a load request for the registered function
            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = GetFunctionLoadRequest(metadata, managedDependencyOptions)
            });
        }
        public override bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            functionDescriptor = null;

            string extension = Path.GetExtension(functionMetadata.Source).ToLower();
            if (!(extension == ".js" || string.IsNullOrEmpty(extension)))
            {
                return false;
            }

            return base.TryCreate(functionMetadata, out functionDescriptor);
        }
        internal NodeFunctionInvoker(ScriptHost host, BindingMetadata trigger, FunctionMetadata functionMetadata, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
            : base(host, functionMetadata)
        {
            _trigger = trigger;
            string scriptFilePath = functionMetadata.Source.Replace('\\', '/');
            _script = string.Format(CultureInfo.InvariantCulture, _functionTemplate, scriptFilePath);
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();

            InitializeFileWatcherIfEnabled();
        }
        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>()))
                .Throws(exception);
            dependencies.Compilation.Setup(c => c.EmitAndLoad(It.IsAny<CancellationToken>()))
                .Returns(typeof(object).Assembly);

            string rootFunctionsFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            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,
                Name = Guid.NewGuid().ToString(),
                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, new FunctionAssemblyLoader(string.Empty),
                dependencies.CompilationServiceFactory.Object, dependencies.TraceWriterFactory.Object);

            // Update the file to trigger a reload
            File.WriteAllText(filePath, string.Empty);

            await TestHelpers.Await(() =>
            {
                return dependencies.TraceWriter.Traces.Any(t => t.Message.Contains("Compilation failed.")) &&
                 dependencies.TraceWriter.Traces.Any(t => t.Message.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode));
            });

            dependencies.TraceWriter.Traces.Clear();

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

            await TestHelpers.Await(() =>
            {
                return dependencies.TraceWriter.Traces.Any(t => t.Message.Contains("Function compilation error")) &&
                 dependencies.TraceWriter.Traces.Any(t => t.Message.Contains(DotNetConstants.MissingFunctionEntryPointCompilationCode));
            });
        }
 public bool IsSupported(FunctionMetadata functionMetadata, string workerRuntime)
 {
     if (string.IsNullOrEmpty(functionMetadata.Language))
     {
         return(false);
     }
     if (string.IsNullOrEmpty(workerRuntime))
     {
         return(true);
     }
     return(functionMetadata.Language.Equals(workerRuntime, StringComparison.OrdinalIgnoreCase));
 }
        public override bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            functionDescriptor = null;

            string extension = Path.GetExtension(functionMetadata.Source).ToLower();
            if (!ScriptFunctionInvoker.IsSupportedScriptType(extension))
            {
                return false;
            }

            return base.TryCreate(functionMetadata, out functionDescriptor);
        }
        // TODO: Is this function still needed? Can we factor it away?
        private static string GetTriggerInputName(FunctionMetadata functionMetadata)
        {
            BindingMetadata triggerBinding = functionMetadata.Bindings.FirstOrDefault(b => b.IsTrigger);

            string triggerName = null;
            if (triggerBinding != null)
            {
                triggerName = triggerBinding.Name;
            }

            return triggerName ?? FunctionDescriptorProvider.DefaultInputParameterName;
        }
        private static string GetFunctionSource(FunctionMetadata functionMetadata)
        {
            string code = null;

            if (File.Exists(functionMetadata.ScriptFile))
            {
                // We use ReadAllBytes here to make sure we preserve the BOM, if present.
                var codeBytes = File.ReadAllBytes(functionMetadata.ScriptFile);
                code = Encoding.UTF8.GetString(codeBytes);
            }

            return code ?? string.Empty;
        }
 public FunctionDescriptor(
     string name, 
     IFunctionInvoker invoker,
     FunctionMetadata metadata,
     Collection<ParameterDescriptor> parameters, 
     Collection<CustomAttributeBuilder> attributes)
 {
     Name = name;
     Invoker = invoker;
     Parameters = parameters;
     CustomAttributes = attributes;
     Metadata = metadata;
 }
Пример #32
0
        public static bool IsCodelessDotNetLanguageFunction(FunctionMetadata functionMetadata)
        {
            if (functionMetadata == null)
            {
                throw new ArgumentNullException(nameof(functionMetadata));
            }

            if (functionMetadata.IsCodeless() && !string.IsNullOrEmpty(functionMetadata.Language))
            {
                return(IsDotNetLanguageFunction(functionMetadata.Language));
            }
            return(false);
        }
Пример #33
0
        public void TryGetFunctionFromException_FunctionMatch()
        {
            string stack = "TypeError: Cannot read property 'is' of undefined\n" +
                           "at Timeout._onTimeout(D:\\home\\site\\wwwroot\\HttpTriggerNode\\index.js:7:35)\n" +
                           "at tryOnTimeout (timers.js:224:11)\n" +
                           "at Timer.listOnTimeout(timers.js:198:5)";
            Collection <FunctionDescriptor> functions = new Collection <FunctionDescriptor>();
            var exception = new InvalidOperationException(stack);

            // no match - empty functions
            bool result = ScriptHost.TryGetFunctionFromException(functions, exception, out FunctionDescriptor functionResult);

            Assert.False(result);
            Assert.Null(functionResult);

            // no match - one non-matching function
            FunctionMetadata metadata = new FunctionMetadata
            {
                Name       = "SomeFunction",
                ScriptFile = "D:\\home\\site\\wwwroot\\SomeFunction\\index.js"
            };
            FunctionDescriptor function = new FunctionDescriptor("TimerFunction", new TestInvoker(), metadata, new Collection <ParameterDescriptor>(), null, null, null);

            functions.Add(function);
            result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.False(result);
            Assert.Null(functionResult);

            // match - exact
            metadata = new FunctionMetadata
            {
                Name       = "HttpTriggerNode",
                ScriptFile = "D:\\home\\site\\wwwroot\\HttpTriggerNode\\index.js"
            };
            function = new FunctionDescriptor("TimerFunction", new TestInvoker(), metadata, new Collection <ParameterDescriptor>(), null, null, null);
            functions.Add(function);
            result = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.True(result);
            Assert.Same(function, functionResult);

            // match - different file from the same function
            stack = "TypeError: Cannot read property 'is' of undefined\n" +
                    "at Timeout._onTimeout(D:\\home\\site\\wwwroot\\HttpTriggerNode\\npm\\lib\\foo.js:7:35)\n" +
                    "at tryOnTimeout (timers.js:224:11)\n" +
                    "at Timer.listOnTimeout(timers.js:198:5)";
            exception = new InvalidOperationException(stack);
            result    = ScriptHost.TryGetFunctionFromException(functions, exception, out functionResult);
            Assert.True(result);
            Assert.Same(function, functionResult);
        }
        public void GivenPackagesWithAssemblyReferences_AssemblyReferencesAreResolved()
        {
            var functionMetadata = new FunctionMetadata()
            {
                Name = "TestFunction",
                ScriptFile = _lockFilePath, /*We just need the path from this*/
                ScriptType = ScriptType.CSharp
            };

            var assemblyResolver = new PackageAssemblyResolver(functionMetadata);

            string nugetHome = PackageManager.GetNugetPackagesPath();

            Assert.Contains<string>(_targetAssemblyFilePath, assemblyResolver.AssemblyReferences);
        }
        public override bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }

            functionDescriptor = null;

            if (functionMetadata.ScriptType != ScriptType.CSharp)
            {
                return false;
            }

            return base.TryCreate(functionMetadata, out functionDescriptor);
        }
        public override bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }

            functionDescriptor = null;

            if (!ScriptFunctionInvoker.IsSupportedScriptType(functionMetadata.ScriptType))
            {
                return false;
            }

            return base.TryCreate(functionMetadata, out functionDescriptor);
        }
        public void ValidateFunction_NoTriggerBinding_Throws()
        {
            FunctionMetadata functionMetadata = new FunctionMetadata();
            functionMetadata.Bindings.Add(new BindingMetadata
            {
                Name = "test",
                Type = "Blob"
            });

            var ex = Assert.Throws<InvalidOperationException>(() =>
            {
                _provider.ValidateFunction(functionMetadata);
            });

            Assert.Equal("No trigger binding specified. A function must have a trigger input binding.", ex.Message);
        }
        public override bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }

            functionDescriptor = null;

            // We can only handle script types supported by the current compilation service factory
            if (!_compilationServiceFactory.SupportedScriptTypes.Contains(functionMetadata.ScriptType))
            {
                return false;
            }

            return base.TryCreate(functionMetadata, out functionDescriptor);
        }
        public void GivenLockFile_PackageReferencesAreResolved()
        {
            var functionMetadata = new FunctionMetadata()
            {
                Name = "TestFunction",
                ScriptFile = _lockFilePath, /*We just need the path from this*/
                ScriptType = ScriptType.CSharp
            };

            var assemblyResolver = new PackageAssemblyResolver(functionMetadata);

            PackageReference package = assemblyResolver.Packages.Single();

            Assert.Equal("Test.Package", package.Name);
            Assert.Equal("1.0.0", package.Version);
            Assert.Equal(1, package.Assemblies.Count);
            Assert.Equal(2, package.FrameworkAssemblies.Count);
        }
Пример #40
0
        public void IsSingleLanguage_Returns_True()
        {
            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "funcJs1",
                Language = "node"
            };
            FunctionMetadata func2 = new FunctionMetadata()
            {
                Name     = "funcJs2",
                Language = "node"
            };
            IEnumerable <FunctionMetadata> functionsList = new Collection <FunctionMetadata>()
            {
                func1, func2
            };

            Assert.True(Utility.IsSingleLanguage(functionsList, null));
        }
Пример #41
0
        public async Task FunctionDispatcherState_Transitions_From_Starting_To_Initialized()
        {
            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher();
            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "func1",
                Language = "node"
            };
            var functions = new List <FunctionMetadata>()
            {
                func1
            };
            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Initializing, functionDispatcher.State);
            await WaitForFunctionDispactherStateInitialized(functionDispatcher);

            Assert.Equal(FunctionInvocationDispatcherState.Initialized, functionDispatcher.State);
        }
Пример #42
0
        public void IsSingleLanguage_Returns_False()
        {
            FunctionMetadata funcJs1 = new FunctionMetadata()
            {
                Name     = "funcJs1",
                Language = "node"
            };
            FunctionMetadata funcPython1 = new FunctionMetadata()
            {
                Name     = "funcPython1",
                Language = "python",
            };
            IEnumerable <FunctionMetadata> functionsList = new Collection <FunctionMetadata>()
            {
                funcJs1, funcPython1
            };

            Assert.False(Utility.IsSingleLanguage(functionsList, null));
        }
Пример #43
0
        public void IsSingleLanguage_Returns_True_Proxy()
        {
            FunctionMetadata proxy = new FunctionMetadata()
            {
                Name    = "proxy",
                IsProxy = true
            };
            FunctionMetadata funcJs = new FunctionMetadata()
            {
                Name     = "funcJs",
                Language = "node"
            };
            IEnumerable <FunctionMetadata> functionsList = new Collection <FunctionMetadata>()
            {
                proxy, funcJs
            };

            Assert.True(Utility.IsSingleLanguage(functionsList, null));
        }
        private Compilation GetScriptCompilation(Script<object> script, FunctionMetadata functionMetadata)
        {
            Compilation compilation = script.GetCompilation();

            if (_optimizationLevel == OptimizationLevel.Debug)
            {
                SyntaxTree scriptTree = compilation.SyntaxTrees.FirstOrDefault(t => string.IsNullOrEmpty(t.FilePath));
                var debugTree = SyntaxFactory.SyntaxTree(scriptTree.GetRoot(),
                  encoding: UTF8WithNoBOM,
                  path: Path.GetFileName(functionMetadata.ScriptFile),
                  options: new CSharpParseOptions(kind: SourceCodeKind.Script));

                compilation = compilation
                    .RemoveAllSyntaxTrees()
                    .AddSyntaxTrees(debugTree);
            }

            return compilation.WithOptions(compilation.Options.WithOptimizationLevel(_optimizationLevel))
                .WithAssemblyName(FunctionAssemblyLoader.GetAssemblyNameFromMetadata(functionMetadata, compilation.AssemblyName));
        }
        public void ResolveAssembly_WithIndirectPrivateDependency_IsResolved()
        {
            var resolver = new FunctionAssemblyLoader("c:\\");

            var metadata1 = new FunctionMetadata { Name = "Test1", Source = @"c:\testroot\test1\test.tst" };
            var metadata2 = new FunctionMetadata { Name = "Test2", Source = @"c:\testroot\test2\test.tst" };
            var traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            var mockResolver = new Mock<IFunctionMetadataResolver>();
            mockResolver.Setup(m => m.ResolveAssembly("MyTestAssembly.dll"))
              .Returns(new TestAssembly(new AssemblyName("MyTestAssembly")));
                
            resolver.CreateOrUpdateContext(metadata1, this.GetType().Assembly, new FunctionMetadataResolver(metadata1, traceWriter), traceWriter);
            resolver.CreateOrUpdateContext(metadata2, this.GetType().Assembly, mockResolver.Object, traceWriter);

            Assembly result = resolver.ResolveAssembly(null, new System.ResolveEventArgs("MyTestAssembly.dll",
                new TestAssembly(new AssemblyName("MyDirectReference"), @"file:///c:/testroot/test2/bin/MyDirectReference.dll")));

            Assert.NotNull(result);
        }
        internal ScriptFunctionInvoker(string scriptFilePath, ScriptHostConfiguration config, BindingMetadata trigger, FunctionMetadata functionMetadata, bool omitInputParameter, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
        {
            _scriptFilePath = scriptFilePath;
            _config = config;
            _scriptType = Path.GetExtension(_scriptFilePath).ToLower().TrimStart('.');
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _functionName = functionMetadata.Name;
            _omitInputParameter = omitInputParameter;
            _trigger = trigger;

            if (config.FileLoggingEnabled)
            {
                string logFilePath = Path.Combine(_config.RootLogPath, "Function", _functionName);
                _fileTraceWriter = new FileTraceWriter(logFilePath, TraceLevel.Verbose);
            }
            else
            {
                _fileTraceWriter = NullTraceWriter.Instance;
            }
        }
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new InvalidOperationException("functionMetadata");
            }

            ValidateFunction(functionMetadata);

            // parse the bindings
            Collection<FunctionBinding> inputBindings = FunctionBinding.GetBindings(Config, functionMetadata.InputBindings, FileAccess.Read);
            Collection<FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, functionMetadata.OutputBindings, FileAccess.Write);

            BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
            string scriptFilePath = Path.Combine(Config.RootScriptPath, functionMetadata.ScriptFile);
            functionDescriptor = null;
            IFunctionInvoker invoker = null;

            try
            {
                invoker = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, inputBindings, outputBindings);

                Collection<CustomAttributeBuilder> methodAttributes = new Collection<CustomAttributeBuilder>();
                Collection<ParameterDescriptor> parameters = GetFunctionParameters(invoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);

                functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes);

                return true;
            }
            catch (Exception)
            {
                IDisposable disposableInvoker = invoker as IDisposable;
                if (disposableInvoker != null)
                {
                    disposableInvoker.Dispose();
                }

                throw;
            }
        }
Пример #48
0
        public async Task ShutdownChannels_DotNetFunctions()
        {
            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "func1",
                Language = "dotnet"
            };
            var functions = new List <FunctionMetadata>()
            {
                func1
            };
            var mockLanguageWorkerChannelManager = new Mock <IWebHostRpcWorkerChannelManager>();
            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher(mockwebHostLanguageWorkerChannelManager: mockLanguageWorkerChannelManager);

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);
            await functionDispatcher.InitializeAsync(functions);

            // Wait longer than debouce action.
            await Task.Delay(6000);

            mockLanguageWorkerChannelManager.Verify(m => m.ShutdownChannelsAsync(), Times.Once);
        }
        internal void SendFunctionLoadRequest(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            if (_managedDependencyOptions?.Value != null)
            {
                _workerChannelLogger?.LogInformation($"Adding dependency download request to {_workerConfig.Language} language worker");
                request.ManagedDependencyEnabled = _managedDependencyOptions.Value.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
Пример #50
0
        /// <summary>
        /// Sets the type that should be directly loaded by WebJobs if using attribute based configuration (these have the "configurationSource" : "attributes" set)
        /// They will be indexed and invoked directly by the WebJobs SDK and skip the IL generator and invoker paths.
        /// </summary>
        private void TrySetDirectType(FunctionMetadata metadata)
        {
            if (!metadata.IsDirect())
            {
                return;
            }

            string path     = metadata.ScriptFile;
            var    typeName = Utility.GetFullClassName(metadata.EntryPoint);

            Assembly assembly = FunctionAssemblyLoadContext.Shared.LoadFromAssemblyPath(path);
            var      type     = assembly.GetType(typeName);

            if (type != null)
            {
                metadata.Properties.Add(ScriptConstants.FunctionMetadataDirectTypeKey, type);
            }
            else
            {
                // This likely means the function.json and dlls are out of sync. Perhaps a badly generated function.json?
                _logger.FailedToLoadType(typeName, path);
            }
        }
Пример #51
0
        public async Task FunctionDispatcherState_Transitions_From_Default_To_Initialized_To_Disposing()
        {
            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher();

            Assert.Equal(FunctionInvocationDispatcherState.Default, functionDispatcher.State);
            FunctionMetadata func1 = new FunctionMetadata()
            {
                Name     = "func1",
                Language = "node"
            };
            var functions = new List <FunctionMetadata>()
            {
                func1
            };
            await functionDispatcher.InitializeAsync(functions);

            Assert.Equal(FunctionInvocationDispatcherState.Initializing, functionDispatcher.State);
            await WaitForFunctionDispactherStateInitialized(functionDispatcher);

            Assert.Equal(FunctionInvocationDispatcherState.Initialized, functionDispatcher.State);
            functionDispatcher.Dispose();
            Assert.True(functionDispatcher == null || functionDispatcher.State == FunctionInvocationDispatcherState.Disposing || functionDispatcher.State == FunctionInvocationDispatcherState.Disposed);
        }
Пример #52
0
        public void IsSingleLanguage_FunctionsWorkerRuntime_Set_Returns_True_()
        {
            FunctionMetadata funcPython1 = new FunctionMetadata()
            {
                Name     = "funcPython1",
                Language = "python",
            };
            FunctionMetadata funcJs = new FunctionMetadata()
            {
                Name     = "funcJs",
                Language = "node"
            };
            FunctionMetadata funcCSharp1 = new FunctionMetadata()
            {
                Name     = "funcCSharp1",
                Language = "CSharp",
            };
            IEnumerable <FunctionMetadata> functionsList = new Collection <FunctionMetadata>()
            {
                funcPython1, funcJs, funcCSharp1
            };

            Assert.True(Utility.IsSingleLanguage(functionsList, "node"));
        }
 public bool IsSupported(FunctionMetadata functionMetadata)
 {
     return(_workerConfigs.Any(config => config.Extension == Path.GetExtension(functionMetadata.ScriptFile)));
 }
Пример #54
0
        public void ValidateFunction_ValidatesHttpRoutes()
        {
            var httpFunctions = new Dictionary <string, HttpTriggerAttribute>();

            // first add an http function
            var metadata  = new FunctionMetadata();
            var function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test", null, metadata, null, null, null, null);
            var attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get")
            {
                Route = "products/{category}/{id?}"
            };

            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);

            ScriptHost.ValidateFunction(function.Object, httpFunctions);
            Assert.Equal(1, httpFunctions.Count);
            Assert.True(httpFunctions.ContainsKey("test"));

            // add another for a completely different route
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test2", null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get")
            {
                Route = "/foo/bar/baz/"
            };
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);
            ScriptHost.ValidateFunction(function.Object, httpFunctions);
            Assert.Equal(2, httpFunctions.Count);
            Assert.True(httpFunctions.ContainsKey("test2"));

            // add another that varies from another only by http methods
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test3", null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "put", "post")
            {
                Route = "/foo/bar/baz/"
            };
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);
            ScriptHost.ValidateFunction(function.Object, httpFunctions);
            Assert.Equal(3, httpFunctions.Count);
            Assert.True(httpFunctions.ContainsKey("test3"));

            // now try to add a function for the same route
            // where the http methods overlap
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test4", null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute
            {
                Route = "/foo/bar/baz/"
            };
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);
            var ex = Assert.Throws <InvalidOperationException>(() =>
            {
                ScriptHost.ValidateFunction(function.Object, httpFunctions);
            });

            Assert.Equal("The route specified conflicts with the route defined by function 'test2'.", ex.Message);
            Assert.Equal(3, httpFunctions.Count);

            // try to add a route under reserved admin route
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test5", null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute
            {
                Route = "admin/foo/bar"
            };
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);
            ex = Assert.Throws <InvalidOperationException>(() =>
            {
                ScriptHost.ValidateFunction(function.Object, httpFunctions);
            });
            Assert.Equal("The specified route conflicts with one or more built in routes.", ex.Message);

            // verify that empty route is defaulted to function name
            function  = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test6", null, metadata, null, null, null, null);
            attribute = new HttpTriggerAttribute();
            function.Setup(p => p.GetTriggerAttributeOrNull <HttpTriggerAttribute>()).Returns(() => attribute);
            ScriptHost.ValidateFunction(function.Object, httpFunctions);
            Assert.Equal(4, httpFunctions.Count);
            Assert.True(httpFunctions.ContainsKey("test6"));
            Assert.Equal("test6", attribute.Route);
        }
Пример #55
0
 public override Assembly Load(FunctionMetadata metadata, IFunctionMetadataResolver metadataResolver, ILogger logger)
 => FunctionAssemblyLoadContext.Shared.LoadFromAssemblyPath(AssemblyPath, true);
Пример #56
0
        protected override Collection <ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata,
                                                                                  BindingMetadata triggerMetadata, Collection <CustomAttributeBuilder> methodAttributes, Collection <FunctionBinding> inputBindings, Collection <FunctionBinding> outputBindings)
        {
            if (functionInvoker == null)
            {
                throw new ArgumentNullException("functionInvoker");
            }
            if (functionMetadata == null)
            {
                throw new ArgumentNullException("functionMetadata");
            }
            if (triggerMetadata == null)
            {
                throw new ArgumentNullException("triggerMetadata");
            }
            if (methodAttributes == null)
            {
                throw new ArgumentNullException("methodAttributes");
            }

            var dotNetInvoker = functionInvoker as DotNetFunctionInvoker;

            if (dotNetInvoker == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Expected invoker of type '{0}' but received '{1}'", typeof(DotNetFunctionInvoker).Name, functionInvoker.GetType().Name));
            }

            try
            {
                ApplyMethodLevelAttributes(functionMetadata, triggerMetadata, methodAttributes);

                MethodInfo      functionTarget = dotNetInvoker.GetFunctionTargetAsync().Result;
                ParameterInfo[] parameters     = functionTarget.GetParameters();
                Collection <ParameterDescriptor> descriptors = new Collection <ParameterDescriptor>();
                IEnumerable <FunctionBinding>    bindings    = inputBindings.Union(outputBindings);
                ParameterDescriptor descriptor = null;
                foreach (var parameter in parameters)
                {
                    // Is it the trigger parameter?
                    if (string.Compare(parameter.Name, triggerMetadata.Name, StringComparison.Ordinal) == 0)
                    {
                        ParameterDescriptor triggerParameter = CreateTriggerParameter(triggerMetadata, parameter.ParameterType);
                        descriptors.Add(triggerParameter);
                    }
                    else
                    {
                        Type parameterType    = parameter.ParameterType;
                        bool parameterIsByRef = parameterType.IsByRef;
                        if (parameterIsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }

                        descriptor = new ParameterDescriptor(parameter.Name, parameter.ParameterType);
                        var binding = bindings.FirstOrDefault(b => string.Compare(b.Metadata.Name, parameter.Name, StringComparison.Ordinal) == 0);
                        if (binding != null)
                        {
                            Collection <CustomAttributeBuilder> customAttributes = binding.GetCustomAttributes(parameter.ParameterType);
                            if (customAttributes != null)
                            {
                                foreach (var customAttribute in customAttributes)
                                {
                                    descriptor.CustomAttributes.Add(customAttribute);
                                }
                            }
                        }

                        // In the C# programming model, IsOut is set for out parameters
                        // In the F# programming model, neither IsOut nor IsIn are set for byref parameters (which are used as out parameters).
                        //   Justification for this cariation of the programming model is that declaring 'out' parameters is (deliberately)
                        //   awkward in F#, they require opening System.Runtime.InteropServices and adding the [<Out>] attribute, and using
                        //   a byref parameter. In contrast declaring a byref parameter alone (neither labelled In nor Out) is simple enough.
                        if (parameter.IsOut || (functionMetadata.ScriptType == ScriptType.FSharp && parameterIsByRef && !parameter.IsIn))
                        {
                            descriptor.Attributes |= ParameterAttributes.Out;
                        }

                        descriptors.Add(descriptor);
                    }
                }

                // Add any additional required System parameters (if they haven't already been defined by the user)
                if (!descriptors.Any(p => p.Type == typeof(ExecutionContext)))
                {
                    // Add ExecutionContext to provide access to InvocationId, etc.
                    descriptors.Add(new ParameterDescriptor(ScriptConstants.SystemExecutionContextParameterName, typeof(ExecutionContext)));
                }

                // If we have an HTTP trigger binding but no parameter binds to the raw HttpRequestMessage,
                // add it as a system parameter so it is accessible later in the pipeline.
                if (string.Compare(triggerMetadata.Type, "httptrigger", StringComparison.OrdinalIgnoreCase) == 0 &&
                    !descriptors.Any(p => p.Type == typeof(HttpRequestMessage)))
                {
                    descriptors.Add(new ParameterDescriptor(ScriptConstants.SystemTriggerParameterName, typeof(HttpRequestMessage)));
                }

                if (TryCreateReturnValueParameterDescriptor(functionTarget.ReturnType, bindings, out descriptor))
                {
                    // If a return value binding has been specified, set up an output
                    // binding to map it to. By convention, this is set up as the last
                    // parameter.
                    descriptors.Add(descriptor);
                }

                return(descriptors);
            }
            catch (AggregateException exc)
            {
                if (!(exc.InnerException is CompilationErrorException))
                {
                    throw;
                }
            }
            catch (CompilationErrorException)
            {
            }

            // We were unable to compile the function to get its signature,
            // setup the descriptor with the default parameters
            methodAttributes.Clear();
            return(base.GetFunctionParameters(functionInvoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings));
        }
Пример #57
0
        public ICompilationService <IJavaScriptCompilation> CreateService(ScriptType scriptType, FunctionMetadata metadata)
        {
            switch (scriptType)
            {
            case ScriptType.Javascript:
                return(new RawJavaScriptCompilationService(metadata));

            case ScriptType.TypeScript:
                return(new TypeScriptCompilationService());

            default:
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture,
                                                              "The script type {0} is not supported by the {1}", scriptType, typeof(JavaScriptCompilationServiceFactory).Name));
            }
        }
Пример #58
0
 public abstract Assembly Load(FunctionMetadata metadata, IFunctionMetadataResolver metadataResolver, ILogger logger);
Пример #59
0
 private static IFunctionMetadataResolver CreateMetadataResolver(ScriptHost host, FunctionMetadata functionMetadata, ILogger logger)
 {
     return(new FunctionMetadataResolver(functionMetadata.ScriptFile, host.ScriptConfig.BindingProviders, logger));
 }
Пример #60
0
 public static string GetAssemblyNameFromMetadata(FunctionMetadata metadata, string suffix)
 {
     return(AssemblyPrefix + metadata.Name + AssemblySeparator + suffix.GetHashCode().ToString());
 }