1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.util.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 
24 import android.util.JsonReader;
25 import android.util.JsonToken;
26 import android.util.MalformedJsonException;
27 
28 import androidx.test.filters.SmallTest;
29 import androidx.test.runner.AndroidJUnit4;
30 
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.io.IOException;
35 import java.io.StringReader;
36 import java.util.Arrays;
37 
38 @SmallTest
39 @RunWith(AndroidJUnit4.class)
40 public final class JsonReaderTest {
41 
42     private static final int READER_BUFFER_SIZE = 1024;
43 
44     @Test
testReadArray()45     public void testReadArray() throws IOException {
46         JsonReader reader = new JsonReader(new StringReader("[true, true]"));
47         reader.beginArray();
48         assertEquals(true, reader.nextBoolean());
49         assertEquals(true, reader.nextBoolean());
50         reader.endArray();
51         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
52     }
53 
54     @Test
testReadEmptyArray()55     public void testReadEmptyArray() throws IOException {
56         JsonReader reader = new JsonReader(new StringReader("[]"));
57         reader.beginArray();
58         assertFalse(reader.hasNext());
59         reader.endArray();
60         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
61     }
62 
63     @Test
testReadObject()64     public void testReadObject() throws IOException {
65         JsonReader reader = new JsonReader(new StringReader(
66                 "{\"a\": \"android\", \"b\": \"banana\"}"));
67         reader.beginObject();
68         assertEquals("a", reader.nextName());
69         assertEquals("android", reader.nextString());
70         assertEquals("b", reader.nextName());
71         assertEquals("banana", reader.nextString());
72         reader.endObject();
73         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
74     }
75 
76     @Test
testReadEmptyObject()77     public void testReadEmptyObject() throws IOException {
78         JsonReader reader = new JsonReader(new StringReader("{}"));
79         reader.beginObject();
80         assertFalse(reader.hasNext());
81         reader.endObject();
82         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
83     }
84 
85     @Test
testSkipObject()86     public void testSkipObject() throws IOException {
87         JsonReader reader = new JsonReader(new StringReader(
88                 "{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}"));
89         reader.beginObject();
90         assertEquals("a", reader.nextName());
91         reader.skipValue();
92         assertEquals("b", reader.nextName());
93         reader.skipValue();
94         reader.endObject();
95         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
96     }
97 
98     @Test(expected=IllegalStateException.class)
testSkipBeforeEndOfObject()99     public void testSkipBeforeEndOfObject() throws IOException {
100         JsonReader reader = new JsonReader(new StringReader("{}"));
101         reader.beginObject();
102         // Should not be possible to skip without elements
103         reader.skipValue();
104     }
105 
106     @Test(expected=IllegalStateException.class)
testSkipBeforeEndOfArray()107     public void testSkipBeforeEndOfArray() throws IOException {
108         JsonReader reader = new JsonReader(new StringReader("[]"));
109         reader.beginArray();
110         // Should not be possible to skip without elements
111         reader.skipValue();
112     }
113 
114     @Test
testSkipAfterEndOfDocument()115     public void testSkipAfterEndOfDocument() throws IOException {
116         JsonReader reader = new JsonReader(new StringReader("{}"));
117         reader.beginObject();
118         reader.endObject();
119         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
120         try {
121             reader.skipValue();
122             fail("Should not be possible to skip without elements.");
123         } catch (IllegalStateException expected) {
124         }
125     }
126 
127     @Test
testHelloWorld()128     public void testHelloWorld() throws IOException {
129         String json = "{\n" +
130                 "   \"hello\": true,\n" +
131                 "   \"foo\": [\"world\"]\n" +
132                 "}";
133         JsonReader reader = new JsonReader(new StringReader(json));
134         reader.beginObject();
135         assertEquals("hello", reader.nextName());
136         assertEquals(true, reader.nextBoolean());
137         assertEquals("foo", reader.nextName());
138         reader.beginArray();
139         assertEquals("world", reader.nextString());
140         reader.endArray();
141         reader.endObject();
142         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
143     }
144 
145     @Test(expected=NullPointerException.class)
testNulls()146     public void testNulls() {
147         new JsonReader(null);
148     }
149 
150     @Test(expected=IOException.class)
testEmptyString1()151     public void testEmptyString1() throws IOException {
152         new JsonReader(new StringReader("")).beginArray();
153     }
154 
155     @Test(expected=IOException.class)
testEmptyString2()156     public void testEmptyString2() throws IOException {
157         new JsonReader(new StringReader("")).beginObject();
158     }
159 
160     @Test(expected=IOException.class)
testNoTopLevelObject()161     public void testNoTopLevelObject() throws IOException {
162         new JsonReader(new StringReader("true")).nextBoolean();
163     }
164 
165     @Test
testCharacterUnescaping()166     public void testCharacterUnescaping() throws IOException {
167         String json = "[\"a\","
168                 + "\"a\\\"\","
169                 + "\"\\\"\","
170                 + "\":\","
171                 + "\",\","
172                 + "\"\\b\","
173                 + "\"\\f\","
174                 + "\"\\n\","
175                 + "\"\\r\","
176                 + "\"\\t\","
177                 + "\" \","
178                 + "\"\\\\\","
179                 + "\"{\","
180                 + "\"}\","
181                 + "\"[\","
182                 + "\"]\","
183                 + "\"\\u0000\","
184                 + "\"\\u0019\","
185                 + "\"\\u20AC\""
186                 + "]";
187         JsonReader reader = new JsonReader(new StringReader(json));
188         reader.beginArray();
189         assertEquals("a", reader.nextString());
190         assertEquals("a\"", reader.nextString());
191         assertEquals("\"", reader.nextString());
192         assertEquals(":", reader.nextString());
193         assertEquals(",", reader.nextString());
194         assertEquals("\b", reader.nextString());
195         assertEquals("\f", reader.nextString());
196         assertEquals("\n", reader.nextString());
197         assertEquals("\r", reader.nextString());
198         assertEquals("\t", reader.nextString());
199         assertEquals(" ", reader.nextString());
200         assertEquals("\\", reader.nextString());
201         assertEquals("{", reader.nextString());
202         assertEquals("}", reader.nextString());
203         assertEquals("[", reader.nextString());
204         assertEquals("]", reader.nextString());
205         assertEquals("\0", reader.nextString());
206         assertEquals("\u0019", reader.nextString());
207         assertEquals("\u20AC", reader.nextString());
208         reader.endArray();
209         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
210     }
211 
212     @Test
testIntegersWithFractionalPartSpecified()213     public void testIntegersWithFractionalPartSpecified() throws IOException {
214         JsonReader reader = new JsonReader(new StringReader("[1.0,1.0,1.0]"));
215         reader.beginArray();
216         assertEquals(1.0, reader.nextDouble(), 0.0f);
217         assertEquals(1, reader.nextInt());
218         assertEquals(1L, reader.nextLong());
219     }
220 
221     @Test
testDoubles()222     public void testDoubles() throws IOException {
223         String json = "[-0.0,"
224                 + "1.0,"
225                 + "1.7976931348623157E308,"
226                 + "4.9E-324,"
227                 + "0.0,"
228                 + "-0.5,"
229                 + "2.2250738585072014E-308,"
230                 + "3.141592653589793,"
231                 + "2.718281828459045,"
232                 + "\"1.0\","
233                 + "\"011.0\","
234                 + "\"NaN\","
235                 + "\"Infinity\","
236                 + "\"-Infinity\""
237                 + "]";
238         JsonReader reader = new JsonReader(new StringReader(json));
239         reader.beginArray();
240         assertEquals(-0.0, reader.nextDouble(), 0.0f);
241         assertEquals(1.0, reader.nextDouble(), 0.0f);
242         assertEquals(1.7976931348623157E308, reader.nextDouble(), 0.0f);
243         assertEquals(4.9E-324, reader.nextDouble(), 0.0f);
244         assertEquals(0.0, reader.nextDouble(), 0.0f);
245         assertEquals(-0.5, reader.nextDouble(), 0.0f);
246         assertEquals(2.2250738585072014E-308, reader.nextDouble(), 0.0f);
247         assertEquals(3.141592653589793, reader.nextDouble(), 0.0f);
248         assertEquals(2.718281828459045, reader.nextDouble(), 0.0f);
249         assertEquals(1.0, reader.nextDouble(), 0.0f);
250         assertEquals(11.0, reader.nextDouble(), 0.0f);
251         assertTrue(Double.isNaN(reader.nextDouble()));
252         assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble(), 0.0f);
253         assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble(), 0.0f);
254         reader.endArray();
255         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
256     }
257 
258     @Test
testLenientDoubles()259     public void testLenientDoubles() throws IOException {
260         String json = "["
261                 + "011.0,"
262                 + "NaN,"
263                 + "NAN,"
264                 + "Infinity,"
265                 + "INFINITY,"
266                 + "-Infinity"
267                 + "]";
268         JsonReader reader = new JsonReader(new StringReader(json));
269         reader.setLenient(true);
270         reader.beginArray();
271         assertEquals(11.0, reader.nextDouble(), 0.0f);
272         assertTrue(Double.isNaN(reader.nextDouble()));
273         try {
274             reader.nextDouble();
275             fail();
276         } catch (NumberFormatException expected) {
277         }
278         assertEquals("NAN", reader.nextString());
279         assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble(), 0.0f);
280         try {
281             reader.nextDouble();
282             fail();
283         } catch (NumberFormatException expected) {
284         }
285         assertEquals("INFINITY", reader.nextString());
286         assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble(), 0.0f);
287         reader.endArray();
288         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
289     }
290 
291     @Test
testBufferBoundary()292     public void testBufferBoundary() throws IOException {
293         char[] pad = new char[READER_BUFFER_SIZE - 8];
294         Arrays.fill(pad, '5');
295         String json = "[\"" + new String(pad) + "\",33333]";
296         JsonReader reader = new JsonReader(new StringReader(json));
297         reader.beginArray();
298         assertEquals(JsonToken.STRING, reader.peek());
299         assertEquals(new String(pad), reader.nextString());
300         assertEquals(JsonToken.NUMBER, reader.peek());
301         assertEquals(33333, reader.nextInt());
302     }
303 
304     @Test
testTruncatedBufferBoundary()305     public void testTruncatedBufferBoundary() throws IOException {
306         char[] pad = new char[READER_BUFFER_SIZE - 8];
307         Arrays.fill(pad, '5');
308         String json = "[\"" + new String(pad) + "\",33333";
309         JsonReader reader = new JsonReader(new StringReader(json));
310         reader.setLenient(true);
311         reader.beginArray();
312         assertEquals(JsonToken.STRING, reader.peek());
313         assertEquals(new String(pad), reader.nextString());
314         assertEquals(JsonToken.NUMBER, reader.peek());
315         assertEquals(33333, reader.nextInt());
316         try {
317             reader.endArray();
318             fail();
319         } catch (IOException e) {
320         }
321     }
322 
323     @Test
testLongestSupportedNumericLiterals()324     public void testLongestSupportedNumericLiterals() throws IOException {
325         verifyLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER);
326     }
327 
328     @Test
testLongerNumericLiterals()329     public void testLongerNumericLiterals() throws IOException {
330         verifyLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING);
331     }
332 
verifyLongNumericLiterals(int length, JsonToken expectedToken)333     private void verifyLongNumericLiterals(int length, JsonToken expectedToken) throws IOException {
334         char[] longNumber = new char[length];
335         Arrays.fill(longNumber, '9');
336         longNumber[0] = '1';
337         longNumber[1] = '.';
338 
339         String json = "[" + new String(longNumber) + "]";
340         JsonReader reader = new JsonReader(new StringReader(json));
341         reader.setLenient(true);
342         reader.beginArray();
343         assertEquals(expectedToken, reader.peek());
344         assertEquals(2.0d, reader.nextDouble(), 0.0f);
345         reader.endArray();
346     }
347 
348     @Test
testLongs()349     public void testLongs() throws IOException {
350         String json = "[0,0,0,"
351                 + "1,1,1,"
352                 + "-1,-1,-1,"
353                 + "-9223372036854775808,"
354                 + "9223372036854775807,"
355                 + "5.0,"
356                 + "1.0e2,"
357                 + "\"011\","
358                 + "\"5.0\","
359                 + "\"1.0e2\""
360                 + "]";
361         JsonReader reader = new JsonReader(new StringReader(json));
362         reader.beginArray();
363         assertEquals(0L, reader.nextLong());
364         assertEquals(0, reader.nextInt());
365         assertEquals(0.0, reader.nextDouble(), 0.0f);
366         assertEquals(1L, reader.nextLong());
367         assertEquals(1, reader.nextInt());
368         assertEquals(1.0, reader.nextDouble(), 0.0f);
369         assertEquals(-1L, reader.nextLong());
370         assertEquals(-1, reader.nextInt());
371         assertEquals(-1.0, reader.nextDouble(), 0.0f);
372         try {
373             reader.nextInt();
374             fail();
375         } catch (NumberFormatException expected) {
376         }
377         assertEquals(Long.MIN_VALUE, reader.nextLong());
378         try {
379             reader.nextInt();
380             fail();
381         } catch (NumberFormatException expected) {
382         }
383         assertEquals(Long.MAX_VALUE, reader.nextLong());
384         assertEquals(5, reader.nextLong());
385         assertEquals(100, reader.nextLong());
386         assertEquals(11, reader.nextLong());
387         assertEquals(5, reader.nextLong());
388         assertEquals(100, reader.nextLong());
389         reader.endArray();
390         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
391     }
392 
393     @Test
testHighPrecisionDouble_losesPrecision()394     public void testHighPrecisionDouble_losesPrecision() throws IOException {
395         // The presence of a fractional part forces us to use Double.parseDouble
396         // instead of Long.parseLong (even though the fractional part is 0).
397         //
398         // A 52 bit mantissa isn't sufficient to precisely represent any of these
399         // values, so we will lose some precision, thereby storing it as
400         // ~(9.223372036854776E18). This value is then implicitly converted into
401         // a long and is required by the JLS to be clamped to Long.MAX_VALUE since
402         // it's larger than the largest long.
403         String json = "["
404                 + "9223372036854775806.000,"  // Long.MAX_VALUE - 1
405                 + "9223372036854775807.000,"  // Long.MAX_VALUE
406                 + "9223372036854775808.000"   // Long.MAX_VALUE + 1
407                 + "]";
408         JsonReader reader = new JsonReader(new StringReader(json));
409         reader.beginArray();
410         assertEquals(Long.MAX_VALUE, reader.nextLong());
411         assertEquals(Long.MAX_VALUE, reader.nextLong());
412         assertEquals(Long.MAX_VALUE, reader.nextLong());
413         reader.endArray();
414     }
415 
416     @Test
testMatchingValidNumbers()417     public void testMatchingValidNumbers() throws IOException {
418         String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]";
419         JsonReader reader = new JsonReader(new StringReader(json));
420         reader.beginArray();
421         for (int i = 0; i < 16; i++) {
422             assertEquals(JsonToken.NUMBER, reader.peek());
423             reader.nextDouble();
424         }
425         reader.endArray();
426     }
427 
428     @Test
testRecognizingInvalidNumbers()429     public void testRecognizingInvalidNumbers() throws IOException {
430         String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]";
431         JsonReader reader = new JsonReader(new StringReader(json));
432         reader.setLenient(true);
433         reader.beginArray();
434         for (int i = 0; i < 16; i++) {
435             assertEquals(JsonToken.STRING, reader.peek());
436             reader.nextString();
437         }
438         reader.endArray();
439     }
440 
441     @Test
testNonFiniteDouble()442     public void testNonFiniteDouble() throws IOException {
443         String json = "[NaN]";
444         JsonReader reader = new JsonReader(new StringReader(json));
445         reader.beginArray();
446         try {
447             reader.nextDouble();
448             fail();
449         } catch (IOException expected) {
450         }
451     }
452 
453     @Test
testNumberWithHexPrefix()454     public void testNumberWithHexPrefix() throws IOException {
455         String json = "[0x11]";
456         JsonReader reader = new JsonReader(new StringReader(json));
457         reader.beginArray();
458         try {
459             reader.nextLong();
460             fail();
461         } catch (IOException expected) {
462         }
463     }
464 
465     @Test
testNumberWithOctalPrefix()466     public void testNumberWithOctalPrefix() throws IOException {
467         String json = "[01]";
468         JsonReader reader = new JsonReader(new StringReader(json));
469         reader.beginArray();
470         try {
471             reader.nextInt();
472             fail();
473         } catch (IOException expected) {
474         }
475     }
476 
477     @Test
testBooleans()478     public void testBooleans() throws IOException {
479         JsonReader reader = new JsonReader(new StringReader("[true,false]"));
480         reader.beginArray();
481         assertEquals(true, reader.nextBoolean());
482         assertEquals(false, reader.nextBoolean());
483         reader.endArray();
484         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
485     }
486 
487     @Test
testMixedCaseLiterals()488     public void testMixedCaseLiterals() throws IOException {
489         JsonReader reader = new JsonReader(new StringReader("[True,TruE,False,FALSE,NULL,nulL]"));
490         reader.beginArray();
491         assertEquals(true, reader.nextBoolean());
492         assertEquals(true, reader.nextBoolean());
493         assertEquals(false, reader.nextBoolean());
494         assertEquals(false, reader.nextBoolean());
495         reader.nextNull();
496         reader.nextNull();
497         reader.endArray();
498         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
499     }
500 
501     @Test
testMissingValue()502     public void testMissingValue() throws IOException {
503         JsonReader reader = new JsonReader(new StringReader("{\"a\":}"));
504         reader.beginObject();
505         assertEquals("a", reader.nextName());
506         try {
507             reader.nextString();
508             fail();
509         } catch (IOException expected) {
510         }
511     }
512 
513     @Test
testPrematureEndOfInput()514     public void testPrematureEndOfInput() throws IOException {
515         JsonReader reader = new JsonReader(new StringReader("{\"a\":true,"));
516         reader.beginObject();
517         assertEquals("a", reader.nextName());
518         assertEquals(true, reader.nextBoolean());
519         try {
520             reader.nextName();
521             fail();
522         } catch (IOException expected) {
523         }
524     }
525 
526     @Test
testPrematurelyClosed()527     public void testPrematurelyClosed() throws IOException {
528         try {
529             JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
530             reader.beginObject();
531             reader.close();
532             reader.nextName();
533             fail();
534         } catch (IllegalStateException expected) {
535         }
536 
537         try {
538             JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
539             reader.close();
540             reader.beginObject();
541             fail();
542         } catch (IllegalStateException expected) {
543         }
544 
545         try {
546             JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
547             reader.beginObject();
548             reader.nextName();
549             reader.peek();
550             reader.close();
551             reader.nextBoolean();
552             fail();
553         } catch (IllegalStateException expected) {
554         }
555     }
556 
557     @Test
testNextFailuresDoNotAdvance()558     public void testNextFailuresDoNotAdvance() throws IOException {
559         JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
560         reader.beginObject();
561         try {
562             reader.nextString();
563             fail();
564         } catch (IllegalStateException expected) {
565         }
566         assertEquals("a", reader.nextName());
567         try {
568             reader.nextName();
569             fail();
570         } catch (IllegalStateException expected) {
571         }
572         try {
573             reader.beginArray();
574             fail();
575         } catch (IllegalStateException expected) {
576         }
577         try {
578             reader.endArray();
579             fail();
580         } catch (IllegalStateException expected) {
581         }
582         try {
583             reader.beginObject();
584             fail();
585         } catch (IllegalStateException expected) {
586         }
587         try {
588             reader.endObject();
589             fail();
590         } catch (IllegalStateException expected) {
591         }
592         assertEquals(true, reader.nextBoolean());
593         try {
594             reader.nextString();
595             fail();
596         } catch (IllegalStateException expected) {
597         }
598         try {
599             reader.nextName();
600             fail();
601         } catch (IllegalStateException expected) {
602         }
603         try {
604             reader.beginArray();
605             fail();
606         } catch (IllegalStateException expected) {
607         }
608         try {
609             reader.endArray();
610             fail();
611         } catch (IllegalStateException expected) {
612         }
613         reader.endObject();
614         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
615         reader.close();
616     }
617 
618     @Test(expected=IllegalStateException.class)
testStringNullIsNotNull()619     public void testStringNullIsNotNull() throws IOException {
620         JsonReader reader = new JsonReader(new StringReader("[\"null\"]"));
621         reader.beginArray();
622         reader.nextNull();
623     }
624 
625     @Test(expected=IllegalStateException.class)
testNullLiteralIsNotAString()626     public void testNullLiteralIsNotAString() throws IOException {
627         JsonReader reader = new JsonReader(new StringReader("[null]"));
628         reader.beginArray();
629         reader.nextString();
630     }
631 
632     @Test
testStrictNameValueSeparator()633     public void testStrictNameValueSeparator() throws IOException {
634         JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
635         reader.beginObject();
636         assertEquals("a", reader.nextName());
637         try {
638             reader.nextBoolean();
639             fail();
640         } catch (IOException expected) {
641         }
642 
643         reader = new JsonReader(new StringReader("{\"a\"=>true}"));
644         reader.beginObject();
645         assertEquals("a", reader.nextName());
646         try {
647             reader.nextBoolean();
648             fail();
649         } catch (IOException expected) {
650         }
651     }
652 
653     @Test
testLenientNameValueSeparator()654     public void testLenientNameValueSeparator() throws IOException {
655         JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
656         reader.setLenient(true);
657         reader.beginObject();
658         assertEquals("a", reader.nextName());
659         assertEquals(true, reader.nextBoolean());
660 
661         reader = new JsonReader(new StringReader("{\"a\"=>true}"));
662         reader.setLenient(true);
663         reader.beginObject();
664         assertEquals("a", reader.nextName());
665         assertEquals(true, reader.nextBoolean());
666     }
667 
668     @Test
testStrictComments()669     public void testStrictComments() throws IOException {
670         JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
671         reader.beginArray();
672         try {
673             reader.nextBoolean();
674             fail();
675         } catch (IOException expected) {
676         }
677 
678         reader = new JsonReader(new StringReader("[# comment \n true]"));
679         reader.beginArray();
680         try {
681             reader.nextBoolean();
682             fail();
683         } catch (IOException expected) {
684         }
685 
686         reader = new JsonReader(new StringReader("[/* comment */ true]"));
687         reader.beginArray();
688         try {
689             reader.nextBoolean();
690             fail();
691         } catch (IOException expected) {
692         }
693     }
694 
695     @Test
testLenientComments()696     public void testLenientComments() throws IOException {
697         JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
698         reader.setLenient(true);
699         reader.beginArray();
700         assertEquals(true, reader.nextBoolean());
701 
702         reader = new JsonReader(new StringReader("[# comment \n true]"));
703         reader.setLenient(true);
704         reader.beginArray();
705         assertEquals(true, reader.nextBoolean());
706 
707         reader = new JsonReader(new StringReader("[/* comment */ true]"));
708         reader.setLenient(true);
709         reader.beginArray();
710         assertEquals(true, reader.nextBoolean());
711     }
712 
713     @Test
testStrictUnquotedNames()714     public void testStrictUnquotedNames() throws IOException {
715         JsonReader reader = new JsonReader(new StringReader("{a:true}"));
716         reader.beginObject();
717         try {
718             reader.nextName();
719             fail();
720         } catch (IOException expected) {
721         }
722     }
723 
724     @Test
testLenientUnquotedNames()725     public void testLenientUnquotedNames() throws IOException {
726         JsonReader reader = new JsonReader(new StringReader("{a:true}"));
727         reader.setLenient(true);
728         reader.beginObject();
729         assertEquals("a", reader.nextName());
730     }
731 
732     @Test
testStrictSingleQuotedNames()733     public void testStrictSingleQuotedNames() throws IOException {
734         JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
735         reader.beginObject();
736         try {
737             reader.nextName();
738             fail();
739         } catch (IOException expected) {
740         }
741     }
742 
743     @Test
testLenientSingleQuotedNames()744     public void testLenientSingleQuotedNames() throws IOException {
745         JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
746         reader.setLenient(true);
747         reader.beginObject();
748         assertEquals("a", reader.nextName());
749     }
750 
751     @Test(expected=MalformedJsonException.class)
testStrictUnquotedStrings()752     public void testStrictUnquotedStrings() throws IOException {
753         JsonReader reader = new JsonReader(new StringReader("[a]"));
754         reader.beginArray();
755         reader.nextString();
756     }
757 
758     @Test
testLenientUnquotedStrings()759     public void testLenientUnquotedStrings() throws IOException {
760         JsonReader reader = new JsonReader(new StringReader("[a]"));
761         reader.setLenient(true);
762         reader.beginArray();
763         assertEquals("a", reader.nextString());
764     }
765 
766     @Test
testStrictSingleQuotedStrings()767     public void testStrictSingleQuotedStrings() throws IOException {
768         JsonReader reader = new JsonReader(new StringReader("['a']"));
769         reader.beginArray();
770         try {
771             reader.nextString();
772             fail();
773         } catch (IOException expected) {
774         }
775     }
776 
777     @Test
testLenientSingleQuotedStrings()778     public void testLenientSingleQuotedStrings() throws IOException {
779         JsonReader reader = new JsonReader(new StringReader("['a']"));
780         reader.setLenient(true);
781         reader.beginArray();
782         assertEquals("a", reader.nextString());
783     }
784 
785     @Test
testStrictSemicolonDelimitedArray()786     public void testStrictSemicolonDelimitedArray() throws IOException {
787         JsonReader reader = new JsonReader(new StringReader("[true;true]"));
788         reader.beginArray();
789         try {
790             reader.nextBoolean();
791             reader.nextBoolean();
792             fail();
793         } catch (IOException expected) {
794         }
795     }
796 
797     @Test
testLenientSemicolonDelimitedArray()798     public void testLenientSemicolonDelimitedArray() throws IOException {
799         JsonReader reader = new JsonReader(new StringReader("[true;true]"));
800         reader.setLenient(true);
801         reader.beginArray();
802         assertEquals(true, reader.nextBoolean());
803         assertEquals(true, reader.nextBoolean());
804     }
805 
806     @Test
testStrictSemicolonDelimitedNameValuePair()807     public void testStrictSemicolonDelimitedNameValuePair() throws IOException {
808         JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
809         reader.beginObject();
810         assertEquals("a", reader.nextName());
811         try {
812             reader.nextBoolean();
813             reader.nextName();
814             fail();
815         } catch (IOException expected) {
816         }
817     }
818 
819     @Test
testLenientSemicolonDelimitedNameValuePair()820     public void testLenientSemicolonDelimitedNameValuePair() throws IOException {
821         JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
822         reader.setLenient(true);
823         reader.beginObject();
824         assertEquals("a", reader.nextName());
825         assertEquals(true, reader.nextBoolean());
826         assertEquals("b", reader.nextName());
827     }
828 
829     @Test
testStrictUnnecessaryArraySeparators()830     public void testStrictUnnecessaryArraySeparators() throws IOException {
831         JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
832         reader.beginArray();
833         assertEquals(true, reader.nextBoolean());
834         try {
835             reader.nextNull();
836             fail();
837         } catch (IOException expected) {
838         }
839 
840         reader = new JsonReader(new StringReader("[,true]"));
841         reader.beginArray();
842         try {
843             reader.nextNull();
844             fail();
845         } catch (IOException expected) {
846         }
847 
848         reader = new JsonReader(new StringReader("[true,]"));
849         reader.beginArray();
850         assertEquals(true, reader.nextBoolean());
851         try {
852             reader.nextNull();
853             fail();
854         } catch (IOException expected) {
855         }
856 
857         reader = new JsonReader(new StringReader("[,]"));
858         reader.beginArray();
859         try {
860             reader.nextNull();
861             fail();
862         } catch (IOException expected) {
863         }
864     }
865 
866     @Test
testLenientUnnecessaryArraySeparators()867     public void testLenientUnnecessaryArraySeparators() throws IOException {
868         JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
869         reader.setLenient(true);
870         reader.beginArray();
871         assertEquals(true, reader.nextBoolean());
872         reader.nextNull();
873         assertEquals(true, reader.nextBoolean());
874         reader.endArray();
875 
876         reader = new JsonReader(new StringReader("[,true]"));
877         reader.setLenient(true);
878         reader.beginArray();
879         reader.nextNull();
880         assertEquals(true, reader.nextBoolean());
881         reader.endArray();
882 
883         reader = new JsonReader(new StringReader("[true,]"));
884         reader.setLenient(true);
885         reader.beginArray();
886         assertEquals(true, reader.nextBoolean());
887         reader.nextNull();
888         reader.endArray();
889 
890         reader = new JsonReader(new StringReader("[,]"));
891         reader.setLenient(true);
892         reader.beginArray();
893         reader.nextNull();
894         reader.nextNull();
895         reader.endArray();
896     }
897 
898     @Test
testStrictMultipleTopLevelValues()899     public void testStrictMultipleTopLevelValues() throws IOException {
900         JsonReader reader = new JsonReader(new StringReader("[] []"));
901         reader.beginArray();
902         reader.endArray();
903         try {
904             reader.peek();
905             fail();
906         } catch (IOException expected) {
907         }
908     }
909 
910     @Test
testLenientMultipleTopLevelValues()911     public void testLenientMultipleTopLevelValues() throws IOException {
912         JsonReader reader = new JsonReader(new StringReader("[] true {}"));
913         reader.setLenient(true);
914         reader.beginArray();
915         reader.endArray();
916         assertEquals(true, reader.nextBoolean());
917         reader.beginObject();
918         reader.endObject();
919         assertEquals(JsonToken.END_DOCUMENT, reader.peek());
920     }
921 
922     @Test
testStrictTopLevelValueType()923     public void testStrictTopLevelValueType() {
924         JsonReader reader = new JsonReader(new StringReader("true"));
925         try {
926             reader.nextBoolean();
927             fail();
928         } catch (IOException expected) {
929         }
930     }
931 
932     @Test
testLenientTopLevelValueType()933     public void testLenientTopLevelValueType() throws IOException {
934         JsonReader reader = new JsonReader(new StringReader("true"));
935         reader.setLenient(true);
936         assertEquals(true, reader.nextBoolean());
937     }
938 
939     @Test
testStrictNonExecutePrefix()940     public void testStrictNonExecutePrefix() {
941         JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
942         try {
943             reader.beginArray();
944             fail();
945         } catch (IOException expected) {
946         }
947     }
948 
949     @Test
testBomIgnoredAsFirstCharacterOfDocument()950     public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
951         JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
952         reader.beginArray();
953         reader.endArray();
954     }
955 
956     @Test
testBomForbiddenAsOtherCharacterInDocument()957     public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
958         JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
959         reader.beginArray();
960         try {
961             reader.endArray();
962             fail();
963         } catch (IOException expected) {
964         }
965     }
966 
967     @Test
testFailWithPosition()968     public void testFailWithPosition() throws IOException {
969         verifyFailWithPosition("Expected literal value at line 6 column 3",
970                 "[\n\n\n\n\n0,}]");
971     }
972 
973     @Test
testFailWithPositionIsOffsetByBom()974     public void testFailWithPositionIsOffsetByBom() throws IOException {
975         verifyFailWithPosition("Expected literal value at line 1 column 4",
976                 "\ufeff[0,}]");
977     }
978 
979     @Test
testFailWithPositionGreaterThanBufferSize()980     public void testFailWithPositionGreaterThanBufferSize() throws IOException {
981         String spaces = repeat(' ', 8192);
982         verifyFailWithPosition("Expected literal value at line 6 column 3",
983                 "[\n\n" + spaces + "\n\n\n0,}]");
984     }
985 
verifyFailWithPosition(String message, String json)986     private void verifyFailWithPosition(String message, String json) throws IOException {
987         JsonReader reader = new JsonReader(new StringReader(json));
988         reader.beginArray();
989         reader.nextInt();
990         try {
991             reader.peek();
992             fail();
993         } catch (IOException expected) {
994             assertEquals(message, expected.getMessage());
995         }
996     }
997 
repeat(char c, int count)998     private String repeat(char c, int count) {
999         char[] array = new char[count];
1000         Arrays.fill(array, c);
1001         return new String(array);
1002     }
1003 }
1004