001/*
002 * Copyright 2005,2009 Ivan SZKIBA
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.ini4j;
017
018import org.ini4j.sample.Dwarf;
019import org.ini4j.sample.Dwarfs;
020
021import org.ini4j.test.DwarfsData;
022import org.ini4j.test.Helper;
023
024import org.junit.After;
025
026import static org.junit.Assert.assertEquals;
027import static org.junit.Assert.assertFalse;
028import static org.junit.Assert.assertNull;
029import static org.junit.Assert.assertSame;
030import static org.junit.Assert.assertTrue;
031import static org.junit.Assert.fail;
032
033import org.junit.Before;
034import org.junit.Test;
035
036import java.io.ByteArrayInputStream;
037import java.io.File;
038import java.io.FileInputStream;
039import java.io.FileOutputStream;
040import java.io.FileReader;
041import java.io.FileWriter;
042import java.io.IOException;
043import java.io.StringReader;
044
045import java.util.HashMap;
046import java.util.List;
047import java.util.Map;
048
049public class ConfigParserTest extends Ini4jCase
050{
051    private static final String SECTION = "section";
052    private static final String OPTION = "option";
053    private static final String DWARFS_PATH = "org/ini4j/addon/dwarfs-py.ini";
054    private static final String BAD = "[bashful\nage=3";
055    private static final String TEST_DATA_PATH = "src/test/resources";
056    private static final String TEST_WORK_PATH = "target";
057    private static final String MISSING = "missing";
058    private static final String MISSING_REF = "%(missing)";
059    private static final String DUMMY = "dummy";
060    protected ConfigParser instance;
061
062    @Before @Override public void setUp() throws Exception
063    {
064        super.setUp();
065        instance = new ConfigParser();
066    }
067
068    @After @Override public void tearDown()
069    {
070    }
071
072    @Test public void testAddHasRemove() throws Exception
073    {
074        assertFalse(instance.hasSection(SECTION));
075        assertFalse(instance.hasOption(SECTION, OPTION));
076        assertFalse(instance.getIni().containsKey(SECTION));
077        instance.addSection(SECTION);
078        assertTrue(instance.hasSection(SECTION));
079        instance.set(SECTION, OPTION, "dummy");
080        assertTrue(instance.hasOption(SECTION, OPTION));
081        assertTrue(instance.getIni().get(SECTION).containsKey(OPTION));
082        instance.removeOption(SECTION, OPTION);
083        assertFalse(instance.hasOption(SECTION, OPTION));
084        instance.removeSection(SECTION);
085        assertFalse(instance.hasSection(SECTION));
086    }
087
088    @Test public void testAddSectionDuplicate() throws Exception
089    {
090        instance.addSection(SECTION);
091        try
092        {
093            instance.addSection(SECTION);
094            missing(ConfigParser.DuplicateSectionException.class);
095        }
096        catch (ConfigParser.DuplicateSectionException x)
097        {
098            //
099        }
100    }
101
102    @Test public void testAddSectionIllegal() throws Exception
103    {
104        try
105        {
106            instance.addSection(ConfigParser.PyIni.DEFAULT_SECTION_NAME);
107            missing(IllegalArgumentException.class);
108        }
109        catch (IllegalArgumentException x)
110        {
111            //
112        }
113    }
114
115    @Test public void testDefaults() throws Exception
116    {
117        Map<String, String> defs = new HashMap<String, String>();
118
119        instance = new ConfigParser(defs);
120
121        assertSame(defs, instance.defaults());
122    }
123
124    @Test public void testDwarfs() throws Exception
125    {
126        readDwarfs();
127        checkEquals(DwarfsData.bashful, Dwarfs.PROP_BASHFUL);
128        checkEquals(DwarfsData.doc, Dwarfs.PROP_DOC);
129        checkEquals(DwarfsData.dopey, Dwarfs.PROP_DOPEY);
130        checkEquals(DwarfsData.happy, Dwarfs.PROP_HAPPY);
131        checkEquals(DwarfsData.grumpy, Dwarfs.PROP_GRUMPY);
132        checkEquals(DwarfsData.sleepy, Dwarfs.PROP_SLEEPY);
133        checkEquals(DwarfsData.sneezy, Dwarfs.PROP_SNEEZY);
134    }
135
136    @Test public void testGet() throws Exception
137    {
138        Ini.Section section = instance.getIni().add(SECTION);
139
140        section.put(OPTION, "on");
141        assertTrue(instance.getBoolean(SECTION, OPTION));
142        section.put(OPTION, "1");
143        assertTrue(instance.getBoolean(SECTION, OPTION));
144        section.put(OPTION, "true");
145        assertTrue(instance.getBoolean(SECTION, OPTION));
146        section.put(OPTION, "yes");
147        assertTrue(instance.getBoolean(SECTION, OPTION));
148        section.put(OPTION, "TruE");
149        assertTrue(instance.getBoolean(SECTION, OPTION));
150
151        //
152        section.put(OPTION, "off");
153        assertFalse(instance.getBoolean(SECTION, OPTION));
154        section.put(OPTION, "0");
155        assertFalse(instance.getBoolean(SECTION, OPTION));
156        section.put(OPTION, "no");
157        assertFalse(instance.getBoolean(SECTION, OPTION));
158        section.put(OPTION, "false");
159        assertFalse(instance.getBoolean(SECTION, OPTION));
160        section.put(OPTION, "FalsE");
161        assertFalse(instance.getBoolean(SECTION, OPTION));
162
163        // ints
164        section.put(OPTION, "12");
165        assertEquals(12, instance.getInt(SECTION, OPTION));
166        assertEquals(12L, instance.getLong(SECTION, OPTION));
167        section.put(OPTION, "1.2");
168        assertEquals(1.2f, instance.getFloat(SECTION, OPTION), Helper.DELTA);
169        assertEquals(1.2, instance.getDouble(SECTION, OPTION), Helper.DELTA);
170    }
171
172    @Test public void testGetBooleanException() throws Exception
173    {
174        Ini.Section section = instance.getIni().add(SECTION);
175
176        section.put(OPTION, "joe");
177        try
178        {
179            instance.getBoolean(SECTION, OPTION);
180            missing(IllegalArgumentException.class);
181        }
182        catch (IllegalArgumentException x)
183        {
184            //
185        }
186    }
187
188    @Test public void testGetMissinOptionException() throws Exception
189    {
190        instance.addSection(SECTION);
191        instance.set(SECTION, OPTION, MISSING_REF);
192        try
193        {
194            instance.get(SECTION, OPTION);
195            missing(ConfigParser.InterpolationMissingOptionException.class);
196        }
197        catch (ConfigParser.InterpolationMissingOptionException x)
198        {
199            //
200        }
201    }
202
203    @Test public void testGetNoOption() throws Exception
204    {
205        instance.getIni().add(SECTION);
206        try
207        {
208            instance.get(SECTION, OPTION);
209            missing(ConfigParser.NoOptionException.class);
210        }
211        catch (ConfigParser.NoOptionException x)
212        {
213            //
214        }
215    }
216
217    @Test public void testGetNoSection() throws Exception
218    {
219        try
220        {
221            instance.get(SECTION, OPTION);
222            missing(ConfigParser.NoSectionException.class);
223        }
224        catch (ConfigParser.NoSectionException x)
225        {
226            //
227        }
228    }
229
230    @Test
231    @SuppressWarnings("empty-statement")
232    public void testGetVars() throws Exception
233    {
234        Map<String, String> vars = new HashMap<String, String>();
235
236        instance = new ConfigParser(vars);
237
238        instance.addSection(SECTION);
239        instance.set(SECTION, OPTION, MISSING_REF);
240        assertEquals(MISSING_REF, instance.get(SECTION, OPTION, true));
241        requireMissingOptionException(SECTION, OPTION);
242        vars.put(MISSING, DUMMY);
243        assertEquals(DUMMY, instance.get(SECTION, OPTION));
244        vars.remove(MISSING);
245        requireMissingOptionException(SECTION, OPTION);
246        instance.getIni().add(ConfigParser.PyIni.DEFAULT_SECTION_NAME);
247        ((ConfigParser.PyIni) instance.getIni()).getDefaultSection().put(MISSING, DUMMY);
248        assertEquals(DUMMY, instance.get(SECTION, OPTION));
249        ((ConfigParser.PyIni) instance.getIni()).getDefaultSection().remove(MISSING);
250        requireMissingOptionException(SECTION, OPTION);
251        instance = new ConfigParser();
252        instance.addSection(SECTION);
253        instance.set(SECTION, OPTION, MISSING_REF);
254        vars.put(MISSING, DUMMY);
255        assertEquals(DUMMY, instance.get(SECTION, OPTION, false, vars));
256    }
257
258    @Test public void testItems() throws Exception
259    {
260        Ini ini = new Ini();
261
262        ini.add(SECTION).from(DwarfsData.dopey);
263        Ini.Section section = ini.get(SECTION);
264        Ini.Section dopey = ini.add(Dwarfs.PROP_DOPEY);
265
266        for (String key : section.keySet())
267        {
268            dopey.put(key.toLowerCase(), section.get(key));
269        }
270
271        readDwarfs();
272        List<Map.Entry<String, String>> items = instance.items(Dwarfs.PROP_DOPEY);
273
274        assertEquals(5, items.size());
275        assertEquals(6, dopey.size());
276        for (Map.Entry<String, String> entry : items)
277        {
278            assertEquals(dopey.get(entry.getKey()), entry.getValue());
279        }
280
281        // raw
282        dopey = instance.getIni().get(Dwarfs.PROP_DOPEY);
283        items = instance.items(Dwarfs.PROP_DOPEY, true);
284
285        assertEquals(5, items.size());
286        assertEquals("%(_weight)", dopey.get(Dwarf.PROP_WEIGHT));
287        assertEquals("%(_height)", dopey.get(Dwarf.PROP_HEIGHT));
288    }
289
290    @Test public void testOptions() throws Exception
291    {
292        instance.addSection(SECTION);
293        assertEquals(0, instance.options(SECTION).size());
294        for (int i = 0; i < 10; i++)
295        {
296            instance.set(SECTION, OPTION + i, DUMMY);
297        }
298
299        assertEquals(10, instance.options(SECTION).size());
300    }
301
302    @Test public void testRead() throws Exception
303    {
304        File file = newTestFile(DWARFS_PATH);
305
306        assertTrue(file.exists());
307        instance.read(file.getCanonicalPath());
308        instance.read(file);
309        instance.read(new FileReader(file));
310        instance.read(new FileInputStream(file));
311        instance.read(file.toURI().toURL());
312    }
313
314    @Test public void testReadFileException() throws Exception
315    {
316        try
317        {
318            instance.read(badFile());
319            missing(ConfigParser.ParsingException.class);
320        }
321        catch (ConfigParser.ParsingException x)
322        {
323            //
324        }
325    }
326
327    @Test public void testReadReaderException() throws Exception
328    {
329        try
330        {
331            instance.read(new StringReader(BAD));
332            missing(ConfigParser.ParsingException.class);
333        }
334        catch (ConfigParser.ParsingException x)
335        {
336            //
337        }
338    }
339
340    @Test public void testReadStreamException() throws Exception
341    {
342        try
343        {
344            instance.read(new ByteArrayInputStream(BAD.getBytes()));
345            missing(ConfigParser.ParsingException.class);
346        }
347        catch (ConfigParser.ParsingException x)
348        {
349            //
350        }
351    }
352
353    @Test public void testReadURLException() throws Exception
354    {
355        try
356        {
357            instance.read(badFile().toURI().toURL());
358            missing(ConfigParser.ParsingException.class);
359        }
360        catch (ConfigParser.ParsingException x)
361        {
362            //
363        }
364    }
365
366    @Test public void testSections() throws Exception
367    {
368        instance.addSection(SECTION);
369        assertEquals(1, instance.sections().size());
370        for (int i = 0; i < 10; i++)
371        {
372            instance.addSection(SECTION + i);
373        }
374
375        assertEquals(11, instance.sections().size());
376    }
377
378    @Test public void testSet() throws Exception
379    {
380        instance.addSection(SECTION);
381        instance.set(SECTION, OPTION, "dummy");
382        assertEquals("dummy", instance.getIni().get(SECTION).get(OPTION));
383        assertTrue(instance.hasOption(SECTION, OPTION));
384        instance.set(SECTION, OPTION, null);
385        assertFalse(instance.hasOption(SECTION, OPTION));
386    }
387
388    @Test public void testSetNoSection() throws Exception
389    {
390        try
391        {
392            instance.set(SECTION, OPTION, "dummy");
393            missing(ConfigParser.NoSectionException.class);
394        }
395        catch (ConfigParser.NoSectionException x)
396        {
397            //
398        }
399    }
400
401    @Test public void testWrite() throws Exception
402    {
403        File input = newTestFile(DWARFS_PATH);
404        File output = new File(TEST_WORK_PATH, input.getName());
405
406        instance.read(input);
407        instance.write(output);
408        checkWrite(output);
409        instance.write(new FileWriter(output));
410        checkWrite(output);
411        instance.write(new FileOutputStream(output));
412        checkWrite(output);
413    }
414
415    protected void checkEquals(Dwarf expected, String sectionName) throws Exception
416    {
417        assertEquals("" + expected.getAge(), instance.get(sectionName, Dwarf.PROP_AGE));
418        assertEquals("" + expected.getHeight(), instance.get(sectionName, Dwarf.PROP_HEIGHT));
419        assertEquals("" + expected.getWeight(), instance.get(sectionName, Dwarf.PROP_WEIGHT));
420        assertEquals("" + expected.getHomePage(), instance.get(sectionName, Dwarf.PROP_HOME_PAGE.toLowerCase()));
421        assertEquals("" + expected.getHomeDir(), instance.get(sectionName, Dwarf.PROP_HOME_DIR.toLowerCase()));
422    }
423
424    protected File newTestFile(String path)
425    {
426        return new File(TEST_DATA_PATH, path);
427    }
428
429    protected void readDwarfs() throws Exception
430    {
431        instance.read(newTestFile(DWARFS_PATH));
432    }
433
434    private File badFile() throws IOException
435    {
436        File f = File.createTempFile("test", "ini");
437
438        f.deleteOnExit();
439        FileWriter w = new FileWriter(f);
440
441        w.write(BAD, 0, BAD.length());
442        w.close();
443
444        return f;
445    }
446
447    private void checkEquals(Map<String, String> a, Map<String, String> b) throws Exception
448    {
449        if (a == null)
450        {
451            assertNull(b);
452        }
453        else
454        {
455            assertEquals(a.size(), b.size());
456            for (String key : a.keySet())
457            {
458                assertEquals(a.get(key), b.get(key));
459            }
460        }
461    }
462
463    private void checkWrite(File file) throws Exception
464    {
465        ConfigParser saved = new ConfigParser(instance.defaults());
466
467        saved.read(file);
468        checkEquals(((ConfigParser.PyIni) instance.getIni()).getDefaultSection(),
469            ((ConfigParser.PyIni) saved.getIni()).getDefaultSection());
470        assertEquals(instance.sections().size(), saved.sections().size());
471        for (String sectionName : instance.sections())
472        {
473            checkEquals(instance.getIni().get(sectionName), saved.getIni().get(sectionName));
474        }
475    }
476
477    @SuppressWarnings("empty-statement")
478    private void requireMissingOptionException(String sectionName, String optionName) throws Exception
479    {
480        try
481        {
482            instance.get(sectionName, optionName);
483            fail();
484        }
485        catch (ConfigParser.InterpolationMissingOptionException x)
486        {
487            ;
488        }
489    }
490}