| package org.apache.maven.plugin.surefire.extensions; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.maven.plugin.surefire.booterclient.output.DeserializedStacktraceWriter; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessEventListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessEventNotifier; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessExitErrorListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessPropertyEventListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessReportEventListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessStackTraceEventListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessStandardOutErrEventListener; |
| import org.apache.maven.plugin.surefire.booterclient.output.ForkedProcessStringEventListener; |
| import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; |
| import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerUtils; |
| import org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelEncoder; |
| import org.apache.maven.surefire.api.event.Event; |
| import org.apache.maven.surefire.extensions.EventHandler; |
| import org.apache.maven.surefire.extensions.ForkNodeArguments; |
| import org.apache.maven.surefire.extensions.util.CountdownCloseable; |
| import org.apache.maven.surefire.api.report.ReportEntry; |
| import org.apache.maven.surefire.api.report.RunMode; |
| import org.apache.maven.surefire.api.report.SafeThrowable; |
| import org.apache.maven.surefire.api.report.StackTraceWriter; |
| import org.apache.maven.surefire.api.util.internal.ObjectUtils; |
| import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.experimental.runners.Enclosed; |
| import org.junit.experimental.theories.DataPoints; |
| import org.junit.experimental.theories.FromDataPoints; |
| import org.junit.experimental.theories.Theories; |
| import org.junit.experimental.theories.Theory; |
| import org.junit.rules.ExpectedException; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.powermock.core.classloader.annotations.PowerMockIgnore; |
| import org.powermock.modules.junit4.PowerMockRunner; |
| |
| import javax.annotation.Nonnull; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.Closeable; |
| import java.io.File; |
| import java.io.LineNumberReader; |
| import java.io.PrintStream; |
| import java.io.StringReader; |
| import java.nio.ByteBuffer; |
| import java.nio.channels.ReadableByteChannel; |
| import java.nio.charset.Charset; |
| import java.util.Map; |
| import java.util.concurrent.BlockingQueue; |
| import java.util.concurrent.LinkedTransferQueue; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import static java.lang.String.format; |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| import static java.util.Arrays.copyOfRange; |
| import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN; |
| import static org.apache.maven.surefire.shared.codec.binary.Base64.encodeBase64String; |
| import static org.apache.maven.surefire.api.util.internal.Channels.newBufferedChannel; |
| import static org.apache.maven.surefire.api.util.internal.Channels.newChannel; |
| import static org.fest.assertions.Assertions.assertThat; |
| import static org.fest.assertions.Index.atIndex; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.rules.ExpectedException.none; |
| import static org.mockito.ArgumentMatchers.anyString; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| /** |
| * Test for {@link ForkedProcessEventNotifier}. |
| * |
| * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a> |
| * @since 3.0.0-M4 |
| */ |
| @RunWith( Enclosed.class ) |
| public class ForkedProcessEventNotifierTest |
| { |
| /** |
| * |
| */ |
| @RunWith( PowerMockRunner.class ) |
| @PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) |
| public static class DecoderOperationsTest |
| { |
| @Rule |
| public final ExpectedException rule = none(); |
| |
| @Test |
| public void shouldBeFailSafe() |
| { |
| assertThat( EventConsumerThread.decode( null, UTF_8 ) ).isNull(); |
| assertThat( EventConsumerThread.decode( "-", UTF_8 ) ).isNull(); |
| assertThat( EventConsumerThread.decodeToInteger( null ) ).isNull(); |
| assertThat( EventConsumerThread.decodeToInteger( "-" ) ).isNull(); |
| } |
| |
| @Test |
| public void shouldHaveSystemProperty() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| Map<String, String> props = ObjectUtils.systemProps(); |
| encoder.sendSystemProperties( props ); |
| wChannel.close(); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| PropertyEventAssertionListener listener = new PropertyEventAssertionListener(); |
| notifier.setSystemPropertiesListener( listener ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| for ( int i = 0; i < props.size(); i++ ) |
| { |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| } |
| |
| assertThat( listener.counter.get() ) |
| .isEqualTo( props.size() ); |
| } |
| |
| @Test |
| public void shouldRecognizeEmptyStream4ReportEntry() |
| { |
| ReportEntry reportEntry = EventConsumerThread.decodeReportEntry( null, null, null, "", "", null, null, "", |
| "", "", null ); |
| assertThat( reportEntry ).isNull(); |
| |
| reportEntry = EventConsumerThread.decodeReportEntry( UTF_8, "", "", "", "", "", "", "-", "", "", "" ); |
| assertThat( reportEntry ).isNotNull(); |
| assertThat( reportEntry.getStackTraceWriter() ).isNotNull(); |
| assertThat( reportEntry.getStackTraceWriter().smartTrimmedStackTrace() ).isEmpty(); |
| assertThat( reportEntry.getStackTraceWriter().writeTraceToString() ).isEmpty(); |
| assertThat( reportEntry.getStackTraceWriter().writeTrimmedTraceToString() ).isEmpty(); |
| assertThat( reportEntry.getSourceName() ).isEmpty(); |
| assertThat( reportEntry.getSourceText() ).isEmpty(); |
| assertThat( reportEntry.getName() ).isEmpty(); |
| assertThat( reportEntry.getNameText() ).isEmpty(); |
| assertThat( reportEntry.getGroup() ).isEmpty(); |
| assertThat( reportEntry.getNameWithGroup() ).isEmpty(); |
| assertThat( reportEntry.getMessage() ).isEmpty(); |
| assertThat( reportEntry.getElapsed() ).isNull(); |
| |
| rule.expect( NumberFormatException.class ); |
| EventConsumerThread.decodeReportEntry( UTF_8, "", "", "", "", "", "", "", "", "", "" ); |
| } |
| |
| @Test |
| @SuppressWarnings( "checkstyle:magicnumber" ) |
| public void testCreatingReportEntry() |
| { |
| final String exceptionMessage = "msg"; |
| final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); |
| |
| final String smartStackTrace = "MyTest:86 >> Error"; |
| final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); |
| |
| final String stackTrace = "Exception: msg\ntrace line 1\ntrace line 2"; |
| final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); |
| |
| final String trimmedStackTrace = "trace line 1\ntrace line 2"; |
| final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); |
| |
| SafeThrowable safeThrowable = new SafeThrowable( exceptionMessage ); |
| StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); |
| when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); |
| when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); |
| when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); |
| when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); |
| |
| ReportEntry reportEntry = mock( ReportEntry.class ); |
| when( reportEntry.getElapsed() ).thenReturn( 102 ); |
| when( reportEntry.getGroup() ).thenReturn( "this group" ); |
| when( reportEntry.getMessage() ).thenReturn( "skipped test" ); |
| when( reportEntry.getName() ).thenReturn( "my test" ); |
| when( reportEntry.getNameText() ).thenReturn( "my display name" ); |
| when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); |
| when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); |
| when( reportEntry.getSourceText() ).thenReturn( "test class display name" ); |
| when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); |
| |
| String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); |
| String encodedSourceText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceText() ) ) ); |
| String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); |
| String encodedText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getNameText() ) ) ); |
| String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); |
| String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); |
| |
| ReportEntry decodedReportEntry = EventConsumerThread.decodeReportEntry( UTF_8, encodedSourceName, |
| encodedSourceText, encodedName, encodedText, encodedGroup, encodedMessage, "-", null, null, null ); |
| |
| assertThat( decodedReportEntry ).isNotNull(); |
| assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); |
| assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); |
| assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); |
| assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); |
| assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); |
| assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); |
| assertThat( decodedReportEntry.getStackTraceWriter() ).isNull(); |
| |
| decodedReportEntry = EventConsumerThread.decodeReportEntry( UTF_8, encodedSourceName, encodedSourceText, |
| encodedName, encodedText, encodedGroup, encodedMessage, "-", encodedExceptionMsg, |
| encodedSmartStackTrace, null ); |
| |
| assertThat( decodedReportEntry ).isNotNull(); |
| assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); |
| assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); |
| assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); |
| assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); |
| assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); |
| assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); |
| assertThat( decodedReportEntry.getElapsed() ).isNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) |
| .isEqualTo( exceptionMessage ); |
| assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) |
| .isEqualTo( smartStackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ) |
| .isNull(); |
| |
| decodedReportEntry = EventConsumerThread.decodeReportEntry( UTF_8, encodedSourceName, encodedSourceText, |
| encodedName, encodedText, encodedGroup, encodedMessage, "1003", encodedExceptionMsg, |
| encodedSmartStackTrace, null ); |
| |
| assertThat( decodedReportEntry ).isNotNull(); |
| assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); |
| assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); |
| assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); |
| assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); |
| assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); |
| assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); |
| assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); |
| assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) |
| .isEqualTo( exceptionMessage ); |
| assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) |
| .isEqualTo( smartStackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ) |
| .isNull(); |
| |
| decodedReportEntry = EventConsumerThread.decodeReportEntry( UTF_8, encodedSourceName, encodedSourceText, |
| encodedName, encodedText, encodedGroup, encodedMessage, "1003", encodedExceptionMsg, |
| encodedSmartStackTrace, encodedStackTrace ); |
| |
| assertThat( decodedReportEntry ).isNotNull(); |
| assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); |
| assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); |
| assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); |
| assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); |
| assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); |
| assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); |
| assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); |
| assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) |
| .isEqualTo( exceptionMessage ); |
| assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) |
| .isEqualTo( smartStackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ).isEqualTo( stackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTrimmedTraceToString() ).isEqualTo( stackTrace ); |
| |
| decodedReportEntry = EventConsumerThread.decodeReportEntry( UTF_8, encodedSourceName, encodedSourceText, |
| encodedName, encodedText, encodedGroup, encodedMessage, "1003", encodedExceptionMsg, |
| encodedSmartStackTrace, encodedTrimmedStackTrace ); |
| |
| assertThat( decodedReportEntry ).isNotNull(); |
| assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); |
| assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); |
| assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); |
| assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); |
| assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); |
| assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); |
| assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); |
| assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ).isNotNull(); |
| assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) |
| .isEqualTo( exceptionMessage ); |
| assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) |
| .isEqualTo( smartStackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ).isEqualTo( trimmedStackTrace ); |
| assertThat( decodedReportEntry.getStackTraceWriter().writeTrimmedTraceToString() ) |
| .isEqualTo( trimmedStackTrace ); |
| } |
| |
| @Test |
| public void shouldSendByeEvent() throws Exception |
| { |
| Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.bye(); |
| String read = new String( out.toByteArray(), UTF_8 ); |
| |
| assertThat( read ) |
| .isEqualTo( ":maven-surefire-event:bye:\n" ); |
| |
| LineNumberReader lines = out.newReader( UTF_8 ); |
| |
| final String cmd = lines.readLine(); |
| assertThat( cmd ) |
| .isNotNull(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| EventAssertionListener listener = new EventAssertionListener(); |
| notifier.setByeListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void shouldSendStopOnNextTestEvent() throws Exception |
| { |
| Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.stopOnNextTest(); |
| String read = new String( out.toByteArray(), UTF_8 ); |
| |
| assertThat( read ) |
| .isEqualTo( ":maven-surefire-event:stop-on-next-test:\n" ); |
| |
| LineNumberReader lines = out.newReader( UTF_8 ); |
| |
| final String cmd = lines.readLine(); |
| assertThat( cmd ) |
| .isNotNull(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| EventAssertionListener listener = new EventAssertionListener(); |
| notifier.setStopOnNextTestListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void shouldCorrectlyDecodeStackTracesWithEmptyStringTraceMessages() throws Exception |
| { |
| String exceptionMessage = ""; |
| String smartStackTrace = "JUnit5Test.failWithEmptyString:16"; |
| String exceptionStackTrace = "org.opentest4j.AssertionFailedError: \n" |
| + "\tat JUnit5Test.failWithEmptyString(JUnit5Test.java:16)\n"; |
| |
| StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); |
| SafeThrowable safeThrowable = new SafeThrowable( exceptionMessage ); |
| when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); |
| when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); |
| when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( exceptionStackTrace ); |
| when( stackTraceWriter.writeTraceToString() ).thenReturn( exceptionStackTrace ); |
| |
| ReportEntry reportEntry = mock( ReportEntry.class ); |
| when( reportEntry.getElapsed() ).thenReturn( 7 ); |
| when( reportEntry.getGroup() ).thenReturn( null ); |
| when( reportEntry.getMessage() ).thenReturn( null ); |
| when( reportEntry.getName() ).thenReturn( "failWithEmptyString" ); |
| when( reportEntry.getNameWithGroup() ).thenReturn( "JUnit5Test" ); |
| when( reportEntry.getSourceName() ).thenReturn( "JUnit5Test" ); |
| when( reportEntry.getSourceText() ).thenReturn( null ); |
| when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); |
| |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.testFailed( reportEntry, true ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| final ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| ReportEventAssertionListener listener = new ReportEventAssertionListener( reportEntry, true ); |
| notifier.setTestFailedListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void shouldSendNextTestEvent() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.acquireNextTest(); |
| String read = new String( out.toByteArray(), UTF_8 ); |
| |
| assertThat( read ) |
| .isEqualTo( ":maven-surefire-event:next-test:\n" ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| EventAssertionListener listener = new EventAssertionListener(); |
| notifier.setAcquireNextTestListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testConsole() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.consoleInfoLog( "msg" ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StringEventAssertionListener listener = new StringEventAssertionListener( "msg" ); |
| notifier.setConsoleInfoListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testError() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.consoleErrorLog( "msg" ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StackTraceEventListener listener = new StackTraceEventListener( "msg", null, null ); |
| notifier.setConsoleErrorListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testErrorWithException() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| Throwable throwable = new Throwable( "msg" ); |
| encoder.consoleErrorLog( throwable ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| String stackTrace = ConsoleLoggerUtils.toString( throwable ); |
| StackTraceEventListener listener = new StackTraceEventListener( "msg", null, stackTrace ); |
| notifier.setConsoleErrorListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testErrorWithStackTraceWriter() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "1", "2", "3" ); |
| encoder.consoleErrorLog( stackTraceWriter, false ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StackTraceEventListener listener = new StackTraceEventListener( "1", "2", "3" ); |
| notifier.setConsoleErrorListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testDebug() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.consoleDebugLog( "msg" ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StringEventAssertionListener listener = new StringEventAssertionListener( "msg" ); |
| notifier.setConsoleDebugListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| |
| assertThat( listener.msg ) |
| .isEqualTo( "msg" ); |
| } |
| |
| @Test |
| public void testWarning() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| encoder.consoleWarningLog( "msg" ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StringEventAssertionListener listener = new StringEventAssertionListener( "msg" ); |
| notifier.setConsoleWarningListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdOutStream() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdOut( "msg", false ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, "msg", false ); |
| notifier.setStdOutListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdOutStreamPrint() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdOut( "", false ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, "", false ); |
| notifier.setStdOutListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdOutStreamPrintWithNull() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdOut( null, false ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, null, false ); |
| notifier.setStdOutListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdOutStreamPrintln() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdOut( "", true ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, "", true ); |
| notifier.setStdOutListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdOutStreamPrintlnWithNull() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdOut( null, true ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, null, true ); |
| notifier.setStdOutListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void testStdErrStream() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.stdErr( "msg", false ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| StandardOutErrEventAssertionListener listener = |
| new StandardOutErrEventAssertionListener( NORMAL_RUN, "msg", false ); |
| notifier.setStdErrListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void shouldCountSameNumberOfSystemProperties() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| WritableBufferedByteChannel wChannel = newBufferedChannel( out ); |
| LegacyMasterProcessChannelEncoder encoder = new LegacyMasterProcessChannelEncoder( wChannel ); |
| encoder.sendSystemProperties( ObjectUtils.systemProps() ); |
| wChannel.close(); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| PropertyEventAssertionListener listener = new PropertyEventAssertionListener(); |
| notifier.setSystemPropertiesListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| |
| @Test |
| public void shouldHandleErrorAfterNullLine() |
| { |
| ForkedProcessEventNotifier decoder = new ForkedProcessEventNotifier(); |
| decoder.setSystemPropertiesListener( new PropertyEventAssertionListener() ); |
| rule.expect( NullPointerException.class ); |
| decoder.notifyEvent( null ); |
| } |
| |
| @Test |
| public void shouldHandleErrorAfterUnknownOperation() throws Exception |
| { |
| String cmd = ":maven-surefire-event:abnormal-run:-:\n"; |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( cmd.getBytes() ) ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 1 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| when( logger.isDebugEnabled() ).thenReturn( true ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.dumpStreamText( anyString() ) ).thenReturn( new File( "" ) ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| countdown.awaitClosed(); |
| } |
| |
| ArgumentCaptor<String> dumpLine = ArgumentCaptor.forClass( String.class ); |
| verify( logger, times( 2 ) ).debug( dumpLine.capture() ); |
| assertThat( dumpLine.getAllValues() ) |
| .hasSize( 2 ) |
| .contains( ":maven-surefire-event:abnormal-run:", atIndex( 0 ) ) |
| .contains( "-:", atIndex( 1 ) ); |
| |
| ArgumentCaptor<String> dumpText = ArgumentCaptor.forClass( String.class ); |
| verify( arguments, times( 2 ) ).dumpStreamText( dumpText.capture() ); |
| String dump = "Corrupted STDOUT by directly writing to native stream in forked JVM 0."; |
| assertThat( dumpText.getAllValues() ) |
| .hasSize( 2 ) |
| .contains( format( dump + " Stream '%s'.", ":maven-surefire-event:abnormal-run:" ), atIndex( 0 ) ) |
| .contains( format( dump + " Stream '%s'.", "-:" ), atIndex( 1 ) ); |
| |
| ArgumentCaptor<String> warning = ArgumentCaptor.forClass( String.class ); |
| verify( arguments, times( 2 ) ).logWarningAtEnd( warning.capture() ); |
| dump += " See FAQ web page and the dump file "; |
| assertThat( warning.getAllValues() ) |
| .hasSize( 2 ); |
| assertThat( warning.getAllValues().get( 0 ) ) |
| .startsWith( dump ); |
| assertThat( warning.getAllValues().get( 1 ) ) |
| .startsWith( dump ); |
| } |
| |
| @Test |
| public void shouldHandleExit() throws Exception |
| { |
| final Stream out = Stream.newStream(); |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| |
| StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); |
| when( stackTraceWriter.getThrowable() ).thenReturn( new SafeThrowable( "1" ) ); |
| when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "2" ); |
| when( stackTraceWriter.writeTraceToString() ).thenReturn( "3" ); |
| when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( "4" ); |
| encoder.sendExitError( stackTraceWriter, false ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| ProcessExitErrorListener listener = new ProcessExitErrorListener(); |
| notifier.setExitErrorEventListener( listener ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| |
| assertThat( listener.called.get() ) |
| .isTrue(); |
| } |
| } |
| |
| /** |
| * |
| */ |
| @RunWith( Theories.class ) |
| public static class ReportEntryTest |
| { |
| @DataPoints( value = "operation" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static String[][] operations = { { "testSetStarting", "setTestSetStartingListener" }, |
| { "testSetCompleted", "setTestSetCompletedListener" }, |
| { "testStarting", "setTestStartingListener" }, |
| { "testSucceeded", "setTestSucceededListener" }, |
| { "testFailed", "setTestFailedListener" }, |
| { "testSkipped", "setTestSkippedListener" }, |
| { "testError", "setTestErrorListener" }, |
| { "testAssumptionFailure", "setTestAssumptionFailureListener" } |
| }; |
| |
| @DataPoints( value = "reportedMessage" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static String[] reportedMessage = { null, "skipped test" }; |
| |
| @DataPoints( value = "elapsed" ) |
| @SuppressWarnings( { "checkstyle:visibilitymodifier", "checkstyle:magicnumber" } ) |
| public static Integer[] elapsed = { null, 102 }; |
| |
| @DataPoints( value = "trim" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static boolean[] trim = { false, true }; |
| |
| @DataPoints( value = "msg" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static boolean[] msg = { false, true }; |
| |
| @DataPoints( value = "smart" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static boolean[] smart = { false, true }; |
| |
| @DataPoints( value = "trace" ) |
| @SuppressWarnings( "checkstyle:visibilitymodifier" ) |
| public static boolean[] trace = { false, true }; |
| |
| @Theory |
| public void testReportEntryOperations( @FromDataPoints( "operation" ) String[] operation, |
| @FromDataPoints( "reportedMessage" ) String reportedMessage, |
| @FromDataPoints( "elapsed" ) Integer elapsed, |
| @FromDataPoints( "trim" ) boolean trim, |
| @FromDataPoints( "msg" ) boolean msg, |
| @FromDataPoints( "smart" ) boolean smart, |
| @FromDataPoints( "trace" ) boolean trace ) |
| throws Exception |
| { |
| String exceptionMessage = msg ? "msg" : null; |
| String smartStackTrace = smart ? "MyTest:86 >> Error" : null; |
| String exceptionStackTrace = |
| trace ? ( trim ? "trace line 1\ntrace line 2" : "Exception: msg\ntrace line 1\ntrace line 2" ) |
| : null; |
| |
| StackTraceWriter stackTraceWriter = null; |
| if ( exceptionStackTrace != null ) |
| { |
| SafeThrowable safeThrowable = new SafeThrowable( exceptionMessage ); |
| stackTraceWriter = mock( StackTraceWriter.class ); |
| when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); |
| when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); |
| when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( exceptionStackTrace ); |
| when( stackTraceWriter.writeTraceToString() ).thenReturn( exceptionStackTrace ); |
| } |
| |
| ReportEntry reportEntry = mock( ReportEntry.class ); |
| when( reportEntry.getElapsed() ).thenReturn( elapsed ); |
| when( reportEntry.getGroup() ).thenReturn( "this group" ); |
| when( reportEntry.getMessage() ).thenReturn( reportedMessage ); |
| when( reportEntry.getName() ).thenReturn( "my test" ); |
| when( reportEntry.getName() ).thenReturn( "display name of test" ); |
| when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); |
| when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); |
| when( reportEntry.getSourceText() ).thenReturn( "test class display name" ); |
| when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); |
| |
| final Stream out = Stream.newStream(); |
| |
| LegacyMasterProcessChannelEncoder encoder = |
| new LegacyMasterProcessChannelEncoder( newBufferedChannel( out ) ); |
| |
| LegacyMasterProcessChannelEncoder.class.getMethod( operation[0], ReportEntry.class, boolean.class ) |
| .invoke( encoder, reportEntry, trim ); |
| |
| ForkedProcessEventNotifier notifier = new ForkedProcessEventNotifier(); |
| |
| ForkedProcessEventNotifier.class.getMethod( operation[1], ForkedProcessReportEventListener.class ) |
| .invoke( notifier, new ReportEventAssertionListener( reportEntry, stackTraceWriter != null ) ); |
| |
| ReadableByteChannel channel = newChannel( new ByteArrayInputStream( out.toByteArray() ) ); |
| |
| EH eventHandler = new EH(); |
| CountdownCloseable countdown = new CountdownCloseable( mock( Closeable.class ), 0 ); |
| ConsoleLogger logger = mock( ConsoleLogger.class ); |
| ForkNodeArguments arguments = mock( ForkNodeArguments.class ); |
| when( arguments.getConsoleLogger() ).thenReturn( logger ); |
| try ( EventConsumerThread t = new EventConsumerThread( "t", channel, eventHandler, countdown, arguments ) ) |
| { |
| t.start(); |
| notifier.notifyEvent( eventHandler.pullEvent() ); |
| } |
| } |
| } |
| |
| private static class ProcessExitErrorListener implements ForkedProcessExitErrorListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| |
| @Override |
| public void handle( StackTraceWriter stackTrace ) |
| { |
| called.set( true ); |
| assertThat( stackTrace.getThrowable().getMessage() ).isEqualTo( "1" ); |
| assertThat( stackTrace.smartTrimmedStackTrace() ).isEqualTo( "2" ); |
| assertThat( stackTrace.writeTraceToString() ).isEqualTo( "3" ); |
| } |
| } |
| |
| private static class PropertyEventAssertionListener implements ForkedProcessPropertyEventListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| private final Map<?, ?> sysProps = System.getProperties(); |
| private final AtomicInteger counter = new AtomicInteger(); |
| |
| public void handle( RunMode runMode, String key, String value ) |
| { |
| called.set( true ); |
| counter.incrementAndGet(); |
| assertThat( runMode ).isEqualTo( NORMAL_RUN ); |
| assertTrue( sysProps.containsKey( key ) ); |
| assertThat( sysProps.get( key ) ).isEqualTo( value ); |
| } |
| } |
| |
| private static class EventAssertionListener implements ForkedProcessEventListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| |
| public void handle() |
| { |
| called.set( true ); |
| } |
| } |
| |
| private static class StringEventAssertionListener implements ForkedProcessStringEventListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| private final String msg; |
| |
| StringEventAssertionListener( String msg ) |
| { |
| this.msg = msg; |
| } |
| |
| public void handle( String msg ) |
| { |
| called.set( true ); |
| assertThat( msg ) |
| .isEqualTo( this.msg ); |
| } |
| } |
| |
| private static class StackTraceEventListener implements ForkedProcessStackTraceEventListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| private final String msg; |
| private final String smartStackTrace; |
| private final String stackTrace; |
| |
| StackTraceEventListener( String msg, String smartStackTrace, String stackTrace ) |
| { |
| this.msg = msg; |
| this.smartStackTrace = smartStackTrace; |
| this.stackTrace = stackTrace; |
| } |
| |
| @Override |
| public void handle( @Nonnull StackTraceWriter stackTrace ) |
| { |
| called.set( true ); |
| |
| assertThat( stackTrace.getThrowable().getMessage() ) |
| .isEqualTo( msg ); |
| |
| assertThat( stackTrace.smartTrimmedStackTrace() ) |
| .isEqualTo( smartStackTrace ); |
| |
| assertThat( stackTrace.writeTraceToString() ) |
| .isEqualTo( this.stackTrace ); |
| } |
| } |
| |
| private static class StandardOutErrEventAssertionListener implements ForkedProcessStandardOutErrEventListener |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| private final RunMode runMode; |
| private final String output; |
| private final boolean newLine; |
| |
| StandardOutErrEventAssertionListener( RunMode runMode, String output, boolean newLine ) |
| { |
| this.runMode = runMode; |
| this.output = output; |
| this.newLine = newLine; |
| } |
| |
| public void handle( RunMode runMode, String output, boolean newLine ) |
| { |
| called.set( true ); |
| |
| assertThat( runMode ) |
| .isEqualTo( this.runMode ); |
| |
| assertThat( output ) |
| .isEqualTo( this.output ); |
| |
| assertThat( newLine ) |
| .isEqualTo( this.newLine ); |
| } |
| } |
| |
| private static class ReportEventAssertionListener implements ForkedProcessReportEventListener<ReportEntry> |
| { |
| final AtomicBoolean called = new AtomicBoolean(); |
| private final ReportEntry reportEntry; |
| private final boolean hasStackTrace; |
| |
| ReportEventAssertionListener( ReportEntry reportEntry, boolean hasStackTrace ) |
| { |
| this.reportEntry = reportEntry; |
| this.hasStackTrace = hasStackTrace; |
| } |
| |
| public void handle( RunMode runMode, ReportEntry reportEntry ) |
| { |
| called.set( true ); |
| assertThat( reportEntry.getSourceName() ).isEqualTo( this.reportEntry.getSourceName() ); |
| assertThat( reportEntry.getSourceText() ).isEqualTo( this.reportEntry.getSourceText() ); |
| assertThat( reportEntry.getName() ).isEqualTo( this.reportEntry.getName() ); |
| assertThat( reportEntry.getNameText() ).isEqualTo( this.reportEntry.getNameText() ); |
| assertThat( reportEntry.getGroup() ).isEqualTo( this.reportEntry.getGroup() ); |
| assertThat( reportEntry.getMessage() ).isEqualTo( this.reportEntry.getMessage() ); |
| assertThat( reportEntry.getElapsed() ).isEqualTo( this.reportEntry.getElapsed() ); |
| if ( reportEntry.getStackTraceWriter() == null ) |
| { |
| assertThat( hasStackTrace ).isFalse(); |
| assertThat( this.reportEntry.getStackTraceWriter() ).isNull(); |
| } |
| else |
| { |
| assertThat( hasStackTrace ).isTrue(); |
| assertThat( this.reportEntry.getStackTraceWriter() ).isNotNull(); |
| |
| assertThat( reportEntry.getStackTraceWriter().getThrowable().getMessage() ) |
| .isEqualTo( this.reportEntry.getStackTraceWriter().getThrowable().getMessage() ); |
| |
| assertThat( reportEntry.getStackTraceWriter().getThrowable().getLocalizedMessage() ) |
| .isEqualTo( this.reportEntry.getStackTraceWriter().getThrowable().getLocalizedMessage() ); |
| |
| assertThat( reportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) |
| .isEqualTo( this.reportEntry.getStackTraceWriter().smartTrimmedStackTrace() ); |
| } |
| } |
| } |
| |
| private static class Stream extends PrintStream |
| { |
| private final ByteArrayOutputStream out; |
| |
| Stream( ByteArrayOutputStream out ) |
| { |
| super( out, true ); |
| this.out = out; |
| } |
| |
| byte[] toByteArray() |
| { |
| return out.toByteArray(); |
| } |
| |
| LineNumberReader newReader( Charset streamCharset ) |
| { |
| return new LineNumberReader( new StringReader( new String( toByteArray(), streamCharset ) ) ); |
| } |
| |
| static Stream newStream() |
| { |
| return new Stream( new ByteArrayOutputStream() ); |
| } |
| } |
| |
| private static byte[] toArray( ByteBuffer buffer ) |
| { |
| return copyOfRange( buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.remaining() ); |
| } |
| |
| private static class EH implements EventHandler<Event> |
| { |
| private final BlockingQueue<Event> cache = new LinkedTransferQueue<>(); |
| |
| Event pullEvent() throws InterruptedException |
| { |
| return cache.poll( 1, TimeUnit.MINUTES ); |
| } |
| |
| @Override |
| public void handleEvent( @Nonnull Event event ) |
| { |
| cache.add( event ); |
| } |
| } |
| } |