|
20 | 20 |
|
21 | 21 | import io.netty.channel.Channel;
|
22 | 22 | import org.junit.jupiter.api.Test;
|
| 23 | +import org.junit.jupiter.api.TestInfo; |
23 | 24 | import org.junit.jupiter.api.extension.RegisterExtension;
|
24 | 25 |
|
25 | 26 | import java.io.IOException;
|
| 27 | +import java.lang.reflect.Method; |
26 | 28 | import java.net.URI;
|
| 29 | +import java.util.Arrays; |
27 | 30 | import java.util.List;
|
| 31 | +import java.util.Objects; |
28 | 32 | import java.util.UUID;
|
29 | 33 | import java.util.function.Consumer;
|
| 34 | +import java.util.stream.Stream; |
30 | 35 |
|
31 | 36 | import org.neo4j.driver.internal.cluster.RoutingSettings;
|
32 | 37 | import org.neo4j.driver.internal.messaging.response.FailureMessage;
|
|
46 | 51 | import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
|
47 | 52 | import org.neo4j.driver.v1.util.SessionExtension;
|
48 | 53 |
|
| 54 | +import static java.util.Arrays.asList; |
49 | 55 | import static java.util.concurrent.TimeUnit.SECONDS;
|
50 | 56 | import static org.hamcrest.CoreMatchers.equalTo;
|
51 | 57 | import static org.hamcrest.CoreMatchers.startsWith;
|
52 | 58 | import static org.hamcrest.Matchers.containsString;
|
| 59 | +import static org.hamcrest.Matchers.greaterThanOrEqualTo; |
| 60 | +import static org.hamcrest.Matchers.hasSize; |
53 | 61 | import static org.hamcrest.Matchers.instanceOf;
|
54 | 62 | import static org.hamcrest.junit.MatcherAssert.assertThat;
|
55 | 63 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
@@ -228,6 +236,20 @@ void shouldCloseChannelOnInboundFatalFailureMessage() throws InterruptedExceptio
|
228 | 236 | assertEquals( queryError.getMessage(), errorMessage );
|
229 | 237 | }
|
230 | 238 |
|
| 239 | + @Test |
| 240 | + void shouldThrowErrorWithNiceStackTrace( TestInfo testInfo ) |
| 241 | + { |
| 242 | + ClientException error = assertThrows( ClientException.class, () -> session.run( "RETURN 10 / 0" ).consume() ); |
| 243 | + |
| 244 | + // thrown error should have this class & method in the stacktrace |
| 245 | + StackTraceElement[] stackTrace = error.getStackTrace(); |
| 246 | + assertTrue( Stream.of( stackTrace ).anyMatch( element -> testClassAndMethodMatch( testInfo, element ) ), |
| 247 | + () -> "Expected stacktrace element is absent:\n" + Arrays.toString( stackTrace ) ); |
| 248 | + |
| 249 | + // thrown error should have a suppressed error with an async stacktrace |
| 250 | + assertThat( asList( error.getSuppressed() ), hasSize( greaterThanOrEqualTo( 1 ) ) ); |
| 251 | + } |
| 252 | + |
231 | 253 | private Throwable testChannelErrorHandling( Consumer<FailingMessageFormat> messageFormatSetup )
|
232 | 254 | throws InterruptedException
|
233 | 255 | {
|
@@ -276,4 +298,23 @@ private void assertNewQueryCanBeExecuted( Session session, ChannelTrackingDriver
|
276 | 298 | Channel lastChannel = channels.get( channels.size() - 1 );
|
277 | 299 | assertTrue( lastChannel.isActive() );
|
278 | 300 | }
|
| 301 | + |
| 302 | + private static boolean testClassAndMethodMatch( TestInfo testInfo, StackTraceElement element ) |
| 303 | + { |
| 304 | + return testClassMatches( testInfo, element ) && testMethodMatches( testInfo, element ); |
| 305 | + } |
| 306 | + |
| 307 | + private static boolean testClassMatches( TestInfo testInfo, StackTraceElement element ) |
| 308 | + { |
| 309 | + String expectedName = testInfo.getTestClass().map( Class::getName ).orElse( "" ); |
| 310 | + String actualName = element.getClassName(); |
| 311 | + return Objects.equals( expectedName, actualName ); |
| 312 | + } |
| 313 | + |
| 314 | + private static boolean testMethodMatches( TestInfo testInfo, StackTraceElement element ) |
| 315 | + { |
| 316 | + String expectedName = testInfo.getTestMethod().map( Method::getName ).orElse( "" ); |
| 317 | + String actualName = element.getMethodName(); |
| 318 | + return Objects.equals( expectedName, actualName ); |
| 319 | + } |
279 | 320 | }
|
0 commit comments