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     */
016    package org.ini4j;
017    
018    import org.ini4j.sample.Dwarf;
019    import org.ini4j.sample.Dwarfs;
020    
021    import org.ini4j.test.DwarfsData;
022    import org.ini4j.test.Helper;
023    
024    import org.junit.After;
025    
026    import static org.junit.Assert.assertEquals;
027    import static org.junit.Assert.assertFalse;
028    import static org.junit.Assert.assertNull;
029    import static org.junit.Assert.assertSame;
030    import static org.junit.Assert.assertTrue;
031    import static org.junit.Assert.fail;
032    
033    import org.junit.Before;
034    import org.junit.Test;
035    
036    import java.io.ByteArrayInputStream;
037    import java.io.File;
038    import java.io.FileInputStream;
039    import java.io.FileOutputStream;
040    import java.io.FileReader;
041    import java.io.FileWriter;
042    import java.io.IOException;
043    import java.io.StringReader;
044    
045    import java.util.HashMap;
046    import java.util.List;
047    import java.util.Map;
048    
049    public 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    }