001/*
002 * ModeShape (http://www.modeshape.org)
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.modeshape.schematic.internal.document;
017
018import static org.hamcrest.core.Is.is;
019import static org.hamcrest.core.IsNull.notNullValue;
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertNull;
023import static org.junit.Assert.assertThat;
024import static org.junit.Assert.fail;
025import java.io.InputStream;
026import org.junit.After;
027import org.junit.Before;
028import org.junit.Test;
029import org.modeshape.schematic.document.Document;
030import org.modeshape.schematic.document.DocumentSequence;
031import org.modeshape.schematic.document.ParsingException;
032import org.modeshape.schematic.internal.annotation.FixFor;
033
034public class JsonReaderTest {
035
036    protected JsonReader reader;
037    protected boolean print;
038    protected Document doc;
039
040    @Before
041    public void beforeTest() {
042        reader = new JsonReader();
043        print = false;
044    }
045
046    @After
047    public void afterTest() {
048        reader = null;
049    }
050
051    @Test
052    public void shouldParseEmptyDocument() throws Exception {
053        doc = reader.read("{ }");
054    }
055
056    @Test
057    public void shouldParseEmptyDocumentWithLeadingWhitespace() throws Exception {
058        doc = reader.read("  { }");
059    }
060
061    @Test
062    public void shouldParseEmptyDocumentWithEmbeddedWhitespace() throws Exception {
063        doc = reader.read("{ \n \t \r\n }  ");
064    }
065
066    @Test
067    public void shouldParseDocumentWithSingleFieldWithStringValue() throws Exception {
068        doc = reader.read("{ \"foo\" : \"bar\" }");
069        assertField("foo", "bar");
070    }
071
072    @Test
073    public void shouldParseDocumentWithSingleFieldWithBooleanFalseValue() throws Exception {
074        doc = reader.read("{ \"foo\" : false }");
075        assertField("foo", false);
076    }
077
078    @Test
079    public void shouldParseDocumentWithSingleFieldWithBooleanTrueValue() throws Exception {
080        doc = reader.read("{ \"foo\" : true }");
081        assertField("foo", true);
082    }
083
084    @Test
085    public void shouldParseDocumentWithSingleFieldWithIntegerValue() throws Exception {
086        doc = reader.read("{ \"foo\" : 0 }");
087        assertField("foo", 0);
088    }
089
090    @Test
091    public void shouldParseDocumentWithSingleFieldWithLongValue() throws Exception {
092        long val = Integer.MAX_VALUE + 10L;
093        doc = reader.read("{ \"foo\" : " + val + " }");
094        assertField("foo", val);
095    }
096
097    @Test
098    public void shouldParseDocumentWithSingleFieldWithDoubleValue() throws Exception {
099        doc = reader.read("{ \"foo\" : 2.3543 }");
100        assertField("foo", 2.3543d);
101    }
102
103    @Test
104    public void shouldParseDocumentWithMultipleFieldsAndExtraDelimiters() throws Exception {
105        doc = reader.read("{ \"foo\" : 32 ,, \"nested\" : { \"bar\" : \"baz\", \"bom\" : true } ,}");
106        assertField("foo", 32);
107        doc = doc.getDocument("nested");
108        assertField("bar", "baz");
109        assertField("bom", true);
110    }
111
112    @Test
113    public void shouldParseMultipleDocuments() throws Exception {
114        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/multiple-json-files.txt");
115        DocumentSequence seq = reader.readMultiple(stream);
116        int count = 0;
117        while (true) {
118            Document doc = seq.nextDocument();
119            if (doc == null) break;
120            ++count;
121        }
122        assertThat(count, is(265));
123    }
124
125    @Test
126    @FixFor( "MODE-2309" )
127    public void shouldParseJsonWithControlCharactersInFieldValues() throws Exception {
128        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/example-with-control-characters.json");
129        doc = reader.read(stream);
130        assertNotNull(doc);
131        assertEquals(6, countFields(doc));
132        assertField("firstName", "Jane");
133        assertField("lastName", "Doe");
134        assertField("fieldWithLF", "This is a value\nwith a line feed");
135        assertField("fieldWithCRLF", "This is a value\r\nwith a line feed\r\ncarriage return");
136
137        doc = doc.getDocument("address");
138        assertEquals(3, countFields(doc));
139        assertField("street", "Main Street");
140        assertField("city", "Memphis");
141        assertField("zip", 12345);
142    }
143
144    @Test
145    @FixFor( "MODE-2082" )
146    public void shouldParseJsonWithComments() throws Exception {
147        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/example-with-comments.json");
148        doc = reader.read(stream);
149        assertNotNull(doc);
150        assertEquals(4, countFields(doc));
151        assertField("firstName", "Jane");
152        assertField("lastName", "Doe");
153
154        doc = doc.getDocument("address");
155        assertEquals(3, countFields(doc));
156        assertField("street", "Main // Street");
157        assertField("city", "Mem/ phis");
158        assertField("zip", 12345);
159    }
160
161    @Test
162    @FixFor( "MODE-2082" )
163    public void shouldNotParseJsonWithInvalidComments() throws Exception {
164        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/invalid-example-with-comments.json");
165        try {
166            doc = reader.read(stream);
167            fail("Expected parsing exception");
168        } catch (ParsingException e) {
169            // expected
170        }
171
172        stream = getClass().getClassLoader().getResourceAsStream("json/invalid-example-with-comments2.json");
173        try {
174            doc = reader.read(stream);
175            fail("Expected parsing exception");
176        } catch (ParsingException e) {
177            // expected
178        }
179    }
180
181    @Test
182    @FixFor( "MODE-2214" )
183    public void shouldNotParseJsonWithInvalidArray() throws Exception {
184        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/invalid-array-repo-config-1.json");
185        try {
186            doc = reader.read(stream);
187            fail("Expected parsing exception");
188        } catch (ParsingException e) {
189            // expected
190        }
191
192        stream = getClass().getClassLoader().getResourceAsStream("json/invalid-array-repo-config-2.json");
193        try {
194            doc = reader.read(stream);
195            fail("Expected parsing exception");
196        } catch (ParsingException e) {
197            // expected
198        }
199    }
200
201    @Test
202    @FixFor( "MODE-2317" )
203    public void shouldParseNonUnicodeEscapeSequence() throws Exception {
204        String url = "jdbc:h2:file:path\\upstream.jboss-integration.modeshape\\modeshape-jcr;DB_CLOSE_DELAY=-1";
205        doc = reader.read("{ \"url\" : \"" + url +  "\"}");
206        assertField("url", url);
207
208        InputStream stream = getClass().getClassLoader().getResourceAsStream("json/non-unicode-escape.json");
209        reader.read(stream);
210    }
211
212    private int countFields( Document doc ) {
213        int fieldCount = 0;
214        for (Document.Field field : doc.fields()) {
215            assertThat(field, is(notNullValue()));
216            fieldCount++;
217        }
218        return fieldCount;
219    }
220
221    protected void assertField( String name,
222                                Object value ) {
223        Object actual = doc.get(name);
224        if (value == null) {
225            assertNull(actual);
226        } else {
227            assertEquals(value, actual);
228        }
229    }
230
231}