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.junit.Assert.assertEquals;
019import static org.junit.Assert.assertTrue;
020import java.io.StringReader;
021import java.util.Calendar;
022import java.util.Date;
023import java.util.TimeZone;
024import java.util.UUID;
025import org.junit.After;
026import org.junit.Before;
027import org.junit.Test;
028import org.modeshape.schematic.document.Binary;
029import org.modeshape.schematic.document.Bson;
030import org.modeshape.schematic.document.Code;
031import org.modeshape.schematic.document.CodeWithScope;
032import org.modeshape.schematic.document.Document;
033import org.modeshape.schematic.document.Null;
034import org.modeshape.schematic.document.ObjectId;
035
036public class JsonReaderParserTest {
037
038    protected boolean print;
039    protected Object value;
040    protected Document bson;
041    protected JsonWriter writer;
042
043    @Before
044    public void beforeTest() {
045        print = false;
046        writer = new CompactJsonWriter();
047    }
048
049    @After
050    public void afterTest() {
051        value = null;
052        bson = null;
053    }
054
055    protected JsonReader.Parser parser( String string ) {
056        return new JsonReader.Parser(new JsonReader.Tokenizer(new StringReader(string)), JsonReader.VALUE_FACTORY,
057                                     JsonReader.DATE_VALUE_MATCHER);
058    }
059
060    @Test
061    public void shouldParseValueAsNullGivenNoContent() throws Exception {
062        value = parser("").parseValue();
063        assertTrue(Null.matches(value));
064    }
065
066    @Test
067    public void shouldParseValueAsNullGivenNullLiteral() throws Exception {
068        value = parser("null").parseValue();
069        assertTrue(Null.matches(value));
070    }
071
072    @Test
073    public void shouldParseValueAsNullGivenNullLiteralWithIncorrectCase() throws Exception {
074        value = parser("nULl").parseValue();
075        assertTrue(Null.matches(value));
076    }
077
078    @Test
079    public void shouldParseValueGivenTrueBooleanLiteral() throws Exception {
080        value = parser("true").parseValue();
081        assertTrue(Boolean.TRUE.equals(value));
082    }
083
084    @Test
085    public void shouldParseValueGivenFalseBooleanLiteral() throws Exception {
086        value = parser("false").parseValue();
087        assertTrue(Boolean.FALSE.equals(value));
088    }
089
090    @Test
091    public void shouldParseValueGivenTrueBooleanLiteralWithIncorrectCase() throws Exception {
092        value = parser("TrUe").parseValue();
093        assertTrue(Boolean.TRUE.equals(value));
094    }
095
096    @Test
097    public void shouldParseValueGivenFalseBooleanLiteralWithIncorrectCase() throws Exception {
098        value = parser("fAlSE").parseValue();
099        assertTrue(Boolean.FALSE.equals(value));
100    }
101
102    @Test
103    public void shouldParseValueGivenIntegerValues() throws Exception {
104        assertEquals(0, parser("0").parseValue());
105        assertEquals(-1, parser("-1").parseValue());
106        assertEquals(1, parser("1").parseValue());
107        assertEquals(123456, parser("123456").parseValue());
108        assertEquals(Integer.MAX_VALUE, parser("" + Integer.MAX_VALUE).parseValue());
109        assertEquals(Integer.MIN_VALUE, parser("" + Integer.MIN_VALUE).parseValue());
110    }
111
112    @Test
113    public void shouldParseValueGivenLongValues() throws Exception {
114        assertEquals(Integer.MAX_VALUE + 1L, parser("" + (Integer.MAX_VALUE + 1L)).parseValue());
115        assertEquals(Integer.MIN_VALUE - 1L, parser("" + (Integer.MIN_VALUE - 1L)).parseValue());
116        assertEquals(Long.MAX_VALUE, parser("" + Long.MAX_VALUE).parseValue());
117        assertEquals(Long.MIN_VALUE, parser("" + Long.MIN_VALUE).parseValue());
118    }
119
120    @Test
121    public void shouldParseValueGivenDoubleValues() throws Exception {
122        assertEquals(0.1d, parser("0.1").parseValue());
123        assertEquals(1.0d, parser("1.0").parseValue());
124        assertEquals(-1.0d, parser("-1.0").parseValue());
125        assertEquals(-1000.0d, parser("-1.0e3").parseValue());
126        assertEquals((double) Float.MAX_VALUE + 1f, parser("" + ((double) Float.MAX_VALUE + 1f)).parseValue());
127        assertEquals((double) Float.MIN_VALUE - 1f, parser("" + ((double) Float.MIN_VALUE - 1f)).parseValue());
128        assertEquals(Double.MAX_VALUE, parser("" + Double.MAX_VALUE).parseValue());
129        assertEquals(Double.MIN_VALUE, parser("" + Double.MIN_VALUE).parseValue());
130    }
131
132    @Test
133    public void shouldParseDocumentWithOneField() throws Exception {
134        bson = (Document)parser("{ \"foo\" : 32 }").parseValue();
135        assertField("foo", 32);
136    }
137
138    @Test
139    public void shouldParseDocumentWithTwoFields() throws Exception {
140        bson = (Document)parser("{ \"foo\" : 32 , \"bar\" : \"baz\" }").parseValue();
141        assertField("foo", 32);
142        assertField("bar", "baz");
143    }
144
145    @Test
146    public void shouldParseDocumentWithThreeFields() throws Exception {
147        bson = (Document)parser("{ \"foo\" : 32 , \"bar\" : \"baz\", \"bom\" : true }").parseValue();
148        assertField("foo", 32);
149        assertField("bar", "baz");
150        assertField("bom", true);
151    }
152
153    @Test
154    public void shouldParseDocumentWithNestedDocument() throws Exception {
155        bson = (Document)parser("{ \"foo\" : 32 , \"nested\" : { \"bar\" : \"baz\", \"bom\" : true }}").parseValue();
156        assertField("foo", 32);
157        bson = bson.getDocument("nested");
158        assertField("bar", "baz");
159        assertField("bom", true);
160    }
161
162    @Test
163    public void shouldParseDocumentWithExtraTrailingFieldDelimiter() throws Exception {
164        bson = (Document)parser("{ \"foo\" : 32 , \"bar\" : \"baz\",  }").parseValue();
165        assertField("foo", 32);
166        assertField("bar", "baz");
167    }
168
169    @Test
170    public void shouldParseDocumentWithExtraFieldDelimiters() throws Exception {
171        bson = (Document)parser("{ \"foo\" : 32 , , \"bar\" : \"baz\",,  }").parseValue();
172        assertField("foo", 32);
173        assertField("bar", "baz");
174    }
175
176    @Test
177    public void shouldParseDocumentWithUuid() throws Exception {
178        UUID obj = UUID.randomUUID();
179        value = parser(writer.write(obj)).parseValue();
180        assertEquals(obj, value);
181    }
182
183    @Test
184    public void shouldParseDocumentWithObjectId() throws Exception {
185        ObjectId obj = new ObjectId(300, 200, 9, 15);
186        value = parser(writer.write(obj)).parseValue();
187        assertEquals(obj, value);
188    }
189
190    @Test
191    public void shouldParseDocumentWithDate() throws Exception {
192        Date obj = now();
193        String dateDoc = writer.write(obj);
194        value = parser(dateDoc).parseValue();
195        assertTrue(value instanceof Date);
196    }
197
198    @Test
199    public void shouldParseDocumentWithCode() throws Exception {
200        Code obj = new Code("foo");
201        value = parser(writer.write(obj)).parseValue();
202        assertEquals(obj, value);
203    }
204
205    @Test
206    public void shouldParseDocumentWithCodeAndSscope() throws Exception {
207        Document scope = (Document)parser("{ \"foo\" : 32 }").parseValue();
208        CodeWithScope obj = new CodeWithScope("foo", scope);
209        // String str = writer.write(obj);
210        // print = true;
211        // print(str);
212        value = parser(writer.write(obj)).parseValue();
213        assertEquals(obj, value);
214    }
215
216    @Test
217    public void shouldParseDocumentWithBinary() throws Exception {
218        byte[] bytes = new byte[] {0x13, 0x22, 0x53, 0x00};
219        Binary obj = new Binary(Bson.BinaryType.MD5, bytes);
220        value = parser(writer.write(obj)).parseValue();
221        assertEquals(obj, value);
222    }
223
224    @Test
225    public void shouldParseIsoFormat() throws Exception {
226        value = Bson.getDateParsingFormatter().parse("2011-06-14T16:05:11GMT+00:00");
227        Date date = (Date)value;
228        assertTrue(date.after(date(2011, 06, 13)));
229        assertTrue(date.before(date(2011, 06, 16)));
230    }
231
232    @Test
233    public void shouldParseMsDateFormat() throws Exception {
234        value = JsonReader.DATE_VALUE_MATCHER.parseValue("\\/Date(2011-06-14T16:05:11GMT+00:00)\\/");
235        assertTrue(value instanceof Date);
236        Date date = (Date)value;
237        assertTrue(date.after(date(2011, 06, 13)));
238        assertTrue(date.before(date(2011, 06, 16)));
239    }
240
241    @Test
242    public void shouldParseMsDateFormatWithSpaces() throws Exception {
243        value = JsonReader.DATE_VALUE_MATCHER.parseValue("\\/Date( 2011-06-14T16:05:11GMT+00:00 )\\/");
244        assertTrue(value instanceof Date);
245        Date date = (Date)value;
246        assertTrue(date.after(date(2011, 06, 13)));
247        assertTrue(date.before(date(2011, 06, 16)));
248    }
249
250    @Test
251    public void shouldParseEscapedDateFormat() throws Exception {
252        value = JsonReader.DATE_VALUE_MATCHER.parseValue("/Date(2011-06-14T16:05:11GMT+00:00)/");
253        assertTrue(value instanceof Date);
254        Date date = (Date)value;
255        assertTrue(date.after(date(2011, 06, 13)));
256        assertTrue(date.before(date(2011, 06, 16)));
257    }
258
259    protected Date date( int year,
260                         int month,
261                         int day ) {
262        Calendar cal = Calendar.getInstance();
263        cal.clear();
264        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
265        cal.set(year, month - 1, day);
266        return cal.getTime();
267    }
268
269    @Test
270    public void shouldParseEscapedDateFormatWithSpaces() throws Exception {
271        value = JsonReader.DATE_VALUE_MATCHER.parseValue("/Date( 2011-06-14T16:05:11GMT+00:00 )/");
272        assertTrue(value instanceof Date);
273        Date date = (Date)value;
274        assertTrue(date.after(date(2011, 06, 13)));
275        assertTrue(date.before(date(2011, 06, 16)));
276    }
277
278    @Test
279    public void shouldEvaluateIsoDateWithGmtTimeZone() throws Exception {
280        value = JsonReader.DATE_VALUE_MATCHER.parseValue("2011-06-14T16:05:11GMT+00:00");
281        assertTrue(value instanceof Date);
282        Date date = (Date)value;
283        assertTrue(date.after(date(2011, 06, 13)));
284        assertTrue(date.before(date(2011, 06, 16)));
285    }
286
287    @Test
288    public void shouldEvaluateIsoDateWithZuluTimeZone() throws Exception {
289        value = JsonReader.DATE_VALUE_MATCHER.parseValue("2011-06-14T16:05:11Z");
290        assertTrue(value instanceof Date);
291        Date date = (Date)value;
292        assertTrue(date.after(date(2011, 06, 13)));
293        assertTrue(date.before(date(2011, 06, 16)));
294    }
295
296    @Test
297    public void shouldParseIsoDateWithZuluTimeZone() throws Exception {
298        Date date = now();
299        value = JsonReader.DATE_VALUE_MATCHER.parseValue(Bson.getDateFormatter().format(date));
300        assertTrue(value instanceof Date);
301    }
302    
303    @Test
304    public void dateMatcherShouldPreserveBackslashEscapeChars() throws Exception {
305        String value1 = "one\\backslash";
306        assertEquals(value1, JsonReader.DATE_VALUE_MATCHER.parseValue(value1));
307        String value2 = "two\\\\backslashes";
308        assertEquals(value2, JsonReader.DATE_VALUE_MATCHER.parseValue(value2));
309        String value3 = "three\\\\\\backslashes";
310        assertEquals(value3, JsonReader.DATE_VALUE_MATCHER.parseValue(value3));
311    }
312
313    protected void print( Object object ) {
314        if (print) {
315            System.out.println(object);
316            System.out.flush();
317        }
318    }
319
320    protected Date now() {
321        return new Date();
322    }
323
324    protected void assertField( String name,
325                                Object value ) {
326        Object actual = bson.get(name);
327        if (value == null) {
328            assertTrue(Null.matches(actual));
329        } else {
330            assertEquals(value, actual);
331        }
332    }
333}