1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertSame;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.Reader;
28 import java.io.StringReader;
29 import java.io.StringWriter;
30 import java.util.Iterator;
31
32 import org.apache.commons.configuration.event.ConfigurationEvent;
33 import org.apache.commons.configuration.event.ConfigurationListener;
34 import org.junit.Before;
35 import org.junit.Test;
36
37
38
39
40
41
42
43
44
45 public class TestPropertiesConfigurationLayout
46 {
47
48 private static final String CR = System.getProperty("line.separator");
49
50
51 private static final String CRNORM = "\n";
52
53
54 static final String TEST_KEY = "myProperty";
55
56
57 static final String TEST_COMMENT = "A comment for my test property";
58
59
60 static final String TEST_VALUE = "myPropertyValue";
61
62
63 PropertiesConfigurationLayout layout;
64
65
66 LayoutTestConfiguration config;
67
68
69 PropertiesBuilder builder;
70
71 @Before
72 public void setUp() throws Exception
73 {
74 config = new LayoutTestConfiguration();
75 layout = new PropertiesConfigurationLayout(config);
76 config.setLayout(layout);
77 builder = new PropertiesBuilder();
78 }
79
80
81
82
83 @Test
84 public void testInit()
85 {
86 assertTrue("Object contains keys", layout.getKeys().isEmpty());
87 assertNull("Header comment not null", layout.getHeaderComment());
88 Iterator<ConfigurationListener> it = config.getConfigurationListeners().iterator();
89 assertTrue("No event listener registered", it.hasNext());
90 assertSame("Layout not registered as event listener", layout, it.next());
91 assertFalse("Multiple event listeners registered", it.hasNext());
92 assertSame("Configuration not stored", config, layout
93 .getConfiguration());
94 assertFalse("Force single line flag set", layout.isForceSingleLine());
95 assertNull("Got a global separator", layout.getGlobalSeparator());
96 }
97
98
99
100
101
102 @Test(expected = IllegalArgumentException.class)
103 public void testInitNull()
104 {
105 new PropertiesConfigurationLayout(null);
106 }
107
108
109
110
111 @Test
112 public void testReadSimple() throws ConfigurationException
113 {
114 builder.addComment(TEST_COMMENT);
115 builder.addProperty(TEST_KEY, TEST_VALUE);
116 layout.load(builder.getReader());
117 assertNull("A header comment was found", layout.getHeaderComment());
118 assertEquals("Wrong number of properties", 1, layout.getKeys().size());
119 assertTrue("Property not found", layout.getKeys().contains(TEST_KEY));
120 assertEquals("Comment not found", TEST_COMMENT, layout
121 .getCanonicalComment(TEST_KEY, false));
122 assertEquals("Wrong number of blanc lines", 0, layout
123 .getBlancLinesBefore(TEST_KEY));
124 assertTrue("Wrong single line flag", layout.isSingleLine(TEST_KEY));
125 assertEquals("Property not stored in config", TEST_VALUE, config
126 .getString(TEST_KEY));
127 }
128
129
130
131
132 @Test
133 public void testBlancLines() throws ConfigurationException
134 {
135 builder.addProperty("prop", "value");
136 builder.addComment(null);
137 builder.addComment(null);
138 builder.addComment(TEST_COMMENT);
139 builder.addComment(null);
140 builder.addProperty(TEST_KEY, TEST_VALUE);
141 layout.load(builder.getReader());
142 assertEquals("Wrong number of blanc lines", 2, layout
143 .getBlancLinesBefore(TEST_KEY));
144 assertEquals("Wrong comment", TEST_COMMENT + CRNORM, layout
145 .getCanonicalComment(TEST_KEY, false));
146 assertEquals("Wrong property value", TEST_VALUE, config
147 .getString(TEST_KEY));
148 }
149
150
151
152
153 @Test
154 public void testIsSingleLine() throws ConfigurationException
155 {
156 builder.addProperty(TEST_KEY, TEST_VALUE + "," + TEST_VALUE + "2");
157 layout.load(builder.getReader());
158 assertTrue("Wrong single line flag", layout.isSingleLine(TEST_KEY));
159 assertEquals("Wrong number of values", 2, config.getList(TEST_KEY)
160 .size());
161 }
162
163
164
165
166 @Test
167 public void testIsSingleLineMulti() throws ConfigurationException
168 {
169 builder.addProperty(TEST_KEY, TEST_VALUE);
170 builder.addProperty("anotherProp", "a value");
171 builder.addProperty(TEST_KEY, TEST_VALUE + "2");
172 layout.load(builder.getReader());
173 assertFalse("Wrong single line flag", layout.isSingleLine(TEST_KEY));
174 assertEquals("Wrong number of values", 2, config.getList(TEST_KEY)
175 .size());
176 }
177
178
179
180
181 @Test
182 public void testCombineComments() throws ConfigurationException
183 {
184 builder.addComment(TEST_COMMENT);
185 builder.addProperty(TEST_KEY, TEST_VALUE);
186 builder.addComment(null);
187 builder.addComment(TEST_COMMENT);
188 builder.addProperty(TEST_KEY, TEST_VALUE + "2");
189 layout.load(builder.getReader());
190 assertEquals("Wrong combined comment",
191 TEST_COMMENT + CRNORM + TEST_COMMENT, layout.getCanonicalComment(
192 TEST_KEY, false));
193 assertEquals("Wrong combined blanc numbers", 0, layout
194 .getBlancLinesBefore(TEST_KEY));
195 }
196
197
198
199
200 @Test
201 public void testHeaderComment() throws ConfigurationException
202 {
203 builder.addComment(TEST_COMMENT);
204 builder.addComment(null);
205 builder.addProperty(TEST_KEY, TEST_VALUE);
206 layout.load(builder.getReader());
207 assertEquals("Wrong header comment", TEST_COMMENT, layout
208 .getCanonicalHeaderComment(false));
209 assertNull("Wrong comment for property", layout.getCanonicalComment(
210 TEST_KEY, false));
211 }
212
213
214
215
216 @Test
217 public void testHeaderCommentWithBlancs() throws ConfigurationException
218 {
219 builder.addComment(TEST_COMMENT);
220 builder.addComment(null);
221 builder.addComment(TEST_COMMENT);
222 builder.addComment(null);
223 builder.addProperty(TEST_KEY, TEST_VALUE);
224 layout.load(builder.getReader());
225 assertEquals("Wrong header comment", TEST_COMMENT + CRNORM + CRNORM
226 + TEST_COMMENT, layout.getCanonicalHeaderComment(false));
227 assertNull("Wrong comment for property", layout.getComment(TEST_KEY));
228 }
229
230
231
232
233
234 @Test
235 public void testHeaderCommentWithBlancsAndPropComment()
236 throws ConfigurationException
237 {
238 builder.addComment(TEST_COMMENT);
239 builder.addComment(null);
240 builder.addComment(TEST_COMMENT);
241 builder.addComment(null);
242 builder.addComment(TEST_COMMENT);
243 builder.addProperty(TEST_KEY, TEST_VALUE);
244 layout.load(builder.getReader());
245 assertEquals("Wrong header comment", TEST_COMMENT + CRNORM + CRNORM
246 + TEST_COMMENT, layout.getCanonicalHeaderComment(false));
247 assertEquals("Wrong comment for property", TEST_COMMENT, layout
248 .getCanonicalComment(TEST_KEY, false));
249 }
250
251
252
253
254 @Test
255 public void testHeaderCommentNull()
256 {
257 assertNull("No null comment with comment chars", layout
258 .getCanonicalHeaderComment(true));
259 assertNull("No null comment without comment chars", layout
260 .getCanonicalHeaderComment(false));
261 }
262
263
264
265
266 @Test
267 public void testEventAdd()
268 {
269 ConfigurationEvent event = new ConfigurationEvent(this,
270 AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_KEY, TEST_VALUE,
271 false);
272 layout.configurationChanged(event);
273 assertTrue("Property not stored", layout.getKeys().contains(TEST_KEY));
274 assertEquals("Blanc lines before new property", 0, layout
275 .getBlancLinesBefore(TEST_KEY));
276 assertTrue("No single line property", layout.isSingleLine(TEST_KEY));
277 assertEquals("Wrong separator", " = ", layout.getSeparator(TEST_KEY));
278 }
279
280
281
282
283
284 @Test
285 public void testEventAddMultiple()
286 {
287 ConfigurationEvent event = new ConfigurationEvent(this,
288 AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_KEY, TEST_VALUE,
289 false);
290 layout.configurationChanged(event);
291 layout.configurationChanged(event);
292 assertFalse("No multi-line property", layout.isSingleLine(TEST_KEY));
293 }
294
295
296
297
298
299 @Test
300 public void testEventAddExisting() throws ConfigurationException
301 {
302 builder.addComment(TEST_COMMENT);
303 builder.addProperty(TEST_KEY, TEST_VALUE);
304 layout.load(builder.getReader());
305 ConfigurationEvent event = new ConfigurationEvent(this,
306 AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_KEY, TEST_VALUE,
307 false);
308 layout.configurationChanged(event);
309 assertFalse("No multi-line property", layout.isSingleLine(TEST_KEY));
310 assertEquals("Comment was modified", TEST_COMMENT, layout
311 .getCanonicalComment(TEST_KEY, false));
312 }
313
314
315
316
317
318 @Test
319 public void testEventSetNonExisting()
320 {
321 ConfigurationEvent event = new ConfigurationEvent(this,
322 AbstractConfiguration.EVENT_SET_PROPERTY, TEST_KEY, TEST_VALUE,
323 false);
324 layout.configurationChanged(event);
325 assertTrue("New property was not found", layout.getKeys().contains(
326 TEST_KEY));
327 }
328
329
330
331
332 @Test
333 public void testEventDelete()
334 {
335 ConfigurationEvent event = new ConfigurationEvent(this,
336 AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_KEY, TEST_VALUE,
337 false);
338 layout.configurationChanged(event);
339 event = new ConfigurationEvent(this,
340 AbstractConfiguration.EVENT_CLEAR_PROPERTY, TEST_KEY, null,
341 false);
342 layout.configurationChanged(event);
343 assertFalse("Property still existing", layout.getKeys().contains(
344 TEST_KEY));
345 }
346
347
348
349
350 @Test
351 public void testEventClearConfig() throws Exception
352 {
353 fillLayout();
354 ConfigurationEvent event = new ConfigurationEvent(this,
355 AbstractConfiguration.EVENT_CLEAR, null, null, false);
356 layout.configurationChanged(event);
357 assertTrue("Keys not empty", layout.getKeys().isEmpty());
358 assertNull("Header comment was not reset", layout.getHeaderComment());
359 }
360
361
362
363
364 @Test
365 public void testEventAddBefore()
366 {
367 ConfigurationEvent event = new ConfigurationEvent(this,
368 AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_KEY, TEST_VALUE,
369 true);
370 layout.configurationChanged(event);
371 assertFalse("Property already stored", layout.getKeys().contains(
372 TEST_KEY));
373 }
374
375
376
377
378 @Test
379 public void testEventReload()
380 {
381 fillLayout();
382 ConfigurationEvent event = new ConfigurationEvent(this,
383 AbstractFileConfiguration.EVENT_RELOAD, null, null, true);
384 layout.configurationChanged(event);
385 assertTrue("Keys not empty", layout.getKeys().isEmpty());
386 assertNull("Header comment was not reset", layout.getHeaderComment());
387 }
388
389
390
391
392
393 @Test
394 public void testEventReloadAfter()
395 {
396 fillLayout();
397 ConfigurationEvent event = new ConfigurationEvent(this,
398 AbstractFileConfiguration.EVENT_RELOAD, null, null, false);
399 layout.configurationChanged(event);
400 assertFalse("Keys are empty", layout.getKeys().isEmpty());
401 assertNotNull("Header comment was reset", layout.getHeaderComment());
402 }
403
404
405
406
407 @Test
408 public void testRecursiveLoadCall() throws ConfigurationException
409 {
410 PropertiesBuilder b = new PropertiesBuilder();
411 b.addComment("A nested header comment.");
412 b.addComment("With multiple lines");
413 b.addComment(null);
414 b.addComment("Second comment");
415 b.addProperty(TEST_KEY, TEST_VALUE);
416 b.addProperty(TEST_KEY + "2", TEST_VALUE + "2");
417 config.builder = b;
418
419 builder.addComment("Header comment");
420 builder.addComment(null);
421 builder.addComment(TEST_COMMENT);
422 builder.addProperty(TEST_KEY, TEST_VALUE);
423 builder.addComment("Include file");
424 builder.addProperty(PropertiesConfiguration.getInclude(), "test");
425
426 layout.load(builder.getReader());
427
428 assertEquals("Wrong header comment", "Header comment", layout
429 .getCanonicalHeaderComment(false));
430 assertFalse("Include property was stored", layout.getKeys().contains(
431 PropertiesConfiguration.getInclude()));
432 assertEquals("Wrong comment for property", TEST_COMMENT + CRNORM
433 + "A nested header comment." + CRNORM + "With multiple lines" + CRNORM
434 + CRNORM + "Second comment", layout.getCanonicalComment(TEST_KEY,
435 false));
436 }
437
438
439
440
441
442 @Test
443 public void testReadAndWrite() throws ConfigurationException
444 {
445 builder.addComment("This is my test properties file,");
446 builder.addComment("which contains a header comment.");
447 builder.addComment(null);
448 builder.addComment(TEST_COMMENT);
449 builder.addProperty(TEST_KEY, TEST_COMMENT);
450 builder.addComment(null);
451 builder.addComment(null);
452 builder.addComment("Another comment");
453 builder.addProperty("property", "and a value");
454 layout.load(builder.getReader());
455 checkLayoutString(builder.toString());
456 }
457
458
459
460
461 @Test
462 public void testSave() throws ConfigurationException
463 {
464 config.addProperty(TEST_KEY, TEST_VALUE);
465 layout.setComment(TEST_KEY, TEST_COMMENT);
466 config.addProperty(TEST_KEY, TEST_VALUE + "2");
467 config.addProperty("AnotherProperty", "AnotherValue");
468 config.addProperty("AnotherProperty", "3rdValue");
469 layout.setComment("AnotherProperty", "AnotherComment");
470 layout.setBlancLinesBefore("AnotherProperty", 2);
471 layout.setSingleLine("AnotherProperty", true);
472 layout.setHeaderComment("A header comment" + CRNORM + "for my properties");
473 checkLayoutString("# A header comment" + CR + "# for my properties"
474 + CR + CR + "# " + TEST_COMMENT + CR + TEST_KEY + " = "
475 + TEST_VALUE + CR + TEST_KEY + " = " + TEST_VALUE + "2" + CR
476 + CR + CR + "# AnotherComment" + CR
477 + "AnotherProperty = AnotherValue,3rdValue" + CR);
478 }
479
480
481
482
483 @Test
484 public void testSaveForceSingleLine() throws ConfigurationException
485 {
486 config.setListDelimiter(';');
487 config.addProperty(TEST_KEY, TEST_VALUE);
488 config.addProperty(TEST_KEY, TEST_VALUE + "2");
489 config.addProperty("AnotherProperty", "value1;value2;value3");
490 layout.setComment(TEST_KEY, TEST_COMMENT);
491 layout.setForceSingleLine(true);
492 checkLayoutString("# " + TEST_COMMENT + CR + TEST_KEY + " = "
493 + TEST_VALUE + ';' + TEST_VALUE + "2" + CR
494 + "AnotherProperty = value1;value2;value3" + CR);
495 }
496
497
498
499
500 @Test
501 public void testTrimComment()
502 {
503 assertEquals("Wrong trimmed comment", "This is a comment" + CR
504 + "that spans multiple" + CR + "lines in a" + CR
505 + " complex way.", PropertiesConfigurationLayout.trimComment(
506 " # This is a comment" + CR + "that spans multiple" + CR
507 + "!lines in a" + CR + " complex way.", false));
508 }
509
510
511
512
513 @Test
514 public void testTrimCommentTrainlingCR()
515 {
516 assertEquals("Wrong trimmed comment", "Comment with" + CR
517 + "trailing CR" + CR, PropertiesConfigurationLayout
518 .trimComment("Comment with" + CR + "! trailing CR" + CR, false));
519 }
520
521
522
523
524 @Test
525 public void testTrimCommentFalse()
526 {
527 assertEquals("Wrong trimmed comment", "# Comment with" + CR
528 + " ! some mixed " + CR + "#comment" + CR + "# lines",
529 PropertiesConfigurationLayout.trimComment("Comment with" + CR
530 + " ! some mixed " + CR + "#comment" + CR + "lines",
531 true));
532 }
533
534
535
536
537 @Test
538 public void testGetNonExistingLayouData()
539 {
540 assertNull("A comment was found", layout.getComment("unknown"));
541 assertTrue("A multi-line property", layout.isSingleLine("unknown"));
542 assertEquals("Leading blanc lines", 0, layout
543 .getBlancLinesBefore("unknown"));
544 }
545
546
547
548
549
550 @Test(expected = IllegalArgumentException.class)
551 public void testGetNullLayouttData()
552 {
553 layout.setComment(null, TEST_COMMENT);
554 }
555
556
557
558
559 @Test
560 public void testSetNullComment()
561 {
562 fillLayout();
563 layout.setComment(TEST_KEY, null);
564 assertNull("Comment was not reset", layout.getComment(TEST_KEY));
565 }
566
567
568
569
570
571 @Test
572 public void testSaveCommentForUnexistingProperty()
573 throws ConfigurationException
574 {
575 fillLayout();
576 layout.setComment("NonExistingKey", "NonExistingComment");
577 String output = getLayoutString();
578 assertTrue("Non existing key was found", output
579 .indexOf("NonExistingKey") < 0);
580 assertTrue("Non existing comment was found", output
581 .indexOf("NonExistingComment") < 0);
582 }
583
584
585
586
587 @Test
588 public void testSaveEmptyLayout() throws ConfigurationException
589 {
590 checkLayoutString("");
591 }
592
593
594
595
596 @Test
597 public void testInitCopy()
598 {
599 fillLayout();
600 PropertiesConfigurationLayout l2 = new PropertiesConfigurationLayout(
601 config, layout);
602 assertEquals("Wrong number of keys", layout.getKeys().size(), l2
603 .getKeys().size());
604 for (Iterator<String> it = layout.getKeys().iterator(); it.hasNext();)
605 {
606 Object key = it.next();
607 assertTrue("Key was not found: " + key, l2.getKeys().contains(key));
608 }
609 }
610
611
612
613
614 @Test
615 public void testInitCopyModify()
616 {
617 fillLayout();
618 PropertiesConfigurationLayout l2 = new PropertiesConfigurationLayout(
619 config, layout);
620 assertEquals("Comments are not equal", layout.getComment(TEST_KEY), l2
621 .getComment(TEST_KEY));
622 layout.setComment(TEST_KEY, "A new comment");
623 assertEquals("Comment was changed", TEST_COMMENT, l2
624 .getCanonicalComment(TEST_KEY, false));
625 l2.setBlancLinesBefore(TEST_KEY, l2.getBlancLinesBefore(TEST_KEY) + 1);
626 assertFalse("Blanc lines do not differ", layout
627 .getBlancLinesBefore(TEST_KEY) == l2
628 .getBlancLinesBefore(TEST_KEY));
629 }
630
631
632
633
634 @Test
635 public void testSetSeparator() throws ConfigurationException
636 {
637 config.addProperty(TEST_KEY, TEST_VALUE);
638 layout.setSeparator(TEST_KEY, ":");
639 checkLayoutString(TEST_KEY + ":" + TEST_VALUE + CR);
640 }
641
642
643
644
645
646 @Test
647 public void testSetGlobalSeparator() throws ConfigurationException
648 {
649 final String sep = "=";
650 config.addProperty(TEST_KEY, TEST_VALUE);
651 config.addProperty("key2", "value2");
652 layout.setSeparator(TEST_KEY, " : ");
653 layout.setGlobalSeparator(sep);
654 checkLayoutString(TEST_KEY + sep + TEST_VALUE + CR + "key2" + sep
655 + "value2" + CR);
656 }
657
658
659
660
661 @Test
662 public void testSetLineSeparator() throws ConfigurationException
663 {
664 final String lf = CR + CR;
665 config.addProperty(TEST_KEY, TEST_VALUE);
666 layout.setBlancLinesBefore(TEST_KEY, 2);
667 layout.setComment(TEST_KEY, TEST_COMMENT);
668 layout.setHeaderComment("Header comment");
669 layout.setLineSeparator(lf);
670 checkLayoutString("# Header comment" + lf + lf + lf + lf + "# "
671 + TEST_COMMENT + lf + TEST_KEY + " = " + TEST_VALUE + lf);
672 }
673
674
675
676
677
678 @Test
679 public void testSetLineSeparatorInComments() throws ConfigurationException
680 {
681 final String lf = "<-\n";
682 config.addProperty(TEST_KEY, TEST_VALUE);
683 layout.setComment(TEST_KEY, TEST_COMMENT + "\nMore comment");
684 layout.setHeaderComment("Header\ncomment");
685 layout.setLineSeparator(lf);
686 checkLayoutString("# Header" + lf + "# comment" + lf + lf + "# "
687 + TEST_COMMENT + lf + "# More comment" + lf + TEST_KEY + " = "
688 + TEST_VALUE + lf);
689 }
690
691
692
693
694 private void fillLayout()
695 {
696 builder.addComment("A header comment");
697 builder.addComment(null);
698 builder.addProperty("prop", "value");
699 builder.addComment(TEST_COMMENT);
700 builder.addProperty(TEST_KEY, TEST_VALUE);
701 builder.addProperty("anotherProp", "anotherValue");
702 try
703 {
704 layout.load(builder.getReader());
705 }
706 catch (ConfigurationException cex)
707 {
708
709 fail("Exception was thrown: " + cex);
710 }
711 }
712
713
714
715
716
717
718
719 private String getLayoutString() throws ConfigurationException
720 {
721 StringWriter out = new StringWriter();
722 layout.save(out);
723 return out.toString();
724 }
725
726
727
728
729
730
731
732 private void checkLayoutString(String expected)
733 throws ConfigurationException
734 {
735 assertEquals("Wrong layout file content", expected, getLayoutString());
736 }
737
738
739
740
741 static class PropertiesBuilder
742 {
743
744 private StringBuilder buf = new StringBuilder();
745
746
747 private int commentCounter;
748
749
750
751
752
753
754
755 public void addProperty(String key, String value)
756 {
757 buf.append(key).append(" = ").append(value).append(CR);
758 }
759
760
761
762
763
764
765
766 public void addComment(String s)
767 {
768 if (s != null)
769 {
770 if (commentCounter % 2 == 0)
771 {
772 buf.append("# ");
773 }
774 else
775 {
776 buf.append("! ");
777 }
778 buf.append(s);
779 commentCounter++;
780 }
781 buf.append(CR);
782 }
783
784
785
786
787
788
789 public Reader getReader()
790 {
791 return new StringReader(buf.toString());
792 }
793
794
795
796
797
798
799 @Override
800 public String toString()
801 {
802 return buf.toString();
803 }
804 }
805
806
807
808
809
810 static class LayoutTestConfiguration extends PropertiesConfiguration
811 {
812
813 public PropertiesBuilder builder;
814
815
816
817
818
819 @Override
820 boolean propertyLoaded(String key, String value)
821 throws ConfigurationException
822 {
823 if (builder == null)
824 {
825 return super.propertyLoaded(key, value);
826 }
827 else
828 {
829 if (PropertiesConfiguration.getInclude().equals(key))
830 {
831 getLayout().load(builder.getReader());
832 return false;
833 }
834 else
835 {
836 return true;
837 }
838 }
839 }
840 }
841 }