You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2020/04/05 00:25:51 UTC
[maven-surefire] branch maven2surefire-jvm-communication updated:
improved coverage in new code
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch maven2surefire-jvm-communication
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
The following commit(s) were added to refs/heads/maven2surefire-jvm-communication by this push:
new 8315fb3 improved coverage in new code
8315fb3 is described below
commit 8315fb38b0fccea057b89851d8b3131703d184ea
Author: tibordigana <ti...@apache.org>
AuthorDate: Sun Apr 5 02:25:41 2020 +0200
improved coverage in new code
---
.../org/apache/maven/surefire/JUnit4SuiteTest.java | 2 -
.../maven/surefire/util/internal/Channels.java | 14 +-
.../java/org/apache/maven/JUnit4SuiteTest.java | 4 +-
.../surefire/util/internal}/AsyncSocketTest.java | 3 +-
.../surefire/util/internal/ChannelsReaderTest.java | 240 ++++++++++++++++++++
.../surefire/util/internal/ChannelsWriterTest.java | 243 +++++++++++++++++++++
.../surefire/booter/ForkedBooterMockTest.java | 36 ++-
7 files changed, 531 insertions(+), 11 deletions(-)
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
index 94754a7..22bf702 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
@@ -40,7 +40,6 @@ import org.apache.maven.plugin.surefire.booterclient.ModularClasspathForkConfigu
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStreamBuilderTest;
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStreamTest;
import org.apache.maven.plugin.surefire.booterclient.output.ForkClientTest;
-import org.apache.maven.plugin.surefire.extensions.AsyncSocketTest;
import org.apache.maven.plugin.surefire.extensions.ConsoleOutputReporterTest;
import org.apache.maven.plugin.surefire.extensions.E2ETest;
import org.apache.maven.plugin.surefire.extensions.ForkedProcessEventNotifierTest;
@@ -111,7 +110,6 @@ public class JUnit4SuiteTest extends TestCase
suite.addTest( new JUnit4TestAdapter( ForkChannelTest.class ) );
suite.addTest( new JUnit4TestAdapter( StreamFeederTest.class ) );
suite.addTest( new JUnit4TestAdapter( E2ETest.class ) );
- suite.addTest( new JUnit4TestAdapter( AsyncSocketTest.class ) );
return suite;
}
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/Channels.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/Channels.java
index a536fc6..b15e6f6 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/Channels.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/Channels.java
@@ -28,7 +28,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousByteChannel;
-import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.concurrent.ExecutionException;
@@ -99,7 +99,9 @@ public final class Channels
catch ( ExecutionException e )
{
Throwable t = e.getCause();
- throw new IOException( ( t == null ? e : t ).getLocalizedMessage(), t );
+ throw t instanceof IOException
+ ? (IOException) t
+ : new IOException( ( t == null ? e : t ).getLocalizedMessage(), t );
}
catch ( Exception e )
{
@@ -124,7 +126,7 @@ public final class Channels
{
channel.close();
}
- catch ( AsynchronousCloseException e )
+ catch ( ClosedChannelException e )
{
// closed channel anyway
}
@@ -157,7 +159,9 @@ public final class Channels
catch ( ExecutionException e )
{
Throwable t = e.getCause();
- throw new IOException( ( t == null ? e : t ).getLocalizedMessage(), t );
+ throw t instanceof IOException
+ ? (IOException) t
+ : new IOException( ( t == null ? e : t ).getLocalizedMessage(), t );
}
catch ( Exception e )
{
@@ -188,7 +192,7 @@ public final class Channels
{
channel.close();
}
- catch ( AsynchronousCloseException e )
+ catch ( ClosedChannelException e )
{
// closed channel anyway
}
diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
index 650807f..231ff74 100644
--- a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
@@ -35,6 +35,7 @@ import org.apache.maven.surefire.util.RunOrderCalculatorTest;
import org.apache.maven.surefire.util.RunOrderTest;
import org.apache.maven.surefire.util.ScanResultTest;
import org.apache.maven.surefire.util.TestsToRunTest;
+import org.apache.maven.surefire.util.internal.AsyncSocketTest;
import org.apache.maven.surefire.util.internal.ChannelsReaderTest;
import org.apache.maven.surefire.util.internal.ChannelsWriterTest;
import org.apache.maven.surefire.util.internal.ConcurrencyUtilsTest;
@@ -66,7 +67,8 @@ import org.junit.runners.Suite;
ImmutableMapTest.class,
ReflectionUtilsTest.class,
ChannelsReaderTest.class,
- ChannelsWriterTest.class
+ ChannelsWriterTest.class,
+ AsyncSocketTest.class
} )
@RunWith( Suite.class )
public class JUnit4SuiteTest
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/AsyncSocketTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/AsyncSocketTest.java
similarity index 98%
rename from maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/AsyncSocketTest.java
rename to surefire-api/src/test/java/org/apache/maven/surefire/util/internal/AsyncSocketTest.java
index 88cba07..8363e29 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/AsyncSocketTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/AsyncSocketTest.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire.extensions;
+package org.apache.maven.surefire.util.internal;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,7 +19,6 @@ package org.apache.maven.plugin.surefire.extensions;
* under the License.
*/
-import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
import org.junit.Test;
import java.io.BufferedInputStream;
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsReaderTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsReaderTest.java
index 0b64a42..5cd6fde 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsReaderTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsReaderTest.java
@@ -23,19 +23,38 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousByteChannel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ShutdownChannelGroupException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
import static java.nio.file.Files.write;
import static org.fest.assertions.Assertions.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
/**
* The tests for {@link Channels#newChannel(InputStream)} and {@link Channels#newBufferedChannel(InputStream)}.
@@ -303,4 +322,225 @@ public class ChannelsReaderTest
assertThat( bb.array() )
.isEqualTo( new byte[] {1, 2, 3, 0} );
}
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput1() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ InputStream is = Channels.newInputStream( channel );
+ is.read( new byte[0], -1, 0 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput2() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ InputStream is = Channels.newInputStream( channel );
+ is.read( new byte[0], 0, -1 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput3() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ InputStream is = Channels.newInputStream( channel );
+ is.read( new byte[0], 1, 0 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput4() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ InputStream is = Channels.newInputStream( channel );
+ is.read( new byte[0], 0, 1 );
+ }
+
+ @Test
+ public void shouldClose() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( true );
+ InputStream is = Channels.newInputStream( channel );
+ is.close();
+ verify( channel, times( 1 ) ).close();
+ }
+
+ @Test
+ public void shouldNotClose() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( false );
+ InputStream is = Channels.newInputStream( channel );
+ is.close();
+ verify( channel, never() ).close();
+ }
+
+ @Test
+ public void shouldAlreadyClosed() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( true );
+ doThrow( ClosedChannelException.class ).when( channel ).close();
+ InputStream is = Channels.newInputStream( channel );
+ is.close();
+ verify( channel ).close();
+ }
+
+ @Test
+ public void shouldReadZeroLength() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ InputStream is = Channels.newInputStream( channel );
+ is.read( new byte[] { 5 }, 0, 0 );
+ verifyZeroInteractions( channel );
+ }
+
+ @Test
+ public void shouldReadArray() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenAnswer( new Answer<Future<Integer>>()
+ {
+ @Override
+ public Future<Integer> answer( InvocationOnMock invocation ) throws Throwable
+ {
+ ByteBuffer bb = (ByteBuffer) invocation.getArguments()[0];
+ bb.put( (byte) 3 );
+ bb.put( (byte) 4 );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() ).thenReturn( 2 );
+ return future;
+ }
+ } );
+
+ InputStream is = Channels.newInputStream( channel );
+ ArgumentCaptor<ByteBuffer> captured = ArgumentCaptor.forClass( ByteBuffer.class );
+ byte[] b = new byte[] { 1, 2, 0, 0, 5 };
+ is.read( b, 2, 2 );
+
+ verify( channel ).read( captured.capture() );
+ verifyNoMoreInteractions( channel );
+
+ assertThat( captured.getAllValues() )
+ .hasSize( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).array() )
+ .containsOnly( new byte[] { 1, 2, 3, 4, 5 } );
+
+ assertThat( captured.getAllValues().get( 0 ).arrayOffset() )
+ .isEqualTo( 0 );
+
+ assertThat( captured.getAllValues().get( 0 ).position() )
+ .isEqualTo( 4 );
+
+ assertThat( captured.getAllValues().get( 0 ).limit() )
+ .isEqualTo( 4 );
+
+ assertThat( captured.getAllValues().get( 0 ).capacity() )
+ .isEqualTo( 5 );
+ }
+
+ @Test
+ public void shouldRead() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenAnswer( new Answer<Future<Integer>>()
+ {
+ @Override
+ public Future<Integer> answer( InvocationOnMock invocation ) throws Throwable
+ {
+ ByteBuffer bb = (ByteBuffer) invocation.getArguments()[0];
+ bb.put( (byte) 3 );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() ).thenReturn( 1 );
+ return future;
+ }
+ } );
+
+ InputStream is = Channels.newInputStream( channel );
+ ArgumentCaptor<ByteBuffer> captured = ArgumentCaptor.forClass( ByteBuffer.class );
+ int b = is.read();
+ assertThat( b )
+ .isEqualTo( 3 );
+
+ verify( channel ).read( captured.capture() );
+ verifyNoMoreInteractions( channel );
+
+ assertThat( captured.getAllValues() )
+ .hasSize( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).array() )
+ .containsOnly( new byte[] { 3 } );
+
+ assertThat( captured.getAllValues().get( 0 ).arrayOffset() )
+ .isEqualTo( 0 );
+
+ assertThat( captured.getAllValues().get( 0 ).position() )
+ .isEqualTo( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).limit() )
+ .isEqualTo( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).capacity() )
+ .isEqualTo( 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnRead() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenThrow( ShutdownChannelGroupException.class );
+ InputStream is = Channels.newInputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectCause( instanceOf( ShutdownChannelGroupException.class ) );
+ is.read( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture1() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( new InterruptedIOException() ) );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ InputStream is = Channels.newInputStream( channel );
+ ee.expect( InterruptedIOException.class );
+ is.read( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture2() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( new RuntimeException( "msg" ) ) );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ InputStream is = Channels.newInputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectCause( instanceOf( RuntimeException.class ) );
+ ee.expectMessage( "msg" );
+ is.read( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture3() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( "msg", null ) );
+ when( channel.read( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ InputStream is = Channels.newInputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectMessage( "msg" );
+ is.read( new byte[1], 0, 1 );
+ }
}
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsWriterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsWriterTest.java
index 35c9ddd..24ed3f3 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsWriterTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ChannelsWriterTest.java
@@ -23,19 +23,37 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousByteChannel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ShutdownChannelGroupException;
import java.nio.channels.WritableByteChannel;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
import static java.nio.file.Files.readAllBytes;
import static org.fest.assertions.Assertions.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
/**
* The tests for {@link Channels#newChannel(OutputStream)} and {@link Channels#newBufferedChannel(OutputStream)}.
@@ -207,4 +225,229 @@ public class ChannelsWriterTest
.hasSize( 3 )
.isEqualTo( new byte[] {1, 2, 3} );
}
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput1() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.write( new byte[0], -1, 0 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput2() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.write( new byte[0], 0, -1 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput3() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.write( new byte[0], 1, 0 );
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldValidateInput4() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.write( new byte[0], 0, 1 );
+ }
+
+ @Test
+ public void shouldClose() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( true );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.close();
+ verify( channel, times( 1 ) ).close();
+ }
+
+ @Test
+ public void shouldNotClose() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( false );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.close();
+ verify( channel, never() ).close();
+ }
+
+ @Test
+ public void shouldAlreadyClosed() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.isOpen() ).thenReturn( true );
+ doThrow( ClosedChannelException.class ).when( channel ).close();
+ OutputStream os = Channels.newOutputStream( channel );
+ os.close();
+ verify( channel ).close();
+ }
+
+ @Test
+ public void shouldWriteZeroLength() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ os.write( new byte[] { 5 }, 0, 0 );
+ verifyZeroInteractions( channel );
+ }
+
+ @Test
+ public void shouldWriteArray() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenAnswer( new Answer<Future<Integer>>()
+ {
+ @Override
+ public Future<Integer> answer( InvocationOnMock invocation ) throws Throwable
+ {
+ ByteBuffer bb = (ByteBuffer) invocation.getArguments()[0];
+ int i = 0;
+ for ( ; bb.hasRemaining(); i++ )
+ {
+ bb.get();
+ }
+ Future<Integer> future = mock( Future.class );
+ when( future.get() ).thenReturn( i );
+ return future;
+ }
+ } );
+
+ OutputStream os = Channels.newOutputStream( channel );
+ ArgumentCaptor<ByteBuffer> captured = ArgumentCaptor.forClass( ByteBuffer.class );
+ os.write( new byte[] { 1, 2, 3, 4, 5 }, 2, 2 );
+
+ verify( channel ).write( captured.capture() );
+ verifyNoMoreInteractions( channel );
+
+ assertThat( captured.getAllValues() )
+ .hasSize( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).array() )
+ .containsOnly( new byte[] { 1, 2, 3, 4, 5 } );
+
+ assertThat( captured.getAllValues().get( 0 ).arrayOffset() )
+ .isEqualTo( 0 );
+
+ assertThat( captured.getAllValues().get( 0 ).position() )
+ .isEqualTo( 4 );
+
+ assertThat( captured.getAllValues().get( 0 ).limit() )
+ .isEqualTo( 4 );
+
+ assertThat( captured.getAllValues().get( 0 ).capacity() )
+ .isEqualTo( 5 );
+ }
+
+ @Test
+ public void shouldWrite() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenAnswer( new Answer<Future<Integer>>()
+ {
+ @Override
+ public Future<Integer> answer( InvocationOnMock invocation ) throws Throwable
+ {
+ ByteBuffer bb = (ByteBuffer) invocation.getArguments()[0];
+ int i = 0;
+ for ( ; bb.hasRemaining(); i++ )
+ {
+ bb.get();
+ }
+ Future<Integer> future = mock( Future.class );
+ when( future.get() ).thenReturn( i );
+ return future;
+ }
+ } );
+
+ OutputStream os = Channels.newOutputStream( channel );
+ ArgumentCaptor<ByteBuffer> captured = ArgumentCaptor.forClass( ByteBuffer.class );
+ os.write( 3 );
+
+ verify( channel ).write( captured.capture() );
+ verifyNoMoreInteractions( channel );
+
+ assertThat( captured.getAllValues() )
+ .hasSize( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).array() )
+ .containsOnly( new byte[] { 3 } );
+
+ assertThat( captured.getAllValues().get( 0 ).arrayOffset() )
+ .isEqualTo( 0 );
+
+ assertThat( captured.getAllValues().get( 0 ).position() )
+ .isEqualTo( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).limit() )
+ .isEqualTo( 1 );
+
+ assertThat( captured.getAllValues().get( 0 ).capacity() )
+ .isEqualTo( 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnWrite() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenThrow( ShutdownChannelGroupException.class );
+ OutputStream os = Channels.newOutputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectCause( instanceOf( ShutdownChannelGroupException.class ) );
+ os.write( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture1() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( new InterruptedIOException() ) );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ OutputStream os = Channels.newOutputStream( channel );
+ ee.expect( InterruptedIOException.class );
+ os.write( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture2() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( new RuntimeException( "msg" ) ) );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ OutputStream os = Channels.newOutputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectCause( instanceOf( RuntimeException.class ) );
+ ee.expectMessage( "msg" );
+ os.write( new byte[1], 0, 1 );
+ }
+
+ @Test
+ public void shouldThrowExceptionOnFuture3() throws Exception
+ {
+ AsynchronousByteChannel channel = mock( AsynchronousByteChannel.class );
+ Future<Integer> future = mock( Future.class );
+ when( future.get() )
+ .thenThrow( new ExecutionException( "msg", null ) );
+ when( channel.write( any( ByteBuffer.class ) ) )
+ .thenReturn( future );
+ OutputStream os = Channels.newOutputStream( channel );
+ ee.expect( IOException.class );
+ ee.expectMessage( "msg" );
+ os.write( new byte[1], 0, 1 );
+ }
}
diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java
index 5604fd1..4a3690e 100644
--- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java
+++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java
@@ -24,6 +24,7 @@ import org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelEncoder;
import org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelProcessorFactory;
import org.apache.maven.surefire.booter.spi.SurefireMasterProcessChannelProcessorFactory;
import org.apache.maven.surefire.report.StackTraceWriter;
+import org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils;
import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
import org.junit.Rule;
import org.junit.Test;
@@ -33,6 +34,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@@ -50,9 +53,11 @@ import static org.fest.assertions.Fail.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.powermock.api.mockito.PowerMockito.doAnswer;
import static org.powermock.api.mockito.PowerMockito.doCallRealMethod;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.doThrow;
@@ -67,7 +72,12 @@ import static org.powermock.reflect.Whitebox.setInternalState;
* PowerMock tests for {@link ForkedBooter}.
*/
@RunWith( PowerMockRunner.class )
-@PrepareForTest( { PpidChecker.class, ForkedBooter.class, LegacyMasterProcessChannelEncoder.class } )
+@PrepareForTest( {
+ PpidChecker.class,
+ ForkedBooter.class,
+ LegacyMasterProcessChannelEncoder.class,
+ ShutdownHookUtils.class
+} )
@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } )
public class ForkedBooterMockTest
{
@@ -349,4 +359,28 @@ public class ForkedBooterMockTest
}
}
}
+
+ @Test
+ public void testFlushEventChannelOnExit() throws Exception
+ {
+ mockStatic( ShutdownHookUtils.class );
+
+ final MasterProcessChannelEncoder eventChannel = mock( MasterProcessChannelEncoder.class );
+ ForkedBooter booter = new ForkedBooter();
+ setInternalState( booter, "eventChannel", eventChannel );
+
+ doAnswer( new Answer<Object>()
+ {
+ @Override
+ public Object answer( InvocationOnMock invocation )
+ {
+ Thread t = invocation.getArgument( 0 );
+ assertThat( t.isDaemon() ).isTrue();
+ t.run();
+ verify( eventChannel, times( 1 ) ).onJvmExit();
+ return null;
+ }
+ } ).when( ShutdownHookUtils.class, "addShutDownHook", any( Thread.class ) );
+ invokeMethod( booter, "flushEventChannelOnExit" );
+ }
}