8286873: Improve websocket test execution time

Reviewed-by: dfuchs, prappo
This commit is contained in:
Daniel Jeliński 2022-05-19 13:22:14 +00:00
parent db19dc6bb9
commit d24c84e768
10 changed files with 101 additions and 72 deletions

@ -57,10 +57,10 @@ public class BlowupOutputQueue extends PendingOperations {
* utilized and then make sure there won't be any errors caused by that.
*
* First, fill the queue with Text messages. Once done, send a Ping message.
* At this stage, there are at least 2 messages are in queue. Now, start
* At this stage, there are at least 2 messages in queue. Now, start
* receiving. Received Ping messages will cause automatic Pong replies. When
* all done, there will be at least 3 messages in the queue. (As at least
* the a single Ping has to be replied). Then send a Close message. Now
* a single Ping has to be replied). Then send a Close message. Now
* there are at least 4 messages in the queue. Finally, receive the last
* message which is a Close message. This will cause an automatic reply with
* a Close message from the client side. All in all there should be at least
@ -111,7 +111,7 @@ public class BlowupOutputQueue extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfText = webSocket.sendText(data, true);
try {
cfText.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfText.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -124,14 +124,14 @@ public class BlowupOutputQueue extends PendingOperations {
webSocket.request(N);
allButCloseReceived.await();
webSocket.request(1); // Receive the last message: Close
List<MockListener.Invocation> invocations = listener.invocations();
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertFalse(invocations.contains(new MockListener.OnError(webSocket, IOException.class)));
assertFalse(cfText.isDone());
assertFalse(cfPing.isDone());
assertFalse(cfClose.isDone());
return null;
}, () -> cfText.isDone());
List<MockListener.Invocation> invocations = listener.invocations();
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertFalse(invocations.contains(new MockListener.OnError(webSocket, IOException.class)));
assertFalse(cfText.isDone());
assertFalse(cfPing.isDone());
assertFalse(cfClose.isDone());
}
}

@ -60,7 +60,7 @@ public class PendingBinaryPingClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfBinary = webSocket.sendBinary(data, last);
try {
cfBinary.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfBinary.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -74,17 +74,16 @@ public class PendingBinaryPingClose extends PendingOperations {
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
cfPing = webSocket.sendPing(ByteBuffer.allocate(125));
assertHangs(cfPing);
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfPing, cfClose);
assertNotDone(cfBinary);
webSocket.abort();
assertFails(IOE, cfBinary);
assertFails(IOE, cfPing);
assertFails(IOE, cfClose);
return null;
}, () -> cfBinary.isDone());
webSocket.abort();
assertFails(IOE, cfBinary);
assertFails(IOE, cfPing);
assertFails(IOE, cfClose);
}
}

@ -38,8 +38,6 @@ import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;
public class PendingBinaryPongClose extends PendingOperations {
@ -62,7 +60,7 @@ public class PendingBinaryPongClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfBinary = webSocket.sendBinary(data, last);
try {
cfBinary.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfBinary.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -76,17 +74,16 @@ public class PendingBinaryPongClose extends PendingOperations {
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
cfPong = webSocket.sendPong(ByteBuffer.allocate(125));
assertHangs(cfPong);
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfPong, cfClose);
assertNotDone(cfBinary);
webSocket.abort();
assertFails(IOE, cfBinary);
assertFails(IOE, cfPong);
assertFails(IOE, cfClose);
return null;
}, () -> cfBinary.isDone());
webSocket.abort();
assertFails(IOE, cfBinary);
assertFails(IOE, cfPong);
assertFails(IOE, cfClose);
}
}

@ -41,10 +41,11 @@ public class PendingOperations {
static final Class<IllegalStateException> ISE = IllegalStateException.class;
static final Class<IOException> IOE = IOException.class;
// Time after which we deem that the local send buffer and remote
// receive buffer must be full. This has been heuristically determined.
// receive buffer must be full.
// At the time of writing, using anything <= 5s on Mac will make the
// tests fail intermittently.
static final long MAX_WAIT_SEC = 10; // seconds.
long waitSec;
DummyWebSocketServer server;
WebSocket webSocket;
@ -63,6 +64,12 @@ public class PendingOperations {
webSocket.abort();
}
/* shortcut */
static void assertAllHang(CompletableFuture<?> cf1,
CompletableFuture<?> cf2) {
assertHangs(CompletableFuture.anyOf(cf1, cf2));
}
/* shortcut */
static void assertHangs(CompletionStage<?> stage) {
Support.assertHangs(stage);
@ -99,6 +106,11 @@ public class PendingOperations {
int iterations = 0;
do {
iterations++;
if (iterations == 1) {
waitSec = initialWaitSec();
} else {
waitSec = MAX_WAIT_SEC;
}
System.out.println("--- iteration " + iterations + " ---");
try {
callable.call();
@ -125,4 +137,8 @@ public class PendingOperations {
}
} while (iterations <= ITERATIONS);
}
long initialWaitSec() {
return 1;
}
}

@ -62,7 +62,7 @@ public class PendingPingBinaryClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfPing = webSocket.sendPing(data);
try {
cfPing.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfPing.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -74,15 +74,20 @@ public class PendingPingBinaryClose extends PendingOperations {
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfBinary = webSocket.sendBinary(ByteBuffer.allocate(4), last);
assertHangs(cfBinary);
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfBinary, cfClose);
assertNotDone(cfPing);
webSocket.abort();
assertFails(IOE, cfPing);
assertFails(IOE, cfBinary);
assertFails(IOE, cfClose);
return null;
}, () -> cfPing.isDone());
webSocket.abort();
assertFails(IOE, cfPing);
assertFails(IOE, cfBinary);
assertFails(IOE, cfClose);
}
@Override
long initialWaitSec() {
// Some Windows machines increase buffer size after 1-2 seconds
return isWindows() ? 3 : 1;
}
}

