test/jdk/java/net/httpclient/http2/ServerPush.java
branchhttp-client-branch
changeset 56037 c026ce4a1a81
parent 56034 43b531ed872b
child 56089 42208b2f224e
equal deleted inserted replaced
56036:89a688549f5d 56037:c026ce4a1a81
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    37 import java.net.*;
    37 import java.net.*;
    38 import java.nio.ByteBuffer;
    38 import java.nio.ByteBuffer;
    39 import java.nio.file.*;
    39 import java.nio.file.*;
    40 import jdk.incubator.http.*;
    40 import jdk.incubator.http.*;
    41 import jdk.incubator.http.HttpResponse.BodyHandler;
    41 import jdk.incubator.http.HttpResponse.BodyHandler;
       
    42 import jdk.incubator.http.HttpResponse.BodySubscriber;
    42 import jdk.incubator.http.HttpResponse.PushPromiseHandler;
    43 import jdk.incubator.http.HttpResponse.PushPromiseHandler;
    43 import java.util.*;
    44 import java.util.*;
    44 import java.util.concurrent.*;
    45 import java.util.concurrent.*;
    45 import java.util.function.Consumer;
    46 import java.util.function.Consumer;
    46 import java.util.function.UnaryOperator;
    47 import java.util.function.UnaryOperator;
    47 
       
    48 import org.testng.annotations.AfterTest;
    48 import org.testng.annotations.AfterTest;
    49 import org.testng.annotations.BeforeTest;
    49 import org.testng.annotations.BeforeTest;
    50 import org.testng.annotations.Test;
    50 import org.testng.annotations.Test;
    51 import static java.nio.charset.StandardCharsets.UTF_8;
    51 import static java.nio.charset.StandardCharsets.UTF_8;
       
    52 import static jdk.incubator.http.HttpResponse.BodyHandler.asByteArrayConsumer;
       
    53 import static jdk.incubator.http.HttpResponse.BodyHandler.asFile;
       
    54 import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
    52 import static org.testng.Assert.*;
    55 import static org.testng.Assert.*;
    53 
    56 
    54 
    57 
    55 public class ServerPush {
    58 public class ServerPush {
    56 
    59 
    62     Http2TestServer server;
    65     Http2TestServer server;
    63     URI uri;
    66     URI uri;
    64 
    67 
    65     @BeforeTest
    68     @BeforeTest
    66     public void setup() throws Exception {
    69     public void setup() throws Exception {
       
    70         tempFile = TestUtil.getAFile(FILE_SIZE);
    67         server = new Http2TestServer(false, 0);
    71         server = new Http2TestServer(false, 0);
    68         server.addHandler(new PushHandler(FILE_SIZE, LOOPS), "/");
    72         server.addHandler(new PushHandler(tempFile, LOOPS), "/");
    69         tempFile = TestUtil.getAFile(FILE_SIZE);
       
    70         System.out.println("Using temp file:" + tempFile);
    73         System.out.println("Using temp file:" + tempFile);
    71 
    74 
    72         System.err.println("Server listening on port " + server.getAddress().getPort());
    75         System.err.println("Server listening on port " + server.getAddress().getPort());
    73         server.start();
    76         server.start();
    74         int port = server.getAddress().getPort();
    77         int port = server.getAddress().getPort();
    78     @AfterTest
    81     @AfterTest
    79     public void teardown() {
    82     public void teardown() {
    80         server.stop();
    83         server.stop();
    81     }
    84     }
    82 
    85 
    83     static final UnaryOperator<HttpResponse<?>>
    86     // Test 1 - custom written push promise handler, everything as a String
    84             assert200ResponseCode = (response) -> {
       
    85                 assertEquals(response.statusCode(), 200);
       
    86                 return response;
       
    87     };
       
    88 
       
    89     interface Peeker<T> extends UnaryOperator<T> {
       
    90         void peek(T t);
       
    91 
       
    92         default T apply(T t)
       
    93         {
       
    94             peek(t);
       
    95             return t;
       
    96         }
       
    97     }
       
    98 
       
    99     @Test
    87     @Test
   100     public void testTypeString() throws Exception {
    88     public void testTypeString() throws Exception {
   101         // use multi-level path
    89         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
   102         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
    90         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>>
   103 
    91                 resultMap = new ConcurrentHashMap<>();
   104         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
    92 
   105 
       
   106         // Attempt 2
       
   107         HttpClient client = HttpClient.newBuilder()
       
   108                 .version(HttpClient.Version.HTTP_2)
       
   109                 .build();
       
   110 
       
   111         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>> results = new ConcurrentHashMap<>();
       
   112 
       
   113 
       
   114         // Example 2 - of(...) building your own Map, everything as a String
       
   115         PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> {
    93         PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> {
   116             BodyHandler<String> s = BodyHandler.asString(UTF_8);
    94             BodyHandler<String> s = BodyHandler.asString(UTF_8);
   117             CompletableFuture<HttpResponse<String>> cf = acceptor.apply(s);
    95             CompletableFuture<HttpResponse<String>> cf = acceptor.apply(s);
   118             results.put(pushRequest, cf);
    96             resultMap.put(pushRequest, cf);
   119         };
    97         };
   120 
    98 
       
    99         HttpClient client = HttpClient.newHttpClient();
       
   100         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
   121         CompletableFuture<HttpResponse<String>> cf =
   101         CompletableFuture<HttpResponse<String>> cf =
   122                 client.sendAsync(request, BodyHandler.asString(), pph);
   102                 client.sendAsync(request, asString(UTF_8), pph);
   123         cf.join();
   103         cf.join();
   124         results.put(request, cf);
   104         resultMap.put(request, cf);
   125 
   105         System.err.println("results.size: " + resultMap.size());
   126         System.err.println(results.size());
   106         for (HttpRequest r : resultMap.keySet()) {
   127         Set<HttpRequest> requests = results.keySet();
   107             HttpResponse<String> response = resultMap.get(r).join();
   128 
   108             assertEquals(response.statusCode(), 200);
   129         System.err.println("results.size: " + results.size());
   109             assertEquals(response.body(), tempFileAsString);
   130         for (HttpRequest r : requests) {
   110         }
   131             String result = results.get(r).get().body();
   111         assertEquals(resultMap.size(), LOOPS + 1);
   132             if (!result.equals(tempFileAsString)) {
   112     }
   133                 System.err.println("Got [" + result + ", expected [" + tempFileAsString + "]");
   113 
   134             }
   114     // Test 2 - of(...) populating the given Map, everything as a String
   135         }
   115     @Test
   136         if (requests.size() != LOOPS + 1)
   116     public void testTypeStringOfMap() throws Exception {
   137             throw new RuntimeException("Some results missing, expected:" + LOOPS + 1 + ", got:" + results.size());
   117         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
       
   118         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>>
       
   119                 resultMap = new ConcurrentHashMap<>();
       
   120 
       
   121         PushPromiseHandler<String> pph =
       
   122                 PushPromiseHandler.of(pushPromise -> asString(UTF_8),
       
   123                                       resultMap);
       
   124 
       
   125         HttpClient client = HttpClient.newHttpClient();
       
   126         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
       
   127         CompletableFuture<HttpResponse<String>> cf =
       
   128                 client.sendAsync(request, asString(UTF_8), pph);
       
   129         cf.join();
       
   130         resultMap.put(request, cf);
       
   131         System.err.println("results.size: " + resultMap.size());
       
   132         for (HttpRequest r : resultMap.keySet()) {
       
   133             HttpResponse<String> response = resultMap.get(r).join();
       
   134             assertEquals(response.statusCode(), 200);
       
   135             assertEquals(response.body(), tempFileAsString);
       
   136         }
       
   137         assertEquals(resultMap.size(), LOOPS + 1);
   138     }
   138     }
   139 
   139 
   140     // --- Path ---
   140     // --- Path ---
   141 
   141 
   142     static final Path dir = Paths.get(".", "serverPush");
   142     static final Path dir = Paths.get(".", "serverPush");
   146         try {
   146         try {
   147             Files.createDirectories(path.getParent());
   147             Files.createDirectories(path.getParent());
   148         } catch (IOException ee) {
   148         } catch (IOException ee) {
   149             throw new UncheckedIOException(ee);
   149             throw new UncheckedIOException(ee);
   150         }
   150         }
   151         return BodyHandler.asFile(path);
   151         return asFile(path);
   152     };
   152     }
   153 
   153 
       
   154     // Test 3 - custom written push promise handler, everything as a Path
   154     @Test
   155     @Test
   155     public void testTypePath() throws Exception {
   156     public void testTypePath() throws Exception {
   156         HttpClient client = HttpClient.newHttpClient();
   157         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
   157         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
   158         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap
   158 
   159                 = new ConcurrentHashMap<>();
   159         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> map
   160 
   160                 = new ConcurrentHashMap<>();
       
   161 
       
   162         // Example 4 - of(...) building your own Map, everything as a Path
       
   163         PushPromiseHandler<Path> pushPromiseHandler = (initial, pushRequest, acceptor) -> {
   161         PushPromiseHandler<Path> pushPromiseHandler = (initial, pushRequest, acceptor) -> {
   164             BodyHandler<Path> pp = requestToPath(pushRequest);
   162             BodyHandler<Path> pp = requestToPath(pushRequest);
   165             CompletableFuture<HttpResponse<Path>> cf = acceptor.apply(pp);
   163             CompletableFuture<HttpResponse<Path>> cf = acceptor.apply(pp);
   166             map.put(pushRequest, cf);
   164             resultsMap.put(pushRequest, cf);
   167         };
   165         };
   168 
   166 
       
   167         HttpClient client = HttpClient.newHttpClient();
       
   168         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
   169         CompletableFuture<HttpResponse<Path>> cf =
   169         CompletableFuture<HttpResponse<Path>> cf =
   170                 client.sendAsync(request, requestToPath(request), pushPromiseHandler);
   170                 client.sendAsync(request, requestToPath(request), pushPromiseHandler);
   171         cf.join();
   171         cf.join();
   172         map.put(request, cf);
   172         resultsMap.put(request, cf);
   173 
   173 
   174         System.err.println("map.size: " + map.size());
   174         for (HttpRequest r : resultsMap.keySet()) {
   175         for (HttpRequest r : map.keySet()) {
   175             HttpResponse<Path> response = resultsMap.get(r).join();
   176             Path path = map.get(r).get().body();
   176             assertEquals(response.statusCode(), 200);
   177             String fileAsString = new String(Files.readAllBytes(path), UTF_8);
   177             String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8);
   178             String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
       
   179             assertEquals(fileAsString, tempFileAsString);
   178             assertEquals(fileAsString, tempFileAsString);
   180         }
   179         }
   181         assertEquals(map.size(),  LOOPS + 1);
   180         assertEquals(resultsMap.size(),  LOOPS + 1);
       
   181     }
       
   182 
       
   183     // Test 4 - of(...) populating the given Map, everything as a Path
       
   184     @Test
       
   185     public void testTypePathOfMap() throws Exception {
       
   186         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
       
   187         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap
       
   188                 = new ConcurrentHashMap<>();
       
   189 
       
   190         PushPromiseHandler<Path> pushPromiseHandler =
       
   191                 PushPromiseHandler.of(pushRequest -> requestToPath(pushRequest),
       
   192                         resultsMap);
       
   193 
       
   194         HttpClient client = HttpClient.newHttpClient();
       
   195         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
       
   196         CompletableFuture<HttpResponse<Path>> cf =
       
   197                 client.sendAsync(request, requestToPath(request), pushPromiseHandler);
       
   198         cf.join();
       
   199         resultsMap.put(request, cf);
       
   200 
       
   201         for (HttpRequest r : resultsMap.keySet()) {
       
   202             HttpResponse<Path> response = resultsMap.get(r).join();
       
   203             assertEquals(response.statusCode(), 200);
       
   204             String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8);
       
   205             assertEquals(fileAsString, tempFileAsString);
       
   206         }
       
   207         assertEquals(resultsMap.size(),  LOOPS + 1);
   182     }
   208     }
   183 
   209 
   184     // ---  Consumer<byte[]> ---
   210     // ---  Consumer<byte[]> ---
   185 
   211 
   186     static class ByteArrayConsumer implements Consumer<Optional<byte[]>> {
   212     static class ByteArrayConsumer implements Consumer<Optional<byte[]>> {
   201                 listByteArrays.add(optionalBytes.get());
   227                 listByteArrays.add(optionalBytes.get());
   202             }
   228             }
   203         }
   229         }
   204     }
   230     }
   205 
   231 
       
   232     // Test 5 - custom written handler, everything as a consumer of optional byte[]
   206     @Test
   233     @Test
   207     public void testTypeByteArrayConsumer() throws Exception {
   234     public void testTypeByteArrayConsumer() throws Exception {
   208         HttpClient client = HttpClient.newHttpClient();
   235         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
   209         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
   236         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap
   210 
       
   211         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultMap
       
   212                 = new ConcurrentHashMap<>();
   237                 = new ConcurrentHashMap<>();
   213         Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap
   238         Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap
   214                 = new ConcurrentHashMap<>();
   239                 = new ConcurrentHashMap<>();
   215 
   240 
       
   241         HttpClient client = HttpClient.newHttpClient();
       
   242         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
   216         ByteArrayConsumer bac = new ByteArrayConsumer();
   243         ByteArrayConsumer bac = new ByteArrayConsumer();
   217         byteArrayConsumerMap.put(request, bac);
   244         byteArrayConsumerMap.put(request, bac);
   218 
   245 
   219         // Example 5 - withXXX and everything as a consumer of optional byte[]
   246         PushPromiseHandler<Void> pushPromiseHandler = (initial, pushRequest, acceptor) -> {
   220         PushPromiseHandler<Void> pushPromiseHandler =
   247             CompletableFuture<HttpResponse<Void>> cf = acceptor.apply(
   221                 PushPromiseHandler.of(pushRequest -> {
   248                     (statusCode, headers) -> {
   222                                                        ByteArrayConsumer bc = new ByteArrayConsumer();
   249                         ByteArrayConsumer bc = new ByteArrayConsumer();
   223                                                        byteArrayConsumerMap.put(pushRequest, bc);
   250                         byteArrayConsumerMap.put(pushRequest, bc);
   224                                                        return BodyHandler.asByteArrayConsumer(bc);
   251                         return BodySubscriber.asByteArrayConsumer(bc); } );
   225                                                     },
   252             resultsMap.put(pushRequest, cf);
   226                                                     resultMap);
   253         };
   227 
   254 
   228         CompletableFuture<HttpResponse<Void>> cf =
   255         CompletableFuture<HttpResponse<Void>> cf =
   229                 client.sendAsync(request, BodyHandler.asByteArrayConsumer(bac), pushPromiseHandler);
   256                 client.sendAsync(request, asByteArrayConsumer(bac), pushPromiseHandler);
   230         cf.join();
   257         cf.join();
   231         resultMap.put(request, cf);
   258         resultsMap.put(request, cf);
   232 
   259 
   233         System.err.println("map.size: " + resultMap.size());
   260         for (HttpRequest r : resultsMap.keySet()) {
   234         for (HttpRequest r : resultMap.keySet()) {
   261             HttpResponse<Void> response = resultsMap.get(r).join();
   235             resultMap.get(r).join();
   262             assertEquals(response.statusCode(), 200);
   236             byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes();
   263             byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes();
   237             String result = new String(ba, UTF_8);
   264             String result = new String(ba, UTF_8);
   238             System.out.println("HEGO result=" + result);
       
   239             System.out.println("HEGO result.length=" + result.length());
       
   240             System.err.printf("%s -> %s\n", r.uri().toString(), result);
       
   241             String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
       
   242             System.out.println("HEGO tempFileAsString=" + tempFileAsString);
       
   243             System.out.println("HEGO tempFileAsString.length=" + tempFileAsString.length());
       
   244             assertEquals(result, tempFileAsString);
   265             assertEquals(result, tempFileAsString);
   245         }
   266         }
   246 
   267         assertEquals(resultsMap.size(), LOOPS + 1);
   247         assertEquals(resultMap.size(), LOOPS + 1);
   268     }
       
   269 
       
   270     // Test 6 - of(...) populating the given Map, everything as a consumer of optional byte[]
       
   271     @Test
       
   272     public void testTypeByteArrayConsumerOfMap() throws Exception {
       
   273         String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
       
   274         ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap
       
   275                 = new ConcurrentHashMap<>();
       
   276         Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap
       
   277                 = new ConcurrentHashMap<>();
       
   278 
       
   279         HttpClient client = HttpClient.newHttpClient();
       
   280         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
       
   281         ByteArrayConsumer bac = new ByteArrayConsumer();
       
   282         byteArrayConsumerMap.put(request, bac);
       
   283 
       
   284         PushPromiseHandler<Void> pushPromiseHandler =
       
   285                 PushPromiseHandler.of(
       
   286                         pushRequest -> {
       
   287                             ByteArrayConsumer bc = new ByteArrayConsumer();
       
   288                             byteArrayConsumerMap.put(pushRequest, bc);
       
   289                             return BodyHandler.asByteArrayConsumer(bc);
       
   290                         },
       
   291                         resultsMap);
       
   292 
       
   293         CompletableFuture<HttpResponse<Void>> cf =
       
   294                 client.sendAsync(request, asByteArrayConsumer(bac), pushPromiseHandler);
       
   295         cf.join();
       
   296         resultsMap.put(request, cf);
       
   297 
       
   298         for (HttpRequest r : resultsMap.keySet()) {
       
   299             HttpResponse<Void> response = resultsMap.get(r).join();
       
   300             assertEquals(response.statusCode(), 200);
       
   301             byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes();
       
   302             String result = new String(ba, UTF_8);
       
   303             assertEquals(result, tempFileAsString);
       
   304         }
       
   305         assertEquals(resultsMap.size(), LOOPS + 1);
   248     }
   306     }
   249 }
   307 }