test/jdk/java/net/httpclient/websocket/MockListener.java
branchhttp-client-branch
changeset 56303 a82058c084ef
child 56314 f92e7a8a189f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/websocket/MockListener.java	Wed Mar 14 13:03:11 2018 +0000
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.http.WebSocket;
+import java.net.http.WebSocket.MessagePart;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Predicate;
+
+public class MockListener implements WebSocket.Listener {
+
+    private final long bufferSize;
+    private long count;
+    private final List<Invocation> invocations = new ArrayList<>();
+    private final CompletableFuture<?> lastCall = new CompletableFuture<>();
+    private final Predicate<? super Invocation> collectUntil;
+
+    public MockListener() {
+        this(i -> i instanceof OnClose || i instanceof OnError);
+    }
+
+    public MockListener(Predicate<? super Invocation> collectUntil) {
+        this(2, collectUntil);
+    }
+
+    /*
+     * Typical buffer sizes: 1, n, Long.MAX_VALUE
+     */
+    public MockListener(long bufferSize,
+                        Predicate<? super Invocation> collectUntil) {
+        if (bufferSize < 1) {
+            throw new IllegalArgumentException();
+        }
+        Objects.requireNonNull(collectUntil);
+        this.bufferSize = bufferSize;
+        this.collectUntil = collectUntil;
+    }
+
+    @Override
+    public void onOpen(WebSocket webSocket) {
+        System.out.printf("onOpen(%s)%n", webSocket);
+        OnOpen inv = new OnOpen(webSocket);
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        onOpen0(webSocket);
+    }
+
+    protected void onOpen0(WebSocket webSocket) {
+        replenish(webSocket);
+    }
+
+    @Override
+    public CompletionStage<?> onText(WebSocket webSocket,
+                                     CharSequence message,
+                                     MessagePart part) {
+        System.out.printf("onText(%s, %s, %s)%n", webSocket, message, part);
+        OnText inv = new OnText(webSocket, message.toString(), part);
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        return onText0(webSocket, message, part);
+    }
+
+    protected CompletionStage<?> onText0(WebSocket webSocket,
+                                         CharSequence message,
+                                         MessagePart part) {
+        replenish(webSocket);
+        return null;
+    }
+
+    @Override
+    public CompletionStage<?> onBinary(WebSocket webSocket,
+                                       ByteBuffer message,
+                                       MessagePart part) {
+        System.out.printf("onBinary(%s, %s, %s)%n", webSocket, message, part);
+        OnBinary inv = new OnBinary(webSocket, fullCopy(message), part);
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        return onBinary0(webSocket, message, part);
+    }
+
+    protected CompletionStage<?> onBinary0(WebSocket webSocket,
+                                           ByteBuffer message,
+                                           MessagePart part) {
+        replenish(webSocket);
+        return null;
+    }
+
+    @Override
+    public CompletionStage<?> onPing(WebSocket webSocket, ByteBuffer message) {
+        System.out.printf("onPing(%s, %s)%n", webSocket, message);
+        OnPing inv = new OnPing(webSocket, fullCopy(message));
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        return onPing0(webSocket, message);
+    }
+
+    protected CompletionStage<?> onPing0(WebSocket webSocket, ByteBuffer message) {
+        replenish(webSocket);
+        return null;
+    }
+
+    @Override
+    public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
+        System.out.printf("onPong(%s, %s)%n", webSocket, message);
+        OnPong inv = new OnPong(webSocket, fullCopy(message));
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        return onPong0(webSocket, message);
+    }
+
+    protected CompletionStage<?> onPong0(WebSocket webSocket, ByteBuffer message) {
+        replenish(webSocket);
+        return null;
+    }
+
+    @Override
+    public CompletionStage<?> onClose(WebSocket webSocket,
+                                      int statusCode,
+                                      String reason) {
+        System.out.printf("onClose(%s, %s, %s)%n", webSocket, statusCode, reason);
+        OnClose inv = new OnClose(webSocket, statusCode, reason);
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+        return null;
+    }
+
+    @Override
+    public void onError(WebSocket webSocket, Throwable error) {
+        System.out.printf("onError(%s, %s)%n", webSocket, error);
+        OnError inv = new OnError(webSocket, error == null ? null : error.getClass());
+        invocations.add(inv);
+        if (collectUntil.test(inv)) {
+            lastCall.complete(null);
+        }
+    }
+
+    public List<Invocation> invocations() {
+        lastCall.join();
+        return new ArrayList<>(invocations);
+    }
+
+    protected void replenish(WebSocket webSocket) {
+        if (--count <= 0) {
+            count = bufferSize - bufferSize / 2;
+        }
+        webSocket.request(count);
+    }
+
+    public abstract static class Invocation {
+
+        public static OnOpen onOpen(WebSocket webSocket) {
+            return new OnOpen(webSocket);
+        }
+
+        public static OnText onText(WebSocket webSocket,
+                                    String text,
+                                    MessagePart part) {
+            return new OnText(webSocket, text, part);
+        }
+
+        public static OnBinary onBinary(WebSocket webSocket,
+                                        ByteBuffer data,
+                                        MessagePart part) {
+            return new OnBinary(webSocket, data, part);
+        }
+
+        public static OnPing onPing(WebSocket webSocket,
+                                    ByteBuffer data) {
+            return new OnPing(webSocket, data);
+        }
+
+        public static OnPong onPong(WebSocket webSocket,
+                                    ByteBuffer data) {
+            return new OnPong(webSocket, data);
+        }
+
+        public static OnClose onClose(WebSocket webSocket,
+                                      int statusCode,
+                                      String reason) {
+            return new OnClose(webSocket, statusCode, reason);
+        }
+
+        public static OnError onError(WebSocket webSocket,
+                                      Class<? extends Throwable> clazz) {
+            return new OnError(webSocket, clazz);
+        }
+
+        final WebSocket webSocket;
+
+        private Invocation(WebSocket webSocket) {
+            this.webSocket = webSocket;
+        }
+    }
+
+    public static final class OnOpen extends Invocation {
+
+        public OnOpen(WebSocket webSocket) {
+            super(webSocket);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Invocation that = (Invocation) o;
+            return Objects.equals(webSocket, that.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onOpen(%s)", webSocket);
+        }
+    }
+
+    public static final class OnText extends Invocation {
+
+        final String text;
+        final MessagePart part;
+
+        public OnText(WebSocket webSocket, String text, MessagePart part) {
+            super(webSocket);
+            this.text = text;
+            this.part = part;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnText onText = (OnText) o;
+            return Objects.equals(text, onText.text) &&
+                    part == onText.part &&
+                    Objects.equals(webSocket, onText.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(text, part, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onText(%s, %s, %s)", webSocket, text, part);
+        }
+    }
+
+    public static final class OnBinary extends Invocation {
+
+        final ByteBuffer data;
+        final MessagePart part;
+
+        public OnBinary(WebSocket webSocket, ByteBuffer data, MessagePart part) {
+            super(webSocket);
+            this.data = data;
+            this.part = part;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnBinary onBinary = (OnBinary) o;
+            return Objects.equals(data, onBinary.data) &&
+                    part == onBinary.part &&
+                    Objects.equals(webSocket, onBinary.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(data, part, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onBinary(%s, %s, %s)", webSocket, data, part);
+        }
+    }
+
+    public static final class OnPing extends Invocation {
+
+        final ByteBuffer data;
+
+        public OnPing(WebSocket webSocket, ByteBuffer data) {
+            super(webSocket);
+            this.data = data;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnPing onPing = (OnPing) o;
+            return Objects.equals(data, onPing.data) &&
+                    Objects.equals(webSocket, onPing.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(data, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onPing(%s, %s)", webSocket, data);
+        }
+    }
+
+    public static final class OnPong extends Invocation {
+
+        final ByteBuffer data;
+
+        public OnPong(WebSocket webSocket, ByteBuffer data) {
+            super(webSocket);
+            this.data = data;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnPong onPong = (OnPong) o;
+            return Objects.equals(data, onPong.data) &&
+                    Objects.equals(webSocket, onPong.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(data, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onPong(%s, %s)", webSocket, data);
+        }
+    }
+
+    public static final class OnClose extends Invocation {
+
+        final int statusCode;
+        final String reason;
+
+        public OnClose(WebSocket webSocket, int statusCode, String reason) {
+            super(webSocket);
+            this.statusCode = statusCode;
+            this.reason = reason;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnClose onClose = (OnClose) o;
+            return statusCode == onClose.statusCode &&
+                    Objects.equals(reason, onClose.reason) &&
+                    Objects.equals(webSocket, onClose.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(statusCode, reason, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onClose(%s, %s, %s)", webSocket, statusCode, reason);
+        }
+    }
+
+    public static final class OnError extends Invocation {
+
+        final Class<? extends Throwable> clazz;
+
+        public OnError(WebSocket webSocket, Class<? extends Throwable> clazz) {
+            super(webSocket);
+            this.clazz = clazz;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OnError onError = (OnError) o;
+            return Objects.equals(clazz, onError.clazz) &&
+                    Objects.equals(webSocket, onError.webSocket);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(clazz, webSocket);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("onError(%s, %s)", webSocket, clazz);
+        }
+    }
+
+    private static ByteBuffer fullCopy(ByteBuffer src) {
+        ByteBuffer copy = ByteBuffer.allocate(src.capacity());
+        int p = src.position();
+        int l = src.limit();
+        src.clear();
+        copy.put(src).position(p).limit(l);
+        src.position(p).limit(l);
+        return copy;
+    }
+}