View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2013-2025 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.jcabi.github;
6   
7   import com.jcabi.aspects.RetryOnFailure;
8   import com.jcabi.log.Logger;
9   import java.io.IOException;
10  import java.net.BindException;
11  import java.net.InetSocketAddress;
12  import java.net.ServerSocket;
13  import org.junit.jupiter.api.Assumptions;
14  import org.junit.jupiter.api.extension.ExtensionContext;
15  import org.junit.jupiter.api.extension.InvocationInterceptor;
16  import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
17  
18  /**
19   * Test resource for skipping tests when random port is busy.
20   * @since 0.8
21   */
22  public class RandomPort implements InvocationInterceptor {
23      @Override
24      public final void interceptTestMethod(
25          final Invocation<Void> invocation,
26          final ReflectiveInvocationContext<java.lang.reflect.Method> context,
27          final ExtensionContext extension
28      ) throws Throwable {
29          try {
30              invocation.proceed();
31          } catch (final BindException ignored) {
32              Logger.warn(
33                  this,
34                  String.format(
35                      "Test %s skipped due to no available ports",
36                      extension.getDisplayName()
37                  )
38              );
39              Assumptions.assumeTrue(false);
40          }
41      }
42  
43      /**
44       * Returns available port number.
45       * @return Available port number
46       * @throws IOException in case of IO error.
47       * @checkstyle NonStaticMethodCheck (5 lines)
48       */
49      @RetryOnFailure
50      @SuppressWarnings("PMD.ProhibitPublicStaticMethods")
51      public static int port() throws IOException {
52          try (ServerSocket socket = new ServerSocket()) {
53              socket.setReuseAddress(true);
54              socket.bind(
55                  new InetSocketAddress("localhost", 0)
56              );
57              return socket.getLocalPort();
58          }
59      }
60  }