1   /*
2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/test/org/jaxen/saxpath/base/XPathReaderTest.java,v 1.16 2005/02/08 20:07:53 elharo Exp $
3    * $Revision: 1.16 $
4    * $Date: 2005/02/08 20:07:53 $
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.16 2005/02/08 20:07:53 elharo Exp $
60   */
61  
62  
63  package org.jaxen.saxpath.base;
64  
65  import javax.xml.parsers.DocumentBuilder;
66  import javax.xml.parsers.DocumentBuilderFactory;
67  
68  import junit.framework.TestCase;
69  
70  import org.jaxen.JaxenException;
71  import org.jaxen.XPath;
72  import org.jaxen.dom.DOMXPath;
73  import org.jaxen.saxpath.Axis;
74  import org.jaxen.saxpath.Operator;
75  import org.jaxen.saxpath.XPathSyntaxException;
76  import org.jaxen.saxpath.conformance.ConformanceXPathHandler;
77  import org.w3c.dom.Document;
78  
79  public class XPathReaderTest extends TestCase
80  {
81      private ConformanceXPathHandler expected;
82      private ConformanceXPathHandler actual;
83  
84      private XPathReader reader;
85      private String text;
86  
87      private String[] paths = {
88          "/foo/bar[@a='1' and @b='2']",
89          "/foo/bar[@a='1' and @b!='2']",
90          "//attribute::*[.!='crunchy']",
91          "'//*[contains(string(text()),\"yada yada\")]'",
92      };
93  
94      private String[][] bogusPaths = {
95          new String[]{"chyld::foo", "Expected valid axis name instead of [chyld]"},
96          new String[]{"foo/tacos()", "Expected node-type"},
97          new String[]{"foo/tacos()", "Expected node-type"},
98          new String[]{"*:foo", "Unexpected ':'"},
99          new String[]{"/foo/bar[baz", "Expected: ]"},
100         new String[]{"/cracker/cheese[(mold > 1) and (sense/taste", "Expected: )"},
101         new String[]{"//", "Location path cannot end with //"}
102     };
103 
104     public XPathReaderTest( String name )
105     {
106         super( name );
107     }
108 
109     public void setUp()
110     {
111         setReader( new XPathReader() );
112         setText( null );
113 
114         this.actual = new ConformanceXPathHandler();
115         this.expected = new ConformanceXPathHandler();
116 
117         getReader().setXPathHandler( actual() );
118     }
119 
120     public void tearDown()
121     {
122         setReader( null );
123         setText( null );
124     }
125 
126     // --------------------------------------------------------------------------------
127     // --------------------------------------------------------------------------------
128 
129 
130     public void testPaths()
131     {
132         XPathReader reader = new XPathReader();
133 
134         System.out.println( "Valid Expressions" );
135 
136         for( int i = 0; i < paths.length; ++i )
137         {
138             System.out.println( "----------------------------------------" );
139             System.out.println( paths[i] );
140             System.out.println( "----------------------------------------" );
141             try
142             {
143                 reader.parse( paths[i] );
144             }
145             catch( org.jaxen.saxpath.SAXPathException e )
146             {
147                 e.printStackTrace();
148                 fail( e.getMessage() );
149             }
150             catch( Exception e )
151             {
152                 fail( e.getMessage() );
153             }
154         }
155     }
156 
157     public void testBogusPaths()
158     {
159         XPathReader reader = new XPathReader();
160 
161         System.out.println( "Bogus Expressions" );
162 
163         for( int i = 0; i < bogusPaths.length; ++i )
164         {
165             final String[] bogusPath = bogusPaths[i];
166             System.out.println( "----------------------------------------" );
167             System.out.println( bogusPath[0] );
168             System.out.println( "----------------------------------------" );
169 
170             try
171             {
172                 reader.parse( bogusPath[0] );
173 
174                 fail( "Should have thrown XPathSyntaxException for " + bogusPath[0]);
175             }
176             catch( XPathSyntaxException e )
177             {
178                 assertEquals( bogusPath[1], e.getMessage() );
179             }
180             catch( org.jaxen.saxpath.SAXPathException e )
181             {
182                 fail( e.getMessage() );
183             }
184             catch( Exception e )
185             {
186                 fail( e.getMessage() );
187             }
188         }
189     }
190 
191     public void testChildrenOfNumber()
192     {
193         XPathReader reader = new XPathReader();
194         try
195         {
196             reader.parse( "1/child::test" );
197             fail( "Should have thrown XPathSyntaxException for 1/child::test");
198         }
199         catch( XPathSyntaxException e )
200         {
201             assertEquals( "Node-set expected", e.getMessage() );
202         }
203         catch( org.jaxen.saxpath.SAXPathException e )
204         {
205             fail( e.getMessage() );
206         }
207         catch( Exception e )
208         {
209             fail( e.getMessage() );
210         }
211     }
212 
213     public void testChildIsNumber()
214     {
215         XPathReader reader = new XPathReader();
216         try
217         {
218             reader.parse( "jane/3" );
219             fail( "Should have thrown XPathSyntaxException for jane/3");
220         }
221         catch( XPathSyntaxException e )
222         {
223             assertEquals( "Expected one of '.', '..', '@', '*', <QName>", e.getMessage() );
224         }
225         catch( org.jaxen.saxpath.SAXPathException e )
226         {
227             fail( e.getMessage() );
228         }
229         catch( Exception e )
230         {
231             fail( e.getMessage() );
232         }
233     }
234 
235     public void testNumberOrNumber()
236     {
237 
238         try
239         {
240             XPath xpath = new DOMXPath( "4 | 5" );
241 
242             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
243             factory.setNamespaceAware(true);
244             DocumentBuilder builder = factory.newDocumentBuilder();
245         
246             Document doc = builder.parse( "xml/basic.xml" );
247 
248             xpath.selectNodes( doc );
249             fail( "Should have thrown XPathSyntaxException for 4 | 5");
250         }
251         catch( JaxenException e )
252         {
253             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
254         }
255         catch( Exception e )
256         {
257             fail( e.getMessage() );
258         }
259     }
260 
261     public void testStringOrNumber()
262     {
263 
264         try
265         {
266             XPath xpath = new DOMXPath( "\"test\" | 5" );
267 
268             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
269             factory.setNamespaceAware(true);
270             DocumentBuilder builder = factory.newDocumentBuilder();
271         
272             Document doc = builder.parse( "xml/basic.xml" );
273 
274             xpath.selectNodes( doc );
275             fail( "Should have thrown XPathSyntaxException for \"test\" | 5");
276         }
277         catch( JaxenException e )
278         {
279             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
280         }
281         catch( Exception e )
282         {
283             fail( e.getMessage() );
284         }
285     }    
286     
287     public void testStringOrString()
288     {
289 
290         try
291         {
292             XPath xpath = new DOMXPath( "\"test\" | \"festival\"" );
293 
294             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
295             factory.setNamespaceAware(true);
296             DocumentBuilder builder = factory.newDocumentBuilder();
297         
298             Document doc = builder.parse( "xml/basic.xml" );
299 
300             xpath.selectNodes( doc );
301             fail( "Should have thrown XPathSyntaxException for \"test\" | 5");
302         }
303         catch( JaxenException e )
304         {
305             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
306         }
307         catch( Exception e )
308         {
309             fail( e.getMessage() );
310         }
311     }    
312     
313     public void testUnionofNodesAndNonNodes()
314     {
315 
316         try
317         {
318             XPath xpath = new DOMXPath( "count(//*) | //* " );
319 
320             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
321             factory.setNamespaceAware(true);
322             DocumentBuilder builder = factory.newDocumentBuilder();
323         
324             Document doc = builder.parse( "xml/basic.xml" );
325 
326             xpath.selectNodes( doc );
327             fail( "Should have thrown XPathSyntaxException for \"count(//*) | //* ");
328         }
329         catch( JaxenException e )
330         {
331             assertEquals( "Unions are only allowed over node-sets", e.getMessage() );
332         }
333         catch( Exception e )
334         {
335             fail( e.getMessage() );
336         }
337     }    
338     
339     public void testValidAxis()
340     {
341         XPathReader reader = new XPathReader();
342 
343         try
344         {
345             reader.parse( "child::foo" );
346         }
347         catch( org.jaxen.saxpath.SAXPathException e )
348         {
349             fail( e.getMessage() );
350         }
351     }
352 
353     public void testInvalidAxis()
354     {
355         XPathReader reader = new XPathReader();
356 
357         try
358         {
359             reader.parse( "chyld::foo" );
360             fail( "Should have thrown XPathSyntaxException" );
361         }
362         catch( XPathSyntaxException e )
363         {
364             // expected and correct
365         }
366         catch( org.jaxen.saxpath.SAXPathException e )
367         {
368             fail( e.getMessage() );
369         }
370 
371     }
372 
373     public void testSimpleNameStep()
374     {
375         try
376         {
377             setText( "foo" );
378 
379             getReader().setUpParse( getText() );
380 
381             getReader().step( );
382 
383             expected().startNameStep( Axis.CHILD,
384                                       "",
385                                       "foo" );
386             expected().endNameStep();
387 
388             compare();
389         }
390         catch( org.jaxen.saxpath.SAXPathException e )
391         {
392             fail( e.getMessage() );
393         }
394 
395     }
396 
397     public void testNameStepWithAxisAndPrefix()
398     {
399         try
400         {
401             setText( "parent::foo:bar" );
402 
403             getReader().setUpParse( getText() );
404 
405             getReader().step( );
406 
407             expected().startNameStep( Axis.PARENT,
408                                       "foo",
409                                       "bar" );
410             expected().endNameStep();
411 
412             compare();
413         }
414         catch( org.jaxen.saxpath.SAXPathException e )
415         {
416             fail( e.getMessage() );
417         }
418     }
419 
420     public void testNodeStepWithAxis()
421     {
422         try
423         {
424             setText( "parent::node()" );
425 
426             getReader().setUpParse( getText() );
427 
428             getReader().step();
429 
430             expected().startAllNodeStep( Axis.PARENT );
431 
432             expected().endAllNodeStep();
433 
434             compare();
435         }
436         catch( org.jaxen.saxpath.SAXPathException e )
437         {
438             fail( e.getMessage() );
439         }
440     }
441 
442     public void testProcessingInstructionStepWithName()
443     {
444         try
445         {
446             setText( "parent::processing-instruction('cheese')" );
447 
448             getReader().setUpParse( getText() );
449 
450             getReader().step( );
451 
452             expected().startProcessingInstructionNodeStep( Axis.PARENT,
453                                                            "cheese" );
454 
455             expected().endProcessingInstructionNodeStep();
456 
457             compare();
458         }
459         catch( org.jaxen.saxpath.SAXPathException e )
460         {
461             fail( e.getMessage() );
462         }
463     }
464 
465     public void testProcessingInstructionStepNoName()
466     {
467         try
468         {
469             setText( "parent::processing-instruction()" );
470 
471             getReader().setUpParse( getText() );
472 
473             getReader().step( );
474 
475             expected().startProcessingInstructionNodeStep( Axis.PARENT,
476                                                            "" );
477 
478             expected().endProcessingInstructionNodeStep();
479 
480             compare();
481         }
482         catch( org.jaxen.saxpath.SAXPathException e )
483         {
484             fail( e.getMessage() );
485         }
486     }
487 
488     public void testAllNodeStep()
489     {
490         try
491         {
492             setText( "parent::node()" );
493 
494             getReader().setUpParse( getText() );
495 
496             getReader().step( );
497 
498             expected().startAllNodeStep( Axis.PARENT );
499 
500             expected().endAllNodeStep();
501 
502             compare();
503         }
504         catch( org.jaxen.saxpath.SAXPathException e )
505         {
506             fail( e.getMessage() );
507         }
508     }
509 
510     public void testTextNodeStep()
511     {
512         try
513         {
514             setText( "parent::text()" );
515 
516             getReader().setUpParse( getText() );
517 
518             getReader().step( );
519 
520             expected().startTextNodeStep( Axis.PARENT );
521 
522             expected().endTextNodeStep();
523 
524             compare();
525         }
526         catch( org.jaxen.saxpath.SAXPathException e )
527         {
528             fail( e.getMessage() );
529         }
530     }
531 
532     public void testCommentNodeStep()
533     {
534         try
535         {
536             setText( "parent::comment()" );
537 
538             getReader().setUpParse( getText() );
539 
540             getReader().step( );
541 
542             expected().startCommentNodeStep( Axis.PARENT );
543 
544             expected().endCommentNodeStep();
545 
546             compare();
547         }
548         catch( org.jaxen.saxpath.SAXPathException e )
549         {
550             fail( e.getMessage() );
551         }
552     }
553 
554     public void testRelativeLocationPath()
555     {
556         try
557         {
558             setText( "foo/bar/baz" );
559 
560             getReader().setUpParse( getText() );
561 
562             getReader().locationPath( false );
563 
564             expected().startRelativeLocationPath();
565 
566             expected().startNameStep( Axis.CHILD,
567                                       "",
568                                       "foo" );
569             expected().endNameStep();
570 
571             expected().startNameStep( Axis.CHILD,
572                                       "",
573                                       "bar" );
574             expected().endNameStep();
575 
576             expected().startNameStep( Axis.CHILD,
577                                       "",
578                                       "baz" );
579             expected().endNameStep();
580 
581             expected().endRelativeLocationPath();
582 
583             compare();
584         }
585         catch( org.jaxen.saxpath.SAXPathException e )
586         {
587             fail( e.getMessage() );
588         }
589     }
590 
591     public void testAbsoluteLocationPath()
592     {
593         try
594         {
595             setText( "/foo/bar/baz" );
596 
597             getReader().setUpParse( getText() );
598 
599             getReader().locationPath( true );
600 
601             expected().startAbsoluteLocationPath();
602 
603             expected().startNameStep( Axis.CHILD,
604                                       "",
605                                       "foo" );
606             expected().endNameStep();
607 
608             expected().startNameStep( Axis.CHILD,
609                                       "",
610                                       "bar" );
611             expected().endNameStep();
612 
613             expected().startNameStep( Axis.CHILD,
614                                       "",
615                                       "baz" );
616             expected().endNameStep();
617 
618             expected().endAbsoluteLocationPath();
619 
620             compare();
621         }
622         catch( org.jaxen.saxpath.SAXPathException e )
623         {
624             fail( e.getMessage() );
625         }
626     }
627 
628     public void testNumberPredicate()
629     {
630         try
631         {
632             setText( "[1]" );
633 
634             getReader().setUpParse( getText() );
635 
636             getReader().predicate();
637 
638             expected().startPredicate();
639 
640             expected().startOrExpr();
641             expected().startAndExpr();
642             expected().startEqualityExpr();
643             expected().startEqualityExpr();
644             expected().startRelationalExpr();
645             expected().startRelationalExpr();
646             expected().startAdditiveExpr();
647             expected().startAdditiveExpr();
648             expected().startMultiplicativeExpr();
649             expected().startMultiplicativeExpr();
650             expected().startUnaryExpr();
651             expected().startUnionExpr();
652             expected().startPathExpr();
653             expected().startFilterExpr();
654 
655             expected().number( 1 );
656 
657             expected().endFilterExpr();
658             expected().endPathExpr();
659             expected().endUnionExpr( false );
660             expected().endUnaryExpr( Operator.NO_OP );
661             expected().endMultiplicativeExpr( Operator.NO_OP );
662             expected().endMultiplicativeExpr( Operator.NO_OP );
663             expected().endAdditiveExpr( Operator.NO_OP );
664             expected().endAdditiveExpr( Operator.NO_OP );
665             expected().endRelationalExpr( Operator.NO_OP );
666             expected().endRelationalExpr( Operator.NO_OP );
667             expected().endEqualityExpr( Operator.NO_OP );
668             expected().endEqualityExpr( Operator.NO_OP );
669             expected().endAndExpr( false );
670             expected().endOrExpr( false );
671 
672             expected().endPredicate();
673 
674             compare();
675         }
676         catch( org.jaxen.saxpath.SAXPathException e )
677         {
678             fail( e.getMessage() );
679         }
680     }
681 
682     // --------------------------------------------------------------------------------
683     // --------------------------------------------------------------------------------
684 
685     private void setText( String text )
686     {
687         this.text = text;
688     }
689 
690     private String getText()
691     {
692         return this.text;
693     }
694 
695     private void setReader( XPathReader reader )
696     {
697         this.reader = reader;
698     }
699 
700     private XPathReader getReader()
701     {
702         return this.reader;
703     }
704 
705     private void compare()
706     {
707         assertEquals( expected(),
708                       actual() );
709     }
710 
711     private ConformanceXPathHandler expected()
712     {
713         return this.expected;
714     }
715 
716     private ConformanceXPathHandler actual()
717     {
718         return this.actual;
719     }
720 }