1 /*
   2  * Copyright (c) 2018, 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         byte[] copy = new byte[data.length];
  83         for (int i = 0; i < data.length; i++) {
  84             copy[i] = (byte) data[i];
  85         }
  86         return serverWithCannedData(copy);
  87     }
  88 
  89     public static DummyWebSocketServer serverWithCannedData(byte... data) {
  90         byte[] copy = Arrays.copyOf(data, data.length);
  91         return new DummyWebSocketServer() {
  92             @Override
  93             protected void write(SocketChannel ch) throws IOException {
  94                 int off = 0; int n = 1; // 1 byte at a time
  95                 while (off + n < copy.length + n) {
  96 //                    try {
  97 //                        TimeUnit.MICROSECONDS.sleep(500);
  98 //                    } catch (InterruptedException e) {
  99 //                        return;
 100 //                    }
 101                     int len = Math.min(copy.length - off, n);
 102                     ByteBuffer bytes = ByteBuffer.wrap(copy, off, len);
 103                     off += len;
 104                     ch.write(bytes);
 105                 }
 106                 super.write(ch);
 107             }
 108         };
 109     }
 110 
 111     /*
 112      * This server does not read from the wire, allowing its client to fill up
 113      * their send buffer. Used to test scenarios with outstanding send
 114      * operations.
 115      */
 116     public static DummyWebSocketServer notReadingServer() {
 117         return new DummyWebSocketServer() {
 118             @Override
 119             protected void read(SocketChannel ch) throws IOException {
 120                 try {
 121                     Thread.sleep(Long.MAX_VALUE);
 122                 } catch (InterruptedException e) {
 123                     throw new IOException(e);
 124                 }
 125             }
 126         };
 127     }
 128 
 129     public static DummyWebSocketServer writingServer(int... data) {
 130         byte[] copy = new byte[data.length];
 131         for (int i = 0; i < data.length; i++) {
 132             copy[i] = (byte) data[i];
 133         }
 134         return new DummyWebSocketServer() {
 135 
 136             @Override
 137             protected void read(SocketChannel ch) throws IOException {
 138                 try {
 139                     Thread.sleep(Long.MAX_VALUE);
 140                 } catch (InterruptedException e) {
 141                     throw new IOException(e);
 142                 }
 143             }
 144 
 145             @Override
 146             protected void write(SocketChannel ch) throws IOException {
 147                 int off = 0; int n = 1; // 1 byte at a time
 148                 while (off + n < copy.length + n) {
 149 //                    try {
 150 //                        TimeUnit.MICROSECONDS.sleep(500);
 151 //                    } catch (InterruptedException e) {
 152 //                        return;
 153 //                    }
 154                     int len = Math.min(copy.length - off, n);
 155                     ByteBuffer bytes = ByteBuffer.wrap(copy, off, len);
 156                     off += len;
 157                     ch.write(bytes);
 158                 }
 159                 super.write(ch);
 160             }
 161         };
 162 
 163     }
 164 
 165     public static String stringWith2NBytes(int n) {
 166         // -- Russian Alphabet (33 characters, 2 bytes per char) --
 167         char[] abc = {
 168                 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416,
 169                 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
 170                 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426,
 171                 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E,
 172                 0x042F,
 173         };
 174         // repeat cyclically
 175         StringBuilder sb = new StringBuilder(n);
 176         for (int i = 0, j = 0; i < n; i++, j = (j + 1) % abc.length) {
 177             sb.append(abc[j]);
 178         }
 179         String s = sb.toString();
 180         assert s.length() == n && s.getBytes(StandardCharsets.UTF_8).length == 2 * n;
 181         return s;
 182     }
 183 
 184     public static String malformedString() {
 185         return new String(new char[]{0xDC00, 0xD800});
 186     }
 187 
 188     public static String incompleteString() {
 189         return new String(new char[]{0xD800});
 190     }
 191 
 192     public static String stringWithNBytes(int n) {
 193         char[] chars = new char[n];
 194         Arrays.fill(chars, 'A');
 195         return new String(chars);
 196     }
 197 }