/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. ******************************************************************************/ package org.apache.olingo.odata2.core.uri.expression; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.uri.expression.ExpressionKind; import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException; import org.junit.Test; /** * */ public class TestParserExceptions extends TestBase { @Test public void testOPMparseOrderByString() { EdmEntityType edmEtAllTypes = edmInfo.getTypeEtAllTypes(); // CASE 1 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice%20ascc // -->Syntax error at position 10. GetPTO(edmEtAllTypes, "String ascc").aExMsgText( "Invalid sort order in OData orderby parser at position 8 in \"String ascc\"."); // CASE 2 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice%20asc, // -->Expression expected at position 12. GetPTO(edmEtAllTypes, "String asc,").aExMsgText("Expression expected after position 11 in \"String asc,\"."); // CASE 3 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice%20asc%20d // -->Syntax error at position 14. GetPTO(edmEtAllTypes, "String asc a").aExMsgText( "Comma or end of expression expected at position 12 in \"String asc a\"."); // CASE 4 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice b // -->Syntax error at position 10. GetPTO(edmEtAllTypes, "String b").aExMsgText( "Invalid sort order in OData orderby parser at position 8 in \"String b\"."); // CASE 5 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice, UnitPrice b // -->Syntax error at position 21. GetPTO(edmEtAllTypes, "String, String b").aExMsgText( "Invalid sort order in OData orderby parser at position 16 in \"String, String b\"."); // CASE 6 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice a, UnitPrice desc // -->Syntax error at position 10. GetPTO(edmEtAllTypes, "String a, String desc").aExMsgText( "Invalid sort order in OData orderby parser at position 8 in \"String a, String desc\"."); // CASE 7 // http://services.odata.org/Northwind/Northwind.svc/Products/?$orderby=UnitPrice asc, UnitPrice b // -->Syntax error at position 25. GetPTO(edmEtAllTypes, "String asc, String b").aExMsgText( "Invalid sort order in OData orderby parser at position 20 in \"String asc, String b\"."); } @Test public void testPMvalidateEdmProperty() { EdmEntityType edmEtAllTypes = edmInfo.getTypeEtAllTypes(); // OK GetPTF(edmEtAllTypes, "'text' eq String").aKind(ExpressionKind.BINARY).aSerialized("{'text' eq String}"); // CASE 1 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter=NotAProperty // -->No property 'NotAProperty' exists in type 'ODataWeb.Northwind.Model.Product' at position 10. GetPTF(edmEtAllTypes, "NotAProperty").aExMsgText( "No property \"NotAProperty\" exists in type \"TecRefScenario.EtAllTypes\" at position 1 in \"NotAProperty\"."); // CASE 2 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter='text'%20eq%20NotAProperty // -->No property 'NotAProperty' exists in type 'ODataWeb.Northwind.Model.Product' at position 10. GetPTF(edmEtAllTypes, "'text' eq NotAProperty") .aExMsgText( "No property \"NotAProperty\" exists in type \"TecRefScenario.EtAllTypes\" at" + " position 11 in \"'text' eq NotAProperty\"."); // CASE 3 GetPTF(edmEtAllTypes, "Complex/NotAProperty") .aExMsgText( "No property \"NotAProperty\" exists in type \"TecRefScenario.CtAllTypes\" at" + " position 9 in \"Complex/NotAProperty\"."); // CASE 4 GetPTF(edmEtAllTypes, "'text' eq Complex/NotAProperty") .aExMsgText( "No property \"NotAProperty\" exists in type \"TecRefScenario.CtAllTypes\" at " + "position 19 in \"'text' eq Complex/NotAProperty\"."); // CASE 5 GetPTF(edmEtAllTypes, "String/NotAProperty").aExMsgText( "No property \"NotAProperty\" exists in type \"Edm.String\" at position 8 in \"String/NotAProperty\"."); // CASE 6 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter='aText'/NotAProperty // -->Exception Stack GetPTF(edmEtAllTypes, "'aText'/NotAProperty").aExMsgText( "Leftside of method operator at position 8 is not a property in \"'aText'/NotAProperty\"."); // CASE 7 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter='Hong Kong' eq ProductName/city // --> No property 'city' exists in type 'System.String' at position 27. GetPTF(edmEtAllTypes, "'Hong Kong' eq DateTime/city").aExMsgText( "No property \"city\" exists in type \"Edm.DateTime\" at position 25 in \"'Hong Kong' eq DateTime/city\"."); // CASE 8 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter='Hong Kong' eq ProductName/city // --> No property 'city' exists in type 'System.String' at position 27. GetPTF(edmEtAllTypes, "'Hong Kong' eq String/city").aExMsgText( "No property \"city\" exists in type \"Edm.String\" at position 23 in \"'Hong Kong' eq String/city\"."); } @Test public void testPMreadParameters() { // OK GetPTF("concat('A','B')").aSerialized("{concat('A','B')}"); // CASE 12 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=startswith() // -->No applicable function found for 'startswith' at position 0 with the specified arguments. The functions // considered are: startswith(System.String, System.String). GetPTF("startswith()") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"startswith\" at position 1 in \"startswith()\" with the specified " + "arguments. Method \"startswith\" requires exact 2 argument(s)."); // CASE 13 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=startswith('A') // -->No applicable function found for 'startswith' at position 0 with the specified arguments. The functions // considered are: startswith(System.String, System.String). GetPTF("startswith('A')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"startswith\" at position 1 in \"startswith('A')\" with the specified " + "arguments. Method \"startswith\" requires exact 2 argument(s)."); // CASE 14 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=startswith('A','B') // -->Resource not found for the segment 'Supplier'. GetPTF("startswith('A','B')").aSerialized("{startswith('A','B')}"); // CASE 15 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=startswith('A','B','C') // -->No applicable function found for 'startswith' at position 0 with the specified arguments. The functions // considered are: startswith(System.String, System.String). GetPTF("startswith('A','B','C')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"startswith\" at position 1 in \"startswith('A','B','C')\" with the" + " specified arguments. Method \"startswith\" requires exact 2 argument(s)."); // CASE 16 GetPTF("concat()") .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"concat()\" with the specified arguments." + " Method \"concat\" requires 2 or more arguments."); // CASE 17 GetPTF("concat('A')") .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"concat('A')\" with the specified " + "arguments. Method \"concat\" requires 2 or more arguments."); // CASE 18 GetPTF("concat('A','B')").aSerialized("{concat('A','B')}"); // CASE 19 GetPTF("concat('A','B','C')").aSerialized("{concat('A','B','C')}"); // CASE 20 GetPTF("'A' and concat('A')") .aExMsgText( "No applicable method found for \"concat\" at position 9 in \"'A' and concat('A')\" with the specified " + "arguments. Method \"concat\" requires 2 or more arguments."); // CASE 1 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=concat( // -->Expression expected at position 7. GetPTF("concat(").aExType(ExpressionParserException.class).aExMsgText( "Expression expected after position 7 in \"concat(\"."); // CASE 2 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=concat(123 // -->')' or ',' expected at position 10. GetPTF("concat(123").aExType(ExpressionParserException.class).aExMsgText( "\")\" or \",\" expected after position 10 in \"concat(123\"."); // .aExMsgText("Missing closing parenthesis \")\" for opening parenthesis \"(\" at position 7 in \"concat(\"."); // CASE 3 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=concat(, // Expression expected at position 7. GetPTF("concat(,").aExType(ExpressionParserException.class).aExMsgText( "Expression expected at position 8 in \"concat(,\"."); // CASE 4 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=concat(123, // -->Expression expected at position 11. GetPTF("concat(123,").aExType(ExpressionParserException.class).aExMsgText( "Expression expected after position 11 in \"concat(123,\"."); // CASE 5 // min = -1, max = -1, GetPTF("testingMINMAX1()").aSerialized("{concat()}"); GetPTF("testingMINMAX1('A')").aSerialized("{concat('A')}"); GetPTF("testingMINMAX1('A','B')").aSerialized("{concat('A','B')}"); GetPTF("testingMINMAX1('A','B','C')").aSerialized("{concat('A','B','C')}"); // CASE 6 // min = 0, max = -1, GetPTF("testingMINMAX2()").aSerialized("{concat()}"); GetPTF("testingMINMAX2('A')").aSerialized("{concat('A')}"); GetPTF("testingMINMAX2('A','B')").aSerialized("{concat('A','B')}"); GetPTF("testingMINMAX2('A','B','C')").aSerialized("{concat('A','B','C')}"); // CASE 7 // min = 2, max = -1, GetPTF("testingMINMAX3()") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX3()\" with the specified " + "arguments. Method \"concat\" requires 2 or more arguments."); GetPTF("testingMINMAX3('A')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX3('A')\" with the specified " + "arguments. Method \"concat\" requires 2 or more arguments."); GetPTF("testingMINMAX3('A','B')").aSerialized("{concat('A','B')}"); GetPTF("testingMINMAX3('A','B','C')").aSerialized("{concat('A','B','C')}"); // CASE 8 // min =-1, max = 0, GetPTF("testingMINMAX4()").aSerialized("{concat()}"); GetPTF("testingMINMAX4('A')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX4('A')\" with the specified " + "arguments. Method \"concat\" requires maximal 0 arguments."); GetPTF("testingMINMAX4('A','B')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX4('A','B')\" with the " + "specified arguments. Method \"concat\" requires maximal 0 arguments."); GetPTF("testingMINMAX4('A','B','C')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX4('A','B','C')\" with the " + "specified arguments. Method \"concat\" requires maximal 0 arguments."); // CASE 9 // min =-1, max = 2, GetPTF("testingMINMAX5()").aSerialized("{concat()}"); GetPTF("testingMINMAX5('A')").aSerialized("{concat('A')}"); GetPTF("testingMINMAX5('A','B')").aSerialized("{concat('A','B')}"); GetPTF("testingMINMAX5('A','B','C')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX5('A','B','C')\" with the " + "specified arguments. Method \"concat\" requires maximal 2 arguments."); // CASE 10 // min =1, max = 2, GetPTF("testingMINMAX6()") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX6()\" with the specified " + "arguments. Method \"concat\" requires between 1 and 2 arguments."); GetPTF("testingMINMAX6('A')").aSerialized("{concat('A')}"); GetPTF("testingMINMAX6('A','B')").aSerialized("{concat('A','B')}"); GetPTF("testingMINMAX6('A','B','C')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX6('A','B','C')\" with the " + "specified arguments. Method \"concat\" requires between 1 and 2 arguments."); // CASE 11 // min =1, max = 2, GetPTF("testingMINMAX7()") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX7()\" with the specified " + "arguments. Method \"concat\" requires exact 1 argument(s)."); GetPTF("testingMINMAX7('A')").aSerialized("{concat('A')}"); GetPTF("testingMINMAX7('A','B')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX7('A','B')\" with the " + "specified arguments. Method \"concat\" requires exact 1 argument(s)."); GetPTF("testingMINMAX7('A','B','C')") .aExType(ExpressionParserException.class) .aExMsgText( "No applicable method found for \"concat\" at position 1 in \"testingMINMAX7('A','B','C')\" with " + "the specified arguments. Method \"concat\" requires exact 1 argument(s)."); // CASE 12 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=concat('a' 'b') // -->')' or ',' expected at position 11. GetPTF("concat('a' 'b')").aExMsgText("\")\" or \",\" expected after position 10 in \"concat('a' 'b')\"."); } @Test public void testPMreadParenthesis() { // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=(123 // -->')' or operator expected at position 4. GetPTF("(123").aExType(ExpressionParserException.class).aExMsgText( "Missing closing parenthesis \")\" for opening parenthesis \"(\" at position 1 in \"(123\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=(123 add (456 // -->')' or operator expected at position 13. GetPTF("(123 add (456").aExType(ExpressionParserException.class).aExMsgText( "Missing closing parenthesis \")\" for opening parenthesis \"(\" at position 10 in \"(123 add (456\"."); } @Test public void testPMvalidateBinaryOperator() {/* PM = Parsermethod */ // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=123 add 'abc' // -->Operator 'add' incompatible with operand types 'System.Int32' and 'System.String' at position 4. GetPTF("123 add 'abc'") .aExType(ExpressionParserException.class) .aExKey(ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR) .aExMsgText( "Operator \"add\" incompatible with operand types \"System.Uint7\" and \"Edm.String\" at " + "position 5 in \"123 add 'abc'\"."); } @Test public void testPMvalidateMethodTypes() /* PM = Parsermethod */{ // CASE 1 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter=year(327686) // -->No applicable function found for 'year' at position 0 with the specified arguments. The functions considered // are: year(System.DateTime). String aInt32 = "327686"; GetPTF("year(" + aInt32 + ")").aExMsgText( "No applicable method found for \"year\" at position 1 in \"year(327686)\" for the specified argument types."); } @Test public void testPMparseFilterString() { /* PM = Parsermethod */ // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter='123 // -->Unterminated string literal at position 4 in ''123'. GetPTF("'123").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.TOKEN_UNDETERMINATED_STRING).aExMsgText( "Unterminated string literal at position 1 in \"'123\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=1%20add%20'123 // -->Unterminated string literal at position 10 in '1 add '123'. GetPTF("1 add '123").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.TOKEN_UNDETERMINATED_STRING).aExMsgText( "Unterminated string literal at position 7 in \"1 add '123\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=datetime'123 // -->Unterminated literal at position 12 in 'datetime'123'. GetPTF("datetime'123").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.TOKEN_UNDETERMINATED_STRING).aExMsgText( "Unterminated string literal at position 9 in \"datetime'123\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=123%20456 // -->Expression of type 'System.Boolean' expected at position 0. GetPTF("123 456").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING).aExMsgText( "Invalid token \"456\" detected after parsing at position 5 in \"123 456\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=123%20456 // -->Expression of type 'System.Boolean' expected at position 0. GetPTF("123 456 789").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING).aExMsgText( "Invalid token \"456\" detected after parsing at position 5 in \"123 456 789\"."); // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=abc%20abc // -->No property 'abc' exists in type 'ODataWeb.Northwind.Model.Supplier' at position 0. GetPTF("abc abc").aExType(ExpressionParserException.class).aExKey( ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING).aExMsgText( "Invalid token \"abc\" detected after parsing at position 5 in \"abc abc\"."); } @Test public void testAdditionalStuff() { GetPTF("( A mul B )/X eq TEST").aSerialized("{{{A mul B}/X} eq TEST}"); GetPTF("( 1 mul 2 )/X eq TEST").aSerialized("{{{1 mul 2}/X} eq TEST}"); // CASE 1 EdmEntityType edmEtAllTypes = edmInfo.getTypeEtAllTypes(); GetPTF(edmEtAllTypes, "( 1 mul 2 )/X eq TEST").aExMsgText( "Leftside of method operator at position 12 is not a property in \"( 1 mul 2 )/X eq TEST\"."); // CASE 2 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter=notsupportedfunction('a') // -->Unknown function 'notsupportedfunction' at position 0. GetPTF("notsupportedfunction('a')").aExMsgText( "Unknown function \"notsupportedfunction\" at position 1 in \"notsupportedfunction('a')\"."); // CASE 3 // http://services.odata.org/Northwind/Northwind.svc/Products/?$filter=notsupportedfunction('a') // -->Unknown function 'notsupportedfunction' at position 0. GetPTF("notsupportedfunction ('a')").aExMsgText( "Unknown function \"notsupportedfunction\" at position 1 in \"notsupportedfunction ('a')\"."); // CASE 4 // Use \ instead of / GetPTF("Address\\NotAProperty").aExMsgText( "Error while tokenizing a ODATA expression on token \"\\\" at position 8 in \"Address\\NotAProperty\"."); // CASE 5 GetPTF("-(-(- 2d)))").aExMsgText("Invalid token \")\" detected after parsing at position 11 in \"-(-(- 2d)))\"."); // CASE 6 GetPTF("a b").aExMsgText("Invalid token \"b\" detected after parsing at position 3 in \"a b\"."); // CASE 7 GetPTF("a eq b b").aExMsgText("Invalid token \"b\" detected after parsing at position 8 in \"a eq b b\"."); // CASE 8 GetPTF(edmEtAllTypes, "year(Complex)").aExMsgText( "No applicable method found for \"year\" at position 1 in \"year(Complex)\" for the specified argument types."); // CASE 9 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=1%20add%202 // -->Expression of type 'System.Boolean' expected at position 0. GetPTF_onlyBinary("1 add 2").aExMsgText( "Expression of type \"Edm.Boolean\" expected at position 1 in \"1 add 2\" (actual type is \"Edm.SByte\")."); // CASE 10 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=1%20add // -->Expression expected at position 5. GetPTF_onlyBinary("1 add").aExMsgText("Expression expected after position 5 in \"1 add\"."); // CASE 11 // http://services.odata.org/Northwind/Northwind.svc/Products(1)/Supplier?$filter=1%20add // -->Expression expected at position 5. GetPTF_onlyBinary("1 add ").aExMsgText("Expression expected after position 5 in \"1 add \"."); } }