    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jxpath.ri;
    17
    18  import org.apache.commons.jxpath.JXPathContext;
    19  import org.apache.commons.jxpath.JXPathTestCase;
    20  import org.apache.commons.jxpath.ri.compiler.Constant;
    21  import org.apache.commons.jxpath.ri.compiler.CoreFunction;
    22  import org.apache.commons.jxpath.ri.compiler.CoreOperationAdd;
    23  import org.apache.commons.jxpath.ri.compiler.CoreOperationAnd;
    24  import org.apache.commons.jxpath.ri.compiler.CoreOperationDivide;
    25  import org.apache.commons.jxpath.ri.compiler.CoreOperationEqual;
    26  import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThan;
    27  import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThanOrEqual;
    28  import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThan;
    29  import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThanOrEqual;
    30  import org.apache.commons.jxpath.ri.compiler.CoreOperationMod;
    31  import org.apache.commons.jxpath.ri.compiler.CoreOperationMultiply;
    32  import org.apache.commons.jxpath.ri.compiler.CoreOperationNegate;
    33  import org.apache.commons.jxpath.ri.compiler.CoreOperationNotEqual;
    34  import org.apache.commons.jxpath.ri.compiler.CoreOperationOr;
    35  import org.apache.commons.jxpath.ri.compiler.CoreOperationSubtract;
    36  import org.apache.commons.jxpath.ri.compiler.CoreOperationUnion;
    37  import org.apache.commons.jxpath.ri.compiler.ExpressionPath;
    38  import org.apache.commons.jxpath.ri.compiler.ExtensionFunction;
    39  import org.apache.commons.jxpath.ri.compiler.LocationPath;
    40  import org.apache.commons.jxpath.ri.compiler.NameAttributeTest;
    41  import org.apache.commons.jxpath.ri.compiler.VariableReference;
    42
    43  /***
    44   * Test compiler.
    45   *
    46   * @author Dmitri Plotnikov
    47   * @version $Revision: 1.5 $ $Date: 2004/02/29 14:17:44 $
    48   */
    49
    50  public class JXPathCompiledExpressionTest extends JXPathTestCase {
    51
    52      /***
    53       * Construct a new instance of this test case.
    54       *
    55       * @param name Name of the test case
    56       */
    57      public JXPathCompiledExpressionTest(String name) {
    58          super(name);
    59      }
    60
    61      public void testConstant() {
    62          assertXPathExpression("1", Constant.class);
    63          assertXPathExpression("1.5", Constant.class);
    64          assertXPathExpression("'foo'", Constant.class);
    65      }
    66
    67      public void testCoreFunction() {
    68          assertXPathExpression("last()", CoreFunction.class);
    69          assertXPathExpression("position()", CoreFunction.class);
    70          assertXPathExpression("count(book)", CoreFunction.class);
    71          assertXPathExpression("id(13)", CoreFunction.class);
    72          assertXPathExpression("local-name()", CoreFunction.class);
    73          assertXPathExpression("local-name(book)", CoreFunction.class);
    74          assertXPathExpression("namespace-uri()", CoreFunction.class);
    75          assertXPathExpression("namespace-uri(book)", CoreFunction.class);
    76          assertXPathExpression("name()", CoreFunction.class);
    77          assertXPathExpression("name(book)", CoreFunction.class);
    78          assertXPathExpression("string(3)", CoreFunction.class);
    79          assertXPathExpression("concat('a', 'b')", CoreFunction.class);
    80          assertXPathExpression("starts-with('a', 'b')", CoreFunction.class);
    81          assertXPathExpression("contains('a', 'b')", CoreFunction.class);
    82          assertXPathExpression("substring-before('a', 1)", CoreFunction.class);
    83          assertXPathExpression("substring-after('a', 2)", CoreFunction.class);
    84          assertXPathExpression("substring('a', 2)", CoreFunction.class);
    85          assertXPathExpression("substring('a', 2, 3)", CoreFunction.class);
    86          assertXPathExpression("string-length('a')", CoreFunction.class);
    87          assertXPathExpression("normalize-space('a')", CoreFunction.class);
    88          assertXPathExpression("translate('a', 'b', 'c')", CoreFunction.class);
    89          assertXPathExpression("boolean('true')", CoreFunction.class);
    90          assertXPathExpression("not(1)", CoreFunction.class);
    91          assertXPathExpression("true()", CoreFunction.class);
    92          assertXPathExpression("false()", CoreFunction.class);
    93          assertXPathExpression("lang('fr')", CoreFunction.class);
    94          assertXPathExpression("number('12')", CoreFunction.class);
    95          assertXPathExpression("sum(book/price)", CoreFunction.class);
    96          assertXPathExpression("floor(11.4)", CoreFunction.class);
    97          assertXPathExpression("ceiling(11.4)", CoreFunction.class);
    98          assertXPathExpression("round(11.4)", CoreFunction.class);
    99          assertXPathExpression("key('title', 'Hobbit')", CoreFunction.class);
    100         assertXPathExpression("format-number(12, '##')", CoreFunction.class);
    101     }
    102
    103     public void testCoreOperationAnd() {
    104         assertXPathExpression(
    105             "2 and 4",
    106             CoreOperationAnd.class);
    107
    108         assertXPathExpression(
    109             "2 > 1 and 4 < 5",
    110             CoreOperationAnd.class);
    111     }
    112
    113     public void testCoreOperationOr() {
    114         assertXPathExpression(
    115             "2 or 4",
    116             CoreOperationOr.class);
    117
    118         assertXPathExpression(
    119             "2 > 1 or 4 < 5",
    120             CoreOperationOr.class);
    121
    122         assertXPathExpression(
    123             "1 > 1 and 2 <= 2 or 3 = 4",
    124             CoreOperationOr.class);
    125     }
    126
    127     public void testCoreOperationEqual() {
    128         assertXPathExpression(
    129             "2 = 4",
    130             CoreOperationEqual.class);
    131
    132         assertXPathExpression(
    133             "2 + 1 = 3",
    134             CoreOperationEqual.class);
    135     }
    136
    137     public void testCoreOperationNameAttributeTest() {
    138         assertXPathExpression(
    139             "@name = 'bar'",
    140             NameAttributeTest.class);
    141     }
    142
    143     public void testCoreOperationNotEqual() {
    144         assertXPathExpression(
    145             "2 != 4",
    146             CoreOperationNotEqual.class);
    147
    148         assertXPathExpression(
    149             "2 + 1 != 3",
    150             CoreOperationNotEqual.class);
    151     }
    152
    153     public void testCoreOperationLessThan() {
    154         assertXPathExpression(
    155             "3<4",
    156             CoreOperationLessThan.class,
    157             "3 < 4");
    158
    159         assertXPathExpression(
    160             "3<(2>=1)",
    161             CoreOperationLessThan.class,
    162             "3 < (2 >= 1)");
    163     }
    164
    165     public void testCoreOperationLessThanOrEqual() {
    166         assertXPathExpression(
    167             "3<=4",
    168             CoreOperationLessThanOrEqual.class,
    169             "3 <= 4");
    170
    171         assertXPathExpression(
    172             "3<=(2>=1)",
    173             CoreOperationLessThanOrEqual.class,
    174             "3 <= (2 >= 1)");
    175     }
    176
    177     public void testCoreOperationGreaterThan() {
    178         assertXPathExpression(
    179             "3>4",
    180             CoreOperationGreaterThan.class,
    181             "3 > 4");
    182
    183         assertXPathExpression(
    184             "3>(2>=1)",
    185             CoreOperationGreaterThan.class,
    186             "3 > (2 >= 1)");
    187
    188         assertXPathExpression(
    189             "1 > (1 and 2 <= (2 or 3) = 4)",
    190             CoreOperationGreaterThan.class);
    191     }
    192
    193     public void testCoreOperationGreaterThanOrEqual() {
    194         assertXPathExpression(
    195             "3>=4",
    196             CoreOperationGreaterThanOrEqual.class,
    197             "3 >= 4");
    198
    199         assertXPathExpression(
    200             "3>=(2>=1)",
    201             CoreOperationGreaterThanOrEqual.class,
    202             "3 >= (2 >= 1)");
    203     }
    204
    205     public void testCoreOperationDivide() {
    206         assertXPathExpression(
    207             "2 div 4",
    208             CoreOperationDivide.class);
    209
    210         assertXPathExpression(
    211             "2|3 div -3",
    212             CoreOperationDivide.class,
    213             "2 | 3 div -3");
    214     }
    215
    216     public void testCoreOperationMod() {
    217         assertXPathExpression(
    218             "2 mod 4",
    219             CoreOperationMod.class);
    220
    221         assertXPathExpression(
    222             "2|3 mod -3",
    223             CoreOperationMod.class,
    224             "2 | 3 mod -3");
    225     }
    226
    227     public void testCoreOperationMultiply() {
    228         assertXPathExpression(
    229             "2*4",
    230             CoreOperationMultiply.class,
    231             "2 * 4");
    232
    233         assertXPathExpression(
    234             "2*(3 + 1)",
    235             CoreOperationMultiply.class,
    236             "2 * (3 + 1)");
    237     }
    238
    239     public void testCoreOperationMinus() {
    240         assertXPathExpression(
    241             "1 - 1",
    242             CoreOperationSubtract.class);
    243
    244         assertXPathExpression(
    245             "1 - 1 - 2",
    246             CoreOperationSubtract.class);
    247
    248         assertXPathExpression(
    249             "1 - (1 - 2)",
    250             CoreOperationSubtract.class);
    251     }
    252
    253     public void testCoreOperationSum() {
    254         assertXPathExpression(
    255             "3 + 1 + 4",
    256             CoreOperationAdd.class);
    257
    258         assertXPathExpression(
    259             "(3 + 1) + 4",
    260             CoreOperationAdd.class,
    261             "3 + 1 + 4");
    262
    263         assertXPathExpression(
    264             "3 + (1 + 4)",
    265             CoreOperationAdd.class,
    266             "3 + 1 + 4");
    267
    268         assertXPathExpression(
    269             "3 + -1",
    270             CoreOperationAdd.class,
    271             "3 + -1");
    272
    273         assertXPathExpression(
    274             "2*-3 + -1",
    275             CoreOperationAdd.class,
    276             "2 * -3 + -1");
    277     }
    278
    279     public void testCoreOperationUnaryMinus() {
    280         assertXPathExpression("-3", CoreOperationNegate.class);
    281         assertXPathExpression("-(3 + 1)", CoreOperationNegate.class);
    282     }
    283
    284     public void testCoreOperationUnion() {
    285         assertXPathExpression(
    286             "3 | 1 | 4",
    287             CoreOperationUnion.class);
    288     }
    289
    290     public void testExpressionPath() {
    291         assertXPathExpression(
    292             "$x/foo/bar",
    293             ExpressionPath.class);
    294         assertXPathExpression(
    295             "(2 + 2)/foo/bar",
    296             ExpressionPath.class);
    297         assertXPathExpression(
    298             "$x[3][2 + 2]/foo/bar",
    299             ExpressionPath.class);
    300     }
    301
    302     public void testExtensionFunction() {
    303         assertXPathExpression(
    304             "my:function(3, other.function())",
    305             ExtensionFunction.class);
    306     }
    307
    308     public void testLocationPathAxisSelf() {
    309         assertXPathExpression(
    310             "self::foo:bar",
    311             LocationPath.class);
    312
    313         assertXPathExpression(
    314             ".",
    315             LocationPath.class);
    316     }
    317
    318     public void testLocationPathAxisChild() {
    319         assertXPathExpression(
    320             "child::foo:bar",
    321             LocationPath.class,
    322             "foo:bar");
    323
    324         assertXPathExpression(
    325             "foo:bar",
    326             LocationPath.class);
    327
    328         assertXPathExpression(
    329             "/foo:bar",
    330             LocationPath.class);
    331
    332         assertXPathExpression(
    333             "/foo/bar",
    334             LocationPath.class);
    335
    336         assertXPathExpression(
    337             "*",
    338             LocationPath.class);
    339
    340         assertXPathExpression(
    341             "foo:*",
    342             LocationPath.class);
    343
    344     }
    345
    346     public void testLocationPathAxisParent() {
    347         assertXPathExpression(
    348             "parent::foo:bar",
    349             LocationPath.class);
    350
    351         assertXPathExpression(
    352             "..",
    353             LocationPath.class);
    354     }
    355
    356     public void testLocationPathAxisAttribute() {
    357         assertXPathExpression(
    358             "attribute::foo:bar",
    359             LocationPath.class,
    360             "@foo:bar");
    361
    362         assertXPathExpression(
    363             "@foo:bar",
    364             LocationPath.class);
    365
    366         assertXPathExpression(
    367             "../@foo:bar",
    368             LocationPath.class);
    369
    370         assertXPathExpression(
    371             "@*",
    372             LocationPath.class);
    373
    374         assertXPathExpression(
    375             "@*[last()]",
    376             LocationPath.class);
    377     }
    378
    379     public void testLocationPathAxisDescendant() {
    380         assertXPathExpression(
    381             "descendant::foo:bar",
    382             LocationPath.class);
    383     }
    384
    385     public void testLocationPathAxisDescendantOrSelf() {
    386         assertXPathExpression(
    387             "descendant-or-self::foo:bar",
    388             LocationPath.class);
    389
    390         assertXPathExpression(
    391             "//foo",
    392             LocationPath.class);
    393
    394         assertXPathExpression(
    395             "foo//bar",
    396             LocationPath.class);
    397     }
    398
    399     public void testLocationPathAxisOther() {
    400         assertXPathExpression(
    401             "ancestor::foo:bar",
    402             LocationPath.class);
    403
    404         assertXPathExpression(
    405             "ancestor-or-self::foo:bar",
    406             LocationPath.class);
    407
    408         assertXPathExpression(
    409             "namespace::foo:bar",
    410             LocationPath.class);
    411
    412         assertXPathExpression(
    413             "preceding::foo:bar",
    414             LocationPath.class);
    415
    416         assertXPathExpression(
    417             "preceding-sibling::foo:bar",
    418             LocationPath.class);
    419
    420         assertXPathExpression(
    421             "following::foo:bar",
    422             LocationPath.class);
    423
    424         assertXPathExpression(
    425             "following-sibling::foo:bar",
    426             LocationPath.class);
    427     }
    428
    429     public void testLocationPathNodeTest() {
    430         assertXPathExpression(
    431             "node()",
    432             LocationPath.class);
    433
    434         assertXPathExpression(
    435             "text()",
    436             LocationPath.class);
    437
    438         assertXPathExpression(
    439             "comment()",
    440             LocationPath.class);
    441
    442         assertXPathExpression(
    443             "processing-instruction()",
    444             LocationPath.class);
    445
    446         assertXPathExpression(
    447             "processing-instruction('test')",
    448             LocationPath.class);
    449     }
    450
    451     public void testVariableReference() {
    452         assertXPathExpression(
    453             "$x",
    454             VariableReference.class);
    455
    456         assertXPathExpression(
    457             "$x:y",
    458             VariableReference.class);
    459     }
    460
    461     /***
    462      * Compiles the xpath into an Expression, checks the expression
    463      * class, converts the expression to string and checks that the string
    464      * matches the expected one.
    465      */
    466     private void assertXPathExpression(
    467         String xpath,
    468         Class expectedClass,
    469         String expected)
    470     {
    471         JXPathCompiledExpression expression =
    472             (JXPathCompiledExpression) JXPathContext.compile(xpath);
    473
    474         assertEquals(
    475             "Expression class for " + xpath,
    476             expectedClass,
    477             expression.getExpression().getClass());
    478
    479         assertEquals(
    480             "Expression toString() for " + xpath,
    481             expected,
    482             expression.getExpression().toString());
    483     }
    484
    485     private void assertXPathExpression(
    486         String xpath,
    487         Class expectedClass)
    488     {
    489         assertXPathExpression(xpath, expectedClass, xpath);
    490     }
    491
    492 }