public void ValidateBindings_ValidName_DoesNotThrow(string bindingName) { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"dupe\",\"direction\": \"in\"}"); if (bindingName == ScriptConstants.SystemReturnParameterBindingName) { rawBindings.Add("{\"type\": \"Blob\",\"name\": \"" + bindingName + "\", \"direction\": \"out\"}"); } else { rawBindings.Add("{\"type\": \"Blob\",\"name\": \"" + bindingName + "\"}"); } try { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); } catch (ArgumentException) { Assert.True(false, $"Valid binding name '{bindingName}' failed validation."); } }
public void ValidateBindings_NoBindings_Throws() { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); var ex = Assert.Throws <FormatException>(() => { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); }); Assert.Equal("At least one binding must be declared.", ex.Message); }
public void ValidateFunctionAppFormat_InputMixedApp() { _logger.ClearLogMessages(); string scriptPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "node"); var environment = SystemEnvironment.Instance; AggregateFunctionMetadataProvider.ValidateFunctionAppFormat(scriptPath, _logger, environment); var traces = _logger.GetLogMessages(); var functionLoadLogs = traces.Where(m => m.FormattedMessage.Contains("Detected mixed function app. Some functions may not be indexed")); Assert.True(functionLoadLogs.Any()); }
public void ValidateBindings_NoTriggerBinding_Throws() { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); rawBindings.Add("{\"type\": \"Blob\",\"name\": \"test\"}"); var ex = Assert.Throws <InvalidOperationException>(() => { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); }); Assert.Equal("No trigger binding specified. A function must have a trigger input binding.", ex.Message); }
public void ValidateBindings_InvalidName_Throws(string bindingName) { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"dupe\",\"direction\": \"in\"}"); rawBindings.Add("{\"type\": \"Blob\",\"name\": \"" + bindingName + "\"}"); var ex = Assert.Throws <ArgumentException>(() => { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); }); Assert.Equal($"The binding name {bindingName} is invalid. Please assign a valid name to the binding.", ex.Message); }
public void ValidateBindings_OutputNameWithoutDirection_Throws() { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"dupe\",\"direction\": \"in\"}"); rawBindings.Add("{\"type\": \"Blob\",\"name\": \"" + ScriptConstants.SystemReturnParameterBindingName + "\"}"); var ex = Assert.Throws <ArgumentException>(() => { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); }); Assert.Equal($"{ScriptConstants.SystemReturnParameterBindingName} bindings must specify a direction of 'out'.", ex.Message); }
public void ValidateBindings_DuplicateBindingNames_Throws() { FunctionMetadata functionMetadata = new FunctionMetadata(); List <string> rawBindings = new List <string>(); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"test\",\"direction\": \"in\", \"blobPath\": \"test\"}"); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"dupe\",\"direction\": \"in\"}"); rawBindings.Add("{\"type\": \"BlobTrigger\",\"name\": \"dupe\",\"direction\": \"in\"}"); var ex = Assert.Throws <InvalidOperationException>(() => { AggregateFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata); }); Assert.Equal("Multiple bindings with name 'dupe' discovered. Binding names must be unique.", ex.Message); }
public void GetFunctionMetadataAsync_InputMixedApp() { // Arrange _logger.ClearLogMessages(); IEnumerable <RawFunctionMetadata> rawFunctionMetadataCollection = new List <RawFunctionMetadata>(); var functionMetadataCollection = new List <FunctionMetadata>(); functionMetadataCollection.Add(GetTestFunctionMetadata()); var workerConfigs = TestHelpers.GetTestWorkerConfigs().ToImmutableArray(); workerConfigs.ToList().ForEach(config => config.Description.WorkerIndexing = "true"); var scriptjobhostoptions = new ScriptJobHostOptions(); scriptjobhostoptions.RootScriptPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "node"); var environment = SystemEnvironment.Instance; environment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionWorkerRuntime, "node"); environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, "EnableWorkerIndexing"); _mockRpcFunctionInvocationDispatcher.Setup(m => m.InitializeAsync(functionMetadataCollection, default)).Returns(Task.FromResult(0)); _mockRpcFunctionInvocationDispatcher.Setup(m => m.GetWorkerMetadata()).Returns(Task.FromResult(rawFunctionMetadataCollection)); _aggregateFunctionMetadataProvider = new AggregateFunctionMetadataProvider( _logger, _mockRpcFunctionInvocationDispatcher.Object, _mockFunctionMetadataProvider.Object, new OptionsWrapper <ScriptJobHostOptions>(scriptjobhostoptions)); // Act var functions = _aggregateFunctionMetadataProvider.GetFunctionMetadataAsync(workerConfigs, environment, false).GetAwaiter().GetResult(); // Assert string expectedLog = "Detected mixed function app. Some functions may not be indexed"; var traces = _logger.GetLogMessages(); Assert.False(traces.Where(m => m.FormattedMessage.Contains(expectedLog)).Any()); Task.Delay(TimeSpan.FromSeconds(65)).Wait(); traces = _logger.GetLogMessages(); Assert.True(traces.Where(m => m.FormattedMessage.Contains(expectedLog)).Any()); }
public void GetFunctionMetadataAsync_WorkerIndexing_HostFallback() { // Arrange _logger.ClearLogMessages(); var function = GetTestRawFunctionMetadata(useDefaultMetadataIndexing: true); IEnumerable <RawFunctionMetadata> rawFunctionMetadataCollection = new List <RawFunctionMetadata>() { function }; var functionMetadataCollection = new List <FunctionMetadata>(); functionMetadataCollection.Add(GetTestFunctionMetadata()); var workerConfigs = TestHelpers.GetTestWorkerConfigs().ToImmutableArray(); workerConfigs.ToList().ForEach(config => config.Description.WorkerIndexing = "true"); var scriptjobhostoptions = new ScriptJobHostOptions(); scriptjobhostoptions.RootScriptPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "node"); var environment = SystemEnvironment.Instance; environment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionWorkerRuntime, "node"); environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsFeatureFlags, "EnableWorkerIndexing"); _mockRpcFunctionInvocationDispatcher.Setup(m => m.InitializeAsync(functionMetadataCollection, default)).Returns(Task.FromResult(0)); _mockRpcFunctionInvocationDispatcher.Setup(m => m.GetWorkerMetadata()).Returns(Task.FromResult(rawFunctionMetadataCollection)); _mockRpcFunctionInvocationDispatcher.Setup(m => m.FinishInitialization(functionMetadataCollection, default)).Returns(Task.FromResult(0)); _mockFunctionMetadataProvider.Setup(m => m.GetFunctionMetadataAsync(workerConfigs, environment, false)).Returns(Task.FromResult(functionMetadataCollection.ToImmutableArray())); _aggregateFunctionMetadataProvider = new AggregateFunctionMetadataProvider(_logger, _mockRpcFunctionInvocationDispatcher.Object, _mockFunctionMetadataProvider.Object, new OptionsWrapper <ScriptJobHostOptions>(scriptjobhostoptions)); // Act var functions = _aggregateFunctionMetadataProvider.GetFunctionMetadataAsync(workerConfigs, environment, false).GetAwaiter().GetResult(); // Assert var traces = _logger.GetLogMessages(); var functionLoadLogs = traces.Where(m => string.Equals(m.FormattedMessage, "Fallback to host indexing as worker denied indexing")); Assert.True(functionLoadLogs.Any()); }