Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#838 close body in RsPrint #879

Merged
merged 3 commits into from
Dec 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/main/java/org/takes/rs/RsPrint.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,9 @@ public void printHead(final Writer writer) throws IOException {
* @throws IOException If fails
*/
public void printBody(final OutputStream output) throws IOException {
final InputStream body = this.body();
//@checkstyle MagicNumberCheck (1 line)
final byte[] buf = new byte[4096];
try {
try (final InputStream body = this.body()) {
while (true) {
final int bytes = body.read(buf);
if (bytes < 0) {
Expand Down
77 changes: 77 additions & 0 deletions src/test/java/org/takes/rs/RsPrintTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,24 @@
package org.takes.rs;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import org.cactoos.io.InputStreamOf;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsEqual;
import org.junit.Test;

/**
* Test case for {@link RsPrint}.
* @author Yegor Bugayenko (yegor256@gmail.com)
* @version $Id$
* @since 0.8
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
*/
@SuppressWarnings("PMD.TooManyMethods")
public final class RsPrintTest {

/**
Expand Down Expand Up @@ -70,6 +75,30 @@ public void flushBodyEvenWhenExceptionHappens() throws IOException {
);
}

/**
* RsPrint can close body contents even when exception happens.
* @throws IOException If some problem inside
*/
@Test
public void closeBodyEvenWhenExceptionHappens() throws IOException {
final IOException exception = new IOException("Smth went wrong");
final FailOutputStream output = new FailOutputStream(exception);
final FakeInput input = new FakeInput(new InputStreamOf("abc"));
try {
new RsPrint(new RsText(input))
.printBody(output);
} catch (final IOException ex) {
if (!ex.equals(exception)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@olenagerasimova it's better to use assertions in tests instead of exception throwing:

MatcherAssert.assertThat("wrong exception", ex, new IsEquals(exception));

throw ex;
}
}
MatcherAssert.assertThat(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@olenagerasimova it's a good practice to add description text to assertThat if we have more than one assertions in test.

"Input body was not closed",
input.isClosed(),
new IsEqual<>(true)
);
}

/**
* RsPrint can flush head contents even when exception happens.
* @throws IOException If some problem inside
Expand Down Expand Up @@ -190,4 +219,52 @@ public boolean haveFlushed() {
return this.flushed;
}
}

/**
* Fake wrapper for InputStream to make sure body is closed.
*
* @author Alena Gerasimova (olena.gerasimova@gmail.com)
* @version $Id$
* @since 2.0
*/
private static final class FakeInput extends InputStream {

/**
* Have input been closed?
*/
private boolean closed;

/**
* Origin.
*/
private final InputStream origin;

/**
* Ctor.
* @param origin Origin input
*/
FakeInput(final InputStream origin) {
super();
this.origin = origin;
}

@Override
public int read() throws IOException {
return this.origin.read();
}

@Override
public void close() throws IOException {
this.origin.close();
this.closed = true;
}

/**
* Have input been closed?
* @return True, if input wes closed, false - otherwise
*/
public boolean isClosed() {
return this.closed;
}
}
}