View Javadoc

1   package org.apache.velocity.tools.test.whitebox;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Locale;
26  import org.junit.*;
27  import static org.junit.Assert.*;
28  import org.apache.commons.beanutils.Converter;
29  import org.apache.commons.beanutils.converters.BooleanConverter;
30  import org.apache.commons.beanutils.converters.DoubleConverter;
31  import org.apache.commons.beanutils.converters.IntegerConverter;
32  import org.apache.velocity.tools.Scope;
33  import org.apache.velocity.tools.config.*;
34  import org.apache.velocity.tools.generic.MathTool;
35  import org.apache.velocity.tools.generic.NumberTool;
36  import org.apache.velocity.tools.generic.ResourceTool;
37  
38  /**
39   * <p>Configuration tests.</p>
40   *
41   * @author Nathan Bubna
42   * @since VelocityTools 2.0
43   * @version $Id$
44   */
45  public class ConfigTests {
46  
47      private static final String XML_PATH = "@test.conf.dir@/tools.test.xml";
48      private static final String OLD_XML_PATH = "@test.conf.dir@/toolbox.test.xml";
49      private static final String PROPS_PATH = "@test.conf.dir@/tools.test.properties";
50  
51      protected FactoryConfiguration getBaseConfig()
52      {
53          FactoryConfiguration base = new FactoryConfiguration();
54  
55          Data datum = new Data();
56              datum.setKey("version");
57              datum.setType("number");
58              datum.setValue("2.0");
59          base.addData(datum);
60  
61          ToolboxConfiguration toolbox = new ToolboxConfiguration();
62          toolbox.setScope(Scope.REQUEST);
63          toolbox.setProperty("locale", Locale.US);
64              ToolConfiguration tool = new ToolConfiguration();
65                  tool.setClass(ResourceTool.class);
66              toolbox.addTool(tool);
67          base.addToolbox(toolbox);
68  
69          toolbox = new ToolboxConfiguration();
70          toolbox.setScope(Scope.APPLICATION);
71              tool = new ToolConfiguration();
72                  tool.setKey("calc");
73                  tool.setClass(MathTool.class);
74              toolbox.addTool(tool);
75  
76              tool = new ToolConfiguration();
77                  tool.setClass(NumberTool.class);
78                  tool.setProperty("locale", Locale.FRENCH);
79              toolbox.addTool(tool);
80          base.addToolbox(toolbox);
81  
82          return base;
83      }
84  
85  
86      public @Test void testBaseConfig()
87      {
88          assertValid(getBaseConfig());
89      }
90  
91      public @Test void testXmlConfig()
92      {
93          FileFactoryConfiguration xml = new XmlFactoryConfiguration();
94          xml.read(XML_PATH);
95  
96          assertValid(xml);
97          assertConfigEquals(getBaseConfig(), xml);
98      }
99  
100     public @Test void testOldConfig()
101     {
102         FileFactoryConfiguration old = new XmlFactoryConfiguration(true);
103         old.read(OLD_XML_PATH);
104 
105         FactoryConfiguration base = getBaseConfig();
106         // remove the request toolbox property locale=en_US manually,
107         // because the old format provide no means to set properties
108         // on a whole toolbox
109         base.getToolbox("request").removeProperty("locale");
110         // add the expected deprecationSupportMode property
111         base.setProperty("deprecationSupportMode", "true");
112 
113         assertValid(old);
114         assertConfigEquals(base, old);
115     }
116 
117     public @Test void testPropsConfig()
118     {
119         FileFactoryConfiguration props = new PropertiesFactoryConfiguration();
120         props.read(PROPS_PATH);
121 
122         assertValid(props);
123         assertConfigEquals(getBaseConfig(), props);
124     }
125 
126     /**
127      * Tests that adding two equal configs produces one that is equal
128      * to the originals.
129      */
130     public @Test void testPropsPlusXmlConfig()
131     {
132         FileFactoryConfiguration props = new PropertiesFactoryConfiguration();
133         props.read(PROPS_PATH);
134 
135         FileFactoryConfiguration xml = new XmlFactoryConfiguration();
136         xml.read(XML_PATH);
137         // make sure they're equal
138         assertConfigEquals(props, xml);
139         // now add them and make sure the result is equal to the original
140         xml.addConfiguration(props);
141         assertValid(xml);
142         assertConfigEquals(xml, props);
143     }
144 
145     public @Test void testEasyConfig()
146     {
147         EasyFactoryConfiguration easy = new EasyFactoryConfiguration();
148         easy.number("version", 2.0);
149         easy.toolbox("request")
150                 .property("locale", Locale.US)
151                 .tool(ResourceTool.class);
152         easy.toolbox("application")
153                 .tool("calc", MathTool.class)
154                 .tool(NumberTool.class)
155                     .property("locale", Locale.FRENCH);
156 
157         assertValid(easy);
158         assertConfigEquals(getBaseConfig(), easy);
159     }
160 
161     public @Test void testToolsClassConfig()
162     {
163         FactoryConfiguration java = ConfigurationUtils.getFromClass("tools");
164 
165         assertValid(java);
166         assertConfigEquals(getBaseConfig(), java);
167     }
168 
169     public @Test void testDefaultConfig()
170     {
171         FactoryConfiguration def = ConfigurationUtils.getDefaultTools();
172         assertValid(def);
173     }
174 
175     public @Test void testAutoConfig()
176     {
177         FactoryConfiguration autoMinusDef = ConfigurationUtils.getAutoLoaded(false);
178         assertValid(autoMinusDef);
179 
180         assertValid(autoMinusDef);
181         assertConfigEquals(getBaseConfig(), autoMinusDef);
182 
183         FactoryConfiguration auto = ConfigurationUtils.getAutoLoaded();
184         assertValid(auto);
185 
186         // get the default tools
187         FactoryConfiguration def = ConfigurationUtils.getDefaultTools();
188         assertValid(def);
189         // add the autoloaded ones (sans defaults) onto the default
190         def.addConfiguration(autoMinusDef);
191         // and see that it comes out the same
192         assertConfigEquals(auto, def);
193     }
194 
195     public @Test void testBadData()
196     {
197         Data datum = new Data();
198         // a fresh datum should be invalid
199         assertInvalid(datum);
200         // setting a key is not enough to be valid
201         datum.setKey("test");
202         assertInvalid(datum);
203 
204         // set type to number value to a non-number
205         datum.setValue("true");
206         datum.setType("number");
207         assertInvalid(datum);
208 
209         // should fail to convert a decimal string to an integer
210         datum.setValue("0.1");
211         datum.convertWith(new IntegerConverter());
212         assertInvalid(datum);
213     }
214 
215     public @Test void testData()
216     {
217         Data datum = new Data();
218         datum.setKey("test");
219         datum.setValue("true");
220         assertValid(datum);
221 
222         // check that the default type is "auto"
223         assertEquals(datum.getType(), "auto");
224 
225         // check that "true" auto-converted to boolean
226         assertSame(datum.getConvertedValue(), Boolean.TRUE);
227 
228         // check that "1" auto-converts to integer
229         datum.setValue("1");
230         assertEquals(datum.getConvertedValue(), Integer.valueOf(1));
231 
232         // check that a really big number converts to a Long
233         datum.setValue(""+Integer.MAX_VALUE+"0");
234         assertEquals(datum.getConvertedValue().getClass(), Long.class);
235 
236         // check that "1.2" auto-converts to double
237         datum.setValue("1.2");
238         assertEquals(datum.getConvertedValue(), 1.2);
239         assertEquals(datum.getConvertedValue().getClass(), Double.class);
240 
241         // check that java.lang.Integer.MIN_VALUE auto-converts to the field
242         datum.setValue("java.lang.Integer.MIN_VALUE");
243         assertEquals(datum.getConvertedValue(), Integer.MIN_VALUE);
244 
245         // check that "yes" also auto-converts to boolean
246         datum.setValue("yes");
247         assertSame(datum.getConvertedValue(), Boolean.TRUE);
248 
249         // check boolean type
250         datum.setType("boolean");
251         assertValid(datum);
252         assertSame(datum.getConvertedValue(), Boolean.TRUE);
253 
254         // check valid field type
255         datum.setValue("java.lang.Boolean.TRUE");
256         datum.setType("field");
257         assertValid(datum);
258         assertSame(datum.getConvertedValue(), Boolean.TRUE);
259 
260         // check invalid field value
261         datum.setValue("blahblah");
262         assertInvalid(datum);
263 
264         // check number type
265         datum.setValue("3.16");
266         datum.setType("number");
267         assertValid(datum);
268         assertEquals(datum.getConvertedValue(), new Double(3.16));
269 
270         // check string type
271         datum.setType("string");
272         assertValid(datum);
273         assertEquals(datum.getConvertedValue(), "3.16");
274 
275         // check list type (singleton)
276         datum.setType("list");
277         assertValid(datum);
278         assertEquals(datum.getConvertedValue(), Collections.singletonList("3.16"));
279 
280         // ok, try a three item list
281         datum.setValue("1,2,3");
282         assertValid(datum);
283         List three = new ArrayList(3);
284         three.add("1");
285         three.add("2");
286         three.add("3");
287         assertEquals(datum.getConvertedValue(), three);
288 
289         // turn that into a list of numbers
290         datum.setType("list.number");
291         assertValid(datum);
292         three.set(0, new Integer(1));
293         three.set(1, new Integer(2));
294         three.set(2, new Integer(3));
295         assertEquals(datum.getConvertedValue(), three);
296 
297         // and a list of booleans
298         datum.setType("list.boolean");
299         datum.setValue("true,false");
300         List two = new ArrayList(2);
301         two.add(Boolean.TRUE);
302         two.add(Boolean.FALSE);
303         assertEquals(datum.getConvertedValue(), two);
304 
305         // and a list of fields
306         datum.setType("list.field");
307         datum.setValue("java.lang.Boolean.TRUE,java.lang.Boolean.FALSE");
308         assertEquals(datum.getConvertedValue(), two);
309 
310         //TODO: test converter/target class stuff
311     }
312 
313     public @Test void testConfiguration()
314     {
315         Configuration conf = new Configuration();
316         // a fresh config should be valid
317         assertValid(conf);
318 
319         // add and retrieve a simple string property
320         conf.setProperty("string", "whatever");
321         assertValid(conf);
322         assertEquals("whatever", conf.getProperty("string").getValue());
323 
324         // add and retrieve a simple boolean property
325         conf.setProperty("boolean", "true");
326         assertValid(conf);
327         assertEquals(Boolean.TRUE, conf.getProperty("boolean").getConvertedValue());
328 
329         // add and retrieve an arbitrary object property
330         conf.setProperty("testclass", this);
331         assertValid(conf);
332         assertSame(this, conf.getProperty("testclass").getValue());
333 
334         // test addConfiguration
335         Configuration cfg = new Configuration();
336         cfg.setProperty("string", "whoever");
337         conf.addConfiguration(cfg);
338         assertEquals("whoever", conf.getProperty("string").getValue());
339 
340         //TODO: test adding convertable properties
341     }
342 
343     //TODO: public @Test void testCompoundConfiguration()
344 
345     public @Test void testBadToolConfig()
346     {
347         ToolConfiguration tool = new ToolConfiguration();
348         // a fresh tool config should be invalid
349         assertInvalid(tool);
350 
351         // set a fake class name and confirm it is invalid
352         tool.setClassname("no.such.Class");
353         assertInvalid(tool);
354     }
355 
356     public @Test void testToolConfig()
357     {
358         ToolConfiguration tool = new ToolConfiguration();
359 
360         // set a real class, confirm it is valid
361         tool.setClass(OldTool.class);
362         assertValid(tool);
363         // and confirm the default key
364         assertEquals("old", tool.getKey());
365 
366         // the toString() should describe this as old, due
367         // to the non-deprecated init() method
368         assertTrue((tool.toString().indexOf("Old") >= 0));
369 
370         // change to a more modern class, confirm it's valid
371         tool.setClassname(FakeTool.class.getName());
372         assertValid(tool);
373         // and confirm the default key annotation works
374         assertEquals("test", tool.getKey());
375 
376         // change the key and ensure it overrides the default
377         tool.setKey("fake");
378         assertEquals("fake", tool.getKey());
379 
380         // test that adding A to B copies A's class to B when B has no class
381         ToolConfiguration alt = new ToolConfiguration();
382         assertNull(alt.getClassname());
383         alt.addConfiguration((Configuration)tool);
384         assertNotNull(alt.getClassname());
385         assertEquals(FakeTool.class.getName(), alt.getClassname());
386 
387         // test that adding A to B doesn't copy A's class to B when A has no class
388         alt = new ToolConfiguration();
389         assertNull(alt.getClassname());
390         tool.addConfiguration(alt);
391         assertEquals(FakeTool.class.getName(), tool.getClassname());
392     }
393 
394     //TODO: add tests for ToolboxConfiguration
395     //TODO: add tests for FactoryConfiguration
396 
397 
398 
399     /************* Support classes and methods ******************/
400 
401 
402     public static class OldTool
403     {
404         public void init(Object foo)
405         {
406             // does nothing
407         }
408 
409         // exists only to keep the testrunner happy
410         public @Test @Ignore void foo() {}
411     }
412 
413     @DefaultKey("test")
414     public static class FakeTool
415     {
416         // exists only to keep the testrunner happy
417         public @Test @Ignore void foo() {}
418     }
419 
420 
421     protected void assertConfigEquals(Configuration one, Configuration two)
422     {
423         assertNotNull(one);
424         assertNotNull(two);
425 
426         // for now, just compare the toString() output
427         assertEquals(one.toString(), two.toString());
428     }
429 
430     protected void assertConfigEquals(FactoryConfiguration one, FactoryConfiguration two)
431     {
432         assertNotNull(one);
433         assertNotNull(two);
434 
435         // for now, just compare the toString() output without source info
436         assertEquals(one.toString(false), two.toString(false));
437     }
438 
439     protected void assertValid(Data valid)
440     {
441         assertNotNull(valid);
442         try
443         {
444             valid.validate();
445             // if we get past the call above, then the test passed
446         }
447         catch (ConfigurationException e)
448         {
449             // then the data was not valid
450             fail("\n**** Unexpected Invalid Data ****\n" + valid
451                  + "\n" + e);
452         }
453     }
454 
455     protected void assertValid(Configuration valid)
456     {
457         assertNotNull(valid);
458         try
459         {
460             valid.validate();
461             // if we get past the call above, then the test passed
462         }
463         catch (ConfigurationException e)
464         {
465             // then the config was not valid
466             fail("\n**** Unexpected Invalid Configuration ****\n" + valid
467                  + "\n" + e);
468         }
469     }
470 
471     protected void assertInvalid(Data invalid)
472     {
473         try
474         {
475             invalid.validate();
476             // if we get past the call above, then the test failed
477             fail("\n**** Unexpected Valid Data ****\n" + invalid);
478         }
479         catch (ConfigurationException e)
480         {
481             // then the data was invalid, as it ought to be
482         }
483     }
484 
485     protected void assertInvalid(Configuration invalid)
486     {
487         try
488         {
489             invalid.validate();
490             // if we get past the call above, then the test failed
491             fail("\n**** Unexpected Valid Configuration ****\n" + invalid);
492         }
493         catch (ConfigurationException e)
494         {
495             // then the config was invalid, as it ought to be
496         }
497     }
498 
499 }