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/02/15 09:34:39 UTC

[maven-surefire] branch maven2surefire-jvm-communication updated: covered ForkedBooter and extensions SPI

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 23d17cf  covered ForkedBooter and extensions SPI
23d17cf is described below

commit 23d17cf0e4634ca52c159a49292bf2e562fc1c48
Author: tibordigana <ti...@apache.org>
AuthorDate: Sat Feb 15 10:34:31 2020 +0100

    covered ForkedBooter and extensions SPI
---
 pom.xml                                            |   2 +-
 .../surefire/booter/ForkedBooterMockTest.java      | 197 +++++++++++++++++++--
 2 files changed, 185 insertions(+), 14 deletions(-)

diff --git a/pom.xml b/pom.xml
index 3b0e4bb..57c0b95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,7 +98,7 @@
     <plexus-java-version>1.0.3</plexus-java-version>
     <!-- maven-shared-utils:3.2.0+ another behavior - broke Surefire performance - end of subprocess notification not arrived in ForkStarter -->
     <mavenSharedUtilsVersion>3.1.0</mavenSharedUtilsVersion>
-    <powermockVersion>2.0.4</powermockVersion>
+    <powermockVersion>2.0.5</powermockVersion>
     <jacocoVersion>0.8.5</jacocoVersion>
     <maven.surefire.scm.devConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-surefire.git</maven.surefire.scm.devConnection>
     <maven.site.path>surefire-archives/surefire-LATEST</maven.site.path>
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 2cbb3f2..fa8011d 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
@@ -19,33 +19,51 @@ package org.apache.maven.surefire.booter;
  * under the License.
  */
 
+import org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelDecoder;
 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.providerapi.MasterProcessChannelDecoder;
+import org.apache.maven.surefire.providerapi.MasterProcessChannelEncoder;
 import org.apache.maven.surefire.report.StackTraceWriter;
+import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
+import org.junit.rules.ErrorCollector;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.nio.channels.ServerSocketChannel;
+
+import static java.net.StandardSocketOptions.SO_KEEPALIVE;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.TCP_NODELAY;
 import static org.fest.assertions.Assertions.assertThat;
+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.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.powermock.api.mockito.PowerMockito.doCallRealMethod;
 import static org.powermock.api.mockito.PowerMockito.doNothing;
 import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
 import static org.powermock.api.mockito.PowerMockito.verifyNoMoreInteractions;
 import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
 import static org.powermock.api.mockito.PowerMockito.when;
 import static org.powermock.reflect.Whitebox.invokeMethod;
 import static org.powermock.reflect.Whitebox.setInternalState;
-import static org.powermock.utils.JavaVersion.JAVA_RECENT;
-import static org.powermock.utils.JavaVersion.JAVA_12;
 
 /**
  * PowerMock tests for {@link ForkedBooter}.
@@ -55,6 +73,9 @@ import static org.powermock.utils.JavaVersion.JAVA_12;
 @PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } )
 public class ForkedBooterMockTest
 {
+    @Rule
+    public final ErrorCollector errorCollector = new ErrorCollector();
+
     @Mock
     private PpidChecker pluginProcessChecker;
 
@@ -62,6 +83,9 @@ public class ForkedBooterMockTest
     private ForkedBooter booter;
 
     @Mock
+    private MasterProcessChannelProcessorFactory channelProcessorFactory;
+
+    @Mock
     private LegacyMasterProcessChannelEncoder eventChannel;
 
     @Captor
@@ -94,7 +118,7 @@ public class ForkedBooterMockTest
     @Test
     public void testMain() throws Exception
     {
-        PowerMockito.mockStatic( ForkedBooter.class );
+        mockStatic( ForkedBooter.class );
 
         doCallRealMethod()
                 .when( ForkedBooter.class, "run", capturedBooter.capture(), capturedArgs.capture() );
@@ -129,14 +153,7 @@ public class ForkedBooterMockTest
     @Test
     public void testMainWithError() throws Exception
     {
-        //does not work in PowerMock
-        //assumeFalse( JAVA_RECENT.atLeast( JAVA_12 ) );
-        if ( JAVA_RECENT.atLeast( JAVA_12 ) )
-        {
-            return;
-        }
-
-        PowerMockito.mockStatic( ForkedBooter.class );
+        mockStatic( ForkedBooter.class );
 
         doCallRealMethod()
                 .when( ForkedBooter.class, "run", any( ForkedBooter.class ), any( String[].class ) );
@@ -148,7 +165,6 @@ public class ForkedBooterMockTest
                 .when( booter, "setupBooter",
                         any( String.class ), any( String.class ), any( String.class ), any( String.class ) );
 
-        // broken in PowerMock JDK 12
         setInternalState( booter, "eventChannel", eventChannel );
 
         String[] args = new String[]{ "/", "dump", "surefire.properties", "surefire-effective.properties" };
@@ -180,4 +196,159 @@ public class ForkedBooterMockTest
 
         verifyNoMoreInteractions( booter );
     }
+
+    @Test
+    public void shouldNotCloseChannelProcessorFactory() throws Exception
+    {
+        setInternalState( booter, "channelProcessorFactory", (MasterProcessChannelProcessorFactory) null );
+
+        doCallRealMethod()
+            .when( booter, "closeForkChannel" );
+
+        invokeMethod( booter, "closeForkChannel" );
+
+        verifyZeroInteractions( channelProcessorFactory );
+    }
+
+    @Test
+    public void shouldCloseChannelProcessorFactory() throws Exception
+    {
+        setInternalState( booter, "channelProcessorFactory", channelProcessorFactory );
+
+        doCallRealMethod()
+            .when( booter, "closeForkChannel" );
+
+        invokeMethod( booter, "closeForkChannel" );
+
+        verify( channelProcessorFactory, times( 1 ) )
+            .close();
+        verifyNoMoreInteractions( channelProcessorFactory );
+    }
+
+    @Test
+    public void shouldFailOnCloseChannelProcessorFactory() throws Exception
+    {
+        setInternalState( booter, "channelProcessorFactory", channelProcessorFactory );
+
+        doThrow( new IOException() )
+            .when( channelProcessorFactory )
+            .close();
+
+        doCallRealMethod()
+            .when( booter, "closeForkChannel" );
+
+        invokeMethod( booter, "closeForkChannel" );
+
+        verify( channelProcessorFactory, times( 1 ) )
+            .close();
+        verifyNoMoreInteractions( channelProcessorFactory );
+    }
+
+    @Test
+    public void shouldLookupLegacyDecoderFactory() throws Exception
+    {
+        mockStatic( ForkedBooter.class );
+
+        doCallRealMethod()
+            .when( ForkedBooter.class, "lookupDecoderFactory", anyString() );
+
+        try ( final MasterProcessChannelProcessorFactory factory =
+                  invokeMethod( ForkedBooter.class, "lookupDecoderFactory", "pipe://3" ) )
+        {
+            assertThat( factory ).isInstanceOf( LegacyMasterProcessChannelProcessorFactory.class );
+
+            assertThat( factory.canUse( "pipe://3" ) ).isTrue();
+
+            assertThat( factory.canUse( "-- whatever --" ) ).isFalse();
+
+            errorCollector.checkThrows( MalformedURLException.class, new ThrowingRunnable()
+            {
+                @Override
+                public void run() throws Throwable
+                {
+                    factory.connect( "tcp://localhost:123" );
+                    fail();
+                }
+            } );
+
+            factory.connect( "pipe://3" );
+
+            MasterProcessChannelDecoder decoder = factory.createDecoder();
+            assertThat( decoder ).isInstanceOf( LegacyMasterProcessChannelDecoder.class );
+            MasterProcessChannelEncoder encoder = factory.createEncoder();
+            assertThat( encoder ).isInstanceOf( LegacyMasterProcessChannelEncoder.class );
+        }
+    }
+
+    @Test
+    public void shouldLookupSurefireDecoderFactory() throws Exception
+    {
+        mockStatic( ForkedBooter.class );
+
+        doCallRealMethod()
+            .when( ForkedBooter.class, "lookupDecoderFactory", anyString() );
+
+        try ( ServerSocketChannel server = ServerSocketChannel.open() )
+        {
+            if ( server.supportedOptions().contains( SO_REUSEADDR ) )
+            {
+                server.setOption( SO_REUSEADDR, true );
+            }
+
+            if ( server.supportedOptions().contains( TCP_NODELAY ) )
+            {
+                server.setOption( TCP_NODELAY, true );
+            }
+
+            if ( server.supportedOptions().contains( SO_KEEPALIVE ) )
+            {
+                server.setOption( SO_KEEPALIVE, true );
+            }
+
+            server.bind( new InetSocketAddress( 0 ) );
+            int serverPort = ( (InetSocketAddress) server.getLocalAddress() ).getPort();
+
+            try ( MasterProcessChannelProcessorFactory factory =
+                     invokeMethod( ForkedBooter.class, "lookupDecoderFactory", "tcp://127.0.0.1:" + serverPort ) )
+            {
+                assertThat( factory )
+                    .isInstanceOf( SurefireMasterProcessChannelProcessorFactory.class );
+
+                assertThat( factory.canUse( "tcp://127.0.0.1:" + serverPort ) )
+                    .isTrue();
+
+                assertThat( factory.canUse( "-- whatever --" ) )
+                    .isFalse();
+
+                errorCollector.checkThrows( MalformedURLException.class, new ThrowingRunnable()
+                {
+                    @Override
+                    public void run() throws Throwable
+                    {
+                        factory.connect( "pipe://1" );
+                        fail();
+                    }
+                } );
+
+                errorCollector.checkThrows( IOException.class, new ThrowingRunnable()
+                {
+                    @Override
+                    public void run() throws Throwable
+                    {
+                        factory.connect( "tcp://localhost:123\u0000\u0000\u0000" );
+                        fail();
+                    }
+                } );
+
+                factory.connect( "tcp://127.0.0.1:" + serverPort );
+
+                MasterProcessChannelDecoder decoder = factory.createDecoder();
+                assertThat( decoder )
+                    .isInstanceOf( LegacyMasterProcessChannelDecoder.class );
+                MasterProcessChannelEncoder encoder = factory.createEncoder();
+                assertThat( encoder )
+                    .isInstanceOf( LegacyMasterProcessChannelEncoder.class );
+            }
+        }
+    }
 }