    1   /*
    2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/test/org/jaxen/saxpath/base/XPathReaderTest.java,v 1.30 2005/09/14 13:04:43 elharo Exp $
    3    * $Revision: 1.30 $
    4    * $Date: 2005/09/14 13:04:43 $
    5    *
    6    * ====================================================================
    7    *
    8    * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
    9    * All rights reserved.
    10   *
    11   * Redistribution and use in source and binary forms, with or without
    12   * modification, are permitted provided that the following conditions
    13   * are met:
    14   *
    15   * 1. Redistributions of source code must retain the above copyright
    16   *    notice, this list of conditions, and the following disclaimer.
    17   *
    18   * 2. Redistributions in binary form must reproduce the above copyright
    19   *    notice, this list of conditions, and the disclaimer that follows
    20   *    these conditions in the documentation and/or other materials
    21   *    provided with the distribution.
    22   *
    23   * 3. The name "Jaxen" must not be used to endorse or promote products
    24   *    derived from this software without prior written permission.  For
    25   *    written permission, please contact license@jaxen.org.
    26   *
    27   * 4. Products derived from this software may not be called "Jaxen", nor
    28   *    may "Jaxen" appear in their name, without prior written permission
    29   *    from the Jaxen Project Management (pm@jaxen.org).
    30   *
    31   * In addition, we request (but do not require) that you include in the
    32   * end-user documentation provided with the redistribution and/or in the
    33   * software itself an acknowledgement equivalent to the following:
    34   *     "This product includes software developed by the
    35   *      Jaxen Project (http://www.jaxen.org/)."
    36   * Alternatively, the acknowledgment may be graphical using the logos
    37   * available at http://www.jaxen.org/
    38   *
    39   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    40   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    41   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    42   * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
    43   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    44   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    45   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    46   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    47   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    48   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    49   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    50   * SUCH DAMAGE.
    51   *
    52   * ====================================================================
    53   * This software consists of voluntary contributions made by many
    54   * individuals on behalf of the Jaxen Project and was originally
    55   * created by bob mcwhirter <bob@werken.com> and
    56   * James Strachan <jstrachan@apache.org>.  For more information on the
    57   * Jaxen Project, please see <http://www.jaxen.org/>.
    58   *
    59   * $Id: XPathReaderTest.java,v 1.30 2005/09/14 13:04:43 elharo Exp $
    60   */
    61
    62
    63  package org.jaxen.saxpath.base;
    64
    65  import java.io.IOException;
    66
    67  import javax.xml.parsers.DocumentBuilder;
    68  import javax.xml.parsers.DocumentBuilderFactory;
    69  import javax.xml.parsers.ParserConfigurationException;
    70
    71  import junit.framework.TestCase;
    72
    73  import org.jaxen.JaxenException;
    74  import org.jaxen.XPath;
    75  import org.jaxen.dom.DOMXPath;
    76  import org.jaxen.saxpath.Axis;
    77  import org.jaxen.saxpath.SAXPathException;
    78  import org.jaxen.saxpath.XPathSyntaxException;
    79  import org.w3c.dom.Document;
    80  import org.xml.sax.SAXException;
    81
    82  public class XPathReaderTest extends TestCase
    83  {
    84      private ConformanceXPathHandler expected;
    85      private ConformanceXPathHandler actual;
    86      private Document doc;
    87
    88      private XPathReader reader;
    89      private String text;
    90
    91      private String[] paths = {
    92          "/foo/bar[@a='1' and @b='2']",
    93          "/foo/bar[@a='1' and @b!='2']",
    94          "$varname[@a='1']",
    95          "//attribute::*[.!='crunchy']",
    96          "'//*[contains(string(text()),\"yada yada\")]'",
    97      };
    98
    99      private String[][] bogusPaths = {
    100         new String[]{"chyld::foo", "Expected valid axis name instead of [chyld]"},
    101         new String[]{"foo/tacos()", "Expected node-type"},
    102         new String[]{"foo/tacos()", "Expected node-type"},
    103         new String[]{"*:foo", "Unexpected ':'"},
    104         new String[]{"/foo/bar[baz", "Expected: ]"},
    105         new String[]{"/cracker/cheese[(mold > 1) and (sense/taste", "Expected: )"},
    106         new String[]{"//", "Location path cannot end with //"},
    107         new String[]{"foo/$variable/foo", "Expected one of '.', '..', '@', '*', <QName>"}
    108     };
    109
    110     public XPathReaderTest( String name )
    111     {
    112         super( name );
    113     }
    114
    115     public void setUp() throws ParserConfigurationException, SAXException, IOException
    116     {
    117         this.reader = new XPathReader();
    118         this.text = null;
    119
    120         this.actual = new ConformanceXPathHandler();
    121         this.expected = new ConformanceXPathHandler();
    122
    123         this.reader.setXPathHandler( this.actual );
    124
    125         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    126         factory.setNamespaceAware(true);
    127         DocumentBuilder builder = factory.newDocumentBuilder();
    128         doc = builder.parse( "xml/basic.xml" );
    129
    130     }
    131
    132     public void tearDown()
    133     {
    134         this.reader = null;
    135         this.text = null;
    136     }
    137
    138     // --------------------------------------------------------------------------------
    139     // --------------------------------------------------------------------------------
    140
    141
    142     public void testPaths() throws SAXPathException
    143     {
    144
    145         for( int i = 0; i < paths.length; ++i )
    146         {
    147             reader.parse( paths[i] );
    148         }
    149     }
    150
    151     public void testBogusPaths() throws SAXPathException
    152     {
    153
    154         for( int i = 0; i < bogusPaths.length; ++i )
    155         {
    156             final String[] bogusPath = bogusPaths[i];
    157
    158             try
    159             {
    160                 reader.parse( bogusPath[0] );
    161                 fail( "Should have thrown XPathSyntaxException for " + bogusPath[0]);
    162             }
    163             catch( XPathSyntaxException e )
    164             {
    165                 assertEquals( bogusPath[1], e.getMessage() );
    166             }
    167         }
    168     }
    169
    170     public void testChildrenOfNumber() throws SAXPathException
    171     {
    172         try
    173         {
    174             reader.parse( "1/child::test" );
    175             fail( "Should have thrown XPathSyntaxException for 1/child::test");
    176         }
    177         catch( XPathSyntaxException e )
    178         {
    179             assertEquals( "Node-set expected", e.getMessage() );
    180         }
    181     }
    182
    183     public void testChildIsNumber() throws SAXPathException
    184     {
    185         try
    186         {
    187             reader.parse( "jane/3" );
    188             fail( "Should have thrown XPathSyntaxException for jane/3");
    189         }
    190         catch( XPathSyntaxException e )
    191         {
    192             assertEquals( "Expected one of '.', '..', '@', '*', <QName>", e.getMessage() );
    193         }
    194
    195     }
    196
    197     public void testNumberOrNumber()
    198     {
    199
    200         try
    201         {
    202             XPath xpath = new DOMXPath( "4 | 5" );
    203             xpath.selectNodes( doc );
    204             fail( "Should have thrown XPathSyntaxException for 4 | 5");
    205         }
    206         catch( JaxenException e )
    207         {
    208             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
    209         }
    210     }
    211
    212     public void testStringOrNumber()
    213     {
    214
    215         try
    216         {
    217             XPath xpath = new DOMXPath( "\"test\" | 5" );
    218             xpath.selectNodes( doc );
    219             fail( "Should have thrown XPathSyntaxException for \"test\" | 5");
    220         }
    221         catch( JaxenException e )
    222         {
    223             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
    224         }
    225     }
    226
    227     public void testStringOrString()
    228     {
    229
    230         try
    231         {
    232             XPath xpath = new DOMXPath( "\"test\" | \"festival\"" );
    233             xpath.selectNodes( doc );
    234             fail( "Should have thrown XPathSyntaxException for \"test\" | 5");
    235         }
    236         catch( JaxenException e )
    237         {
    238             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
    239         }
    240
    241     }
    242
    243     public void testUnionofNodesAndNonNodes()
    244     {
    245
    246         try
    247         {
    248             XPath xpath = new DOMXPath( "count(//*) | //* " );
    249             xpath.selectNodes( doc );
    250             fail( "Should have thrown XPathSyntaxException for \"count(//*) | //* ");
    251         }
    252         catch( JaxenException e )
    253         {
    254             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
    255         }
    256     }
    257
    258     public void testValidAxis() throws SAXPathException
    259     {
    260         reader.parse( "child::foo" );
    261     }
    262
    263     public void testInvalidAxis() throws SAXPathException
    264     {
    265
    266         try
    267         {
    268             reader.parse( "chyld::foo" );
    269             fail( "Should have thrown XPathSyntaxException" );
    270         }
    271         catch( XPathSyntaxException ex )
    272         {
    273             assertNotNull(ex.getMessage());
    274         }
    275
    276     }
    277
    278     public void testSimpleNameStep() throws SAXPathException
    279     {
    280         this.text = "foo";
    281         this.reader.setUpParse( this.text );
    282         this.reader.step( );
    283         this.expected.startNameStep( Axis.CHILD,
    284                                   "",
    285                                   "foo" );
    286         this.expected.endNameStep();
    287         assertEquals( this.expected,
    288           this.actual );
    289
    290     }
    291
    292     public void testNameStepWithAxisAndPrefix() throws SAXPathException
    293     {
    294         this.text = "parent::foo:bar";
    295         this.reader.setUpParse( this.text );
    296         this.reader.step( );
    297         this.expected.startNameStep( Axis.PARENT,
    298                                   "foo",
    299                                   "bar" );
    300         this.expected.endNameStep();
    301         assertEquals( this.expected,
    302           this.actual );
    303
    304     }
    305
    306     public void testNodeStepWithAxis() throws SAXPathException
    307     {
    308
    309         this.text = "parent::node()";
    310         this.reader.setUpParse( this.text );
    311         this.reader.step();
    312         this.expected.startAllNodeStep( Axis.PARENT );
    313         this.expected.endAllNodeStep();
    314         assertEquals( this.expected,
    315           this.actual );
    316
    317     }
    318
    319     public void testProcessingInstructionStepWithName() throws SAXPathException
    320     {
    321         this.text = "parent::processing-instruction('cheese')";
    322         this.reader.setUpParse( this.text );
    323         this.reader.step( );
    324         this.expected.startProcessingInstructionNodeStep( Axis.PARENT,
    325                                                            "cheese" );
    326         this.expected.endProcessingInstructionNodeStep();
    327         assertEquals( this.expected,
    328           this.actual );
    329     }
    330
    331     public void testProcessingInstructionStepNoName() throws SAXPathException
    332     {
    333         this.text = "parent::processing-instruction()";
    334         this.reader.setUpParse( this.text );
    335         this.reader.step( );
    336         this.expected.startProcessingInstructionNodeStep( Axis.PARENT,
    337                                                        "" );
    338         this.expected.endProcessingInstructionNodeStep();
    339         assertEquals( this.expected,
    340           this.actual );
    341
    342     }
    343
    344     public void testAllNodeStep() throws SAXPathException
    345     {
    346
    347         this.text = "parent::node()";
    348         this.reader.setUpParse( this.text );
    349         this.reader.step( );
    350         this.expected.startAllNodeStep( Axis.PARENT );
    351         this.expected.endAllNodeStep();
    352         assertEquals( this.expected,
    353           this.actual );
    354
    355     }
    356
    357     public void testTextNodeStep() throws SAXPathException
    358     {
    359
    360         this.text = "parent::text()";
    361         this.reader.setUpParse( this.text );
    362         this.reader.step( );
    363         this.expected.startTextNodeStep( Axis.PARENT );
    364         this.expected.endTextNodeStep();
    365         assertEquals( this.expected,
    366           this.actual );
    367
    368     }
    369
    370     public void testCommentNodeStep() throws SAXPathException
    371     {
    372
    373         this.text = "parent::comment()";
    374         this.reader.setUpParse( this.text );
    375         this.reader.step( );
    376         this.expected.startCommentNodeStep( Axis.PARENT );
    377         this.expected.endCommentNodeStep();
    378         assertEquals( this.expected,
    379           this.actual );
    380
    381     }
    382
    383     public void testLocationPathStartsWithVariable() throws SAXPathException
    384     {
    385
    386         reader.parse( "$variable/foo" );
    387
    388     }
    389
    390     public void testLocationPathStartsWithParentheses() throws SAXPathException
    391     {
    392
    393         reader.parse( "(//x)/foo" );
    394
    395     }
    396
    397     public void testRelativeLocationPath() throws SAXPathException
    398     {
    399
    400         this.text = "foo/bar/baz";
    401         this.reader.setUpParse( this.text );
    402         this.reader.locationPath( false );
    403         this.expected.startRelativeLocationPath();
    404         this.expected.startNameStep( Axis.CHILD,
    405                                   "",
    406                                   "foo" );
    407         this.expected.endNameStep();
    408         this.expected.startNameStep( Axis.CHILD,
    409                                   "",
    410                                   "bar" );
    411         this.expected.endNameStep();
    412         this.expected.startNameStep( Axis.CHILD,
    413                                   "",
    414                                   "baz" );
    415         this.expected.endNameStep();
    416         this.expected.endRelativeLocationPath();
    417         assertEquals( this.expected,
    418           this.actual );
    419
    420     }
    421
    422     public void testAbsoluteLocationPath() throws SAXPathException
    423     {
    424
    425         this.text = "/foo/bar/baz";
    426         this.reader.setUpParse( this.text );
    427         this.reader.locationPath( true );
    428         this.expected.startAbsoluteLocationPath();
    429         this.expected.startNameStep( Axis.CHILD,
    430                                   "",
    431                                   "foo" );
    432         this.expected.endNameStep();
    433         this.expected.startNameStep( Axis.CHILD,
    434                                   "",
    435                                   "bar" );
    436         this.expected.endNameStep();
    437         this.expected.startNameStep( Axis.CHILD,
    438                                   "",
    439                                   "baz" );
    440         this.expected.endNameStep();
    441         this.expected.endAbsoluteLocationPath();
    442         assertEquals( this.expected,
    443           this.actual );
    444
    445     }
    446
    447     public void testNoSpaceAfterDiv() throws JaxenException
    448     {
    449         XPath xpath = new DOMXPath( "105 div10" );
    450         Double result = (Double) xpath.evaluate(doc);
    451         assertEquals(10.5, result.doubleValue(), 0.000001);
    452     }
    453
    454
    455     public void testNoSpaceAfterMod() throws JaxenException
    456     {
    457         XPath xpath = new DOMXPath( "105 mod10" );
    458         Double result = (Double) xpath.evaluate(doc);
    459         assertEquals(5, result.intValue());
    460     }
    461
    462
    463     public void testNoSpaceAfterPlus() throws JaxenException
    464     {
    465         XPath xpath = new DOMXPath( "105 +10" );
    466         Double result = (Double) xpath.evaluate(doc);
    467         assertEquals(115, result.intValue());
    468     }
    469
    470     public void testNoSpaceAfterAnd() throws JaxenException
    471     {
    472         XPath xpath = new DOMXPath("true() andfalse()");
    473         Boolean result = (Boolean) xpath.evaluate(doc);
    474         assertFalse(result.booleanValue());
    475     }
    476
    477     public void testNoSpaceAfterOr() throws JaxenException
    478     {
    479         XPath xpath = new DOMXPath("true() orfalse()");
    480         Boolean result = (Boolean) xpath.evaluate(doc);
    481         assertTrue(result.booleanValue());
    482     }
    483
    484     public void testAndImmediatelyFollowedByRelativeLocationPath() throws JaxenException
    485     {
    486         XPath xpath = new DOMXPath("true() andfoo");
    487         Boolean result = (Boolean) xpath.evaluate(doc);
    488         assertTrue(result.booleanValue());
    489     }
    490
    491 }