View Javadoc

1   // Copyright (C) 2000 - 2011 Philip Aston
2   // All rights reserved.
3   //
4   // This file is part of The Grinder software distribution. Refer to
5   // the file LICENSE which is part of The Grinder distribution for
6   // licensing details. The Grinder distribution is available on the
7   // Internet at http://grinder.sourceforge.net/
8   //
9   // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
13  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17  // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
18  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
20  // OF THE POSSIBILITY OF SUCH DAMAGE.
21  
22  package net.grinder.common;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertNull;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  
29  import java.io.File;
30  import java.io.FileInputStream;
31  import java.io.FileOutputStream;
32  import java.io.FileWriter;
33  import java.io.InputStream;
34  import java.io.OutputStream;
35  import java.io.PrintWriter;
36  import java.io.StringWriter;
37  import java.util.Map.Entry;
38  import java.util.Properties;
39  
40  import net.grinder.testutility.AbstractJUnit4FileTestCase;
41  import net.grinder.testutility.FileUtilities;
42  import net.grinder.testutility.Serializer;
43  
44  import org.junit.Before;
45  import org.junit.Test;
46  
47  
48  /**
49   *  Unit test case for {@link GrinderProperties}.
50   *
51   * @author Philip Aston
52   */
53  public class TestGrinderProperties extends AbstractJUnit4FileTestCase {
54  
55    private final static String s_prefix = "prefix.";
56  
57    private GrinderProperties m_emptyGrinderProperties;
58    private GrinderProperties m_grinderProperties;
59  
60    private final Properties m_allSet = new Properties();
61    private final Properties m_prefixSet = new Properties();
62    private final Properties m_stringSet = new Properties();
63    private final Properties m_intSet = new Properties();
64    private final Properties m_brokenIntSet = new Properties();
65    private final Properties m_longSet = new Properties();
66    private final Properties m_brokenLongSet = new Properties();
67    private final Properties m_shortSet = new Properties();
68    private final Properties m_brokenShortSet = new Properties();
69    private final Properties m_doubleSet = new Properties();
70    private final Properties m_brokenDoubleSet = new Properties();
71    private final Properties m_booleanSet = new Properties();
72    private final Properties m_brokenBooleanSet = new Properties();
73    private final Properties m_fileSet = new Properties();
74    private final Properties m_grinderSet = new Properties();
75  
76    private final StringWriter m_stringWriter = new StringWriter();
77    private final PrintWriter m_errorWriter = new PrintWriter(m_stringWriter);
78  
79    @Before public void setUp() throws Exception {
80      m_emptyGrinderProperties = new GrinderProperties();
81  
82      m_emptyGrinderProperties.setErrorWriter(m_errorWriter);
83  
84      m_prefixSet.put(s_prefix + "A string", "Some more text");
85      m_prefixSet.put(s_prefix + "An int", "9");
86  
87      m_stringSet.put("A_string", "Some text");
88      m_stringSet.put("Another_String", "Some text");
89      m_stringSet.put("", "Some text");
90      m_stringSet.put("-83*(&(*991(*&(*", "\n\r\n");
91      m_stringSet.put("Another_empty_string_test", "");
92  
93      // A couple of properties that are almost in m_grinderSet.
94      m_stringSet.put("grinder", ".no_dot_suffix");
95      m_stringSet.put("grinder_", "blah");
96  
97      m_intSet.put("An_integer", "9");
98      m_intSet.put("Number", "-9");
99      m_intSet.put("AnotherNumber", "-9  ");
100 
101     m_brokenIntSet.put("Broken_int_1", "9x");
102     m_brokenIntSet.put("Broken_int_2", "");
103     m_brokenIntSet.put("Broken_int_3", "1234567890123456");
104     m_brokenIntSet.put("Broken_int_4", "1e-3");
105 
106     m_longSet.put("A_long", "1234542222");
107     m_longSet.put("Another_long", "-19");
108     m_longSet.put("YetAnother_long", "  -19");
109 
110     m_brokenLongSet.put("Broken_long_1", "0x9");
111     m_brokenLongSet.put("Broken_long_2", "");
112     m_brokenLongSet.put("Broken_long_3", "123456789012345612321321321321");
113     m_brokenLongSet.put("Broken_long_4", "10.4");
114 
115     m_shortSet.put("A_short", "123");
116     m_shortSet.put("Another_short", "0");
117     m_shortSet.put("OneMore_short", " 0 ");
118 
119     m_brokenShortSet.put("Broken_short_1", "0x9");
120     m_brokenShortSet.put("Broken_short_2", "1.4");
121     m_brokenShortSet.put("Broken_short_3", "-0123456");
122 
123     m_doubleSet.put("A_double", "1.0");
124     m_doubleSet.put("Another_double", "1");
125     m_doubleSet.put("Mines_a_double", "  1");
126 
127     m_brokenDoubleSet.put("Broken_double_1", "0x9");
128     m_brokenDoubleSet.put("Broken_double_2", "1/0");
129 
130     m_booleanSet.put("A_boolean", "true");
131     m_booleanSet.put("Another_boolean", "false");
132     m_booleanSet.put("Yet_another_boolean", "yes");
133     m_booleanSet.put("One_more_boolean", "no");
134 
135     m_brokenBooleanSet.put("Broken_boolean_1", "abc");
136     m_brokenBooleanSet.put("Broken_boolean_2", "019321 xx");
137     m_brokenBooleanSet.put("Broken_boolean_3", "uhuh");
138 
139     m_fileSet.put("A_file", "a/b");
140     m_fileSet.put("Another_file", "b");
141 
142     // All properties that begin with "grinder."
143     m_grinderSet.put("grinder.abc", "xyz");
144     m_grinderSet.put("grinder.blah.blah", "123");
145 
146     m_allSet.putAll(m_prefixSet);
147     m_allSet.putAll(m_stringSet);
148     m_allSet.putAll(m_intSet);
149     m_allSet.putAll(m_brokenIntSet);
150     m_allSet.putAll(m_longSet);
151     m_allSet.putAll(m_brokenLongSet);
152     m_allSet.putAll(m_shortSet);
153     m_allSet.putAll(m_brokenShortSet);
154     m_allSet.putAll(m_doubleSet);
155     m_allSet.putAll(m_brokenDoubleSet);
156     m_allSet.putAll(m_booleanSet);
157     m_allSet.putAll(m_brokenBooleanSet);
158     m_allSet.putAll(m_fileSet);
159     m_allSet.putAll(m_grinderSet);
160 
161     m_grinderProperties = new GrinderProperties();
162     m_grinderProperties.putAll(m_allSet);
163     m_grinderProperties.setErrorWriter(m_errorWriter);
164   }
165 
166   @Test public void testGetPropertySubset() throws Exception {
167     final GrinderProperties all =
168       m_grinderProperties.getPropertySubset("");
169 
170     assertEquals(all, m_allSet);
171     assertEquals(all.hashCode(), m_allSet.hashCode());
172 
173     final GrinderProperties none =
174       m_grinderProperties.getPropertySubset("Not there");
175 
176     assertEquals(0, none.size());
177 
178     final GrinderProperties prefixSet =
179       m_grinderProperties.getPropertySubset(s_prefix);
180 
181     assertEquals(prefixSet.size(), m_prefixSet.size());
182 
183     for (Entry<?, ?> entry : prefixSet.entrySet()) {
184       final String key = (String)entry.getKey();
185       final String value = (String)entry.getValue();
186 
187       assertEquals(value, m_prefixSet.get(s_prefix + key));
188     }
189   }
190 
191   @Test public void testGetInt() throws Exception {
192     assertEquals(1, m_grinderProperties.getInt("Not there", 1));
193 
194     (new IterateOverProperties(m_intSet) {
195         void match(String key, String value) throws Exception {
196           assertEquals(Integer.parseInt(value.trim()),
197                        m_grinderProperties.getInt(key, 99));
198         }
199       }
200      ).run();
201 
202     assertEquals(0, countErrorLines());
203   }
204 
205   private int countErrorLines() {
206     final String errorOutput = m_stringWriter.toString();
207 
208     if (errorOutput.length() == 0) {
209       return 0;
210     }
211 
212     return errorOutput.split("\n").length;
213   }
214 
215   @Test public void testGetIntBroken() throws Exception {
216 
217     (new IterateOverProperties(m_brokenIntSet) {
218         void match(String key, String value) {
219           assertEquals(99, m_grinderProperties.getInt(key, 99));
220         }
221       }
222      ).run();
223 
224     assertEquals(m_brokenIntSet.size(), countErrorLines());
225   }
226 
227   @Test public void testGetLong() throws Exception {
228     assertEquals(1, m_grinderProperties.getLong("Not there", 1));
229 
230     (new IterateOverProperties(m_longSet) {
231         void match(String key, String value) throws Exception {
232           assertEquals(Long.parseLong(value.trim()),
233                        m_grinderProperties.getLong(key, 99));
234         }
235       }
236      ).run();
237 
238     assertEquals(0, countErrorLines());
239   }
240 
241   @Test public void testGetLongBroken() throws Exception {
242 
243     (new IterateOverProperties(m_brokenLongSet) {
244         void match(String key, String value) {
245           assertEquals(99, m_grinderProperties.getLong(key, 99));
246         }
247       }
248      ).run();
249 
250     assertEquals(m_brokenLongSet.size(), countErrorLines());
251   }
252 
253   @Test public void testGetShort() throws Exception {
254     assertEquals((short)1, m_grinderProperties.getShort("Not there",
255                                                         (short)1));
256 
257     (new IterateOverProperties(m_shortSet) {
258         void match(String key, String value) throws Exception {
259           assertEquals(key,
260                       Short.parseShort(value.trim()),
261                        m_grinderProperties.getShort(key, (short)99));
262         }
263       }
264      ).run();
265 
266     assertEquals(0, countErrorLines());
267   }
268 
269   @Test public void testGetShortBroken() throws Exception {
270 
271     (new IterateOverProperties(m_brokenShortSet) {
272         void match(String key, String value) {
273           assertEquals(99, m_grinderProperties.getShort(key,
274                                                         (short)99));
275         }
276       }
277      ).run();
278 
279     assertEquals(m_brokenShortSet.size(), countErrorLines());
280   }
281 
282   @Test public void testGetDouble() throws Exception {
283     assertEquals(1.0, m_grinderProperties.getDouble("Not there", 1.0), 0);
284 
285     (new IterateOverProperties(m_doubleSet) {
286         void match(String key, String value) throws Exception {
287           assertEquals(Double.parseDouble(value),
288                        m_grinderProperties.getDouble(key, 99.0), 0);
289         }
290       }
291      ).run();
292 
293     assertEquals(0, countErrorLines());
294   }
295 
296   @Test public void testGetDoubleBroken() throws Exception {
297 
298     (new IterateOverProperties(m_brokenDoubleSet) {
299         void match(String key, String value) {
300           assertEquals(99.0,
301                        m_grinderProperties.getDouble(key, 99.0),
302                        0);
303         }
304       }
305      ).run();
306 
307     assertEquals(m_brokenDoubleSet.size(), countErrorLines());
308   }
309 
310   @Test public void testGetBoolean() throws Exception {
311     assertTrue(m_grinderProperties.getBoolean("Not there", true));
312     assertTrue(!m_grinderProperties.getBoolean("Not there", false));
313 
314     (new IterateOverProperties(m_booleanSet) {
315         void match(String key, String value) throws Exception {
316           assertTrue(!(Boolean.valueOf(value).booleanValue() ^
317                        m_grinderProperties.getBoolean(key, false)));
318         }
319       }
320      ).run();
321 
322     (new IterateOverProperties(m_brokenBooleanSet) {
323         void match(String key, String value) {
324           // If the key exists, the boolean will always
325           // parse as false.
326           assertTrue(!m_grinderProperties.getBoolean(key, false));
327         }
328       }
329      ).run();
330   }
331 
332   @Test public void testGetFile() throws Exception {
333     final File f = new File("foo");
334     assertEquals(f, m_grinderProperties.getFile("Not there", f));
335 
336     (new IterateOverProperties(m_fileSet) {
337         void match(String key, String value) throws Exception {
338           assertEquals(new File(value),
339                        m_grinderProperties.getFile(key, null));
340         }
341       }
342      ).run();
343   }
344 
345   @Test public void testSetInt() throws Exception {
346     final GrinderProperties properties = new GrinderProperties();
347 
348     (new IterateOverProperties(m_intSet) {
349         void match(String key, String value) throws Exception {
350           properties.setInt(key, Integer.parseInt(value.trim()));
351           assertEquals(value.trim(), properties.getProperty(key, null));
352         }
353       }
354      ).run();
355   }
356 
357   @Test public void testSetLong() throws Exception {
358     final GrinderProperties properties = new GrinderProperties();
359 
360     (new IterateOverProperties(m_longSet) {
361         void match(String key, String value) throws Exception {
362           properties.setLong(key, Long.parseLong(value.trim()));
363           assertEquals(value.trim(), properties.getProperty(key, null));
364         }
365       }
366      ).run();
367   }
368 
369   @Test public void testSetShort() throws Exception {
370     final GrinderProperties properties = new GrinderProperties();
371 
372     (new IterateOverProperties(m_shortSet) {
373         void match(String key, String value) throws Exception {
374           properties.setShort(key, Short.parseShort(value.trim()));
375           assertEquals(value.trim(), properties.getProperty(key, null));
376         }
377       }
378      ).run();
379   }
380 
381   @Test public void testSetDouble() throws Exception {
382     final GrinderProperties properties = new GrinderProperties();
383 
384     (new IterateOverProperties(m_doubleSet) {
385         void match(String key, String value) throws Exception {
386           properties.setDouble(key, Double.parseDouble(value));
387           assertEquals(Double.parseDouble(value),
388                        Double.parseDouble(
389                          properties.getProperty(key, null)),
390                        0);
391         }
392       }
393      ).run();
394   }
395 
396   @Test public void testSetBoolean() throws Exception {
397     final GrinderProperties properties = new GrinderProperties();
398 
399     (new IterateOverProperties(m_booleanSet) {
400         void match(String key, String value) throws Exception {
401           properties.setBoolean(key,
402                                 Boolean.valueOf(value).
403                                 booleanValue());
404           assertEquals(Boolean.valueOf(value).toString(),
405                        properties.getProperty(key, null));
406         }
407       }
408      ).run();
409   }
410 
411   @Test public void testSetFile() throws Exception {
412     final GrinderProperties properties = new GrinderProperties();
413 
414     (new IterateOverProperties(m_fileSet) {
415         void match(String key, String value) throws Exception {
416           properties.setFile(key, new File(value));
417 
418           assertEquals(new File(value).getPath(),
419                        properties.getProperty(key, null));
420         }
421       }
422      ).run();
423   }
424 
425   @Test public void testDefaultProperties() throws Exception {
426     setSystemProperties();
427 
428     try {
429       // Default constructor doesn't add system properties.
430       final GrinderProperties properties = new GrinderProperties();
431       assertEquals(new Properties(), properties);
432     }
433     finally {
434       restoreSystemProperties();
435     }
436   }
437 
438   @Test public void testPropertiesFileHanding() throws Exception {
439     setSystemProperties();
440 
441     try {
442       final File file = File.createTempFile("testing", "12", getDirectory());
443 
444       final PrintWriter writer =
445         new PrintWriter(new FileWriter(file), true);
446 
447       (new IterateOverProperties(m_grinderSet) {
448           void match(String key, String value) throws Exception {
449             writer.println(key + ":" + "should be overridden");
450           }
451         }
452        ).run();
453 
454       (new IterateOverProperties(m_stringSet) {
455           void match(String key, String value) throws Exception {
456             writer.println(key + ":" + "not overridden");
457           }
458         }
459        ).run();
460 
461       writer.close();
462 
463       // Constructor that takes a file adds system properties
464       // beginning with "grinder.", and nothing else.
465       final GrinderProperties properties = new GrinderProperties(file);
466 
467       (new IterateOverProperties(m_grinderSet) {
468           void match(String key, String value) throws Exception {
469             assertEquals(value, properties.getProperty(key, null));
470             properties.remove(key);
471           }
472         }
473        ).run();
474 
475       (new IterateOverProperties(m_stringSet) {
476           void match(String key, String value) throws Exception {
477             assertEquals("not overridden", properties.getProperty(key, null));
478             properties.remove(key);
479           }
480         }
481        ).run();
482 
483       // All other properties must have been picked up from other
484       // System grinder.properties.
485       (new IterateOverProperties(properties) {
486           void match(String key, String value) throws Exception {
487             assertTrue(key.startsWith("grinder."));
488             assertEquals(value, System.getProperty(key));
489           }
490         }).run();
491     }
492     finally {
493       restoreSystemProperties();
494     }
495   }
496 
497   @Test public void testSave() throws Exception {
498 
499     try {
500       assertNull(m_grinderProperties.getAssociatedFile());
501       m_grinderProperties.save();
502       fail("Expected GrinderException as no associated file");
503     }
504     catch (GrinderException e) {
505     }
506 
507     final GrinderProperties defaultFileProperties =
508       new GrinderProperties(GrinderProperties.DEFAULT_PROPERTIES);
509     assertEquals(new File("grinder.properties"),
510                  defaultFileProperties.getAssociatedFile());
511 
512     final File file = File.createTempFile("testing", "123", getDirectory());
513 
514     final GrinderProperties properties = new GrinderProperties(file);
515     assertEquals(file, properties.getAssociatedFile());
516     properties.putAll(m_allSet);
517 
518     properties.save();
519 
520     final Properties readProperties = new Properties();
521     final InputStream in = new FileInputStream(file);
522     readProperties.load(in);
523     in.close();
524 
525     (new IterateOverProperties(m_allSet) {
526         void match(String key, String value) throws Exception {
527           assertEquals(value, readProperties.getProperty(key));
528         }
529       }
530      ).run();
531   }
532 
533   @Test public void testSaveSingleProperty() throws Exception {
534 
535     try {
536       assertNull(m_grinderProperties.getAssociatedFile());
537       m_grinderProperties.setProperty("foo", "bah");
538       m_grinderProperties.saveSingleProperty("foo");
539       fail("Expected GrinderException as no associated file");
540     }
541     catch (GrinderException e) {
542     }
543 
544     final File file = File.createTempFile("testing", "1234", getDirectory());
545 
546     final Properties plainProperties = new Properties();
547     plainProperties.setProperty("existing", "property");
548     final OutputStream out = new FileOutputStream(file);
549     plainProperties.store(out, "");
550     out.close();
551 
552     final GrinderProperties properties = new GrinderProperties(file);
553     assertEquals(file, properties.getAssociatedFile());
554     properties.putAll(m_allSet);
555 
556     properties.setProperty("foo", "bah");
557     properties.saveSingleProperty("foo");
558 
559     properties.setBoolean("blah", true);
560     properties.saveSingleProperty("blah");
561 
562     final InputStream in = new FileInputStream(file);
563     plainProperties.load(in);
564     in.close();
565 
566     assertEquals(3, plainProperties.size());
567     assertEquals("bah", plainProperties.getProperty("foo"));
568     assertEquals("property", plainProperties.getProperty("existing"));
569     assertEquals("true", plainProperties.getProperty("blah"));
570   }
571 
572   private void setSystemProperties() throws Exception {
573     (new IterateOverProperties(m_grinderProperties) {
574         void match(String key, String value) throws Exception
575         {
576           if (key.length() > 0) {
577             System.setProperty(key, value);
578           }
579         }
580       }
581      ).run();
582   }
583 
584   @Test public void testFileHandingWithBadFiles() throws Exception {
585     final File readOnlyFile =
586       File.createTempFile("testing", "", getDirectory());
587 
588     final GrinderProperties properties1 = new GrinderProperties(readOnlyFile);
589 
590     FileUtilities.setCanAccess(readOnlyFile, false);
591 
592     try {
593       properties1.save();
594       fail("Expected GrinderException");
595     }
596     catch (GrinderException e) {
597     }
598 
599     try {
600       properties1.saveSingleProperty("foo");
601       fail("Expected GrinderException");
602     }
603     catch (GrinderException e) {
604     }
605 
606     try {
607       new GrinderProperties(readOnlyFile);
608       fail("Expected GrinderException");
609     }
610     catch (GrinderException e) {
611     }
612   }
613 
614   private void restoreSystemProperties() {
615     // Do nothing! When run under Ant, System.getProperties()
616     // returns an empty object, so we can't cache/restore the old
617     // properties.
618   }
619 
620   private abstract class IterateOverProperties {
621     private final Properties m_properties;
622 
623     IterateOverProperties(Properties properties) {
624       m_properties = properties;
625     }
626 
627     void run() throws Exception {
628       for (Entry<?, ?> entry : m_properties.entrySet()) {
629         final String key = (String)entry.getKey();
630         final String value = (String)entry.getValue();
631 
632         match(key, value);
633       }
634     }
635 
636     abstract void match(String key, String value) throws Exception;
637   }
638 
639   @Test public void testSerialisation() throws Exception {
640     final GrinderProperties properties = new GrinderProperties();
641     properties.setProperty("Hello", "World");
642 
643     final GrinderProperties properties2 = Serializer.serialize(properties);
644 
645     assertEquals(properties, properties2);
646   }
647 
648   @Test public void testResolveRelativeFile() throws Exception {
649     final File relativeDirectory = new File("d");
650     final File absoluteDirectory = relativeDirectory.getCanonicalFile();
651     final File absolute1 = new File(absoluteDirectory, "blah");
652     final File relative1 = new File("winterlong");
653     final File relative2 = new File(relative1, "i wait for you");
654 
655     final GrinderProperties properties = new GrinderProperties();
656 
657     assertNull(properties.resolveRelativeFile(null));
658     assertEquals(relative1, properties.resolveRelativeFile(relative1));
659     assertEquals(absolute1, properties.resolveRelativeFile(absolute1));
660 
661     properties.setAssociatedFile(new File(relativeDirectory, "my.properties"));
662 
663     assertEquals(new File(relativeDirectory, relative1.getPath()),
664                  properties.resolveRelativeFile(relative1));
665     assertEquals(new File(relativeDirectory, relative2.getPath()),
666       properties.resolveRelativeFile(relative2));
667     assertEquals(absolute1, properties.resolveRelativeFile(absolute1));
668     assertNull(properties.resolveRelativeFile(null));
669 
670     properties.setAssociatedFile(new File(absoluteDirectory, "my.properties"));
671 
672     assertEquals(new File(absoluteDirectory, relative1.getPath()),
673       properties.resolveRelativeFile(relative1));
674     assertEquals(new File(absoluteDirectory, relative2.getPath()),
675       properties.resolveRelativeFile(relative2));
676     assertEquals(absolute1, properties.resolveRelativeFile(absolute1));
677     assertNull(properties.resolveRelativeFile(null));
678   }
679 }
680