1   package org.apache.commons.configuration;
2   
3   /*
4    * Copyright 2001-2004 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.math.BigDecimal;
20  import java.math.BigInteger;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.NoSuchElementException;
24  import java.util.Properties;
25  import java.util.Vector;
26  
27  import junit.framework.TestCase;
28  import junitx.framework.ObjectAssert;
29  
30  /***
31   * Tests some basic functions of the BaseConfiguration class. Missing keys might
32   * return null.
33   *
34   * @version $Id: TestBaseNullConfiguration.java,v 1.1 2004/09/20 19:46:26 henning Exp $
35   */
36  public class TestBaseNullConfiguration extends TestCase
37  {
38          protected BaseConfiguration config = null;
39  
40  	protected static Class missingElementException = NoSuchElementException.class;
41  	protected static Class incompatibleElementException = ConversionException.class;
42  
43          protected void setUp()
44              throws Exception
45          {
46              config = new BaseConfiguration();
47              config.setThrowExceptionOnMissing(false);
48          }
49  
50          public void testThrowExceptionOnMissing()
51          {
52              assertFalse("Throw Exception Property is set!", config.isThrowExceptionOnMissing());
53          }
54  
55  	public void testGetProperty()
56  	{
57  		/* should be empty and return null */
58  		assertEquals("This returns null", config.getProperty("foo"), null);
59  
60  		/* add a real value, and get it two different ways */
61  		config.setProperty("number", "1");
62  		assertEquals("This returns '1'", config.getProperty("number"), "1");
63  		assertEquals("This returns '1'", config.getString("number"), "1");
64  	}
65  
66  	public void testGetByte()
67  	{
68  		config.setProperty("number", "1");
69  		byte oneB = 1;
70  		byte twoB = 2;
71  		assertEquals("This returns 1(byte)", oneB, config.getByte("number"));
72  		assertEquals("This returns 1(byte)", oneB, config.getByte("number", twoB));
73  		assertEquals("This returns 2(default byte)", twoB, config.getByte("numberNotInConfig", twoB));
74  		assertEquals("This returns 1(Byte)", new Byte(oneB), config.getByte("number", new Byte("2")));
75  
76  		// missing key without default value
77  		Throwable t = null;
78  		try {
79  			config.getByte("numberNotInConfig");
80  		} catch (Throwable T) {
81  			t = T;
82  		}
83  		assertNotNull("No exception thrown for missing keys", t);
84  		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
85  
86  		// existing key with an incompatible value
87  		config.setProperty("test.empty", "");
88  		t = null;
89  		try {
90  			config.getByte("test.empty");
91  		} catch (Throwable T) {
92  			t = T;
93  		}
94  		assertNotNull("No exception thrown for incompatible values", t);
95  		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
96  	}
97  
98  	public void testGetShort()
99  	{
100 		config.setProperty("numberS", "1");
101 		short oneS = 1;
102 		short twoS = 2;
103 		assertEquals("This returns 1(short)", oneS, config.getShort("numberS"));
104 		assertEquals("This returns 1(short)", oneS, config.getShort("numberS", twoS));
105 		assertEquals("This returns 2(default short)", twoS, config.getShort("numberNotInConfig", twoS));
106 		assertEquals("This returns 1(Short)", new Short(oneS), config.getShort("numberS", new Short("2")));
107 
108 		// missing key without default value
109 		Throwable t = null;
110 		try {
111 			config.getShort("numberNotInConfig");
112 		} catch (Throwable T) {
113 			t = T;
114 		}
115 		assertNotNull("No exception thrown for missing keys", t);
116 		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
117 
118 		// existing key with an incompatible value
119 		config.setProperty("test.empty", "");
120 		t = null;
121 		try {
122 			config.getShort("test.empty");
123 		} catch (Throwable T) {
124 			t = T;
125 		}
126 		assertNotNull("No exception thrown for incompatible values", t);
127 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
128 	}
129 
130 	public void testGetLong()
131 	{
132 		config.setProperty("numberL", "1");
133 		long oneL = 1;
134 		long twoL = 2;
135 		assertEquals("This returns 1(long)", oneL, config.getLong("numberL"));
136 		assertEquals("This returns 1(long)", oneL, config.getLong("numberL", twoL));
137 		assertEquals("This returns 2(default long)", twoL, config.getLong("numberNotInConfig", twoL));
138 		assertEquals("This returns 1(Long)", new Long(oneL), config.getLong("numberL", new Long("2")));
139 
140 		// missing key without default value
141 		Throwable t = null;
142 		try {
143 			config.getLong("numberNotInConfig");
144 		} catch (Throwable T) {
145 			t = T;
146 		}
147 		assertNotNull("No exception thrown for missing keys", t);
148 		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
149 
150 		// existing key with an incompatible value
151 		config.setProperty("test.empty", "");
152 		t = null;
153 		try {
154 			config.getLong("test.empty");
155 		} catch (Throwable T) {
156 			t = T;
157 		}
158 		assertNotNull("No exception thrown for incompatible values", t);
159 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
160 	}
161 
162 	public void testGetFloat()
163 	{
164 		config.setProperty("numberF", "1.0");
165 		float oneF = 1;
166 		float twoF = 2;
167 		assertEquals("This returns 1(float)", oneF, config.getFloat("numberF"), 0);
168 		assertEquals("This returns 1(float)", oneF, config.getFloat("numberF", twoF), 0);
169 		assertEquals("This returns 2(default float)", twoF, config.getFloat("numberNotInConfig", twoF), 0);
170 		assertEquals("This returns 1(Float)", new Float(oneF), config.getFloat("numberF", new Float("2")));
171 
172 		// missing key without default value
173 		Throwable t = null;
174 		try {
175 			config.getFloat("numberNotInConfig");
176 		} catch (Throwable T) {
177 			t = T;
178 		}
179 		assertNotNull("No exception thrown for missing keys", t);
180 		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
181 
182 		// existing key with an incompatible value
183 		config.setProperty("test.empty", "");
184 		t = null;
185 		try {
186 			config.getFloat("test.empty");
187 		} catch (Throwable T) {
188 			t = T;
189 		}
190 		assertNotNull("No exception thrown for incompatible values", t);
191 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
192 	}
193 
194 	public void testGetDouble()
195 	{
196 		config.setProperty("numberD", "1.0");
197 		double oneD = 1;
198 		double twoD = 2;
199 		assertEquals("This returns 1(double)", oneD, config.getDouble("numberD"), 0);
200 		assertEquals("This returns 1(double)", oneD, config.getDouble("numberD", twoD), 0);
201 		assertEquals("This returns 2(default double)", twoD, config.getDouble("numberNotInConfig", twoD), 0);
202 		assertEquals("This returns 1(Double)", new Double(oneD), config.getDouble("numberD", new Double("2")));
203 
204 		// missing key without default value
205 		Throwable t = null;
206 		try {
207 			config.getDouble("numberNotInConfig");
208 		} catch (Throwable T) {
209 			t = T;
210 		}
211 		assertNotNull("No exception thrown for missing keys", t);
212 		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
213 
214 		// existing key with an incompatible value
215 		config.setProperty("test.empty", "");
216 		t = null;
217 		try {
218 			config.getDouble("test.empty");
219 		} catch (Throwable T) {
220 			t = T;
221 		}
222 		assertNotNull("No exception thrown for incompatible values", t);
223 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
224 	}
225 
226 	public void testGetBigDecimal()
227 	{
228 		config.setProperty("numberBigD", "123.456");
229 		BigDecimal number = new BigDecimal("123.456");
230 		BigDecimal defaultValue = new BigDecimal("654.321");
231 
232 		assertEquals("Existing key", number, config.getBigDecimal("numberBigD"));
233 		assertEquals("Existing key with default value", number, config.getBigDecimal("numberBigD", defaultValue));
234 		assertEquals("Missing key with default value", defaultValue, config.getBigDecimal("numberNotInConfig", defaultValue));
235 
236 		// missing key without default value
237                 assertEquals("Missing Key is not null!", null, config.getBigDecimal("numberNotInConfig"));
238 
239 		// existing key with an incompatible value
240 		config.setProperty("test.empty", "");
241 		Throwable t = null;
242 		try {
243 			config.getBigDecimal("test.empty");
244 		} catch (Throwable T) {
245 			t = T;
246 		}
247 		assertNotNull("No exception thrown for incompatible values", t);
248 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
249 	}
250 
251 	public void testGetBigInteger()
252 	{
253 		config.setProperty("numberBigI", "1234567890");
254 		BigInteger number = new BigInteger("1234567890");
255 		BigInteger defaultValue = new BigInteger("654321");
256 
257 		assertEquals("Existing key", number, config.getBigInteger("numberBigI"));
258 		assertEquals("Existing key with default value", number, config.getBigInteger("numberBigI", defaultValue));
259 		assertEquals("Missing key with default value", defaultValue, config.getBigInteger("numberNotInConfig", defaultValue));
260 
261 		// missing key without default value
262                 assertEquals("Missing Key is not null!", null, config.getBigInteger("numberNotInConfig"));
263 
264 		// existing key with an incompatible value
265 		config.setProperty("test.empty", "");
266 		Throwable t = null;
267 		try {
268 			config.getBigInteger("test.empty");
269 		} catch (Throwable T) {
270 			t = T;
271 		}
272 		assertNotNull("No exception thrown for incompatible values", t);
273 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
274 	}
275 
276 
277 	public void testGetString()
278 	{
279 		config.setProperty("testString", "The quick brown fox");
280 		String string = new String("The quick brown fox");
281 		String defaultValue = new String("jumps over the lazy dog");
282 
283 		assertEquals("Existing key", string, config.getString("testString"));
284 		assertEquals("Existing key with default value", string, config.getString("testString", defaultValue));
285 		assertEquals("Missing key with default value", defaultValue, config.getString("stringNotInConfig", defaultValue));
286 
287 		// missing key without default value
288                 assertEquals("Missing Key is not null!", null, config.getString("stringNotInConfig"));
289 
290 	}
291 
292 	public void testGetBoolean()
293 	{
294 		config.setProperty("boolA", Boolean.TRUE);
295 		boolean boolT = true, boolF = false;
296 		assertEquals("This returns true", boolT, config.getBoolean("boolA"));
297 		assertEquals("This returns true, not the default", boolT, config.getBoolean("boolA", boolF));
298 		assertEquals("This returns false(default)", boolF, config.getBoolean("boolNotInConfig", boolF));
299 		assertEquals("This returns true(Boolean)", new Boolean(boolT), config.getBoolean("boolA", new Boolean(boolF)));
300 
301 		// missing key without default value
302 		Throwable t = null;
303 		try {
304 			config.getBoolean("numberNotInConfig");
305 		} catch (Throwable T) {
306 			t = T;
307 		}
308 		assertNotNull("No exception thrown for missing keys", t);
309 		ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
310 
311 		// existing key with an incompatible value
312 		config.setProperty("test.empty", "");
313 		t = null;
314 		try {
315 			config.getBoolean("test.empty");
316 		} catch (Throwable T) {
317 			t = T;
318 		}
319 		assertNotNull("No exception thrown for incompatible values", t);
320 		ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
321 	}
322 
323 	public void testGetList()
324 	{
325 		config.addProperty("number", "1");
326 		config.addProperty("number", "2");
327 		List list = config.getList("number");
328 		assertNotNull("The list is null", list);
329 		assertEquals("List size", 2, list.size());
330 		assertTrue("The number 1 is missing from the list", list.contains("1"));
331 		assertTrue("The number 2 is missing from the list", list.contains("2"));
332 
333 		/*
334 		 *  now test dan's new fix where we get the first scalar
335 		 *  when we access a list valued property
336 		 */
337 		try
338 		{
339 			config.getString("number");
340 		}
341 		catch (NoSuchElementException nsse)
342 		{
343 			fail("Should return a string");
344 		}
345 	}
346 
347 	public void testGetVector()
348 	{
349 		config.addProperty("number", "1");
350 		config.addProperty("number", "2");
351 		Vector vector = config.getVector("number");
352 		assertNotNull("The vector is null", vector);
353 		assertEquals("Vector size", 2, vector.size());
354 		assertTrue("The number 1 is missing from the vector", vector.contains("1"));
355 		assertTrue("The number 2 is missing from the vector", vector.contains("2"));
356 
357 		/*
358 		 *  now test dan's new fix where we get the first scalar
359 		 *  when we access a vector valued property
360 		 */
361 		try
362 		{
363 			config.getString("number");
364 		}
365 		catch (NoSuchElementException nsse)
366 		{
367 			fail("Should return a string");
368 		}
369 	}
370 
371 	public void testCommaSeparatedString()
372 	{
373 		String prop = "hey, that's a test";
374 		config.setProperty("prop.string", prop);
375 		try
376 		{
377 			config.getList("prop.string");
378 		}
379 		catch (NoSuchElementException nsse)
380 		{
381 			fail("Should return a list");
382 		}
383 
384 		String prop2 = "hey//, that's a test";
385 		config.clearProperty("prop.string");
386 		config.setProperty("prop.string", prop2);
387 		try
388 		{
389 			config.getString("prop.string");
390 		}
391 		catch (NoSuchElementException nsse)
392 		{
393 			fail("Should return a list");
394 		}
395 
396 	}
397 
398 	public void testPropertyAccess()
399 	{
400 		config.clearProperty("prop.properties");
401 		config.setProperty("prop.properties", "");
402 		assertEquals(
403 			"This returns an empty Properties object",
404 			config.getProperties("prop.properties"),
405 			new Properties());
406 		config.clearProperty("prop.properties");
407 		config.setProperty("prop.properties", "foo=bar, baz=moo, seal=clubber");
408 
409 		Properties p = new Properties();
410 		p.setProperty("foo", "bar");
411 		p.setProperty("baz", "moo");
412 		p.setProperty("seal", "clubber");
413 		assertEquals(
414 			"This returns a filled in Properties object",
415 			config.getProperties("prop.properties"),
416 			p);
417 	}
418 
419 	public void testSubset()
420 	{
421 		/*
422 		 * test subset : assure we don't reprocess the data elements
423 		 * when generating the subset
424 		 */
425 
426 		String prop = "hey, that's a test";
427 		String prop2 = "hey//, that's a test";
428 		config.setProperty("prop.string", prop2);
429 		config.setProperty("property.string", "hello");
430 
431 		Configuration subEprop = config.subset("prop");
432 
433 		assertEquals(
434 			"Returns the full string",
435 			prop,
436 			subEprop.getString("string"));
437 		try
438 		{
439 			subEprop.getString("string");
440 		}
441 		catch (NoSuchElementException nsse)
442 		{
443 			fail("Should return a string");
444 		}
445 		try
446 		{
447 			subEprop.getList("string");
448 		}
449 		catch (NoSuchElementException nsse)
450 		{
451 			fail("Should return a list");
452 		}
453 
454 		Iterator it = subEprop.getKeys();
455 		it.next();
456 		assertFalse(it.hasNext());
457 
458 		subEprop = config.subset("prop.");
459 		it = subEprop.getKeys();
460 		assertFalse(it.hasNext());
461 	}
462 
463 	public void testInterpolation() throws Exception
464 	{
465 		config.setProperty("applicationRoot", "/home/applicationRoot");
466 		config.setProperty("db", "${applicationRoot}/db/hypersonic");
467 		String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
468 		config.setProperty("dbFailedInterpolate", unInterpolatedValue);
469 		String dbProp = "/home/applicationRoot/db/hypersonic";
470 
471 		//construct a new config, using config as the defaults config for it.
472 		BaseConfiguration superProp = config;
473 
474 		assertEquals(
475 			"Checking interpolated variable",dbProp,
476 			superProp.getString("db"));
477 		assertEquals(
478 			"lookup fails, leave variable as is",
479 			superProp.getString("dbFailedInterpolate"),
480 			unInterpolatedValue);
481 
482 		superProp.setProperty("arrayInt", "${applicationRoot}/1");
483 		String[] arrayInt = superProp.getStringArray("arrayInt");
484 		assertEquals(
485 			"check first entry was interpolated",
486 			"/home/applicationRoot/1",
487 			arrayInt[0]);
488 	}
489 
490 	public void testMultipleInterpolation() throws Exception
491 	{
492 		config.setProperty("test.base-level", "/base-level");
493 		config.setProperty("test.first-level", "${test.base-level}/first-level");
494 		config.setProperty(
495 			"test.second-level",
496 			"${test.first-level}/second-level");
497 		config.setProperty(
498 			"test.third-level",
499 			"${test.second-level}/third-level");
500 
501 		String expectedValue =
502 			"/base-level/first-level/second-level/third-level";
503 
504 		assertEquals(config.getString("test.third-level"), expectedValue);
505 	}
506 
507 	public void testInterpolationLoop() throws Exception
508 	{
509 		config.setProperty("test.a", "${test.b}");
510 		config.setProperty("test.b", "${test.a}");
511 
512 		try
513 		{
514 			config.getString("test.a");
515 		}
516 		catch (IllegalStateException e)
517 		{
518 			return;
519 		}
520 
521 		fail("IllegalStateException should have been thrown for looped property references");
522 	}
523 
524     public void testSplit()
525     {
526         String s1 = "abc,xyz";
527         List tokens = config.split(s1);
528         assertEquals("number of tokens in '" + s1 + "'", 2, tokens.size());
529         assertEquals("1st token for '" + s1 + "'", "abc", tokens.get(0));
530         assertEquals("2nd token for '" + s1 + "'", "xyz", tokens.get(1));
531 
532         String s2 = "abc//,xyz";
533         tokens = config.split(s2);
534         assertEquals("number of tokens in '" + s2 + "'", 1, tokens.size());
535         assertEquals("1st token for '" + s2 + "'", "abc,xyz", tokens.get(0));
536     }
537 
538 }
539