/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import okhttp3.internal.Version;
import okio.ByteString;
/**
* Exercises the web socket implementation against the <a
* href="http://autobahn.ws/testsuite/">Autobahn Testsuite</a>.
*/
public final class AutobahnTester {
private static final String HOST = "ws://localhost:9099";
public static void main(String... args) throws IOException {
new AutobahnTester().run();
}
final OkHttpClient client = new OkHttpClient();
private WebSocket newWebSocket(String path, WebSocketListener listener) {
Request request = new Request.Builder().url(HOST + path).build();
return client.newWebSocket(request, listener);
}
public void run() throws IOException {
try {
long count = getTestCount();
System.out.println("Test count: " + count);
for (long number = 1; number <= count; number++) {
runTest(number, count);
}
updateReports();
} finally {
client.dispatcher().executorService().shutdown();
}
}
private void runTest(final long number, final long count) {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicLong startNanos = new AtomicLong();
newWebSocket("/runCase?case=" + number + "&agent=okhttp", new WebSocketListener() {
@Override public void onOpen(WebSocket webSocket, Response response) {
System.out.println("Executing test case " + number + "/" + count);
startNanos.set(System.nanoTime());
}
@Override public void onMessage(final WebSocket webSocket, final ByteString bytes) {
webSocket.send(bytes);
}
@Override public void onMessage(final WebSocket webSocket, final String text) {
webSocket.send(text);
}
@Override public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
latch.countDown();
}
@Override public void onFailure(WebSocket webSocket, Throwable t, Response response) {
t.printStackTrace(System.out);
latch.countDown();
}
});
try {
if (!latch.await(30, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timed out waiting for test " + number + " to finish.");
}
} catch (InterruptedException e) {
throw new AssertionError();
}
long endNanos = System.nanoTime();
long tookMs = TimeUnit.NANOSECONDS.toMillis(endNanos - startNanos.get());
System.out.println("Took " + tookMs + "ms");
}
private long getTestCount() throws IOException {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicLong countRef = new AtomicLong();
final AtomicReference<Throwable> failureRef = new AtomicReference<>();
newWebSocket("/getCaseCount", new WebSocketListener() {
@Override public void onMessage(WebSocket webSocket, String text) {
countRef.set(Long.parseLong(text));
}
@Override public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
latch.countDown();
}
@Override public void onFailure(WebSocket webSocket, Throwable t, Response response) {
failureRef.set(t);
latch.countDown();
}
});
try {
if (!latch.await(10, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timed out waiting for count.");
}
} catch (InterruptedException e) {
throw new AssertionError();
}
Throwable failure = failureRef.get();
if (failure != null) {
throw new RuntimeException(failure);
}
return countRef.get();
}
private void updateReports() {
final CountDownLatch latch = new CountDownLatch(1);
newWebSocket("/updateReports?agent=" + Version.userAgent(), new WebSocketListener() {
@Override public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
latch.countDown();
}
@Override public void onFailure(WebSocket webSocket, Throwable t, Response response) {
latch.countDown();
}
});
try {
if (!latch.await(10, TimeUnit.SECONDS)) {
throw new IllegalStateException("Timed out waiting for count.");
}
} catch (InterruptedException e) {
throw new AssertionError();
}
}
}