All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mike10004.harreplay.tests.ReplayManagerTester Maven / Gradle / Ivy

package io.github.mike10004.harreplay.tests;

import com.google.common.base.Strings;
import com.google.common.net.HostAndPort;
import io.github.mike10004.harreplay.ReplayManager;
import io.github.mike10004.harreplay.ReplayServerConfig;
import io.github.mike10004.harreplay.ReplaySessionConfig;
import io.github.mike10004.harreplay.ReplaySessionConfig.Builder;
import io.github.mike10004.harreplay.ReplaySessionConfig.ServerTerminationCallback;
import io.github.mike10004.harreplay.ReplaySessionControl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Preconditions.checkState;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

public abstract class ReplayManagerTester {

    private final Path tempDir;
    private final File harFile;

    public ReplayManagerTester(Path tempDir, File harFile) {
        this.tempDir = tempDir;
        this.harFile = harFile;
    }

    public interface ReplayClient {
        T useReplayServer(Path tempDir, ReplaySessionControl sessionControl) throws Exception;
    }

    protected ReplayServerConfig configureReplayModule() {
        return ReplayServerConfig.empty();
    }

    protected abstract ReplayManager createReplayManager();

    public  T exercise(ReplayClient client, @Nullable Integer httpPort) throws Exception {
        ReplayManager replay = createReplayManager();
        AwaitableServerTerminationCallback infoCallback = new AwaitableServerTerminationCallback();
        Builder rscb = ReplaySessionConfig.builder(tempDir)
                .config(configureReplayModule())
                .onTermination(infoCallback);
        if (httpPort != null) {
            rscb.port(httpPort);
        }
        ReplaySessionConfig sessionParams = rscb.build(harFile);
        HostAndPort proxy = HostAndPort.fromParts("localhost", sessionParams.port);
        System.out.format("ReplayManagerTester: exercise: proxy = %s%n", proxy);
        @SuppressWarnings("OptionalAssignedToNull")
        Optional result = null;
        Exception exception = null;
        ReplaySessionControl sessionControlCopy = null;
        boolean infoCallbackAwaitSucceeded;
        System.out.format("ReplayManagerTester: starting replay session%n");
        try (ReplaySessionControl sessionControl = replay.start(sessionParams)) {
            System.out.format("ReplayManagerTester: replay session started on %s%n", sessionControl.getSocketAddress());
            sessionControlCopy = sessionControl;
            result = Optional.ofNullable(client.useReplayServer(tempDir, sessionControl));
        } catch (Exception e) {
            System.out.format("ReplayManagerTester: exercise() aborting abnormally due to exception%n");
            e.printStackTrace(System.err);
            exception = e;
            exerciseAbortedAbnormally(e);
        } finally {
            if (sessionControlCopy != null) {
                assertFalse("process still alive", sessionControlCopy.isAlive());
            }
            System.out.println("ReplayManagerTester: awaiting execution of process callback");
            infoCallbackAwaitSucceeded = infoCallback.await(3, TimeUnit.SECONDS);
        }
        assertNull("exception was thrown, probably from useReplayServer", exception);
        assertTrue("callback executed", infoCallback.wasExecuted());
        assertTrue("infoCallbackAwaitSucceeded", infoCallbackAwaitSucceeded);
        checkState(result != null, "result never set");
        return result.orElse(null);
    }

    protected void exerciseAbortedAbnormally(Exception e) {

    }

    private static class AwaitableServerTerminationCallback implements ServerTerminationCallback {

        private final CountDownLatch latch = new CountDownLatch(1);

        public boolean await(long duration, TimeUnit unit) throws InterruptedException {
            return latch.await(duration, unit);
        }

        public boolean wasExecuted() {
            return latch.getCount() == 0;
        }

        @Override
        public void terminated(@Nullable Throwable cause) {
            System.out.println("AwaitableServerTerminationCallback: terminated");
            if (cause != null) {
                System.out.format("AwaitableServerTerminationCallback: program terminated with exception %s%n", cause);
            }
            latch.countDown();
        }

    }

    private static final Logger log = LoggerFactory.getLogger(ReplayManagerTester.class);

    public static int findOpenPort() throws IOException {
        try (ServerSocket socket = new ServerSocket(0)) {
            return socket.getLocalPort();
        }
    }

    public static int findReservedPort(String systemPropertyName) throws IOException {
        String portStr = System.getProperty(systemPropertyName);
        if (Strings.isNullOrEmpty(portStr)) { // probably running with IDE test runner, not Maven
            log.trace("unit test port not reserved by build process; will try to find open port");
            try (ServerSocket socket = new ServerSocket(0)) {
                int reservedPort = socket.getLocalPort();
                log.debug("found open port {} by opening socket %s%n", reservedPort, socket);
                return reservedPort;
            }
        } else {
            return Integer.parseInt(portStr);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy