TreeTraversingParserReadConstraintsTest.java
package tools.jackson.databind.node;
import org.junit.jupiter.api.Test;
import tools.jackson.core.*;
import tools.jackson.core.exc.StreamConstraintsException;
import tools.jackson.databind.*;
import tools.jackson.databind.testutil.DatabindTestUtil;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for {@link TreeTraversingParser} constructors that take explicit
* {@link StreamReadConstraints}, for use by tree-backed format backends
* that need their {@code TokenStreamFactory}'s constraints applied
* regardless of {@link ObjectReadContext} given.
*/
public class TreeTraversingParserReadConstraintsTest extends DatabindTestUtil
{
private final static int MAX_TOKENS = 4;
private final static StreamReadConstraints CONSTRAINTS = StreamReadConstraints.builder()
.maxTokenCount(MAX_TOKENS).build();
private final ObjectMapper MAPPER = newJsonMapper();
// 10 tokens: START_ARRAY, 8 x VALUE_NUMBER_INT, END_ARRAY
private JsonNode _tree() throws Exception {
return MAPPER.readTree("[0,1,2,3,4,5,6,7]");
}
@Test
void constraintsExposed() throws Exception
{
try (JsonParser p = new TreeTraversingParser(_tree(), ObjectReadContext.empty(), CONSTRAINTS)) {
assertSame(CONSTRAINTS, p.streamReadConstraints());
}
try (JsonParser p = new TreeTraversingParser(_tree(), ObjectReadContext.empty(), null, CONSTRAINTS)) {
assertSame(CONSTRAINTS, p.streamReadConstraints());
}
// and without explicit constraints, those of read context (here: defaults)
try (JsonParser p = new TreeTraversingParser(_tree(), ObjectReadContext.empty())) {
assertSame(StreamReadConstraints.defaults(), p.streamReadConstraints());
assertFalse(p.streamReadConstraints().hasMaxTokenCount());
}
}
@Test
void tokenCountEnforced() throws Exception
{
try (JsonParser p = new TreeTraversingParser(_tree(), ObjectReadContext.empty(), CONSTRAINTS)) {
for (int i = 0; i < MAX_TOKENS; ++i) {
assertNotNull(p.nextToken());
}
try {
p.nextToken();
fail("Should not pass");
} catch (StreamConstraintsException e) {
verifyException(e, "Token count (" + (MAX_TOKENS + 1) + ")");
verifyException(e, "exceeds the maximum allowed (" + MAX_TOKENS);
}
}
}
@Test
void tokenCountNotEnforcedWithoutConstraints() throws Exception
{
// Same tree, read context with default (unlimited) constraints: fine
try (JsonParser p = new TreeTraversingParser(_tree(), ObjectReadContext.empty())) {
int count = 0;
while (p.nextToken() != null) {
++count;
}
assertEquals(10, count);
}
}
// Parent context variant must retain both the parent and the constraints
@Test
void withParentContext() throws Exception
{
JsonNode root = MAPPER.readTree("{\"a\":[0,1,2,3,4,5,6,7]}");
try (JsonParser outer = new TreeTraversingParser(root)) {
assertToken(JsonToken.START_OBJECT, outer.nextToken());
assertToken(JsonToken.PROPERTY_NAME, outer.nextToken());
assertToken(JsonToken.START_ARRAY, outer.nextToken());
JsonNode sub = root.get("a");
try (JsonParser p = new TreeTraversingParser(sub, ObjectReadContext.empty(),
outer.streamReadContext().getParent(), CONSTRAINTS)) {
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertEquals("/a", p.streamReadContext().pathAsPointer().toString());
assertSame(CONSTRAINTS, p.streamReadConstraints());
p.nextToken(); p.nextToken(); p.nextToken();
assertThrows(StreamConstraintsException.class, p::nextToken);
}
}
}
}