From 1be8abfbf9cf0bbee7ed7b312e8a0376dfaa98e4 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" <rien.korstanje@gmail.com> Date: Sat, 23 Mar 2024 18:08:01 +0100 Subject: [PATCH] java: include stacktrace in Convertor.toMessage(Throwable) --- CHANGELOG.md | 2 ++ java/pom.xml | 8 ++++++ .../java/io/cucumber/messages/Convertor.java | 25 +++++++++++++++++-- .../io/cucumber/messages/ConvertorTest.java | 22 +++++++++++++--- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e22dbcdfb..4119c665d 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 e09223e95..dc053f98e 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -87,6 +87,14 @@ </resource> </resources> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <configuration> + <propertiesEncoding>UTF-8</propertiesEncoding> + </configuration> + </plugin> + <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> diff --git a/java/src/main/java/io/cucumber/messages/Convertor.java b/java/src/main/java/io/cucumber/messages/Convertor.java index a16771385..4f995b716 100644 --- a/java/src/main/java/io/cucumber/messages/Convertor.java +++ b/java/src/main/java/io/cucumber/messages/Convertor.java @@ -4,29 +4,50 @@ import io.cucumber.messages.types.Exception; import io.cucumber.messages.types.Timestamp; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; + +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 f22e4bc78..b2fec86f9 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:")) ); }