Checking in Jackson 0.9.1 baseline.

diff --git a/src/test/main/TestJsonParser.java b/src/test/main/TestJsonParser.java
new file mode 100644
index 0000000..de36df2
--- /dev/null
+++ b/src/test/main/TestJsonParser.java
@@ -0,0 +1,262 @@
+package main;
+
+import org.codehaus.jackson.*;
+
+import java.io.IOException;
+
+/**
+ * Set of basic unit tests for verifying that the basic parser
+ * functionality works as expected.
+ */
+public class TestJsonParser
+    extends BaseTest
+{
+
+    /**
+     * This basic unit test verifies that example given in the Json
+     * specification (RFC-4627 or later) is properly parsed at
+     * high-level, without verifying values.
+     */
+    public void testSpecExampleSkipping()
+        throws Exception
+    {
+        doTestSpec(false);
+    }
+
+    /**
+     * Unit test that verifies that the spec example JSON is completely
+     * parsed, and proper values are given for contents of all
+     * events/tokens.
+     */
+    public void testSpecExampleFully()
+        throws Exception
+    {
+        doTestSpec(true);
+    }
+
+    /**
+     * Unit test that verifies that 3 basic keywords (null, true, false)
+     * are properly parsed in various contexts.
+     */
+    public void testKeywords()
+        throws Exception
+    {
+        final String DOC = "{\n"
+            +"\"key1\" : null,\n"
+            +"\"key2\" : true,\n"
+            +"\"key3\" : false,\n"
+            +"\"key4\" : [ false, null, true ]\n"
+            +"}"
+            ;
+
+        JsonParser jp = createParserUsingStream(DOC, "UTF-8");
+        assertToken(JsonToken.START_OBJECT, jp.nextToken());
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        verifyFieldName(jp, "key1");
+        assertToken(JsonToken.VALUE_NULL, jp.nextToken());
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        verifyFieldName(jp, "key2");
+        assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        verifyFieldName(jp, "key3");
+        assertToken(JsonToken.VALUE_FALSE, jp.nextToken());
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        verifyFieldName(jp, "key4");
+        assertToken(JsonToken.START_ARRAY, jp.nextToken());
+        assertToken(JsonToken.VALUE_FALSE, jp.nextToken());
+        assertToken(JsonToken.VALUE_NULL, jp.nextToken());
+        assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
+        assertToken(JsonToken.END_ARRAY, jp.nextToken());
+
+        assertToken(JsonToken.END_OBJECT, jp.nextToken());
+    }
+
+    public void testInvalidKeywords()
+        throws Exception
+    {
+        doTestInvalidKeyword1("nul");
+        doTestInvalidKeyword2("nulla", JsonToken.VALUE_NULL);
+        doTestInvalidKeyword1("fal");
+        doTestInvalidKeyword3("False");
+        doTestInvalidKeyword2("falsett0", JsonToken.VALUE_FALSE);
+        doTestInvalidKeyword1("tr");
+        doTestInvalidKeyword1("truE");
+        doTestInvalidKeyword2("trueenough", JsonToken.VALUE_TRUE);
+    }
+
+    /*
+    /////////////////////////////////////////////
+    // Helper methods
+    /////////////////////////////////////////////
+    */
+
+    private void doTestSpec(boolean verify)
+        throws IOException
+    {
+        // First, using a StringReader:
+        doTestSpecIndividual(null, verify);
+
+        // Then with streams using supported encodings:
+        doTestSpecIndividual("UTF-8", verify);
+        doTestSpecIndividual("UTF-16BE", verify);
+        doTestSpecIndividual("UTF-16LE", verify);
+
+        /* Hmmh. UTF-32 is harder only because JDK doesn't come with
+         * a codec for it. Can't test it yet using this method
+         */
+        //doTestSpecIndividual("UTF-32", verify);
+    }
+
+    private void doTestSpecIndividual(String enc, boolean verify)
+        throws IOException
+    {
+        String doc = SAMPLE_DOC_JSON_SPEC;
+        JsonParser jp;
+
+        if (enc == null) {
+            jp = createParserUsingReader(doc);
+        } else {
+            jp = createParserUsingStream(doc, enc);
+        }
+
+        assertToken(JsonToken.START_OBJECT, jp.nextToken()); // main object
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image'
+        if (verify) {
+            verifyFieldName(jp, "Image");
+        }
+
+        assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width'
+        if (verify) {
+            verifyFieldName(jp, "Width");
+        }
+
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        if (verify) {
+            verifyIntValue(jp, SAMPLE_SPEC_VALUE_WIDTH);
+        }
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height'
+        if (verify) {
+            verifyFieldName(jp, "Height");
+        }
+
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_HEIGHT);
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title'
+        if (verify) {
+            verifyFieldName(jp, "Title");
+        }
+        assertToken(JsonToken.VALUE_STRING, jp.nextToken());
+        assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp));
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail'
+        if (verify) {
+            verifyFieldName(jp, "Thumbnail");
+        }
+
+        assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url'
+        if (verify) {
+            verifyFieldName(jp, "Url");
+        }
+        assertToken(JsonToken.VALUE_STRING, jp.nextToken());
+        if (verify) {
+            assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp));
+        }
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height'
+        if (verify) {
+            verifyFieldName(jp, "Height");
+        }
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_HEIGHT);
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width'
+        if (verify) {
+            verifyFieldName(jp, "Width");
+        }
+        // Width value is actually a String in the example
+        assertToken(JsonToken.VALUE_STRING, jp.nextToken());
+        assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp));
+
+        assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object
+
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs'
+        assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[0]
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1);
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[1]
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2);
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[2]
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3);
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[3]
+        verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4);
+        assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array
+
+        assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object
+
+        assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object
+    }
+
+    private void verifyFieldName(JsonParser jp, String expName)
+        throws IOException
+    {
+        assertEquals(expName, jp.getText());
+        assertEquals(expName, jp.getCurrentName());
+    }
+
+    private void verifyIntValue(JsonParser jp, long expValue)
+        throws IOException
+    {
+        // First, via textual
+        assertEquals(String.valueOf(expValue), jp.getText());
+    }
+
+    private void doTestInvalidKeyword1(String value)
+        throws IOException
+    {
+        JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8");
+        assertToken(JsonToken.START_OBJECT, jp.nextToken());
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        try {
+            jp.nextToken();
+            fail("Expected an exception for malformed value keyword");
+        } catch (JsonParseException jex) {
+            verifyException(jex, "Unrecognized token");
+        }
+    }
+
+    private void doTestInvalidKeyword2(String value, JsonToken firstValue)
+        throws IOException
+    {
+        JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8");
+        assertToken(JsonToken.START_OBJECT, jp.nextToken());
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        assertToken(firstValue, jp.nextToken());
+        try {
+            jp.nextToken();
+            fail("Expected an exception for malformed value keyword");
+        } catch (JsonParseException jex) {
+            verifyException(jex, "Unexpected character");
+        }
+    }
+
+    private void doTestInvalidKeyword3(String value)
+        throws IOException
+    {
+        JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8");
+        assertToken(JsonToken.START_OBJECT, jp.nextToken());
+        assertToken(JsonToken.FIELD_NAME, jp.nextToken());
+        try {
+            jp.nextToken();
+            fail("Expected an exception for malformed value keyword");
+        } catch (JsonParseException jex) {
+            verifyException(jex, "expected a valid value");
+        }
+    }
+}
+