diff --git a/CHANGELOG.md b/CHANGELOG.md index e22dbcdf..4119c665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- java: include stacktrace in Convertor.toMessage(Throwable) ([#213](https://github.com/cucumber/messages/pull/213)) ## [24.0.1] - 2023-12-21 ### Fixed diff --git a/java/pom.xml b/java/pom.xml index e09223e9..dc053f98 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -87,6 +87,14 @@ + + org.apache.maven.plugins + maven-resources-plugin + + UTF-8 + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/java/src/main/java/io/cucumber/messages/Convertor.java b/java/src/main/java/io/cucumber/messages/Convertor.java index a1677138..fcff908f 100644 --- a/java/src/main/java/io/cucumber/messages/Convertor.java +++ b/java/src/main/java/io/cucumber/messages/Convertor.java @@ -4,29 +4,47 @@ import io.cucumber.messages.types.Exception; import io.cucumber.messages.types.Timestamp; +import java.io.PrintWriter; +import java.io.StringWriter; + +import static java.util.Objects.requireNonNull; + public final class Convertor { private Convertor(){ } - public static Exception toMessage(Throwable t) { - return new Exception(t.getClass().getName(), t.getMessage(), null); + public static Exception toMessage(Throwable throwable) { + requireNonNull(throwable, "throwable may not be null"); + return new Exception(throwable.getClass().getName(), throwable.getMessage(), extractStackTrace(throwable)); + } + + private static String extractStackTrace(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + try (PrintWriter printWriter = new PrintWriter(stringWriter)) { + throwable.printStackTrace(printWriter); + } + return stringWriter.toString(); } public static Timestamp toMessage(java.time.Instant instant) { + requireNonNull(instant, "instant may not be null"); return new Timestamp(instant.getEpochSecond(), (long) instant.getNano()); } public static Duration toMessage(java.time.Duration duration) { + requireNonNull(duration, "duration may not be null"); return new Duration(duration.getSeconds(), (long) duration.getNano()); } public static java.time.Instant toInstant(Timestamp timestamp) { + requireNonNull(timestamp, "timestamp may not be null"); return java.time.Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); } public static java.time.Duration toDuration(Duration duration) { + requireNonNull(duration, "duration may not be null"); return java.time.Duration.ofSeconds(duration.getSeconds(), duration.getNanos()); } diff --git a/java/src/test/java/io/cucumber/messages/ConvertorTest.java b/java/src/test/java/io/cucumber/messages/ConvertorTest.java index f22e4bc7..b2fec86f 100644 --- a/java/src/test/java/io/cucumber/messages/ConvertorTest.java +++ b/java/src/test/java/io/cucumber/messages/ConvertorTest.java @@ -3,10 +3,14 @@ import io.cucumber.messages.types.Duration; import io.cucumber.messages.types.Exception; import io.cucumber.messages.types.Timestamp; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Test; import java.util.Optional; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,13 +18,25 @@ class ConvertorTest { @Test void convertsExceptionToMessage() { + Exception e = Convertor.toMessage(new RuntimeException()); + assertAll( + () -> assertEquals(Optional.empty(), e.getMessage()), + () -> assertEquals("java.lang.RuntimeException", e.getType()), + () -> assertThat(e.getStackTrace().get(), startsWith("" + + "java.lang.RuntimeException\n" + + "\tat io.cucumber.messages.ConvertorTest.convertsExceptionToMessage(ConvertorTest.java:")) + ); + } + + @Test + void convertsExceptionWithMessageToMessage() { Exception e = Convertor.toMessage(new RuntimeException("Hello world!")); - Exception e2 = Convertor.toMessage(new RuntimeException()); assertAll( () -> assertEquals(Optional.of("Hello world!"), e.getMessage()), - () -> assertEquals(Optional.empty(), e2.getMessage()), () -> assertEquals("java.lang.RuntimeException", e.getType()), - () -> assertEquals("java.lang.RuntimeException", e2.getType()) + () -> assertThat(e.getStackTrace().get(), startsWith("" + + "java.lang.RuntimeException: Hello world!\n" + + "\tat io.cucumber.messages.ConvertorTest.convertsExceptionWithMessageToMessage(ConvertorTest.java:")) ); }