1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.IOException;
  25 import java.nio.ByteBuffer;
  26 import java.nio.channels.SocketChannel;
  27 import java.nio.charset.StandardCharsets;
  28 import java.util.Arrays;
  29 import java.util.concurrent.CompletableFuture;
  30 import java.util.concurrent.CompletionException;
  31 import java.util.concurrent.CompletionStage;
  32 import java.util.concurrent.TimeUnit;
  33 import java.util.concurrent.TimeoutException;
  34 
  35 import static org.testng.Assert.assertThrows;
  36 
  37 public class Support {
  38 
  39     private Support() { }
  40 
  41     public static void assertFails(Class<? extends Throwable> clazz,
  42                                     CompletionStage<?> stage) {
  43         Support.assertCompletesExceptionally(clazz, stage);
  44     }
  45 
  46     public static void assertCompletesExceptionally(Class<? extends Throwable> clazz,
  47                                                     CompletionStage<?> stage) {
  48         CompletableFuture<?> cf =
  49                 CompletableFuture.completedFuture(null).thenCompose(x -> stage);
  50         assertThrows(clazz, () -> {
  51             try {
  52                 cf.join();
  53             } catch (CompletionException e) {
  54                 throw e.getCause();
  55             }
  56         });
  57     }
  58 
  59     public static void assertHangs(CompletionStage<?> stage) {
  60         Support.assertDoesNotCompleteWithin(5, TimeUnit.SECONDS, stage);
  61     }
  62 
  63     public static void assertDoesNotCompleteWithin(long timeout,
  64                                                    TimeUnit unit,
  65                                                    CompletionStage<?> stage) {
  66         CompletableFuture<?> cf =
  67                 CompletableFuture.completedFuture(null).thenCompose(x -> stage);
  68         assertThrows(TimeoutException.class, () -> cf.get(timeout, unit));
  69     }
  70 
  71     public static ByteBuffer fullCopy(ByteBuffer src) {
  72         ByteBuffer copy = ByteBuffer.allocate(src.capacity());
  73         int p = src.position();
  74         int l = src.limit();
  75         src.clear();
  76         copy.put(src).position(p).limit(l);
  77         src.position(p).limit(l);
  78         return copy;
  79     }
  80 
  81     public static DummyWebSocketServer serverWithCannedData(int... data) {
  82         return serverWithCannedDataAndAuthentication(null, null, data);
  83     }
  84 
  85     public static DummyWebSocketServer serverWithCannedDataAndAuthentication(
  86             String username,
  87             String password,
  88             int... data)
  89     {
  90         byte[] copy = new byte[data.length];
  91         for (int i = 0; i < data.length; i++) {
  92             copy[i] = (byte) data[i];
  93         }
  94         return serverWithCannedDataAndAuthentication(username, password, copy);
  95     }
  96 
  97     public static DummyWebSocketServer serverWithCannedData(byte... data) {
  98        return serverWithCannedDataAndAuthentication(null, null, data);
  99     }
 100 
 101     public static DummyWebSocketServer serverWithCannedDataAndAuthentication(
 102             String username,
 103             String password,
 104             byte... data)
 105     {
 106         byte[] copy = Arrays.copyOf(data, data.length);
 107         return new DummyWebSocketServer(username, password) {
 108             @Override
 109             protected void write(SocketChannel ch) throws IOException {
 110                 int off = 0; int n = 1; // 1 byte at a time
 111                 while (off + n < copy.length + n) {
 112 //                    try {
 113 //                        TimeUnit.MICROSECONDS.sleep(500);
 114 //                    } catch (InterruptedException e) {
 115 //                        return;
 116 //                    }
 117                     int len = Math.min(copy.length - off, n);
 118                     ByteBuffer bytes = ByteBuffer.wrap(copy, off, len);
 119                     off += len;
 120                     ch.write(bytes);
 121                 }
 122                 super.write(ch);
 123             }
 124         };
 125     }
 126 
 127     /*
 128      * This server does not read from the wire, allowing its client to fill up
 129      * their send buffer. Used to test scenarios with outstanding send
 130      * operations.
 131      */
 132     public static DummyWebSocketServer notReadingServer() {
 133         return new DummyWebSocketServer() {
 134             @Override
 135             protected void read(SocketChannel ch) throws IOException {
 136                 try {
 137                     Thread.sleep(Long.MAX_VALUE);
 138                 } catch (InterruptedException e) {
 139                     throw new IOException(e);
 140                 }
 141             }
 142         };
 143     }
 144 
 145     public static DummyWebSocketServer writingServer(int... data) {
 146         byte[] copy = new byte[data.length];
 147         for (int i = 0; i < data.length; i++) {
 148             copy[i] = (byte) data[i];
 149         }
 150         return new DummyWebSocketServer() {
 151 
 152             @Override
 153             protected void read(SocketChannel ch) throws IOException {
 154                 try {
 155                     Thread.sleep(Long.MAX_VALUE);
 156                 } catch (InterruptedException e) {
 157                     throw new IOException(e);
 158                 }
 159             }
 160 
 161             @Override
 162             protected void write(SocketChannel ch) throws IOException {
 163                 int off = 0; int n = 1; // 1 byte at a time
 164                 while (off + n < copy.length + n) {
 165 //                    try {
 166 //                        TimeUnit.MICROSECONDS.sleep(500);
 167 //                    } catch (InterruptedException e) {
 168 //                        return;
 169 //                    }
 170                     int len = Math.min(copy.length - off, n);
 171                     ByteBuffer bytes = ByteBuffer.wrap(copy, off, len);
 172                     off += len;
 173                     ch.write(bytes);
 174                 }
 175                 super.write(ch);
 176             }
 177         };
 178 
 179     }
 180 
 181     public static String stringWith2NBytes(int n) {
 182         // -- Russian Alphabet (33 characters, 2 bytes per char) --
 183         char[] abc = {
 184                 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416,
 185                 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
 186                 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426,
 187                 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E,
 188                 0x042F,
 189         };
 190         // repeat cyclically
 191         StringBuilder sb = new StringBuilder(n);
 192         for (int i = 0, j = 0; i < n; i++, j = (j + 1) % abc.length) {
 193             sb.append(abc[j]);
 194         }
 195         String s = sb.toString();
 196         assert s.length() == n && s.getBytes(StandardCharsets.UTF_8).length == 2 * n;
 197         return s;
 198     }
 199 
 200     public static String malformedString() {
 201         return new String(new char[]{0xDC00, 0xD800});
 202     }
 203 
 204     public static String incompleteString() {
 205         return new String(new char[]{0xD800});
 206     }
 207 
 208     public static String stringWithNBytes(int n) {
 209         char[] chars = new char[n];
 210         Arrays.fill(chars, 'A');
 211         return new String(chars);
 212     }
 213 }