public void TestValidatorSucceeds() { var nr = new FakeNameResolver().Add("k1", "v1"); var host = TestHelpers.NewJobHost <GoodFunction>(new FakeExtClient(), nr); host.Call("Good", new { k2 = "xxxx" }); }
public void TestValidationError() { var nr = new FakeNameResolver().Add("x", "error"); var host = TestHelpers.NewJobHost <Program>(nr, new FakeExtClient()); TestHelpers.AssertIndexingError(() => host.Call("Func"), "Program.Func", FakeExtClient.IndexErrorMsg); }
public async Task Catch_Bad_Name_At_Runtime() { var nameResolver = new FakeNameResolver().Add("key", "1"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <ProgramWithVariableQueueName>(builder => { builder.AddAzureStorageQueues(); builder.UseQueueService(queueServiceClient); }) .ConfigureServices(services => { services.AddSingleton <INameResolver>(nameResolver); }) .Build(); await host.GetJobHost().CallAsync <ProgramWithVariableQueueName>("Func", new { x = "1" }); // succeeds with valid char try { await host.GetJobHost().CallAsync <ProgramWithVariableQueueName>("Func", new { x = "*" }); // produces an error pattern. Assert.False(true, "should have failed"); } catch (FunctionInvocationException e) { Assert.AreEqual("Exception binding parameter 'q'", e.InnerException.Message); string errorMessage = GetErrorMessageForBadQueueName("q1-test*", "name"); Assert.AreEqual(errorMessage, e.InnerException.InnerException.Message); } }
public async Task Catch_Bad_Name_At_Runtime_With_Illegal_Static_Chars() { var nameResolver = new FakeNameResolver().Add("key", "$"); // Illegal IHost host = new HostBuilder() .ConfigureDefaultTestHost <ProgramWithVariableQueueName>(builder => { builder.UseFakeStorage(); }) .ConfigureServices(services => { services.AddSingleton <INameResolver>(nameResolver); }) .Build(); try { await host.GetJobHost().CallAsync <ProgramWithVariableQueueName>("Func", new { x = "1" }); // produces an error pattern. Assert.False(true, "should have failed"); } catch (FunctionInvocationException e) // Not an index exception! { Assert.Equal("Exception binding parameter 'q'", e.InnerException.Message); string errorMessage = GetErrorMessageForBadQueueName("q$-test1", "name"); Assert.Equal(errorMessage, e.InnerException.InnerException.Message); } }
public void Test() { var client = new FakeQueueTypedClient(); var nr = new FakeNameResolver(); nr.Add("appsetting1", "val1"); var host = new HostBuilder() .ConfigureDefaultTestHost <Functions>(b => { b.AddExtension(client); }) .ConfigureServices(s => s.AddSingleton <INameResolver>(nr)) .Build(); host.GetJobHost().Call(typeof(Functions).GetMethod(nameof(Functions.T1))); Assert.Equal(6, client._items.Count); Assert_IsSpecialData("q1a", client._items[0]); Assert_IsSpecialData("val1:q1b", client._items[1]); // attr has prefix Assert_Type <DateTime>(DateTime.MaxValue, client._items[2]); Assert_IsSpecialData("q2", client._items[3]); Assert_IsSpecialData("q3a", client._items[4]); Assert_IsSpecialData("q3b", client._items[5]); }
public void DefaultMethodName(string propValue, string expectedValue) { Attr5 attr = new Attr5 { AutoResolve = propValue }; // Pick method name var nameResolver = new FakeNameResolver() .Add("empty2", "") .Add("value2", "456"); Dictionary <string, object> values = new Dictionary <string, object>() { { "empty", "" }, { "value", "123" } }; new SystemBindingData { MethodName = "MyMethod" }.AddToBindingData(values); var ctx = GetCtx(values); var cloner = new AttributeCloner <Attr5>(attr, GetBindingContract(values), nameResolver); var attr2 = cloner.ResolveFromBindingData(ctx); Assert.Equal(expectedValue, attr2.AutoResolve); }
public void ConnectionStringAttribute_ResolvesCorrectly() { ConnectionStrings attr = new ConnectionStrings { Connection = "key", ConnectionAtRoot = "rootKey", ConnectionWithNestedPath = "nested:path:key", ConnectionOverrideDefault = "overridden" }; var config = TestHelpers.CreateInMemoryCollection() .AddSetting("key", "unused") .AddSetting("rootKey", "rootValue") .AddSetting("connectionStrings:key", "connectionStringsValue") .AddSetting("nested:path:key", "nestedPathValue") .AddSetting("nested:path:defaultKey", "nestedPathDefaultValue") .AddSetting("connectionStrings:overridden", "connectionStringsOverriddenValue") .AddSetting("connectionStrings:defaultSetting", "fromConnStr") .AddSetting("defaultSetting", "fromRoot") .BuildConfiguration(); var nameResolver = new FakeNameResolver(); var cloner = new AttributeCloner <ConnectionStrings>(attr, emptyContract, config, nameResolver); var cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("connectionStringsValue", cloned.Connection); Assert.Equal("rootValue", cloned.ConnectionAtRoot); Assert.Equal("nestedPathValue", cloned.ConnectionWithNestedPath); Assert.Equal("connectionStringsOverriddenValue", cloned.ConnectionOverrideDefault); Assert.Equal("nestedPathDefaultValue", cloned.ConnectionWithNestedDefaultPath); Assert.Equal("fromConnStr", cloned.ConnectionWithDefault); Assert.Equal("fromRoot", cloned.AppSettingWithDefault); }
public void TestLocalValidatorSkipped() { // Local validator only run if we use the given rule. var nr = new FakeNameResolver().Add("k1", "v1"); var host = TestHelpers.NewJobHost <LocalFunction1>(new FakeExtClient2(), nr); host.Call("NoValidation", new { k2 = "xxxx" }); // Succeeds since validate doesn't run on this rule }
public void TestValidatorFails() { var nr = new FakeNameResolver().Add("k1", "v1"); var host = TestHelpers.NewJobHost <BadFunction>(new FakeExtClient(), nr); TestHelpers.AssertIndexingError( () => host.Call("Valid"), "BadFunction.Bad", TestAttribute.ErrorMessage); }
public async Task TestValidatorSucceeds() { var nr = new FakeNameResolver().Add("k1", "v1"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <GoodFunction>(b => { b.AddExtension <FakeExtClient>(); }, nr) .Build(); await host.GetJobHost <GoodFunction>().CallAsync("Good", new { k2 = "xxxx" }); }
public void TestLocalValidatorApplied() { // Local validator only run if we use the given rule. var nr = new FakeNameResolver().Add("k1", "v1"); var host = TestHelpers.NewJobHost <LocalFunction2>(new FakeExtClient2(), nr); TestHelpers.AssertIndexingError( () => host.Call("WithValidation"), "LocalFunction2.WithValidation", TestAttribute.ErrorMessage); }
public void TestValidatorFails() { var nr = new FakeNameResolver().Add("k1", "v1"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <BadFunction>(b => { b.AddExtension <FakeExtClient>(); }, nr) .Build(); TestHelpers.AssertIndexingError( () => host.GetJobHost <BadFunction>().CallAsync("Valid").GetAwaiter().GetResult(), "BadFunction.Bad", TestAttribute.ErrorMessage); }
public void AppSettingAttribute_Resolves_IfDefaultMatched() { Attr3 a3 = new Attr3() { Required = "req" }; var nameResolver = new FakeNameResolver().Add("default", "defaultval").Add("req", "reqval"); var cloner = new AttributeCloner <Attr3>(a3, emptyContract, nameResolver); var cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("reqval", cloned.Required); Assert.Equal("defaultval", cloned.Default); }
public void Setting_WithNoValueInResolver_UsesDefault() { Attr2 a2 = new Attr2(string.Empty, string.Empty) { ResolvedSetting = "appsetting" }; var nameResolver = new FakeNameResolver().Add("appsetting", "ABC").Add("default", "default"); var cloner = new AttributeCloner <Attr2>(a2, emptyContract, nameResolver); var a2Cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("default", a2Cloned.DefaultSetting); }
public void TestValidationError() { var nr = new FakeNameResolver().Add("x", "error"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <Program>(b => { b.AddExtension <FakeExtClient>(); }, nameResolver: nr) .Build(); TestHelpers.AssertIndexingError(() => host.GetJobHost <Program>().CallAsync("Func").GetAwaiter().GetResult(), "Program.Func", FakeExtClient.IndexErrorMsg); }
public async Task TestLocalValidatorSkipped() { // Local validator only run if we use the given rule. var nr = new FakeNameResolver().Add("k1", "v1"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <LocalFunction1>(b => { b.AddExtension <FakeExtClient2>(); }, nameResolver: nr) .Build(); await host.GetJobHost <LocalFunction1>().CallAsync("NoValidation", new { k2 = "xxxx" }); // Succeeds since validate doesn't run on this rule }
public void AppSettingAttribute_DoesNotThrowIfNullValueAndNoDefault() { Attr4 a4 = new Attr4(); a4.AutoResolve = "auto"; a4.AppSetting = null; var nameResolver = new FakeNameResolver(); var cloner = new AttributeCloner <Attr4>(a4, emptyContract, nameResolver); var cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("auto", cloned.AutoResolve); Assert.Equal(null, cloned.AppSetting); }
public void TryAutoResolveValue_UnresolvedValue_ThrowsExpectedException() { var resolver = new FakeNameResolver(); var attribute = new Attr2(string.Empty, string.Empty) { ResolvedSetting = "MySetting" }; var prop = attribute.GetType().GetProperty("ResolvedSetting"); string resolvedValue = null; var ex = Assert.Throws <InvalidOperationException>(() => AttributeCloner <Attr2> .TryAutoResolveValue(attribute, prop, resolver, out resolvedValue)); Assert.Equal("Unable to resolve value for property 'Attr2.ResolvedSetting'.", ex.Message); }
public void Setting() { Attr2 a2 = new Attr2(string.Empty, string.Empty) { ResolvedSetting = "appsetting" }; var nameResolver = new FakeNameResolver().Add("appsetting", "ABC"); var cloner = new AttributeCloner <Attr2>(a2, EmptyContract, nameResolver); var a2Cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("ABC", a2Cloned.ResolvedSetting); }
public void TestSuccessNull() { var prog = new Program(); var jobActivator = new FakeActivator(); jobActivator.Add(prog); var nr = new FakeNameResolver().Add("x", "something"); var host = TestHelpers.NewJobHost <Program>(nr, jobActivator, new FakeExtClient()); host.Call(nameof(Program.FuncNull)); // Skipped first rule, applied second Assert.Equal(prog._value, "xxx"); }
public void TryAutoResolveValue_UnresolvedValue_ThrowsExpectedException() { var resolver = new FakeNameResolver(); var attribute = new Attr2(string.Empty, string.Empty) { ResolvedSetting = "MySetting" }; var prop = attribute.GetType().GetProperty("ResolvedSetting"); var attr = prop.GetCustomAttribute <AppSettingAttribute>(); string resolvedValue = "MySetting"; var ex = Assert.Throws <InvalidOperationException>(() => AttributeCloner <Attr2> .GetAppSettingResolver(resolvedValue, attr, resolver, prop, skipValidation)); Assert.Contains("Unable to resolve app setting for property 'Attr2.ResolvedSetting'.", ex.Message); }
public void TestLocalValidatorApplied() { // Local validator only run if we use the given rule. var nr = new FakeNameResolver().Add("k1", "v1"); IHost host = new HostBuilder() .ConfigureDefaultTestHost <LocalFunction2>(b => { b.AddExtension <FakeExtClient2>(); }, nr) .Build(); TestHelpers.AssertIndexingError( () => host.GetJobHost <LocalFunction2>().CallAsync("WithValidation").GetAwaiter().GetResult(), "LocalFunction2.WithValidation", TestAttribute.ErrorMessage); }
public async Task InvokeString() { Attr1 a1 = new Attr1 { Path = "%test%" }; Assert.Null(a1 as IAttributeInvokeDescriptor <Attr1>); // Does not implement the interface var nameResolver = new FakeNameResolver(); nameResolver._dict["test"] = "ABC"; var cloner = new AttributeCloner <Attr1>(a1, EmptyContract, nameResolver); Attr1 attr2 = await cloner.ResolveFromInvokeString("xy"); Assert.Equal("xy", attr2.Path); }
public static void NotRecursive() { var resolver = new FakeNameResolver(); resolver.Add("one", "1"); resolver.Add("two", "2"); resolver.Add("<", "%"); resolver.Add(">", "%"); Assert.Equal("1", resolver.ResolveWholeString("%one%")); Assert.Equal("12", resolver.ResolveWholeString("%one%%two%")); // directly adjacent Assert.Equal("%one%", resolver.ResolveWholeString("%<%one%>%")); // Not recurisve, only applied once. // Failure when resolving a missing item Assert.Throws <InvalidOperationException>(() => resolver.ResolveWholeString("%one%_%missing%")); }
public void Setting_WithNoValueInResolver_UsesDefault() { Attr2 a2 = new Attr2(string.Empty, string.Empty) { ResolvedSetting = "appsetting" }; var nameResolver = new FakeNameResolver(); var config = TestHelpers.CreateInMemoryCollection() .AddSetting("appsetting", "ABC") .AddSetting("default", "default") .BuildConfiguration(); var cloner = new AttributeCloner <Attr2>(a2, emptyContract, config, nameResolver); var a2Cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("default", a2Cloned.DefaultSetting); }
// Glue to initialize a JobHost with the correct config and invoke the Test method. // Config also has the program on it. private void TestWorker <TConfig>() where TConfig : IExtensionConfigProvider, ITest <TConfig>, new() { var prog = new TConfig(); var jobActivator = new FakeActivator(); jobActivator.Add(prog); var appSettings = new FakeNameResolver(); appSettings.Add("y", "123"); IExtensionConfigProvider ext = prog; var host = TestHelpers.NewJobHost <TConfig>(jobActivator, ext, appSettings); ITest <TConfig> test = prog; test.Test(host); }
public void AppSettingAttribute_ResolvesWholeValueAsSetting() { Attr4 a4 = new Attr4(); var name = "test{x}and%y%"; a4.AppSetting = a4.AutoResolve = name; var nameResolver = new FakeNameResolver() .Add("y", "Setting") .Add(name, "AppSetting"); var cloner = new AttributeCloner <Attr4>(a4, GetBindingContract("x"), nameResolver); var cloned = cloner.GetNameResolvedAttribute(); // autoresolve resolves tokens Assert.Equal("test{x}andSetting", cloned.AutoResolve); // appsetting treats entire string as app setting name Assert.Equal("AppSetting", cloned.AppSetting); }
public void Catch_Bad_Name_At_Runtime_With_Illegal_Static_Chars() { var nameResolver = new FakeNameResolver().Add("key", "$"); // Illegal IStorageAccount account = CreateFakeStorageAccount(); var host = TestHelpers.NewJobHost <ProgramWithVariableQueueName>(account, nameResolver); try { host.Call("Func", new { x = "1" }); // produces an error pattern. Assert.False(true, "should have failed"); } catch (FunctionInvocationException e) // Not an index exception! { Assert.Equal("Exception binding parameter 'q'", e.InnerException.Message); string errorMessage = GetErrorMessageForBadQueueName("q$-test1", "name"); Assert.Equal(errorMessage, e.InnerException.InnerException.Message); } }
public void AppSettingAttribute_Resolves_IfDefaultMatched() { Attr3 a3 = new Attr3() { Required = "req" }; var nameResolver = new FakeNameResolver(); var config = TestHelpers.CreateInMemoryCollection() .AddSetting("default", "defaultval") .AddSetting("req", "reqval") .BuildConfiguration(); var cloner = new AttributeCloner <Attr3>(a3, emptyContract, config, nameResolver); var cloned = cloner.GetNameResolvedAttribute(); Assert.Equal("reqval", cloned.Required); Assert.Equal("defaultval", cloned.Default); }
public void Catch_Bad_Name_At_Runtime() { var nameResolver = new FakeNameResolver().Add("key", "1"); IStorageAccount account = CreateFakeStorageAccount(); var host = TestHelpers.NewJobHost <ProgramWithVariableQueueName>(account, nameResolver); host.Call("Func", new { x = "1" }); // succeeds with valid char try { host.Call("Func", new { x = "*" }); // produces an error pattern. Assert.False(true, "should have failed"); } catch (FunctionInvocationException e) { Assert.Equal("Exception binding parameter 'q'", e.InnerException.Message); string errorMessage = GetErrorMessageForBadQueueName("q1-test*", "name"); Assert.Equal(errorMessage, e.InnerException.InnerException.Message); } }