Skip to content

Commit

Permalink
Backport part of junit5 changes to 2.16
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Feb 11, 2024
1 parent a1c1205 commit 7df89c4
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 8 deletions.
210 changes: 210 additions & 0 deletions src/test/java/com/fasterxml/jackson/core/JUnit5TestBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package com.fasterxml.jackson.core;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

import com.fasterxml.jackson.core.testsupport.MockDataInput;
import com.fasterxml.jackson.core.testsupport.ThrottledInputStream;
import com.fasterxml.jackson.core.testsupport.ThrottledReader;

import static org.junit.jupiter.api.Assertions.fail;

/**
* Intended replacement for {@link BaseTest}
*/
public class JUnit5TestBase
{
protected final static int MODE_INPUT_STREAM = 0;
protected final static int MODE_INPUT_STREAM_THROTTLED = 1;
protected final static int MODE_READER = 2;
protected final static int MODE_READER_THROTTLED = 3;
protected final static int MODE_DATA_INPUT = 4;

protected final static int[] ALL_MODES = new int[] {
MODE_INPUT_STREAM,
MODE_INPUT_STREAM_THROTTLED,
MODE_READER,
MODE_READER_THROTTLED,
MODE_DATA_INPUT
};

protected final static int[] ALL_BINARY_MODES = new int[] {
MODE_INPUT_STREAM,
MODE_INPUT_STREAM_THROTTLED,
MODE_DATA_INPUT
};

protected final static int[] ALL_TEXT_MODES = new int[] {
MODE_READER,
MODE_READER_THROTTLED
};

// DataInput not streaming
protected final static int[] ALL_STREAMING_MODES = new int[] {
MODE_INPUT_STREAM,
MODE_INPUT_STREAM_THROTTLED,
MODE_READER,
MODE_READER_THROTTLED
};

/*
/**********************************************************************
/* Factory methods
/**********************************************************************
*/

protected JsonFactory newStreamFactory() {
return new JsonFactory();
}

protected JsonFactoryBuilder streamFactoryBuilder() {
return (JsonFactoryBuilder) JsonFactory.builder();
}

protected JsonParser createParser(TokenStreamFactory f, int mode, String doc) throws IOException
{
switch (mode) {
case MODE_INPUT_STREAM:
return createParserUsingStream(f, doc, "UTF-8");
case MODE_INPUT_STREAM_THROTTLED:
return f.createParser(new ThrottledInputStream(utf8Bytes(doc), 1));
case MODE_READER:
return createParserUsingReader(f, doc);
case MODE_READER_THROTTLED:
return f.createParser(new ThrottledReader(doc, 1));
case MODE_DATA_INPUT:
return createParserForDataInput(f, new MockDataInput(doc));
default:
}
throw new RuntimeException("internal error");
}

protected JsonParser createParser(TokenStreamFactory f, int mode, byte[] doc) throws IOException
{
switch (mode) {
case MODE_INPUT_STREAM:
return f.createParser(new ByteArrayInputStream(doc));
case MODE_INPUT_STREAM_THROTTLED:
return f.createParser(new ThrottledInputStream(doc, 1));
case MODE_READER:
return f.createParser(new StringReader(new String(doc, "UTF-8")));
case MODE_READER_THROTTLED:
return f.createParser(new ThrottledReader(new String(doc, "UTF-8"), 1));
case MODE_DATA_INPUT:
return createParserForDataInput(f, new MockDataInput(doc));
default:
}
throw new RuntimeException("internal error");
}

protected JsonParser createParserUsingReader(TokenStreamFactory f, String input)
throws IOException
{
return f.createParser(new StringReader(input));
}

protected JsonParser createParserUsingStream(TokenStreamFactory f,
String input, String encoding)
throws IOException
{

/* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to
* use our own codec too (which is not optimal since there's
* a chance both encoder and decoder might have bugs, but ones
* that cancel each other out or such)
*/
byte[] data;
if (encoding.equalsIgnoreCase("UTF-32")) {
data = encodeInUTF32BE(input);
} else {
data = input.getBytes(encoding);
}
InputStream is = new ByteArrayInputStream(data);
return f.createParser(is);
}

protected JsonParser createParserForDataInput(TokenStreamFactory f,
DataInput input)
throws IOException
{
return f.createParser(input);
}

/*
/**********************************************************************
/* Assertions
/**********************************************************************
*/

protected void assertToken(JsonToken expToken, JsonToken actToken)
{
if (actToken != expToken) {
fail("Expected token "+expToken+", current token "+actToken);
}
}

protected void assertToken(JsonToken expToken, JsonParser p)
{
assertToken(expToken, p.currentToken());
}

/**
* @param e Exception to check
* @param anyMatches Array of Strings of which AT LEAST ONE ("any") has to be included
* in {@code e.getMessage()} -- using case-INSENSITIVE comparison
*/
public static void verifyException(Throwable e, String... anyMatches)
{
String msg = e.getMessage();
String lmsg = (msg == null) ? "" : msg.toLowerCase();
for (String match : anyMatches) {
String lmatch = match.toLowerCase();
if (lmsg.indexOf(lmatch) >= 0) {
return;
}
}
fail("Expected an exception with one of substrings ("+Arrays.asList(anyMatches)+"): got one with message \""+msg+"\"");
}

/*
/**********************************************************************
/* Escaping/quoting
/**********************************************************************
*/

protected String q(String str) {
return '"'+str+'"';
}

protected String a2q(String json) {
return json.replace("'", "\"");
}

protected byte[] utf8Bytes(String str) {
return str.getBytes(StandardCharsets.UTF_8);
}

protected String utf8String(ByteArrayOutputStream bytes) {
return new String(bytes.toByteArray(), StandardCharsets.UTF_8);
}

public static byte[] encodeInUTF32BE(String input)
{
int len = input.length();
byte[] result = new byte[len * 4];
int ptr = 0;
for (int i = 0; i < len; ++i, ptr += 4) {
char c = input.charAt(i);
result[ptr] = result[ptr+1] = (byte) 0;
result[ptr+2] = (byte) (c >> 8);
result[ptr+3] = (byte) c;
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,38 @@

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.core.*;

import static org.junit.jupiter.api.Assertions.*;

public class ParserErrorHandlingTest
extends com.fasterxml.jackson.core.BaseTest
extends JUnit5TestBase
{
private final JsonFactory JSON_F = newStreamFactory();

@Test
public void testInvalidKeywordsBytes() throws Exception {
_testInvalidKeywords(MODE_INPUT_STREAM);
_testInvalidKeywords(MODE_INPUT_STREAM_THROTTLED);
_testInvalidKeywords(MODE_DATA_INPUT);
}

@Test
public void testInvalidKeywordsChars() throws Exception {
_testInvalidKeywords(MODE_READER);
}

// Tests for [core#105] ("eager number parsing misses errors")
@Test
public void testMangledIntsBytes() throws Exception {
_testMangledNumbersInt(MODE_INPUT_STREAM);
_testMangledNumbersInt(MODE_INPUT_STREAM_THROTTLED);
_testMangledNumbersInt(MODE_DATA_INPUT);
}

@Test
public void testMangledFloatsBytes() throws Exception {
_testMangledNumbersFloat(MODE_INPUT_STREAM);
_testMangledNumbersFloat(MODE_INPUT_STREAM_THROTTLED);
Expand All @@ -34,6 +42,7 @@ public void testMangledFloatsBytes() throws Exception {
_testMangledNumbersFloat(MODE_DATA_INPUT);
}

@Test
public void testMangledNumbersChars() throws Exception {
_testMangledNumbersInt(MODE_READER);
_testMangledNumbersFloat(MODE_READER);
Expand Down Expand Up @@ -65,7 +74,7 @@ private void doTestInvalidKeyword1(int mode, String value)
throws IOException
{
String doc = "{ \"key1\" : "+value+" }";
JsonParser p = createParser(mode, doc);
JsonParser p = createParser(JSON_F, mode, doc);
assertToken(JsonToken.START_OBJECT, p.nextToken());
// Note that depending on parser impl, we may
// get the exception early or late...
Expand All @@ -82,7 +91,7 @@ private void doTestInvalidKeyword1(int mode, String value)

// Try as root-level value as well:
doc = value + " "; // may need space after for DataInput
p = createParser(mode, doc);
p = createParser(JSON_F, mode, doc);
try {
p.nextToken();
fail("Expected an exception for malformed value keyword");
Expand All @@ -96,7 +105,7 @@ private void doTestInvalidKeyword1(int mode, String value)

private void _testMangledNumbersInt(int mode) throws Exception
{
JsonParser p = createParser(mode, "123true");
JsonParser p = createParser(JSON_F, mode, "123true");
try {
JsonToken t = p.nextToken();
fail("Should have gotten an exception; instead got token: "+t);
Expand All @@ -109,7 +118,7 @@ private void _testMangledNumbersInt(int mode) throws Exception
private void _testMangledNumbersFloat(int mode) throws Exception
{
// Also test with floats
JsonParser p = createParser(mode, "1.5false");
JsonParser p = createParser(JSON_F, mode, "1.5false");
try {
JsonToken t = p.nextToken();
fail("Should have gotten an exception; instead got token: "+t);
Expand Down

0 comments on commit 7df89c4

Please sign in to comment.