@ -65,7 +65,7 @@ public class PendingPingTextClose extends PendingOperations {
if (debug) System.out.printf("begin cycle #%s at %s%n", i, start);
cfPing = webSocket.sendPing(data);
try {
cfPing.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfPing.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
done = true;
@ -73,31 +73,35 @@ public class PendingPingTextClose extends PendingOperations {
break;
} finally {
long stop = System.currentTimeMillis();
if (debug || done || (stop - start) > (MAX_WAIT_SEC * 1000L)/2L)
if (debug || done || (stop - start) > (waitSec * 1000L)/2L)
System.out.printf("end cycle #%s at %s (%s ms)%n", i, stop, stop - start);
}
}
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
System.out.println("asserting that sendText hangs");
cfText = webSocket.sendText("hello", last);
assertHangs(cfText);
System.out.println("asserting that sendClose hangs");
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
System.out.println("asserting that sendText and sendClose hang");
assertAllHang(cfText, cfClose);
System.out.println("asserting that cfPing is not completed");
assertNotDone(cfPing);
System.out.println("finishing");
webSocket.abort();
assertFails(IOE, cfPing);
assertFails(IOE, cfText);
assertFails(IOE, cfClose);
return null;
}, () -> cfPing.isDone()); // can't use method ref: cfPing not initialized
webSocket.abort();
assertFails(IOE, cfPing);
assertFails(IOE, cfText);
assertFails(IOE, cfClose);
} catch (Throwable t) {
System.err.printf("pendingPingTextClose(%s) failed: %s%n", last, t);
t.printStackTrace();
throw t;
}
}
@Override
long initialWaitSec() {
// Some Windows machines increase buffer size after 1-2 seconds
return isWindows() ? 3 : 1;
}
}

@ -62,7 +62,7 @@ public class PendingPongBinaryClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfPong = webSocket.sendPong(data);
try {
cfPong.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfPong.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -74,15 +74,20 @@ public class PendingPongBinaryClose extends PendingOperations {
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfBinary = webSocket.sendBinary(ByteBuffer.allocate(4), last);
assertHangs(cfBinary);
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfBinary, cfClose);
assertNotDone(cfPong);
webSocket.abort();
assertFails(IOE, cfPong);
assertFails(IOE, cfBinary);
assertFails(IOE, cfClose);
return null;
}, () -> cfPong.isDone());
webSocket.abort();
assertFails(IOE, cfPong);
assertFails(IOE, cfBinary);
assertFails(IOE, cfClose);
}
@Override
long initialWaitSec() {
// Some Windows machines increase buffer size after 1-2 seconds
return isWindows() ? 3 : 1;
}
}

@ -62,7 +62,7 @@ public class PendingPongTextClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfPong = webSocket.sendPong(data);
try {
cfPong.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfPong.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -74,15 +74,20 @@ public class PendingPongTextClose extends PendingOperations {
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfText = webSocket.sendText("hello", last);
assertHangs(cfText);
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfText, cfClose);
assertNotDone(cfPong);
webSocket.abort();
assertFails(IOE, cfPong);
assertFails(IOE, cfText);
assertFails(IOE, cfClose);
return null;
}, () -> cfPong.isDone());
webSocket.abort();
assertFails(IOE, cfPong);
assertFails(IOE, cfText);
assertFails(IOE, cfClose);
}
@Override
long initialWaitSec() {
// Some Windows machines increase buffer size after 1-2 seconds
return isWindows() ? 3 : 1;
}
}

@ -62,7 +62,7 @@ public class PendingTextPingClose extends PendingOperations {
cfText = webSocket.sendText(data, last);
try {
if (!cfText.isDone()) System.gc();
cfText.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfText.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -76,17 +76,16 @@ public class PendingTextPingClose extends PendingOperations {
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
cfPing = webSocket.sendPing(ByteBuffer.allocate(125));
assertHangs(cfPing);
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfPing, cfClose);
assertNotDone(cfText);
webSocket.abort();
assertFails(IOE, cfText);
assertFails(IOE, cfPing);
assertFails(IOE, cfClose);
return null;
}, () -> cfText.isDone());
webSocket.abort();
assertFails(IOE, cfText);
assertFails(IOE, cfPing);
assertFails(IOE, cfClose);
}
}

@ -61,7 +61,7 @@ public class PendingTextPongClose extends PendingOperations {
System.out.printf("begin cycle #%s at %s%n", i, start);
cfText = webSocket.sendText(data, last);
try {
cfText.get(MAX_WAIT_SEC, TimeUnit.SECONDS);
cfText.get(waitSec, TimeUnit.SECONDS);
data.clear();
} catch (TimeoutException e) {
break;
@ -75,17 +75,16 @@ public class PendingTextPongClose extends PendingOperations {
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
cfPong = webSocket.sendPong(ByteBuffer.allocate(125));
assertHangs(cfPong);
assertFails(ISE, webSocket.sendPing(ByteBuffer.allocate(125)));
assertFails(ISE, webSocket.sendPong(ByteBuffer.allocate(125)));
cfClose = webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
assertHangs(cfClose);
assertAllHang(cfPong, cfClose);
assertNotDone(cfText);
webSocket.abort();
assertFails(IOE, cfText);
assertFails(IOE, cfPong);
assertFails(IOE, cfClose);
return null;
}, () -> cfText.isDone());
webSocket.abort();
assertFails(IOE, cfText);
assertFails(IOE, cfPong);
assertFails(IOE, cfClose);
}
}