mirror of
https://github.com/ethauvin/JSON-java.git
synced 2025-06-17 07:50:52 -07:00
295 lines
12 KiB
Java
295 lines
12 KiB
Java
package org.json.junit;
|
|
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertFalse;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.junit.Assert.fail;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.Reader;
|
|
import java.io.StringReader;
|
|
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
import org.json.JSONTokener;
|
|
import org.junit.Test;
|
|
|
|
/**
|
|
* Test specific to the {@link org.json.JSONTokener} class.
|
|
* @author John Aylward
|
|
*
|
|
*/
|
|
public class JSONTokenerTest {
|
|
|
|
/**
|
|
* verify that back() fails as expected.
|
|
* @throws IOException thrown if something unexpected happens.
|
|
*/
|
|
@Test
|
|
public void verifyBackFailureZeroIndex() throws IOException {
|
|
try(Reader reader = new StringReader("some test string")) {
|
|
final JSONTokener tokener = new JSONTokener(reader);
|
|
try {
|
|
// this should fail since the index is 0;
|
|
tokener.back();
|
|
fail("Expected an exception");
|
|
} catch (JSONException e) {
|
|
assertEquals("Stepping back two steps is not supported", e.getMessage());
|
|
} catch (Exception e) {
|
|
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
|
|
}
|
|
|
|
}
|
|
}
|
|
/**
|
|
* verify that back() fails as expected.
|
|
* @throws IOException thrown if something unexpected happens.
|
|
*/
|
|
@Test
|
|
public void verifyBackFailureDoubleBack() throws IOException {
|
|
try(Reader reader = new StringReader("some test string")) {
|
|
final JSONTokener tokener = new JSONTokener(reader);
|
|
tokener.next();
|
|
tokener.back();
|
|
try {
|
|
// this should fail since the index is 0;
|
|
tokener.back();
|
|
fail("Expected an exception");
|
|
} catch (JSONException e) {
|
|
assertEquals("Stepping back two steps is not supported", e.getMessage());
|
|
} catch (Exception e) {
|
|
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testValid() {
|
|
checkValid("0",Number.class);
|
|
checkValid(" 0 ",Number.class);
|
|
checkValid("23",Number.class);
|
|
checkValid("23.5",Number.class);
|
|
checkValid(" 23.5 ",Number.class);
|
|
checkValid("null",null);
|
|
checkValid(" null ",null);
|
|
checkValid("true",Boolean.class);
|
|
checkValid(" true\n",Boolean.class);
|
|
checkValid("false",Boolean.class);
|
|
checkValid("\nfalse ",Boolean.class);
|
|
checkValid("{}",JSONObject.class);
|
|
checkValid(" {} ",JSONObject.class);
|
|
checkValid("{\"a\":1}",JSONObject.class);
|
|
checkValid(" {\"a\":1} ",JSONObject.class);
|
|
checkValid("[]",JSONArray.class);
|
|
checkValid(" [] ",JSONArray.class);
|
|
checkValid("[1,2]",JSONArray.class);
|
|
checkValid("\n\n[1,2]\n\n",JSONArray.class);
|
|
checkValid("1 2", String.class);
|
|
}
|
|
|
|
@Test
|
|
public void testErrors() {
|
|
// Check that stream can detect that a value is found after
|
|
// the first one
|
|
checkError(" { \"a\":1 } 4 ");
|
|
checkError("null \"a\"");
|
|
checkError("{} true");
|
|
}
|
|
|
|
private Object checkValid(String testStr, Class<?> aClass) {
|
|
Object result = nextValue(testStr);
|
|
|
|
// Check class of object returned
|
|
if( null == aClass ) {
|
|
if(JSONObject.NULL.equals(result)) {
|
|
// OK
|
|
} else {
|
|
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
|
|
}
|
|
} else {
|
|
if( null == result ) {
|
|
throw new JSONException("Unexpected null result");
|
|
} else if(!aClass.isAssignableFrom(result.getClass()) ) {
|
|
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private void checkError(String testStr) {
|
|
try {
|
|
nextValue(testStr);
|
|
|
|
fail("Error should be triggered: (\""+testStr+"\")");
|
|
} catch (JSONException e) {
|
|
// OK
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verifies that JSONTokener can read a stream that contains a value. After
|
|
* the reading is done, check that the stream is left in the correct state
|
|
* by reading the characters after. All valid cases should reach end of stream.
|
|
* @param testStr
|
|
* @return
|
|
* @throws Exception
|
|
*/
|
|
private Object nextValue(String testStr) throws JSONException {
|
|
try(StringReader sr = new StringReader(testStr);){
|
|
JSONTokener tokener = new JSONTokener(sr);
|
|
|
|
Object result = tokener.nextValue();
|
|
|
|
if( result == null ) {
|
|
throw new JSONException("Unable to find value token in JSON stream: ("+tokener+"): "+testStr);
|
|
}
|
|
|
|
char c = tokener.nextClean();
|
|
if( 0 != c ) {
|
|
throw new JSONException("Unexpected character found at end of JSON stream: "+c+ " ("+tokener+"): "+testStr);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests the failure of the skipTo method with a buffered reader. Preferably
|
|
* we'd like this not to fail but at this time we don't have a good recovery.
|
|
*
|
|
* @throws IOException thrown if something unexpected happens.
|
|
*/
|
|
@Test
|
|
public void testSkipToFailureWithBufferedReader() throws IOException {
|
|
final byte[] superLongBuffer = new byte[1000001];
|
|
// fill our buffer
|
|
for(int i=0;i<superLongBuffer.length;i++) {
|
|
superLongBuffer[i] = 'A';
|
|
}
|
|
try(Reader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(superLongBuffer)))) {
|
|
final JSONTokener tokener = new JSONTokener(reader);
|
|
try {
|
|
// this should fail since the internal markAhead buffer is only 1,000,000
|
|
// but 'B' doesn't exist in our buffer that is 1,000,001 in size
|
|
tokener.skipTo('B');
|
|
fail("Expected exception");
|
|
} catch (JSONException e) {
|
|
assertEquals("Mark invalid", e.getMessage());
|
|
} catch (Exception e) {
|
|
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests the success of the skipTo method with a String reader.
|
|
*
|
|
* @throws IOException thrown if something unexpected happens.
|
|
*/
|
|
@Test
|
|
public void testSkipToSuccessWithStringReader() throws IOException {
|
|
final StringBuilder superLongBuffer = new StringBuilder(1000001);
|
|
// fill our buffer
|
|
for(int i=0;i<superLongBuffer.length();i++) {
|
|
superLongBuffer.append('A');
|
|
}
|
|
try(Reader reader = new StringReader(superLongBuffer.toString())) {
|
|
final JSONTokener tokener = new JSONTokener(reader);
|
|
try {
|
|
// this should not fail since the internal markAhead is ignored for StringReaders
|
|
tokener.skipTo('B');
|
|
} catch (Exception e) {
|
|
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify that next and back are working properly and tracking the correct positions
|
|
* with different new line combinations.
|
|
*/
|
|
@Test
|
|
public void testNextBackComboWithNewLines() {
|
|
final String testString = "this is\nA test\r\nWith some different\rNew Lines";
|
|
// ^ ^ ^ ^
|
|
// index positions 0 8 16 36
|
|
final JSONTokener tokener = new JSONTokener(testString);
|
|
assertEquals(" at 0 [character 1 line 1]", tokener.toString());
|
|
assertEquals('t',tokener.next());
|
|
assertEquals(" at 1 [character 2 line 1]", tokener.toString());
|
|
tokener.skipTo('\n');
|
|
assertEquals("skipTo() improperly modifying indexes"," at 7 [character 8 line 1]", tokener.toString());
|
|
assertEquals('\n',tokener.next());
|
|
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
|
|
assertEquals('A',tokener.next());
|
|
assertEquals(" at 9 [character 1 line 2]", tokener.toString());
|
|
tokener.back();
|
|
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
|
|
tokener.skipTo('\r');
|
|
assertEquals("skipTo() improperly modifying indexes"," at 14 [character 6 line 2]", tokener.toString());
|
|
// verify \r\n combo doesn't increment the line twice
|
|
assertEquals('\r', tokener.next());
|
|
assertEquals(" at 15 [character 0 line 3]", tokener.toString());
|
|
assertEquals('\n', tokener.next());
|
|
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
|
|
// verify stepping back after reading the \n of an \r\n combo doesn't increment the line incorrectly
|
|
tokener.back();
|
|
assertEquals(" at 15 [character 6 line 2]", tokener.toString());
|
|
assertEquals('\n', tokener.next());
|
|
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
|
|
assertEquals('W', tokener.next());
|
|
assertEquals(" at 17 [character 1 line 3]", tokener.toString());
|
|
assertEquals('i', tokener.next());
|
|
assertEquals(" at 18 [character 2 line 3]", tokener.toString());
|
|
tokener.skipTo('\r');
|
|
assertEquals("skipTo() improperly modifying indexes"," at 35 [character 19 line 3]", tokener.toString());
|
|
assertEquals('\r', tokener.next());
|
|
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
|
|
tokener.back();
|
|
assertEquals(" at 35 [character 19 line 3]", tokener.toString());
|
|
assertEquals('\r', tokener.next());
|
|
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
|
|
assertEquals('N', tokener.next());
|
|
assertEquals(" at 37 [character 1 line 4]", tokener.toString());
|
|
|
|
// verify we get the same data just walking though, no calls to back
|
|
final JSONTokener t2 = new JSONTokener(testString);
|
|
for(int i=0; i<7; i++) {
|
|
assertTrue(t2.toString().startsWith(" at " + i + " "));
|
|
assertEquals(testString.charAt(i), t2.next());
|
|
}
|
|
assertEquals(" at 7 [character 8 line 1]", t2.toString());
|
|
assertEquals(testString.charAt(7), t2.next());
|
|
assertEquals(" at 8 [character 0 line 2]", t2.toString());
|
|
for(int i=8; i<14; i++) {
|
|
assertTrue(t2.toString().startsWith(" at " + i + " "));
|
|
assertEquals(testString.charAt(i), t2.next());
|
|
}
|
|
assertEquals(" at 14 [character 6 line 2]", t2.toString());
|
|
assertEquals('\r', t2.next());
|
|
assertEquals(" at 15 [character 0 line 3]", t2.toString());
|
|
assertEquals('\n', t2.next());
|
|
assertEquals(" at 16 [character 0 line 3]", t2.toString());
|
|
assertEquals('W', t2.next());
|
|
assertEquals(" at 17 [character 1 line 3]", t2.toString());
|
|
for(int i=17; i<37; i++) {
|
|
assertTrue(t2.toString().startsWith(" at " + i + " "));
|
|
assertEquals(testString.charAt(i), t2.next());
|
|
}
|
|
assertEquals(" at 37 [character 1 line 4]", t2.toString());
|
|
for(int i=37; i<testString.length(); i++) {
|
|
assertTrue(t2.toString().startsWith(" at " + i + " "));
|
|
assertEquals(testString.charAt(i), t2.next());
|
|
}
|
|
assertEquals(" at "+ testString.length() +" [character 9 line 4]", t2.toString());
|
|
// end of the input
|
|
assertEquals(0, t2.next());
|
|
assertFalse(t2.more());
|
|
}
|
|
}
|