FailedGeneratorConstructionCloseTest.java
package tools.jackson.core.unittest.json;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import tools.jackson.core.*;
import tools.jackson.core.io.IOContext;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.unittest.JacksonCoreTestBase;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests to verify that streams Jackson itself opens for {@link File} /
* {@link java.nio.file.Path} targets get closed if construction of generator
* fails after opening.
*/
class FailedGeneratorConstructionCloseTest extends JacksonCoreTestBase
{
static class CloseTrackingOutputStream extends FilterOutputStream {
public boolean closed;
CloseTrackingOutputStream(OutputStream out) { super(out); }
@Override
public void close() throws IOException {
closed = true;
super.close();
}
}
/**
* Factory that fails the way format backends can (say, when schema
* validation fails), that is, after source/target has been opened.
*/
static class FailingFactory extends JsonFactory {
private static final long serialVersionUID = 1L;
public final List<CloseTrackingOutputStream> outputs = new ArrayList<>();
@Override
protected OutputStream _fileOutputStream(File f) throws JacksonException {
CloseTrackingOutputStream out = new CloseTrackingOutputStream(super._fileOutputStream(f));
outputs.add(out);
return out;
}
@Override
protected JsonGenerator _createGenerator(ObjectWriteContext writeCtxt,
IOContext ioCtxt, Writer out) throws JacksonException {
throw new IllegalStateException("Test-induced construction failure");
}
@Override
protected JsonGenerator _createUTF8Generator(ObjectWriteContext writeCtxt,
IOContext ioCtxt, OutputStream out) throws JacksonException {
throw new IllegalStateException("Test-induced construction failure");
}
}
private File _tempFile() throws IOException {
File f = File.createTempFile("jackson-core-test", ".json");
f.deleteOnExit();
Files.write(f.toPath(), utf8Bytes("{\"a\":1}"));
return f;
}
@Test
void closesFileOutputStreamOnFailedGeneratorConstruction() throws Exception
{
for (JsonEncoding enc : new JsonEncoding[] { JsonEncoding.UTF8, JsonEncoding.UTF16_BE }) {
FailingFactory f = new FailingFactory();
File dst = _tempFile();
assertThrows(IllegalStateException.class,
() -> f.createGenerator(ObjectWriteContext.empty(), dst, enc));
assertEquals(1, f.outputs.size(), enc.toString());
assertTrue(f.outputs.get(0).closed,
"OutputStream Jackson opened should have been closed, encoding "+enc);
}
}
}