diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 837dc1394..c24ebb4ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,8 @@ # 8. multinode-xa-test: Multinode XA integration tests (needs: build-test) # 9. oracle-test: Oracle database tests (needs: build-test) # 10. sqlserver-tests: SQL Server tests (needs: build-test) -# 11. notify-integration: Triggers integration repo workflow +# 11. ojp-testcontainers-test: OJP TestContainers integration tests (needs: build-test) +# 12. notify-integration: Triggers integration repo workflow # # SEQUENTIAL EXECUTION: # All specialized test jobs depend on build-test completing successfully. @@ -1844,7 +1845,52 @@ jobs: run: cat /tmp/ojp-server.log || echo "/tmp/ojp-server.log not found" # =========================================================================== - # JOB 11: Notify Integration Repository + # JOB 11: OJP TestContainers Integration Tests + # =========================================================================== + # + # This job validates the ojp-testcontainers module by: + # 1. Building the ojp-testcontainers module from the local source so tests + # always run against the latest code rather than a published artifact. + # 2. Starting an OJP Server Docker container via OjpContainer and asserting + # that the server port is reachable over TCP. + # + # Execution: Only runs AFTER build-test job succeeds (needs: [build-test]) + # + # =========================================================================== + ojp-testcontainers-test: + name: OJP TestContainers Integration Tests + runs-on: ubuntu-latest + # DEPENDENCY: This job only runs if build-test succeeds + needs: [build-test] + + permissions: + contents: read + + steps: + - name: Git checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 22 + uses: actions/setup-java@v4 + with: + java-version: 22 + distribution: 'temurin' + cache: maven + + # Build and install the ojp-testcontainers module locally so integration + # tests always exercise the latest code from this repository. + - name: Build and Install (ojp-testcontainers) locally + run: mvn clean install -pl ojp-testcontainers -am -DskipTests -Dgpg.skip=true + + # Run the OjpContainerIntegrationTest which starts the OJP Docker container + # and verifies TCP connectivity to the exposed OJP port. + - name: Run OJP TestContainers Integration Tests + run: mvn test -pl ojp-testcontainers -Dgpg.skip=true -DenableOjpContainerTests=true + + # =========================================================================== + # JOB 12: Notify Integration Repository # =========================================================================== # # This job triggers a workflow in the ojp-framework-integration repository diff --git a/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerIntegrationTest.java b/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerIntegrationTest.java new file mode 100644 index 000000000..1e07e6bf2 --- /dev/null +++ b/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerIntegrationTest.java @@ -0,0 +1,67 @@ +package org.openjproxy.testcontainers; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Integration tests for OjpContainer. + *

+ * These tests start a real Docker container and verify that OJP Server is accessible. + * They are disabled by default and must be explicitly enabled via the system property: + * {@code -DenableOjpContainerTests=true} + *

+ * + *

Requires Docker to be available in the test environment.

+ */ +@EnabledIf("org.openjproxy.testcontainers.OjpContainerIntegrationTest#isEnabled") +class OjpContainerIntegrationTest { + + /** + * Returns {@code true} when the {@code enableOjpContainerTests} system property is set to {@code true}. + * Used by {@link EnabledIf} to conditionally enable this test class. + */ + static boolean isEnabled() { + return Boolean.parseBoolean(System.getProperty("enableOjpContainerTests", "false")); + } + + /** + * Verifies that the OJP container starts successfully and is reachable on its exposed port. + *
    + *
  1. Starts an {@link OjpContainer} using the default Docker image.
  2. + *
  3. Asserts that the container is running.
  4. + *
  5. Asserts that a TCP connection can be established to the OJP port.
  6. + *
  7. Asserts that {@link OjpContainer#getOjpConnectionString()} returns the expected value.
  8. + *
+ */ + @Test + void testContainerStartsAndIsReachable() throws IOException { + try (OjpContainer container = new OjpContainer()) { + container.start(); + + assertTrue(container.isRunning(), "OJP container should be running after start()"); + + String host = container.getOjpHost(); + int port = container.getOjpPort(); + + assertNotNull(host, "OJP host must not be null"); + assertTrue(port > 0, "OJP mapped port must be a positive number"); + + // Verify TCP-level connectivity to the OJP server port + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(host, port), 5_000); + assertTrue(socket.isConnected(), "Should be able to open a TCP connection to OJP port"); + } + + assertEquals(host + ":" + port, container.getOjpConnectionString(), + "getOjpConnectionString() must return 'host:port'"); + } + } +} diff --git a/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerTest.java b/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerTest.java index 3f051fb11..9503ca522 100644 --- a/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerTest.java +++ b/ojp-testcontainers/src/test/java/org/openjproxy/testcontainers/OjpContainerTest.java @@ -1,6 +1,7 @@ package org.openjproxy.testcontainers; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; import org.testcontainers.utility.DockerImageName; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -52,6 +53,7 @@ void testIncompatibleImageNameThrowsException() { } @Test + @EnabledIf("org.openjproxy.testcontainers.OjpContainerIntegrationTest#isEnabled") void testStartAndGetConnectionInfo() { try (OjpContainer container = new OjpContainer()) { container.start(); @@ -73,6 +75,7 @@ void testStartAndGetConnectionInfo() { } @Test + @EnabledIf("org.openjproxy.testcontainers.OjpContainerIntegrationTest#isEnabled") void testContainerIsReady() { try (OjpContainer container = new OjpContainer()) { container.start();