Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.servicetalk.transport.netty.internal.NoopTransportObserver;

import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

Expand All @@ -43,6 +44,7 @@
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nullable;

import static io.servicetalk.concurrent.api.Single.collectUnordered;
Expand Down Expand Up @@ -77,7 +79,8 @@ void h1OrH2(int numRequests, int maxConcurrency, boolean clientPreferH2, boolean

CountingConnectionObserver connectionObserver = new CountingConnectionObserver();
final AtomicInteger numRetries = new AtomicInteger(0);
try (ServerContext ctx = HttpServers.forAddress(localAddress(0))
try (Spinner unused = new Spinner(Runtime.getRuntime().availableProcessors() * 2);
ServerContext ctx = HttpServers.forAddress(localAddress(0))
.sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, DefaultTestCerts::loadServerKey)
.build())
.protocols(protocolConfigs(serverPreferH2, h1ServerProtocol, h2ServerProtocol))
Expand Down Expand Up @@ -122,6 +125,11 @@ void h1OrH2(int numRequests, int maxConcurrency, boolean clientPreferH2, boolean
}
}

@RepeatedTest(100)
void repro() throws Exception {
h1OrH2(5000, 100, true, true);
}

private static class CountingConnectionObserver implements TransportObserver {
private final AtomicInteger count = new AtomicInteger();

Expand All @@ -138,4 +146,34 @@ private static HttpProtocolConfig[] protocolConfigs(boolean preferH2, H1Protocol
new HttpProtocolConfig[] {h2Config, h1Config} :
new HttpProtocolConfig[] {h1Config, h2Config};
}

private static final class Spinner implements AutoCloseable {
private final AtomicLong counter = new AtomicLong();
private final List<Thread> threads;
private volatile boolean stop;

private Spinner(final int threadCount) {
threads = new ArrayList<>(threadCount);
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(this::go);
t.setDaemon(true);
t.start();
threads.add(t);
}
}

@Override
public void close() throws Exception {
stop = true;
for (Thread t : threads) {
t.join();
}
}

private void go() {
while (!stop) {
counter.incrementAndGet();
}
}
}
}