You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2016/11/07 10:15:23 UTC
zest-java git commit: Review FreePortFinder test utility to reduce
test flakiness on CI
Repository: zest-java
Updated Branches:
refs/heads/develop 246e588cd -> 420054295
Review FreePortFinder test utility to reduce test flakiness on CI
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/42005429
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/42005429
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/42005429
Branch: refs/heads/develop
Commit: 420054295fe5138f61051bb33676afb7280b9ba5
Parents: 246e588
Author: Paul Merlin <pa...@apache.org>
Authored: Mon Nov 7 11:15:09 2016 +0100
Committer: Paul Merlin <pa...@apache.org>
Committed: Mon Nov 7 11:15:09 2016 +0100
----------------------------------------------------------------------
.../apache/zest/test/util/FreePortFinder.java | 190 +++++++++++++++++--
.../zest/library/rest/admin/RestTest.java | 2 +-
.../zest/library/servlet/ServletTest.java | 2 +-
.../library/shiro/web/WebHttpShiroTest.java | 2 +-
.../library/shiro/web/WebRealmServiceTest.java | 2 +-
.../library/shiro/web/WebServletShiroTest.java | 2 +-
6 files changed, 176 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/core/testsupport/src/main/java/org/apache/zest/test/util/FreePortFinder.java
----------------------------------------------------------------------
diff --git a/core/testsupport/src/main/java/org/apache/zest/test/util/FreePortFinder.java b/core/testsupport/src/main/java/org/apache/zest/test/util/FreePortFinder.java
index f52a485..7f4eef5 100644
--- a/core/testsupport/src/main/java/org/apache/zest/test/util/FreePortFinder.java
+++ b/core/testsupport/src/main/java/org/apache/zest/test/util/FreePortFinder.java
@@ -20,42 +20,194 @@
package org.apache.zest.test.util;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.OptionalInt;
+import java.util.function.IntPredicate;
+import java.util.stream.Stream;
+
+import static java.util.Collections.shuffle;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.IntStream.rangeClosed;
public class FreePortFinder
{
+ private static class Range
+ {
+ final int lowerBound;
+ final int higherBound;
+
+ private Range( int lowerBound, int higherBound )
+ {
+ this.lowerBound = lowerBound;
+ this.higherBound = higherBound;
+ }
+ }
+
+ // Presumably the least used port ranges with >500 slots
+ // See http://stackoverflow.com/a/28369841/300053
+ private static final List<Range> LEAST_USED_RANGES = Arrays.asList(
+ new Range( 29170, 29998 ),
+ new Range( 38866, 39680 ),
+ new Range( 41798, 42507 ),
+ new Range( 43442, 44122 ),
+ new Range( 46337, 46997 ),
+ new Range( 35358, 36000 ),
+ new Range( 36866, 37474 ),
+ new Range( 38204, 38799 ),
+ new Range( 33657, 34248 ),
+ new Range( 30261, 30831 ),
+ new Range( 41231, 41793 ),
+ new Range( 21011, 21552 ),
+ new Range( 28590, 29117 ),
+ new Range( 14415, 14935 ),
+ new Range( 26490, 26999 )
+ );
+
+ private static final int MAX_PORT_CHECKS = 20;
+
+ public static boolean isFreePortOnLocalHost( int port )
+ {
+ return isFreePort( getLocalHostUnchecked(), port );
+ }
+
+ public static boolean isFreePort( InetAddress address, int port )
+ {
+ try
+ {
+ checkFreePort( address, port );
+ return true;
+ }
+ catch( IOException ex )
+ {
+ return false;
+ }
+ }
+
+ public static void checkFreePortOnLocalHost( int port ) throws IOException
+ {
+ checkFreePort( getLocalHostUnchecked(), port );
+ }
- public static int findFreePortOnLoopback()
- throws IOException
+ public static void checkFreePort( InetAddress address, int port ) throws IOException
{
- return findFreePortOnIface( InetAddress.getLocalHost() );
+ ServerSocket server = null;
+ try
+ {
+ server = new ServerSocket( port, 1, address );
+ }
+ finally
+ {
+ if( server != null )
+ {
+ try
+ {
+ server.close();
+ }
+ catch( IOException e )
+ {
+ // Ignore
+ }
+ }
+ }
}
- public static int findFreePortOnLoopback( int prefered )
- throws IOException
+ public static int findFreePortOnLocalHost()
+ throws IOException
{
- return findFreePortOnIface( InetAddress.getLocalHost(), prefered );
+ return findFreePort( getLocalHostUnchecked() );
}
- public static int findFreePortOnIface( InetAddress address )
- throws IOException
+ public static int findFreePort( InetAddress address )
+ throws IOException
{
- return findFreePortOnIface( address, -1 );
+ FreePortPredicate check = new FreePortPredicate( address );
+ // Randomly choose MAX_PORT_CHECKS ports from the least used ranges
+ OptionalInt port = LEAST_USED_RANGES.stream()
+ .flatMapToInt( range -> rangeClosed( range.lowerBound, range.higherBound ) )
+ .boxed()
+ .collect( collectingAndThen( toList(), collected ->
+ {
+ shuffle( collected );
+ return collected.stream();
+ } ) )
+ .limit( MAX_PORT_CHECKS )
+ .mapToInt( Integer::intValue )
+ .filter( check )
+ .findFirst();
+ return port.orElseThrow( () ->
+ {
+ IOException exception = new IOException( "Unable to find a free port on " + address );
+ check.errors.build().forEach( exception::addSuppressed );
+ return exception;
+ } );
}
- public static int findFreePortOnIface( InetAddress address, int prefered )
- throws IOException
+ public static int findFreePortInRangeOnLocalhost( int lowerBound, int higherBound )
+ throws IOException
{
- ServerSocket server;
- if ( prefered > 0 ) {
- server = new ServerSocket( prefered, 1, address );
- } else {
- server = new ServerSocket( 0, 1, address );
+ return findFreePortInRange( getLocalHostUnchecked(), lowerBound, higherBound );
+ }
+
+ public static int findFreePortInRange( InetAddress address, int lowerBound, int higherBound )
+ throws IOException
+ {
+ if( higherBound - lowerBound < 0 )
+ {
+ throw new IllegalArgumentException( "Invalid port range " + lowerBound + '-' + higherBound );
}
- int port = server.getLocalPort();
- server.close();
- return port;
+ FreePortPredicate check = new FreePortPredicate( address );
+ OptionalInt port = rangeClosed( lowerBound, higherBound ).filter( check ).findFirst();
+ return port.orElseThrow( () ->
+ {
+ String message = "Unable to find a free port in range " + lowerBound + '-' + higherBound + " on " + address;
+ IOException exception = new IOException( message );
+ check.errors.build().forEach( exception::addSuppressed );
+ return exception;
+ } );
}
+ private static class FreePortPredicate implements IntPredicate
+ {
+ private final InetAddress address;
+ private final Stream.Builder<Throwable> errors;
+
+ private FreePortPredicate( InetAddress address )
+ {
+ this.address = address;
+ this.errors = Stream.builder();
+ }
+
+ @Override
+ public boolean test( int candidate )
+ {
+ try
+ {
+ checkFreePort( address, candidate );
+ return true;
+ }
+ catch( IOException ex )
+ {
+ errors.add( ex );
+ return false;
+ }
+ }
+ }
+
+ private static InetAddress getLocalHostUnchecked()
+ {
+ try
+ {
+ return InetAddress.getLocalHost();
+ }
+ catch( UnknownHostException ex )
+ {
+ throw new UncheckedIOException( ex );
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/libraries/rest/src/test/java/org/apache/zest/library/rest/admin/RestTest.java
----------------------------------------------------------------------
diff --git a/libraries/rest/src/test/java/org/apache/zest/library/rest/admin/RestTest.java b/libraries/rest/src/test/java/org/apache/zest/library/rest/admin/RestTest.java
index fef807b..0bec7e8 100644
--- a/libraries/rest/src/test/java/org/apache/zest/library/rest/admin/RestTest.java
+++ b/libraries/rest/src/test/java/org/apache/zest/library/rest/admin/RestTest.java
@@ -74,7 +74,7 @@ public class RestTest extends AbstractZestTest
{
try
{
- ADMIN_PORT = FreePortFinder.findFreePortOnLoopback();
+ ADMIN_PORT = FreePortFinder.findFreePortOnLocalHost();
}
catch( IOException ex )
{
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/libraries/servlet/src/test/java/org/apache/zest/library/servlet/ServletTest.java
----------------------------------------------------------------------
diff --git a/libraries/servlet/src/test/java/org/apache/zest/library/servlet/ServletTest.java b/libraries/servlet/src/test/java/org/apache/zest/library/servlet/ServletTest.java
index 29aa1eb..a0dda4e 100644
--- a/libraries/servlet/src/test/java/org/apache/zest/library/servlet/ServletTest.java
+++ b/libraries/servlet/src/test/java/org/apache/zest/library/servlet/ServletTest.java
@@ -88,7 +88,7 @@ public class ServletTest
public void test()
throws Exception
{
- int port = FreePortFinder.findFreePortOnLoopback( 9001 );
+ int port = FreePortFinder.findFreePortOnLocalHost();
Server server = new Server( port );
try {
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebHttpShiroTest.java
----------------------------------------------------------------------
diff --git a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebHttpShiroTest.java b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebHttpShiroTest.java
index c6d54a9..95d9dca 100644
--- a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebHttpShiroTest.java
+++ b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebHttpShiroTest.java
@@ -49,7 +49,7 @@ public class WebHttpShiroTest
new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
// END SNIPPET: assembly
- port = FreePortFinder.findFreePortOnLoopback();
+ port = FreePortFinder.findFreePortOnLocalHost();
JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
config.hostName().set( "127.0.0.1" );
config.port().set( port );
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebRealmServiceTest.java
----------------------------------------------------------------------
diff --git a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebRealmServiceTest.java b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebRealmServiceTest.java
index d810dd3..0b2aaea 100644
--- a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebRealmServiceTest.java
+++ b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebRealmServiceTest.java
@@ -143,7 +143,7 @@ public class WebRealmServiceTest
new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
// END SNIPPET: assembly
- port = FreePortFinder.findFreePortOnLoopback();
+ port = FreePortFinder.findFreePortOnLocalHost();
JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
config.hostName().set( "127.0.0.1" );
config.port().set( port );
http://git-wip-us.apache.org/repos/asf/zest-java/blob/42005429/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebServletShiroTest.java
----------------------------------------------------------------------
diff --git a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebServletShiroTest.java b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebServletShiroTest.java
index 73c9a4a..7eb5245 100644
--- a/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebServletShiroTest.java
+++ b/libraries/shiro-web/src/test/java/org/apache/zest/library/shiro/web/WebServletShiroTest.java
@@ -36,7 +36,7 @@ public class WebServletShiroTest
public void test()
throws Exception
{
- int port = FreePortFinder.findFreePortOnLoopback( 9001 );
+ int port = FreePortFinder.findFreePortOnLocalHost();
Server server = new Server( port );
try {