Skip to content

Commit

Permalink
Minor cleanup/unification post #386
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jul 12, 2023
1 parent cdd70bb commit ae170b2
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,13 @@ private Feature(boolean defaultState) {
/**********************************************************
*/

final protected IOContext _ioContext;
protected final IOContext _ioContext;

/**
* @since 2.16
*/
protected final StreamWriteConstraints _streamWriteConstraints;

/**
* Bit flag composed of bits that indicate which
* {@link AvroGenerator.Feature}s
Expand Down Expand Up @@ -140,6 +145,7 @@ public AvroGenerator(IOContext ctxt, int jsonFeatures, int avroFeatures,
{
super(jsonFeatures, codec);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_formatFeatures = avroFeatures;
_output = output;
_avroContext = AvroWriteContext.nullContext();
Expand All @@ -159,7 +165,7 @@ public void setSchema(AvroSchema schema)

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
return _streamWriteConstraints;
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.fasterxml.jackson.dataformat.avro.dos;

import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.dataformat.avro.AvroFactory;
import com.fasterxml.jackson.dataformat.avro.AvroMapper;
import com.fasterxml.jackson.dataformat.avro.AvroSchema;
import com.fasterxml.jackson.dataformat.avro.AvroTestBase;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicAvroDataSerTest extends AvroTestBase
{

public static class Bean
{
Bean _next;
final String _name;

public Bean(Bean next, String name) {
_next = next;
_name = name;
}

public Bean getNext() { return _next; }
public String getName() { return _name; }

public void assignNext(Bean n) { _next = n; }
}

private final AvroMapper MAPPER = getMapper();

// Unlike default depth of 1000 for other formats, use lower (400) here
// because we cannot actually generate 1000 levels due to Avro codec's
// limitations
private final AvroMapper MAPPER_400;
{
AvroFactory f = AvroFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(400).build())
.build();
MAPPER_400 = new AvroMapper(f);
}

public void testDirectCyclic() throws Exception {
Bean bean = new Bean(null, "123");
bean.assignNext(bean);
try {
AvroSchema schema = MAPPER.schemaFor(Bean.class);
MAPPER.writer(schema).writeValueAsBytes(bean);
fail("expected InvalidDefinitionException");
} catch (InvalidDefinitionException idex) {
assertTrue("InvalidDefinitionException message is as expected?",
idex.getMessage().startsWith("Direct self-reference leading to cycle"));
}
}

// With 2.16 also test looser loops, wrt new limits
public void testLooserCyclic() throws Exception
{
Bean beanRoot = new Bean(null, "123");
Bean bean2 = new Bean(beanRoot, "456");
beanRoot.assignNext(bean2);

// 12-Jul-2023, tatu: Alas, won't work -- Avro serialization by-passes many
// checks. Needs more work in future

if (false) {
try {
AvroSchema schema = MAPPER_400.schemaFor(Bean.class);
MAPPER_400.writer(schema).writeValueAsBytes(beanRoot);
fail("expected InvalidDefinitionException");
} catch (InvalidDefinitionException idex) {
assertTrue("InvalidDefinitionException message is as expected?",
idex.getMessage().startsWith("Direct self-reference leading to cycle"));
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,14 @@ public int getMask() {
/**********************************************************
*/

final protected IOContext _ioContext;
protected final IOContext _ioContext;

final protected OutputStream _out;
/**
* @since 2.16
*/
protected final StreamWriteConstraints _streamWriteConstraints;

protected final OutputStream _out;

/**
* Bit flag composed of bits that indicate which
Expand Down Expand Up @@ -293,6 +298,7 @@ public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
_cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = Feature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_out = out;
_bufferRecyclable = true;
_stringRefs = Feature.STRINGREF.enabledIn(formatFeatures) ? new HashMap<>() : null;
Expand Down Expand Up @@ -330,6 +336,7 @@ public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
_cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = Feature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_out = out;
_bufferRecyclable = bufferRecyclable;
_outputTail = offset;
Expand Down Expand Up @@ -381,7 +388,7 @@ public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() {

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
return _streamWriteConstraints;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package com.fasterxml.jackson.dataformat.cbor.gen.dos;

import com.fasterxml.jackson.core.StreamWriteConstraints;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.StreamWriteConstraints;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest extends CBORTestBase
public class CyclicCBORDataSerTest extends CBORTestBase
{
private final ObjectMapper MAPPER = cborMapper();

Expand All @@ -21,11 +20,11 @@ public void testListWithSelfReference() throws Exception {
list.add(list);
try {
MAPPER.writeValueAsBytes(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
fail("expected DatabindException");
} catch (DatabindException jmex) {
String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
assertTrue("JsonMappingException message is as expected?",
assertTrue("DatabindException message is as expected?",
jmex.getMessage().startsWith(exceptionPrefix));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package com.fasterxml.jackson.dataformat.cbor.parse.dos;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.core.StreamWriteConstraints;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.exc.StreamConstraintsException;

import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
* Unit tests for deeply nested JSON
*/
Expand All @@ -22,10 +19,9 @@ public void testDeeplyNestedObjects() throws Exception
final int depth = 1500;
ByteArrayOutputStream out = new ByteArrayOutputStream();
genDeepDoc(out, depth);
try (JsonParser jp = cborParser(out)) {
JsonToken jt;
while ((jt = jp.nextToken()) != null) {

try (JsonParser p = cborParser(out)) {
while (p.nextToken() != null) {
;
}
fail("expected StreamConstraintsException");
} catch (StreamConstraintsException e) {
Expand All @@ -44,10 +40,9 @@ public void testDeeplyNestedObjectsWithUnconstrainedMapper() throws Exception
CBORFactory cborFactory = CBORFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(Integer.MAX_VALUE).build())
.build();
try (JsonParser jp = cborParser(cborFactory, out)) {
JsonToken jt;
while ((jt = jp.nextToken()) != null) {

try (JsonParser p = cborParser(cborFactory, out)) {
while (p.nextToken() != null) {
;
}
}
}
Expand All @@ -57,10 +52,9 @@ public void testDeeplyNestedArrays() throws Exception
final int depth = 750;
ByteArrayOutputStream out = new ByteArrayOutputStream();
genDeepArrayDoc(out, depth);
try (JsonParser jp = cborParser(out)) {
JsonToken jt;
while ((jt = jp.nextToken()) != null) {

try (JsonParser p = cborParser(out)) {
while (p.nextToken() != null) {
;
}
fail("expected StreamConstraintsException");
} catch (StreamConstraintsException e) {
Expand All @@ -79,10 +73,9 @@ public void testDeeplyNestedArraysWithUnconstrainedMapper() throws Exception
CBORFactory cborFactory = CBORFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(Integer.MAX_VALUE).build())
.build();
try (JsonParser jp = cborParser(cborFactory, out)) {
JsonToken jt;
while ((jt = jp.nextToken()) != null) {

try (JsonParser p = cborParser(cborFactory, out)) {
while (p.nextToken() != null) {
;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ private Feature(boolean defaultState) {

protected final IOContext _ioContext;

/**
* @since 2.16
*/
protected final StreamWriteConstraints _streamWriteConstraints;

/**
* Bit flag composed of bits that indicate which
* {@link IonGenerator.Feature}s
Expand Down Expand Up @@ -140,8 +145,8 @@ public IonGenerator(int jsonFeatures, final int ionFeatures, ObjectCodec codec,
_writer = ion;
_ionWriterIsManaged = ionWriterIsManaged;
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_destination = dst;

}

@Override
Expand All @@ -151,7 +156,7 @@ public Version version() {

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
return _streamWriteConstraints;
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.fasterxml.jackson.dataformat.ion.dos;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.StreamWriteConstraints;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.*;

import com.fasterxml.jackson.dataformat.ion.IonObjectMapper;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
Expand All @@ -16,7 +17,7 @@
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest
public class CyclicIonDataSerTest
{
private final ObjectMapper MAPPER = IonObjectMapper.builderForTextualWriters().build();

Expand All @@ -26,12 +27,12 @@ public void testListWithSelfReference() throws Exception {
list.add(list);
try {
MAPPER.writeValueAsBytes(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
fail("expected DatabindException");
} catch (DatabindException e) {
String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
assertTrue("JsonMappingException message is as expected?",
jmex.getMessage().startsWith(exceptionPrefix));
assertTrue("DatabindException message is as expected?",
e.getMessage().startsWith(exceptionPrefix));
}
}
}
Loading

0 comments on commit ae170b2

Please sign in to comment.