GeneratorBasicTest.java
package com.fasterxml.jackson.core.write;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.core.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* Set of basic unit tests for verifying that the basic generator
* functionality works as expected.
*/
public class GeneratorBasicTest
extends com.fasterxml.jackson.core.JUnit5TestBase
{
private final JsonFactory JSON_F = new JsonFactory();
// // // First, tests for primitive (non-structured) values
@Test
void stringWrite() throws Exception
{
String[] inputStrings = new String[] { "", "X", "1234567890" };
for (int useReader = 0; useReader < 2; ++useReader) {
for (int writeString = 0; writeString < 2; ++writeString) {
for (int strIx = 0; strIx < inputStrings.length; ++strIx) {
String input = inputStrings[strIx];
JsonGenerator gen;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
if (useReader != 0) {
gen = JSON_F.createGenerator(new OutputStreamWriter(bout, "UTF-8"));
} else {
gen = JSON_F.createGenerator(bout, JsonEncoding.UTF8);
}
if (writeString > 0) {
gen.writeString(input);
} else {
int len = input.length();
char[] buffer = new char[len + 20];
// Let's use non-zero base offset too...
input.getChars(0, len, buffer, strIx);
gen.writeString(buffer, strIx, len);
}
gen.flush();
gen.close();
JsonParser jp = JSON_F.createParser(new ByteArrayInputStream(bout.toByteArray()));
JsonToken t = jp.nextToken();
assertNotNull(t, "Document \""+utf8String(bout)+"\" yielded no tokens");
assertEquals(JsonToken.VALUE_STRING, t);
assertEquals(input, jp.getText());
assertNull(jp.nextToken());
jp.close();
}
}
}
}
@Test
void intValueWrite() throws Exception
{
// char[]
doTestIntValueWrite(false, false);
doTestIntValueWrite(true, false);
// byte[]
doTestIntValueWrite(false, true);
doTestIntValueWrite(true, true);
}
@Test
void longValueWrite() throws Exception
{
// char[]
doTestLongValueWrite(false, false);
doTestLongValueWrite(true, false);
// byte[]
doTestLongValueWrite(false, true);
doTestLongValueWrite(true, true);
}
@Test
void booleanWrite() throws Exception
{
for (int i = 0; i < 4; ++i) {
boolean state = (i & 1) == 0;
boolean pad = (i & 2) == 0;
StringWriter sw = new StringWriter();
JsonGenerator gen = JSON_F.createGenerator(sw);
gen.writeBoolean(state);
if (pad) {
gen.writeRaw(" ");
}
gen.close();
String docStr = sw.toString();
JsonParser jp = createParserUsingReader(docStr);
JsonToken t = jp.nextToken();
String exp = Boolean.valueOf(state).toString();
if (!exp.equals(jp.getText())) {
fail("Expected '"+exp+"', got '"+jp.getText());
}
assertEquals(state ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE, t);
assertNull(jp.nextToken());
jp.close();
}
}
@Test
void nullWrite()
throws Exception
{
for (int i = 0; i < 2; ++i) {
boolean pad = (i & 1) == 0;
StringWriter sw = new StringWriter();
JsonGenerator gen = JSON_F.createGenerator(sw);
gen.writeNull();
if (pad) {
gen.writeRaw(" ");
}
gen.close();
String docStr = sw.toString();
JsonParser jp = createParserUsingReader(docStr);
JsonToken t = jp.nextToken();
String exp = "null";
if (!exp.equals(jp.getText())) {
fail("Expected '"+exp+"', got '"+jp.getText());
}
assertEquals(JsonToken.VALUE_NULL, t);
assertNull(jp.nextToken());
jp.close();
}
}
// // Then root-level output testing
@Test
void rootIntsWrite() throws Exception {
_testRootIntsWrite(false);
_testRootIntsWrite(true);
}
private void _testRootIntsWrite(boolean useBytes) throws Exception
{
StringWriter sw = new StringWriter();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
JsonGenerator gen;
if (useBytes) {
gen = JSON_F.createGenerator(bytes);
} else {
gen = JSON_F.createGenerator(sw);
}
gen.writeNumber(1);
gen.writeNumber((short) 2); // for test coverage
gen.writeNumber(-13);
gen.close();
String docStr = useBytes ? utf8String(bytes) : sw.toString();
try {
JsonParser jp = createParserUsingReader(docStr);
assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(1, jp.getIntValue());
assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(2, jp.getIntValue());
assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(-13, jp.getIntValue());
jp.close();
} catch (IOException e) {
fail("Problem with document ["+docStr+"]: "+e.getMessage());
}
}
// Convenience methods
@Test
void fieldValueWrites() throws Exception {
_testFieldValueWrites(false);
_testFieldValueWrites(true);
}
public void _testFieldValueWrites(boolean useBytes) throws Exception
{
StringWriter sw = new StringWriter();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
JsonGenerator gen;
if (useBytes) {
gen = JSON_F.createGenerator(bytes);
} else {
gen = JSON_F.createGenerator(sw);
}
gen.writeStartObject();
gen.writeNumberField("short", (short) 3);
gen.writeNumberField("int", 3);
gen.writeNumberField("long", 3L);
gen.writeNumberField("big", new BigInteger("1707"));
gen.writeNumberField("double", 0.25);
gen.writeNumberField("float", -0.25f);
gen.writeNumberField("decimal", new BigDecimal("17.07"));
gen.writeEndObject();
gen.close();
String docStr = useBytes ? utf8String(bytes) : sw.toString();
assertEquals("{\"short\":3,\"int\":3,\"long\":3,\"big\":1707,\"double\":0.25,\"float\":-0.25,\"decimal\":17.07}",
docStr.trim());
}
/**
* Test to verify that output context actually contains useful information
*/
@Test
void outputContext() throws Exception
{
StringWriter sw = new StringWriter();
JsonGenerator gen = JSON_F.createGenerator(sw);
JsonStreamContext ctxt = gen.getOutputContext();
assertTrue(ctxt.inRoot());
gen.writeStartObject();
assertTrue(gen.getOutputContext().inObject());
gen.writeFieldName("a");
assertEquals("a", gen.getOutputContext().getCurrentName());
gen.writeStartArray();
assertTrue(gen.getOutputContext().inArray());
gen.writeStartObject();
assertTrue(gen.getOutputContext().inObject());
gen.writeFieldName("b");
ctxt = gen.getOutputContext();
assertEquals("b", ctxt.getCurrentName());
gen.writeNumber(123);
assertEquals("b", ctxt.getCurrentName());
gen.writeFieldName("c");
assertEquals("c", gen.getOutputContext().getCurrentName());
gen.writeNumber(5);
// assertEquals("c", gen.getOutputContext().getCurrentName());
gen.writeFieldName("d");
assertEquals("d", gen.getOutputContext().getCurrentName());
gen.writeStartArray();
ctxt = gen.getOutputContext();
assertTrue(ctxt.inArray());
assertEquals(0, ctxt.getCurrentIndex());
assertEquals(0, ctxt.getEntryCount());
gen.writeBoolean(true);
ctxt = gen.getOutputContext();
assertTrue(ctxt.inArray());
// NOTE: index still refers to currently output entry
assertEquals(0, ctxt.getCurrentIndex());
assertEquals(1, ctxt.getEntryCount());
gen.writeNumber(3);
ctxt = gen.getOutputContext();
assertTrue(ctxt.inArray());
assertEquals(1, ctxt.getCurrentIndex());
assertEquals(2, ctxt.getEntryCount());
gen.writeEndArray();
assertTrue(gen.getOutputContext().inObject());
gen.writeEndObject();
assertTrue(gen.getOutputContext().inArray());
gen.writeEndArray();
assertTrue(gen.getOutputContext().inObject());
gen.writeEndObject();
assertTrue(gen.getOutputContext().inRoot());
gen.close();
}
@Test
void getOutputTarget() throws Exception
{
OutputStream out = new ByteArrayOutputStream();
JsonGenerator gen = JSON_F.createGenerator(out);
assertSame(out, gen.getOutputTarget());
gen.close();
StringWriter sw = new StringWriter();
gen = JSON_F.createGenerator(sw);
assertSame(sw, gen.getOutputTarget());
gen.close();
}
// for [core#195]
@Test
void getOutputBufferd() throws Exception
{
OutputStream out = new ByteArrayOutputStream();
JsonGenerator gen = JSON_F.createGenerator(out);
_testOutputBuffered(gen);
gen.close();
StringWriter sw = new StringWriter();
gen = JSON_F.createGenerator(sw);
_testOutputBuffered(gen);
gen.close();
}
private void _testOutputBuffered(JsonGenerator gen) throws IOException
{
gen.writeStartArray(); // 1 byte
gen.writeNumber(1234); // 4 bytes
assertEquals(5, gen.getOutputBuffered());
gen.flush();
assertEquals(0, gen.getOutputBuffered());
gen.writeEndArray();
assertEquals(1, gen.getOutputBuffered());
gen.close();
assertEquals(0, gen.getOutputBuffered());
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
private void doTestIntValueWrite(boolean pad, boolean useBytes) throws Exception
{
int[] VALUES = new int[] {
0, 1, -9, 32, -32, 57, 189, 2017, -9999, 13240, 123456,
1111111, 22222222, 123456789,
7300999, -7300999,
99300999, -99300999,
999300999, -999300999,
1000300999, 2000500126, -1000300999, -2000500126,
Integer.MIN_VALUE, Integer.MAX_VALUE
};
for (int i = 0; i < VALUES.length; ++i) {
int VALUE = VALUES[i];
String docStr;
JsonParser p;
if (useBytes) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
JsonGenerator gen = JSON_F.createGenerator(bytes);
gen.writeNumber(VALUE);
if (pad) {
gen.writeRaw(" ");
}
gen.close();
docStr = utf8String(bytes);
p = JSON_F.createParser(bytes.toByteArray());
} else {
StringWriter sw = new StringWriter();
JsonGenerator gen = JSON_F.createGenerator(sw);
gen.writeNumber(VALUE);
if (pad) {
gen.writeRaw(" ");
}
gen.close();
docStr = sw.toString();
p = JSON_F.createParser(docStr);
}
JsonToken t = null;
try {
t = p.nextToken();
} catch (IOException e) {
fail("Problem with value "+VALUE+", document ["+docStr+"]: "+e.getMessage());
}
assertNotNull(t, "Document \""+docStr+"\" yielded no tokens");
// Number are always available as lexical representation too
String exp = ""+VALUE;
if (!exp.equals(p.getText())) {
fail("Expected '"+exp+"', got '"+p.getText());
}
assertEquals(JsonToken.VALUE_NUMBER_INT, t);
assertEquals(VALUE, p.getIntValue());
assertNull(p.nextToken());
p.close();
}
}
private void doTestLongValueWrite(boolean pad, boolean useBytes) throws Exception
{
long[] VALUES = new long[] {
0L, 1L, -1L, 2000100345, -12005002294L,
5111222333L, -5111222333L,
65111222333L, -65111222333L,
123456789012L, -123456789012L,
123456789012345L, -123456789012345L,
123456789012345789L, -123456789012345789L,
Long.MIN_VALUE, Long.MAX_VALUE
};
for (int i = 0; i < VALUES.length; ++i) {
long VALUE = VALUES[i];
String docStr;
JsonParser p;
if (useBytes) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
JsonGenerator gen = JSON_F.createGenerator(bytes);
gen.writeNumber(VALUE);
if (pad) {
gen.writeRaw(" ");
}
gen.close();
docStr = utf8String(bytes);
p = JSON_F.createParser(bytes.toByteArray());
} else {
StringWriter sw = new StringWriter();
JsonGenerator gen = JSON_F.createGenerator(sw);
gen.writeNumber(VALUE);
if (pad) {
gen.writeRaw(" ");
}
gen.close();
docStr = sw.toString();
p = JSON_F.createParser(docStr);
}
JsonToken t = null;
try {
t = p.nextToken();
} catch (IOException e) {
fail("Problem with number "+VALUE+", document ["+docStr+"]: "+e.getMessage());
}
assertNotNull(t, "Document \""+docStr+"\" yielded no tokens");
String exp = ""+VALUE;
if (!exp.equals(p.getText())) {
fail("Expected '"+exp+"', got '"+p.getText());
}
assertEquals(JsonToken.VALUE_NUMBER_INT, t);
assertEquals(VALUE, p.getLongValue());
assertNull(p.nextToken());
p.close();
}
}
}