test/jdk/java/net/httpclient/http2/java.net.http/java/net/http/internal/hpack/BuffersTestingKit.java
branchhttp-client-branch
changeset 56092 fd85b2bf2b0d
parent 56091 aedd6133e7a0
child 56093 22d94c4a3641
equal deleted inserted replaced
56091:aedd6133e7a0 56092:fd85b2bf2b0d
     1 /*
       
     2  * Copyright (c) 2015, 2017, 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 package java.net.http.internal.hpack;
       
    24 
       
    25 import java.nio.ByteBuffer;
       
    26 import java.util.*;
       
    27 import java.util.function.Consumer;
       
    28 import java.util.function.Function;
       
    29 import java.util.function.Supplier;
       
    30 
       
    31 import static java.nio.ByteBuffer.allocate;
       
    32 
       
    33 public final class BuffersTestingKit {
       
    34 
       
    35     /**
       
    36      * Relocates a {@code [position, limit)} region of the given buffer to
       
    37      * corresponding region in a new buffer starting with provided {@code
       
    38      * newPosition}.
       
    39      *
       
    40      * <p> Might be useful to make sure ByteBuffer's users do not rely on any
       
    41      * absolute positions, but solely on what's reported by position(), limit().
       
    42      *
       
    43      * <p> The contents between the given buffer and the returned one are not
       
    44      * shared.
       
    45      */
       
    46     public static ByteBuffer relocate(ByteBuffer buffer, int newPosition,
       
    47                                       int newCapacity) {
       
    48         int oldPosition = buffer.position();
       
    49         int oldLimit = buffer.limit();
       
    50 
       
    51         if (newPosition + oldLimit - oldPosition > newCapacity) {
       
    52             throw new IllegalArgumentException();
       
    53         }
       
    54 
       
    55         ByteBuffer result;
       
    56         if (buffer.isDirect()) {
       
    57             result = ByteBuffer.allocateDirect(newCapacity);
       
    58         } else {
       
    59             result = allocate(newCapacity);
       
    60         }
       
    61 
       
    62         result.position(newPosition);
       
    63         result.put(buffer).limit(result.position()).position(newPosition);
       
    64         buffer.position(oldPosition);
       
    65 
       
    66         if (buffer.isReadOnly()) {
       
    67             return result.asReadOnlyBuffer();
       
    68         }
       
    69         return result;
       
    70     }
       
    71 
       
    72     public static Iterable<? extends ByteBuffer> relocateBuffers(
       
    73             Iterable<? extends ByteBuffer> source) {
       
    74         return () ->
       
    75                 new Iterator<ByteBuffer>() {
       
    76 
       
    77                     private final Iterator<? extends ByteBuffer> it = source.iterator();
       
    78 
       
    79                     @Override
       
    80                     public boolean hasNext() {
       
    81                         return it.hasNext();
       
    82                     }
       
    83 
       
    84                     @Override
       
    85                     public ByteBuffer next() {
       
    86                         ByteBuffer buf = it.next();
       
    87                         int remaining = buf.remaining();
       
    88                         int newCapacity = remaining + random.nextInt(17);
       
    89                         int newPosition = random.nextInt(newCapacity - remaining + 1);
       
    90                         return relocate(buf, newPosition, newCapacity);
       
    91                     }
       
    92                 };
       
    93     }
       
    94 
       
    95     // TODO: not always of size 0 (it's fine for buffer to report !b.hasRemaining())
       
    96     public static Iterable<? extends ByteBuffer> injectEmptyBuffers(
       
    97             Iterable<? extends ByteBuffer> source) {
       
    98         return injectEmptyBuffers(source, () -> allocate(0));
       
    99     }
       
   100 
       
   101     public static Iterable<? extends ByteBuffer> injectEmptyBuffers(
       
   102             Iterable<? extends ByteBuffer> source,
       
   103             Supplier<? extends ByteBuffer> emptyBufferFactory) {
       
   104 
       
   105         return () ->
       
   106                 new Iterator<ByteBuffer>() {
       
   107 
       
   108                     private final Iterator<? extends ByteBuffer> it = source.iterator();
       
   109                     private ByteBuffer next = calculateNext();
       
   110 
       
   111                     private ByteBuffer calculateNext() {
       
   112                         if (random.nextBoolean()) {
       
   113                             return emptyBufferFactory.get();
       
   114                         } else if (it.hasNext()) {
       
   115                             return it.next();
       
   116                         } else {
       
   117                             return null;
       
   118                         }
       
   119                     }
       
   120 
       
   121                     @Override
       
   122                     public boolean hasNext() {
       
   123                         return next != null;
       
   124                     }
       
   125 
       
   126                     @Override
       
   127                     public ByteBuffer next() {
       
   128                         if (!hasNext()) {
       
   129                             throw new NoSuchElementException();
       
   130                         }
       
   131                         ByteBuffer next = this.next;
       
   132                         this.next = calculateNext();
       
   133                         return next;
       
   134                     }
       
   135                 };
       
   136     }
       
   137 
       
   138     public static ByteBuffer concat(Iterable<? extends ByteBuffer> split) {
       
   139         return concat(split, ByteBuffer::allocate);
       
   140     }
       
   141 
       
   142     public static ByteBuffer concat(Iterable<? extends ByteBuffer> split,
       
   143                                     Function<? super Integer, ? extends ByteBuffer> concatBufferFactory) {
       
   144         int size = 0;
       
   145         for (ByteBuffer bb : split) {
       
   146             size += bb.remaining();
       
   147         }
       
   148 
       
   149         ByteBuffer result = concatBufferFactory.apply(size);
       
   150         for (ByteBuffer bb : split) {
       
   151             result.put(bb);
       
   152         }
       
   153 
       
   154         result.flip();
       
   155         return result;
       
   156     }
       
   157 
       
   158     public static void forEachSplit(ByteBuffer bb,
       
   159                                     Consumer<? super Iterable<? extends ByteBuffer>> action) {
       
   160         forEachSplit(bb.remaining(),
       
   161                 (lengths) -> {
       
   162                     int end = bb.position();
       
   163                     List<ByteBuffer> buffers = new LinkedList<>();
       
   164                     for (int len : lengths) {
       
   165                         ByteBuffer d = bb.duplicate();
       
   166                         d.position(end);
       
   167                         d.limit(end + len);
       
   168                         end += len;
       
   169                         buffers.add(d);
       
   170                     }
       
   171                     action.accept(buffers);
       
   172                 });
       
   173     }
       
   174 
       
   175     private static void forEachSplit(int n, Consumer<? super Iterable<? extends Integer>> action) {
       
   176         forEachSplit(n, new Stack<>(), action);
       
   177     }
       
   178 
       
   179     private static void forEachSplit(int n, Stack<Integer> path,
       
   180                                      Consumer<? super Iterable<? extends Integer>> action) {
       
   181         if (n == 0) {
       
   182             action.accept(path);
       
   183         } else {
       
   184             for (int i = 1; i <= n; i++) {
       
   185                 path.push(i);
       
   186                 forEachSplit(n - i, path, action);
       
   187                 path.pop();
       
   188             }
       
   189         }
       
   190     }
       
   191 
       
   192     private static final Random random = new Random();
       
   193 
       
   194     private BuffersTestingKit() {
       
   195         throw new InternalError();
       
   196     }
       
   197 
       
   198 //    public static void main(String[] args) {
       
   199 //
       
   200 //        List<ByteBuffer> buffers = Arrays.asList(
       
   201 //                (ByteBuffer) allocate(3).position(1).limit(2),
       
   202 //                allocate(0),
       
   203 //                allocate(7));
       
   204 //
       
   205 //        Iterable<? extends ByteBuffer> buf = relocateBuffers(injectEmptyBuffers(buffers));
       
   206 //        List<ByteBuffer> result = new ArrayList<>();
       
   207 //        buf.forEach(result::add);
       
   208 //        System.out.println(result);
       
   209 //    }
       
   210 }