public void AddCustomFunction_CustomFunctionDoesntExist_ShouldAdd() { string customFunctionName = "my.NewCustomFunction"; try { // New not existing custom function var newCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetInt32(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature); // Assert // Make sure both signatures exists FunctionSignatureWithReturnType[] customFunctionSignatures = GetCustomFunctionSignaturesOrNull(customFunctionName); customFunctionSignatures.Length.Should().Be(1); customFunctionSignatures[0].Should().BeSameAs(newCustomFunctionSignature); } finally { // Clean from CustomUriFunctions cache CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); } }
public static void RegisterCustomFunctions() { var signature = new[] { new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), new IEdmTypeReference[] { EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true), }), new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), new IEdmTypeReference[] { EdmCoreModel.Instance.GetInt32(true), EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)) }), new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), new IEdmTypeReference[] { EdmCoreModel.Instance.GetInt32(true), EdmCoreModel.Instance.GetString(true) //new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(true))) }) }; foreach (var sign in signature) { CustomUriFunctions.AddCustomUriFunction("incollection", sign); CustomUriFunctions.AddCustomUriFunction("notincollection", sign); } CustomUriFunctions.AddCustomUriFunction("containsany", new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), new IEdmTypeReference[] { EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true), })); }
/// <summary> /// This is a shortcut of removing the FunctionSignature through 'CustomUriFunctions' class and /// unbinding the function name from it's MethodInfo through 'UriFunctionsBinder' class. /// See these classes documentations. /// </summary> /// <param name="functionName">The uri function name that appears in the OData request uri.</param> /// <param name="functionSignature">The new custom function signature.</param> /// <param name="methodInfo">The MethodInfo to bind the given function name.</param> /// <exception cref="Exception">Any exception thrown by 'CustomUriFunctions.RemoveCustomUriFunction' and 'UriFunctionsBinder.UnbindUriFunctionName' methods.</exception> /// <returns>'True' if the fucntion signature has successfully removed and unbinded. 'False' otherwise.</returns> public static bool RemoveCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature, MethodInfo methodInfo) { return (CustomUriFunctions.RemoveCustomUriFunction(functionName, functionSignature) && UriFunctionsBinder.UnbindUriFunctionName(functionName, methodInfo)); }
static EdmModelExtensions() { CustomUriFunctions.AddCustomUriFunction("empty", new FunctionSignatureWithReturnType( EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetString(true))); }
static EdmModelExtensions() { CustomUriFunctions.AddCustomUriFunction("empty", new FunctionSignatureWithReturnType( EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetUntyped())); CustomUriFunctions.AddCustomUriFunction("exists", new FunctionSignatureWithReturnType( EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetUntyped())); CustomUriFunctions.AddCustomUriFunction("matchs", new FunctionSignatureWithReturnType( EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetString(false), EdmCoreModel.Instance.GetString(false))); CustomUriFunctions.AddCustomUriFunction("distanceto", new FunctionSignatureWithReturnType( EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetInt32(true), EdmCoreModel.Instance.GetInt32(true))); }
private FunctionSignatureWithReturnType[] GetCustomFunctionSignaturesOrNull(string customFunctionName) { FunctionSignatureWithReturnType[] resultFunctionSignaturesWithReturnType = null; CustomUriFunctions.TryGetCustomFunction(customFunctionName, out resultFunctionSignaturesWithReturnType); return(resultFunctionSignaturesWithReturnType as FunctionSignatureWithReturnType[]); }
public void AddCustomFunction_FunctionCannotBeNull() { Action addNullFunctionAction = () => CustomUriFunctions.AddCustomUriFunction("my.MyNullCustomFunction", null); addNullFunctionAction.ShouldThrow <ArgumentNullException>(); }
public void AddCustomFunction_CustomFunctionNameExistsButNotFullSignature_ShouldAddAsAnOverload() { string customFunctionName = "my.ExistingCustomFunction"; try { // Prepare FunctionSignatureWithReturnType existingCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature); //Test // Same name, but different signature var newCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetInt32(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature); // Assert // Make sure both signatures exists bool areSiganturesAdded = GetCustomFunctionSignaturesOrNull(customFunctionName). All(x => x.Equals(existingCustomFunctionSignature) || x.Equals(newCustomFunctionSignature)); Assert.True(areSiganturesAdded); } finally { // Clean both signatures from CustomUriFunctions cache Assert.True(CustomUriFunctions.RemoveCustomUriFunction(customFunctionName)); } }
public void ParseWithCustomFunction_EnumParameter() { try { var enumType = new EdmEnumType("Fully.Qualified.Namespace", "NonFlagShape", EdmPrimitiveTypeKind.SByte, false); enumType.AddMember("Rectangle", new EdmEnumMemberValue(1)); enumType.AddMember("Triangle", new EdmEnumMemberValue(2)); enumType.AddMember("foursquare", new EdmEnumMemberValue(3)); var enumTypeRef = new EdmEnumTypeReference(enumType, false); FunctionSignatureWithReturnType signature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), enumTypeRef); CustomUriFunctions.AddCustomUriFunction("enumFunc", signature); var fullUri = new Uri("http://www.odata.com/OData/People" + "?$filter=enumFunc('Rectangle')"); ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri("http://www.odata.com/OData/"), fullUri); var enumFuncWithArgs = parser.ParseFilter().Expression.ShouldBeSingleValueFunctionCallQueryNode("enumFunc").Parameters.ToList(); enumFuncWithArgs[0].ShouldBeEnumNode(enumType, "Rectangle"); } finally { Assert.True(CustomUriFunctions.RemoveCustomUriFunction("enumFunc")); } }
public void ParseWithCustomUriFunction_EnableCaseInsensitive_ShouldThrowDueToAmbiguity() { string lowerCaseName = "myfunction"; string upperCaseName = lowerCaseName.ToUpper(); FunctionSignatureWithReturnType myStringFunction = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(true), EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true)); // Add two customer uri functions with same argument types, with names different in cases. CustomUriFunctions.AddCustomUriFunction(lowerCaseName, myStringFunction); CustomUriFunctions.AddCustomUriFunction(upperCaseName, myStringFunction); string rootUri = "http://www.odata.com/OData/"; string uriTemplate = rootUri + "People?$filter={0}(Name,'BlaBla')"; try { int strLen = lowerCaseName.Length; string mixedCaseFunctionName = lowerCaseName.Substring(0, strLen / 2).ToUpper() + lowerCaseName.Substring(strLen / 2); // Uri with mix-case function names referring to equivalent-argument-typed functions, // should result in exception for resolver with case insensitive enabled due to ambiguity (multiple equivalent matches). var fullUri = new Uri(string.Format(uriTemplate, mixedCaseFunctionName)); ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri(rootUri), fullUri); parser.Resolver.EnableCaseInsensitive = true; Action action = () => parser.ParseFilter(); Assert.Throws <ODataException>(action); } finally { Assert.True(CustomUriFunctions.RemoveCustomUriFunction(lowerCaseName)); Assert.True(CustomUriFunctions.RemoveCustomUriFunction(upperCaseName)); } }
public void RemoveCustomFunction_RemoveFunctionWithSameNameAndSignature() { string customFunctionName = "my.ExistingCustomFunction"; try { // Prepare FunctionSignatureWithReturnType existingCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature); Assert.True(GetCustomFunctionSignaturesOrNull(customFunctionName)[0].Equals(existingCustomFunctionSignature)); // Test bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, existingCustomFunctionSignature); // Assert Assert.True(isRemoveSucceeded); Assert.Null(GetCustomFunctionSignaturesOrNull(customFunctionName)); } finally { CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); } }
public void ParseWithMixedCaseCustomUriFunction_EnableCaseInsensitive_ShouldWork() { try { FunctionSignatureWithReturnType myStringFunction = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(true), EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true)); // Add a custom uri function CustomUriFunctions.AddCustomUriFunction("myFirstMixedCasestringfunction", myStringFunction); // Uri with mixed-case, should work for resolver with case insensitive enabled. var fullUri = new Uri("http://www.odata.com/OData/People" + "?$filter=mYFirstMixedCasesTrInGfUnCtIoN(Name, 'BlaBla')"); ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri("http://www.odata.com/OData/"), fullUri); parser.Resolver.EnableCaseInsensitive = true; var startsWithArgs = parser.ParseFilter().Expression.ShouldBeSingleValueFunctionCallQueryNode("myFirstMixedCasestringfunction") .Parameters.ToList(); startsWithArgs[0].ShouldBeSingleValuePropertyAccessQueryNode(HardCodedTestModel.GetPersonNameProp()); startsWithArgs[1].ShouldBeConstantQueryNode("BlaBla"); } finally { Assert.True(CustomUriFunctions.RemoveCustomUriFunction("myFirstMixedCasestringfunction")); } }
public void AddCustomFunction_FunctionCannotBeNull() { Action addNullFunctionAction = () => CustomUriFunctions.AddCustomUriFunction("my.MyNullCustomFunction", null); Assert.Throws <ArgumentNullException>("functionSignature", addNullFunctionAction); }
public void RemoveCustomFunction_CannotRemoveFunctionWithSameNameAndDifferentSignature() { string customFunctionName = "my.ExistingCustomFunction"; try { // Prepare FunctionSignatureWithReturnType existingCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature); Assert.True(GetCustomFunctionSignaturesOrNull(customFunctionName)[0].Equals(existingCustomFunctionSignature)); // Function with different siganture FunctionSignatureWithReturnType customFunctionSignatureToRemove = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetInt16(false), EdmCoreModel.Instance.GetBoolean(false)); // Test // Try Remove a function with the same name but different siganture bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, customFunctionSignatureToRemove); // Assert Assert.False(isRemoveSucceeded); } finally { // Clean up cahce CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); } }
public void ParseWithMixedCaseCustomUriFunction_DisableCaseInsensitive_ShouldFailed() { bool exceptionThrown = false; try { FunctionSignatureWithReturnType myStringFunction = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(true), EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true)); // Add a custom uri function CustomUriFunctions.AddCustomUriFunction("myMixedCasestringfunction", myStringFunction); // Uri with mixed-case, should fail for default resolver with case-insensitive disabled. var fullUri = new Uri("http://www.odata.com/OData/People" + "?$filter=mYMixedCasesTrInGfUnCtIoN(Name, 'BlaBla')"); ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri("http://www.odata.com/OData/"), fullUri); parser.Resolver.EnableCaseInsensitive = false; parser.ParseFilter(); } catch (ODataException e) { Assert.Equal("An unknown function with name 'mYMixedCasesTrInGfUnCtIoN' was found. " + "This may also be a function import or a key lookup on a navigation property, which is not allowed.", e.Message); exceptionThrown = true; } finally { Assert.True(CustomUriFunctions.RemoveCustomUriFunction("myMixedCasestringfunction")); } Assert.True(exceptionThrown, "Exception should be thrown trying to parse mixed-case uri function when case-insensitive is disabled."); }
/// <summary> /// Finds all signatures for the given function name. /// Search in both BuiltIn uri functions and Custom uri functions. /// Combine and return the signatures overloads of the results. /// </summary> /// <param name="functionName">The function to get the signatures for.</param> /// <returns>The signatures which match the supplied function name.</returns> internal static FunctionSignatureWithReturnType[] GetUriFunctionSignatures(string functionName) { FunctionSignatureWithReturnType[] customUriFunctionsSignatures = null; FunctionSignatureWithReturnType[] builtInUriFunctionsSignatures = null; // Try to find the function in the user custom functions and in our built-in functions bool customFound = CustomUriFunctions.TryGetCustomFunction(functionName, out customUriFunctionsSignatures); bool builtInFound = BuiltInUriFunctions.TryGetBuiltInFunction(functionName, out builtInUriFunctionsSignatures); if (!customFound && !builtInFound) { // Not found in both built-in and custom. throw new ODataException(ODataErrorStrings.MetadataBinder_UnknownFunction(functionName)); } if (!customFound) { Debug.Assert(builtInUriFunctionsSignatures != null, "No Built-in functions found"); return(builtInUriFunctionsSignatures); } if (!builtInFound) { Debug.Assert(customUriFunctionsSignatures != null, "No Custom functions found"); return(customUriFunctionsSignatures); } return(builtInUriFunctionsSignatures.Concat(customUriFunctionsSignatures).ToArray()); }
public void AddCustomFunction_CustomFunctionDoesntExist_ShouldAdd_NoArgumnetsToFunctionSignature() { string customFunctionName = "my.NewCustomFunction"; try { // New not existing custom function - function without any argumnets var newCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature); // Assert // Make sure both signatures exists FunctionSignatureWithReturnType[] customFunctionSignatures = GetCustomFunctionSignaturesOrNull(customFunctionName); Assert.Single(customFunctionSignatures); Assert.Same(newCustomFunctionSignature, customFunctionSignatures[0]); } finally { // Clean from CustomUriFunctions cache CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); } }
public void AddCustomFunction_CannotAddFunctionWithFullSignatureExistsAsCustomFunction_AddAsOverload() { string customFunctionName = "my.ExistingCustomFunction"; try { // Prepare var existingCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature); // Test var newCustomFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); Action addCustomFunction = () => CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature); // Asserts addCustomFunction.Throws <ODataException>(Strings.CustomUriFunctions_AddCustomUriFunction_CustomFunctionOverloadExists(customFunctionName)); } finally { // Clean from CustomUriFunctions cache CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); } }
public void AddCustomFunction_ShouldAddFunctionWhichAlreadyExistsAsBuiltInWithSameName_AddAsOverload() { try { FunctionSignatureWithReturnType customFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); // Add with 'addAsOverload' 'true' CustomUriFunctions.AddCustomUriFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME, customFunctionSignature); FunctionSignatureWithReturnType[] resultFunctionSignaturesWithReturnType = this.GetCustomFunctionSignaturesOrNull(BUILT_IN_GEODISTANCE_FUNCTION_NAME); // Assert Assert.NotNull(resultFunctionSignaturesWithReturnType); Assert.Single(resultFunctionSignaturesWithReturnType); Assert.Same(customFunctionSignature, resultFunctionSignaturesWithReturnType[0]); } finally { // Clean from CustomUriFunctions cache CustomUriFunctions.RemoveCustomUriFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME); } }
public void FirstTest() { var intparam = EdmCoreModel.Instance.GetInt32(false); var daysFromNowSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDate(false), intparam); CustomUriFunctions.AddCustomUriFunction("daysFromNow", daysFromNowSignature); var filterPath = $"persons?$filter = Birthday gt daysFromNow(-3)"; var uri = new Uri(filterPath, UriKind.Relative); var model = CreateModel("persons"); var parser = new ODataUriParser(model, new Uri("http://www.odata.com/OData"), uri); var filterClause = parser.ParseFilter(); var parsedUri = parser.ParseUri(); var expression = filterClause.Expression; var person1 = new Person { Id = 0, Name = "Hallo", Birthday = DateTime.Now.AddDays(-5) }; var person2 = new Person { Id = 1, Name = "Hallo2", Birthday = DateTime.Now }; var persons = new List <Person> { person1, person2 }; var p = persons.Where(i => Evaluate(expression, i)).ToList(); Assert.IsTrue(p.Count == 1); Assert.IsTrue(p.FirstOrDefault().Name == "Hallo2"); }
private FunctionSignatureWithReturnType[] GetCustomFunctionSignaturesOrNull(string customFunctionName) { IList <KeyValuePair <string, FunctionSignatureWithReturnType> > resultFunctionSignaturesWithReturnType = null; CustomUriFunctions.TryGetCustomFunction(customFunctionName, out resultFunctionSignaturesWithReturnType); return(resultFunctionSignaturesWithReturnType?.Select(_ => _.Value).ToArray()); }
public void RemoveCustomFunction_EmptyStringFunctionName() { // Test Action removeFunction = () => CustomUriFunctions.RemoveCustomUriFunction(string.Empty); // Assert Assert.Throws <ArgumentNullException>("functionName", removeFunction); }
public void RemoveCustomFunction_NullFunctionSignature() { // Test Action removeFunction = () => CustomUriFunctions.RemoveCustomUriFunction("FunctionName", null); // Assert removeFunction.ShouldThrow <ArgumentNullException>(); }
public void RemoveCustomFunction_NullFunctionSignature() { // Test Action removeFunction = () => CustomUriFunctions.RemoveCustomUriFunction("FunctionName", null); // Assert Assert.Throws <ArgumentNullException>("functionSignature", removeFunction); }
public void RemoveCustomFunction_EmptyStringFunctionName() { // Test Action removeFunction = () => CustomUriFunctions.RemoveCustomUriFunction(string.Empty); // Assert removeFunction.ShouldThrow <ArgumentNullException>(); }
public void RemoveCustomFunction_CannotRemoveFunctionWhichDoesntExist_ByName() { string customFunctionName = "my.ExistingCustomFunction"; // Test bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName); // Assert Assert.False(isRemoveSucceeded); }
public void AddCustomFunction_FunctionNameCannotBeNull() { FunctionSignatureWithReturnType customFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetInt32(false)); Action addNullFunctionNameAction = () => CustomUriFunctions.AddCustomUriFunction(null, customFunctionSignature); addNullFunctionNameAction.ShouldThrow <ArgumentNullException>(); }
public void AddCustomFunction_FunctionNameCannotBeEmptyString() { FunctionSignatureWithReturnType customFunctionSignature = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetInt32(false)); Action addCustomFunctionSignature = () => CustomUriFunctions.AddCustomUriFunction(string.Empty, customFunctionSignature); Assert.Throws <ArgumentNullException>("functionName", addCustomFunctionSignature); }
public void AddCustomFunction_CannotAddFunctionSignatureWithNullReturnType() { FunctionSignatureWithReturnType customFunctionSignatureWithNullReturnType = new FunctionSignatureWithReturnType(null, EdmCoreModel.Instance.GetInt32(false)); Action addCustomFunctionSignature = () => CustomUriFunctions.AddCustomUriFunction("my.customFunctionWithNoReturnType", customFunctionSignatureWithNullReturnType); Assert.Throws <ArgumentNullException>("functionSignatureWithReturnType must contain a return type", addCustomFunctionSignature); }
public void AddCustomFunction_CannotAddFunctionSignatureWithNullReturnType() { FunctionSignatureWithReturnType customFunctionSignatureWithNullReturnType = new FunctionSignatureWithReturnType(null, EdmCoreModel.Instance.GetInt32(false)); Action addCustomFunctionSignature = () => CustomUriFunctions.AddCustomUriFunction("my.customFunctionWithNoReturnType", customFunctionSignatureWithNullReturnType); addCustomFunctionSignature.ShouldThrow <ArgumentNullException>(); }