blob: bb9e484d6c97dca4cd293c5528c155b4b6c67134 [file] [log] [blame]
package org.codehaus.jackson.main;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.*;
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.MappingJsonFactory;
/**
* Set of basic unit tests for verifying basic generator
* features.
*/
public class TestGeneratorMisc
extends main.BaseTest
{
final static class Pojo
{
public int getX() { return 4; }
}
/*
/**********************************************************
/* Tests for closing, status
/**********************************************************
*/
public void testIsClosed()
throws IOException
{
JsonFactory jf = new JsonFactory();
for (int i = 0; i < 2; ++i) {
boolean stream = ((i & 1) == 0);
JsonGenerator jg = stream ?
jf.createJsonGenerator(new StringWriter())
: jf.createJsonGenerator(new ByteArrayOutputStream(), JsonEncoding.UTF8)
;
assertFalse(jg.isClosed());
jg.writeStartArray();
jg.writeNumber(-1);
jg.writeEndArray();
assertFalse(jg.isClosed());
jg.close();
assertTrue(jg.isClosed());
jg.close();
assertTrue(jg.isClosed());
}
}
/*
/**********************************************************
/* Tests for data binding integration
/**********************************************************
*/
public void testPojoWriting()
throws IOException
{
JsonFactory jf = new MappingJsonFactory();
StringWriter sw = new StringWriter();
JsonGenerator gen = jf.createJsonGenerator(sw);
gen.writeObject(new Pojo());
gen.close();
// trimming needed if main-level object has leading space
String act = sw.toString().trim();
assertEquals("{\"x\":4}", act);
}
public void testPojoWritingFailing()
throws IOException
{
// regular factory can't do it, without a call to setCodec()
JsonFactory jf = new JsonFactory();
try {
StringWriter sw = new StringWriter();
JsonGenerator gen = jf.createJsonGenerator(sw);
gen.writeObject(new Pojo());
gen.close();
fail("Expected an exception: got sw '"+sw.toString()+"'");
} catch (IllegalStateException e) {
verifyException(e, "No ObjectCodec defined");
}
}
// Also, "very simple" objects are supported even without Codec:
public void testSimpleWriteObject() throws IOException
{
// note: NOT mapping factory, for this test
JsonFactory jf = new JsonFactory();
StringWriter sw = new StringWriter();
JsonGenerator gen = jf.createJsonGenerator(sw);
gen.writeStartArray();
// simple wrappers first
gen.writeObject(Integer.valueOf(1));
gen.writeObject(Short.valueOf((short)-2));
gen.writeObject(Long.valueOf(3));
gen.writeObject(Byte.valueOf((byte)-4));
gen.writeObject(Double.valueOf(0.25));
gen.writeObject(Float.valueOf(-0.125f));
gen.writeObject(Boolean.TRUE);
gen.close();
String act = sw.toString().trim();
assertEquals("[1,-2,3,-4,0.25,-0.125,true]", act);
// then other basic types
sw = new StringWriter();
gen = jf.createJsonGenerator(sw);
gen.writeStartArray();
gen.writeObject(BigInteger.valueOf(1234));
gen.writeObject(new BigDecimal(0.5));
gen.writeEndArray();
gen.close();
act = sw.toString().trim();
assertEquals("[1234,0.5]", act);
// then Atomic types
sw = new StringWriter();
gen = jf.createJsonGenerator(sw);
gen.writeStartArray();
gen.writeObject(new AtomicBoolean(false));
gen.writeObject(new AtomicInteger(13));
gen.writeObject(new AtomicLong(-127L));
gen.writeEndArray();
gen.close();
act = sw.toString().trim();
assertEquals("[false,13,-127]", act);
}
/*
/**********************************************************
/* Tests for raw output
/**********************************************************
*/
public void testRaw() throws IOException
{
JsonFactory jf = new JsonFactory();
StringWriter sw = new StringWriter();
JsonGenerator gen = jf.createJsonGenerator(sw);
gen.writeStartArray();
gen.writeRaw("-123, true");
gen.writeRaw(", \"x\" ");
gen.writeEndArray();
gen.close();
JsonParser jp = createParserUsingReader(sw.toString());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(-123, jp.getIntValue());
assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
assertEquals("x", jp.getText());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
public void testRawValue() throws IOException
{
JsonFactory jf = new JsonFactory();
StringWriter sw = new StringWriter();
JsonGenerator gen = jf.createJsonGenerator(sw);
gen.writeStartArray();
gen.writeRawValue("7");
gen.writeRawValue("[ null ]");
gen.writeRawValue("false");
gen.writeEndArray();
gen.close();
JsonParser jp = createParserUsingReader(sw.toString());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(7, jp.getIntValue());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NULL, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_FALSE, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
/*
/**********************************************************
/* Tests for binary data
/**********************************************************
*/
/**
* This is really inadequate test, all in all, but should serve
* as some kind of sanity check. Reader-side should more thoroughly
* test things, as it does need writers to construct the data first.
*/
public void testBinaryWrite() throws Exception
{
_testBinaryWrite(false);
_testBinaryWrite(true);
}
private void _testBinaryWrite(boolean useCharBased) throws Exception
{
/* The usual sample input string, from Thomas Hobbes's "Leviathan"
* (via Wikipedia)
*/
final String INPUT = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
final byte[] INPUT_BYTES = INPUT.getBytes("US-ASCII");
// as per MIME variant, result minus lfs =
final String OUTPUT =
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
+"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
+"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
+"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
+"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
;
/* Let's only test the standard base64 variant; but write
* values in root, array and object contexts.
*/
Base64Variant b64v = Base64Variants.getDefaultVariant();
JsonFactory jf = new JsonFactory();
for (int i = 0; i < 3; ++i) {
JsonGenerator gen;
ByteArrayOutputStream bout = new ByteArrayOutputStream(200);
if (useCharBased) {
gen = jf.createJsonGenerator(new OutputStreamWriter(bout, "UTF-8"));
} else {
gen = jf.createJsonGenerator(bout, JsonEncoding.UTF8);
}
switch (i) {
case 0: // root
gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length);
break;
case 1: // array
gen.writeStartArray();
gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length);
gen.writeEndArray();
break;
default: // object
gen.writeStartObject();
gen.writeFieldName("field");
gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length);
gen.writeEndObject();
break;
}
gen.close();
JsonParser jp = jf.createJsonParser(new ByteArrayInputStream(bout.toByteArray()));
// Need to skip other events before binary data:
switch (i) {
case 0:
break;
case 1:
assertEquals(JsonToken.START_ARRAY, jp.nextToken());
break;
default:
assertEquals(JsonToken.START_OBJECT, jp.nextToken());
assertEquals(JsonToken.FIELD_NAME, jp.nextToken());
break;
}
assertEquals(JsonToken.VALUE_STRING, jp.nextToken());
String actualValue = jp.getText();
jp.close();
assertEquals(OUTPUT, actualValue);
}
}
/*
/**********************************************************
/* Tests for object writing
/**********************************************************
*/
/**
* Unit test that tries to trigger buffer-boundary conditions
*/
public void testLongerObjects() throws Exception
{
JsonFactory jf = new JsonFactory();
for (int i = 0; i < 2; ++i) {
boolean useChars = (i == 0);
JsonGenerator jgen;
ByteArrayOutputStream bout = new ByteArrayOutputStream(200);
if (useChars) {
jgen = jf.createJsonGenerator(new OutputStreamWriter(bout, "UTF-8"));
} else {
jgen = jf.createJsonGenerator(bout, JsonEncoding.UTF8);
}
jgen.writeStartObject();
for (int rounds = 0; rounds < 1500; ++rounds) {
for (int letter = 'a'; letter <= 'z'; ++letter) {
for (int index = 0; index < 20; ++index) {
String name;
if (letter > 'f') {
name = "X"+letter+index;
} else if (letter > 'p') {
name = ""+letter+index;
} else {
name = "__"+index+letter;
}
jgen.writeFieldName(name);
jgen.writeNumber(index-1);
}
jgen.writeRaw('\n');
}
}
jgen.writeEndObject();
jgen.close();
byte[] json = bout.toByteArray();
JsonParser jp = jf.createJsonParser(json);
assertToken(JsonToken.START_OBJECT, jp.nextToken());
for (int rounds = 0; rounds < 1500; ++rounds) {
for (int letter = 'a'; letter <= 'z'; ++letter) {
for (int index = 0; index < 20; ++index) {
assertToken(JsonToken.FIELD_NAME, jp.nextToken());
String name;
if (letter > 'f') {
name = "X"+letter+index;
} else if (letter > 'p') {
name = ""+letter+index;
} else {
name = "__"+index+letter;
}
assertEquals(name, jp.getCurrentName());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(index-1, jp.getIntValue());
}
}
}
assertToken(JsonToken.END_OBJECT, jp.nextToken());
}
}
}