1   package org.apache.velocity.test;
2   
3   import org.apache.velocity.exception.MethodInvocationException;
4   import org.apache.velocity.exception.VelocityException;
5   import org.apache.velocity.exception.ParseErrorException;
6   import org.apache.velocity.runtime.RuntimeConstants;
7   
8   /**
9    * Test strict reference mode turned on by the velocity property
10   * runtime.references.strict
11   */
12  public class StrictReferenceTestCase extends BaseEvalTestCase
13  {
14      public StrictReferenceTestCase(String name)
15      {
16          super(name);
17      }
18  
19      public void setUp() throws Exception
20      {
21          super.setUp();
22          engine.setProperty(RuntimeConstants.RUNTIME_REFERENCES_STRICT, Boolean.TRUE);
23          context.put("NULL", null);
24          context.put("bar", null);
25          context.put("TRUE", Boolean.TRUE);
26      }
27      
28  
29      /**
30       * Test the modified behavior of #if in strict mode.  Mainly, that
31       * single variables references in #if statements use non strict rules
32       */
33      public void testIfStatement()
34      {
35          Fargo fargo = new Fargo();
36          fargo.next = new Fargo();
37          context.put("fargo", fargo);
38          assertEvalEquals("", "#if($bogus)xxx#end");
39          assertEvalEquals("xxx", "#if($fargo)xxx#end");
40          assertEvalEquals("", "#if( ! $fargo)xxx#end");
41          assertEvalEquals("xxx", "#if($bogus || $fargo)xxx#end");
42          assertEvalEquals("", "#if($bogus && $fargo)xxx#end");
43          assertEvalEquals("", "#if($fargo != $NULL && $bogus)xxx#end");
44          assertEvalEquals("xxx", "#if($fargo == $NULL || ! $bogus)xxx#end");
45          assertEvalEquals("xxx", "#if(! $bogus1 && ! $bogus2)xxx#end");
46          assertEvalEquals("xxx", "#if($fargo.prop == \"propiness\" && ! $bogus && $bar == $NULL)xxx#end");
47          assertEvalEquals("", "#if($bogus && $bogus.foo)xxx#end");
48  
49          assertMethodEx("#if($bogus.foo)#end");
50          assertMethodEx("#if(!$bogus.foo)#end");
51      }
52      
53      
54      /**       
55       * We make sure that variables can actuall hold null
56       * values.
57       */
58      public void testAllowNullValues()
59          throws Exception
60      {
61          evaluate("$bar");
62          assertEvalEquals("true", "#if($bar == $NULL)true#end");
63          assertEvalEquals("true", "#set($foobar = $NULL)#if($foobar == $NULL)true#end");
64          assertEvalEquals("13", "#set($list = [1, $NULL, 3])#foreach($item in $list)#if($item != $NULL)$item#end#end");
65      }
66      
67      /**
68       * Test that variables references that have not been defined throw exceptions 
69       */
70      public void testStrictVariableRef()
71          throws Exception
72      {
73          // We expect a Method exception on the following
74          assertMethodEx("$bogus");
75          assertMethodEx("#macro(test)$bogus#end #test()");
76  
77          assertMethodEx("#set($bar = $bogus)");
78  
79          assertMethodEx("#if($bogus == \"bar\") #end");
80          assertMethodEx("#if($bogus != \"bar\") #end");
81          assertMethodEx("#if(\"bar\" == $bogus) #end");
82          assertMethodEx("#if($bogus > 1) #end");
83          assertMethodEx("#foreach($item in $bogus)#end");
84  
85          // make sure no exceptions are thrown here    
86          evaluate("#set($foo = \"bar\") $foo");     
87          evaluate("#macro(test1 $foo1) $foo1 #end #test1(\"junk\")");
88          evaluate("#macro(test2) #set($foo2 = \"bar\") $foo2 #end #test2()");
89      }
90      
91      /**
92       * Test that exceptions are thrown when methods are called on
93       * references that contains objects that do not contains those
94       * methods.
95       */
96      public void testStrictMethodRef()
97      {
98          Fargo fargo = new Fargo();
99          fargo.next = new Fargo();
100         context.put("fargo", fargo);        
101 
102         // Mainly want to make sure no exceptions are thrown here
103         assertEvalEquals("propiness", "$fargo.prop");
104         assertEvalEquals("$fargo.nullVal", "$fargo.nullVal");
105         assertEvalEquals("", "$!fargo.nullVal");
106         assertEvalEquals("propiness", "$fargo.next.prop");
107 
108         assertMethodEx("$fargo.foobar");
109         assertMethodEx("$fargo.next.foobar");
110         assertMethodEx("$fargo.foobar()");
111         assertMethodEx("#set($fargo.next.prop = $TRUE)");
112         assertMethodEx("$fargo.next.setProp($TRUE)");
113     }
114   
115     /**
116      * Make sure exceptions are thrown when when we attempt to call
117      * methods on null values.
118      */
119     public void testStrictMethodOnNull()
120     {
121         Fargo fargo = new Fargo();
122         fargo.next = new Fargo();
123         context.put("fargo", fargo);
124 
125         assertVelocityEx("$NULL.bogus");
126         assertVelocityEx("$fargo.nullVal.bogus");
127         assertVelocityEx("$fargo.next.nullVal.bogus");
128         assertVelocityEx("#if (\"junk\" == $fargo.nullVal.bogus)#end");
129         assertVelocityEx("#if ($fargo.nullVal.bogus > 2)#end");
130         assertVelocityEx("#set($fargo.next.nullVal.bogus = \"junk\")");
131         assertVelocityEx("#set($foo = $NULL.bogus)");
132         assertVelocityEx("#foreach($item in $fargo.next.nullVal.bogus)#end");
133 
134         evaluate("$fargo.prop.toString()");
135         assertVelocityEx("#set($fargo.prop = $NULL)$fargo.prop.next");
136 
137         // make sure no exceptions are thrown here
138         evaluate("$fargo.next.next");
139         evaluate("$fargo.next.nullVal");
140         evaluate("#foreach($item in $fargo.nullVal)#end");
141     }
142 
143     /**
144      * Make sure undefined macros throw exceptions
145      */
146     public void testMacros()
147     {
148         assertParseEx("#bogus()");
149         assertParseEx("#bogus (  )");
150         assertParseEx("#bogus( $a )");        
151         assertParseEx("abc#bogus ( $a )a ");
152 
153         assertEvalEquals(" true ", "#macro(test1) true #end#test1()");
154         assertEvalEquals(" true ", "#macro(test2 $a) $a #end#test2 ( \"true\")");
155         assertEvalEquals("#CCFFEE", "#CCFFEE");
156         assertEvalEquals("#F - ()", "#F - ()");
157         assertEvalEquals("#F{}", "#F{}");
158     }
159     
160     
161     /**
162      * Assert that we get a MethodInvocationException when calling evaluate
163      */
164     public void assertMethodEx(String template)
165     {
166         assertEvalException(template, MethodInvocationException.class);
167     }
168 
169     /**
170      * Assert that we get a VelocityException when calling evaluate
171      */
172     public void assertVelocityEx(String template)
173     {
174         assertEvalException(template, VelocityException.class);
175     }
176 
177     /**
178      * Assert that we get a MethodInvocationException when calling evaluate
179      */
180     public void assertParseEx(String template)
181     {
182         assertEvalException(template, ParseErrorException.class);
183     }
184 
185 
186     public static class Fargo
187     {
188         String prop = "propiness";
189         Fargo next = null;
190       
191         public String getProp()
192         {
193             return prop;
194         }
195 
196         public void setProp(String val)
197         {
198             this.prop = prop;
199         }
200 
201         public String getNullVal()
202         {
203             return null;
204         }
205 
206         public Fargo getNext()
207         {
208             return next;
209         }      
210     }  
211 }