test/jdk/java/net/httpclient/ShortResponseBody.java
branchhttp-client-branch
changeset 56730 b08918259eed
parent 56695 d219df0c7d24
child 56752 54e96d77af2c
equal deleted inserted replaced
56729:d32f57638b7b 56730:b08918259eed
    23 
    23 
    24 /*
    24 /*
    25  * @test
    25  * @test
    26  * @summary Tests Exception detail message when too few response bytes are
    26  * @summary Tests Exception detail message when too few response bytes are
    27  *          received before a socket exception or eof.
    27  *          received before a socket exception or eof.
    28  * @run testng/othervm ShortResponseBody
    28  * @library /lib/testlibrary
    29  * @run testng/othervm -Djdk.httpclient.enableAllMethodRetry ShortResponseBody
    29  * @build jdk.testlibrary.SimpleSSLContext
       
    30  * @run testng/othervm
       
    31  *       -Djdk.internal.httpclient.debug=true
       
    32  *       ShortResponseBody
       
    33  * @run testng/othervm
       
    34  *       -Djdk.internal.httpclient.debug=true
       
    35  *       -Djdk.httpclient.enableAllMethodRetry
       
    36  *       ShortResponseBody
    30  */
    37  */
    31 
    38 
    32 import java.io.IOException;
    39 import java.io.IOException;
    33 import java.io.InputStream;
    40 import java.io.InputStream;
    34 import java.io.OutputStream;
    41 import java.io.OutputStream;
    38 import java.net.ServerSocket;
    45 import java.net.ServerSocket;
    39 import java.net.Socket;
    46 import java.net.Socket;
    40 import java.net.URI;
    47 import java.net.URI;
    41 import java.net.http.HttpClient;
    48 import java.net.http.HttpClient;
    42 import java.net.http.HttpRequest;
    49 import java.net.http.HttpRequest;
       
    50 import java.net.http.HttpRequest.BodyPublishers;
    43 import java.net.http.HttpResponse;
    51 import java.net.http.HttpResponse;
    44 import java.util.ArrayList;
    52 import java.util.ArrayList;
    45 import java.util.Arrays;
    53 import java.util.Arrays;
    46 import java.util.List;
    54 import java.util.List;
    47 import java.util.concurrent.ExecutionException;
    55 import java.util.concurrent.ExecutionException;
    48 import java.util.stream.Stream;
    56 import java.util.stream.Stream;
       
    57 import jdk.testlibrary.SimpleSSLContext;
    49 import org.testng.annotations.AfterTest;
    58 import org.testng.annotations.AfterTest;
    50 import org.testng.annotations.BeforeTest;
    59 import org.testng.annotations.BeforeTest;
    51 import org.testng.annotations.DataProvider;
    60 import org.testng.annotations.DataProvider;
    52 import org.testng.annotations.Test;
    61 import org.testng.annotations.Test;
       
    62 import javax.net.ssl.SSLContext;
       
    63 import javax.net.ssl.SSLServerSocketFactory;
       
    64 import javax.net.ssl.SSLSocket;
    53 import static java.lang.System.out;
    65 import static java.lang.System.out;
    54 import static java.net.http.HttpClient.Builder.NO_PROXY;
    66 import static java.net.http.HttpClient.Builder.NO_PROXY;
    55 import static java.net.http.HttpResponse.BodyHandlers.ofString;
    67 import static java.net.http.HttpResponse.BodyHandlers.ofString;
    56 import static java.nio.charset.StandardCharsets.US_ASCII;
    68 import static java.nio.charset.StandardCharsets.US_ASCII;
    57 import static java.util.stream.Collectors.toList;
    69 import static java.util.stream.Collectors.toList;
    60 import static org.testng.Assert.fail;
    72 import static org.testng.Assert.fail;
    61 
    73 
    62 public class ShortResponseBody {
    74 public class ShortResponseBody {
    63 
    75 
    64     Server closeImmediatelyServer;
    76     Server closeImmediatelyServer;
       
    77     Server closeImmediatelyHttpsServer;
    65     Server variableLengthServer;
    78     Server variableLengthServer;
       
    79     Server variableLengthHttpsServer;
    66     Server fixedLengthServer;
    80     Server fixedLengthServer;
    67 
    81 
    68     String httpURIClsImed;
    82     String httpURIClsImed;
       
    83     String httpsURIClsImed;
    69     String httpURIVarLen;
    84     String httpURIVarLen;
       
    85     String httpsURIVarLen;
    70     String httpURIFixLen;
    86     String httpURIFixLen;
       
    87 
       
    88     SSLContext sslContext;
    71 
    89 
    72     static final String EXPECTED_RESPONSE_BODY =
    90     static final String EXPECTED_RESPONSE_BODY =
    73             "<html><body><h1>Heading</h1><p>Some Text</p></body></html>";
    91             "<html><body><h1>Heading</h1><p>Some Text</p></body></html>";
    74 
    92 
    75     @DataProvider(name = "sanity")
    93     @DataProvider(name = "sanity")
    76     public Object[][] sanity() {
    94     public Object[][] sanity() {
    77         return new Object[][]{
    95         return new Object[][]{
    78             { httpURIVarLen + "?length=all" },
    96             { httpURIVarLen  + "?length=all" },
    79             { httpURIFixLen + "?length=all" },
    97             { httpsURIVarLen + "?length=all" },
       
    98             { httpURIFixLen  + "?length=all" },
    80         };
    99         };
    81     }
   100     }
    82 
   101 
    83     @Test(dataProvider = "sanity")
   102     @Test(dataProvider = "sanity")
    84     void sanity(String url) throws Exception {
   103     void sanity(String url) throws Exception {
    85         HttpClient client = HttpClient.newBuilder().build();
   104         HttpClient client = HttpClient.newBuilder()
       
   105                 .proxy(NO_PROXY)
       
   106                 .sslContext(sslContext)
       
   107                 .build();
    86         HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
   108         HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
    87         HttpResponse<String> response = client.send(request, ofString());
   109         HttpResponse<String> response = client.send(request, ofString());
    88         String body = response.body();
   110         String body = response.body();
    89         assertEquals(body, EXPECTED_RESPONSE_BODY);
   111         assertEquals(body, EXPECTED_RESPONSE_BODY);
    90         client.sendAsync(request, ofString())
   112         client.sendAsync(request, ofString())
    97     public Object[][] variants() {
   119     public Object[][] variants() {
    98         String[][] cases = new String[][] {
   120         String[][] cases = new String[][] {
    99             // The length query string is the total number of bytes in the reply,
   121             // The length query string is the total number of bytes in the reply,
   100             // including headers, before the server closes the connection. The
   122             // including headers, before the server closes the connection. The
   101             // second arg is a partial-expected-detail message in the exception.
   123             // second arg is a partial-expected-detail message in the exception.
   102             { httpURIVarLen + "?length=0",   "no bytes"    }, // EOF without receiving anything
   124             { httpURIVarLen + "?length=0",   "no bytes"     }, // EOF without receiving anything
   103             { httpURIVarLen + "?length=1",   "status line" }, // EOF during status-line
   125             { httpURIVarLen + "?length=1",   "status line"  }, // EOF during status-line
   104             { httpURIVarLen + "?length=2",   "status line" },
   126             { httpURIVarLen + "?length=2",   "status line"  },
   105             { httpURIVarLen + "?length=10",  "status line" },
   127             { httpURIVarLen + "?length=10",  "status line"  },
   106             { httpURIVarLen + "?length=19",  "header"      }, // EOF during Content-Type header
   128             { httpURIVarLen + "?length=19",  "header"       }, // EOF during Content-Type header
   107             { httpURIVarLen + "?length=30",  "header"      },
   129             { httpURIVarLen + "?length=30",  "header"       },
   108             { httpURIVarLen + "?length=45",  "header"      },
   130             { httpURIVarLen + "?length=45",  "header"       },
   109             { httpURIVarLen + "?length=48",  "header"      },
   131             { httpURIVarLen + "?length=48",  "header"       },
   110             { httpURIVarLen + "?length=51",  "header"      },
   132             { httpURIVarLen + "?length=51",  "header"       },
   111             { httpURIVarLen + "?length=98",  "header"      }, // EOF during Connection header
   133             { httpURIVarLen + "?length=98",  "header"       }, // EOF during Connection header
   112             { httpURIVarLen + "?length=100", "header"      },
   134             { httpURIVarLen + "?length=100", "header"       },
   113             { httpURIVarLen + "?length=101", "header"      },
   135             { httpURIVarLen + "?length=101", "header"       },
   114             { httpURIVarLen + "?length=104", "header"      },
   136             { httpURIVarLen + "?length=104", "header"       },
   115             { httpURIVarLen + "?length=106", "chunked transfer encoding" }, // EOF during chunk header ( length )
   137             { httpURIVarLen + "?length=106", "chunked transfer encoding" }, // EOF during chunk header ( length )
   116             { httpURIVarLen + "?length=110", "chunked transfer encoding" }, // EOF during chunk response body data
   138             { httpURIVarLen + "?length=110", "chunked transfer encoding" }, // EOF during chunk response body data
       
   139 
       
   140             { httpsURIVarLen + "?length=0",   "no bytes"    },
       
   141             { httpsURIVarLen + "?length=1",   "status line" },
       
   142             { httpsURIVarLen + "?length=2",   "status line" },
       
   143             { httpsURIVarLen + "?length=10",  "status line" },
       
   144             { httpsURIVarLen + "?length=19",  "header"      },
       
   145             { httpsURIVarLen + "?length=30",  "header"      },
       
   146             { httpsURIVarLen + "?length=45",  "header"      },
       
   147             { httpsURIVarLen + "?length=48",  "header"      },
       
   148             { httpsURIVarLen + "?length=51",  "header"      },
       
   149             { httpsURIVarLen + "?length=98",  "header"      },
       
   150             { httpsURIVarLen + "?length=100", "header"      },
       
   151             { httpsURIVarLen + "?length=101", "header"      },
       
   152             { httpsURIVarLen + "?length=104", "header"      },
       
   153             { httpsURIVarLen + "?length=106", "chunked transfer encoding" },
       
   154             { httpsURIVarLen + "?length=110", "chunked transfer encoding" },
   117 
   155 
   118             { httpURIFixLen + "?length=0",   "no bytes"    }, // EOF without receiving anything
   156             { httpURIFixLen + "?length=0",   "no bytes"    }, // EOF without receiving anything
   119             { httpURIFixLen + "?length=1",   "status line" }, // EOF during status-line
   157             { httpURIFixLen + "?length=1",   "status line" }, // EOF during status-line
   120             { httpURIFixLen + "?length=2",   "status line" },
   158             { httpURIFixLen + "?length=2",   "status line" },
   121             { httpURIFixLen + "?length=10",  "status line" },
   159             { httpURIFixLen + "?length=10",  "status line" },
   129             { httpURIFixLen + "?length=86",  "header"      },
   167             { httpURIFixLen + "?length=86",  "header"      },
   130             { httpURIFixLen + "?length=104", "fixed content-length" }, // EOF during body
   168             { httpURIFixLen + "?length=104", "fixed content-length" }, // EOF during body
   131             { httpURIFixLen + "?length=106", "fixed content-length" },
   169             { httpURIFixLen + "?length=106", "fixed content-length" },
   132             { httpURIFixLen + "?length=110", "fixed content-length" },
   170             { httpURIFixLen + "?length=110", "fixed content-length" },
   133 
   171 
       
   172             // ## ADD https fixed
       
   173 
   134             { httpURIClsImed,  "no bytes"},
   174             { httpURIClsImed,  "no bytes"},
       
   175             { httpsURIClsImed, "no bytes"},
   135         };
   176         };
   136 
   177 
   137         List<Object[]> list = new ArrayList<>();
   178         List<Object[]> list = new ArrayList<>();
   138         Arrays.asList(cases).stream()
   179         Arrays.asList(cases).stream()
   139                 .map(e -> new Object[] {e[0], e[1], true})  // reuse client
   180                 .map(e -> new Object[] {e[0], e[1], true})  // reuse client
   152     {
   193     {
   153         out.print("---\n");
   194         out.print("---\n");
   154         HttpClient client = null;
   195         HttpClient client = null;
   155         for (int i=0; i< ITERATION_COUNT; i++) {
   196         for (int i=0; i< ITERATION_COUNT; i++) {
   156             if (!sameClient || client == null)
   197             if (!sameClient || client == null)
   157                 client = HttpClient.newBuilder().proxy(NO_PROXY).build();
   198                 client = HttpClient.newBuilder()
       
   199                         .proxy(NO_PROXY)
       
   200                         .sslContext(sslContext)
       
   201                         .build();
   158             HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
   202             HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
   159             try {
   203             try {
   160                 HttpResponse<String> response = client.send(request, ofString());
   204                 HttpResponse<String> response = client.send(request, ofString());
   161                 String body = response.body();
   205                 String body = response.body();
   162                 out.println(response + ": " + body);
   206                 out.println(response + ": " + body);
   178     {
   222     {
   179         out.print("---\n");
   223         out.print("---\n");
   180         HttpClient client = null;
   224         HttpClient client = null;
   181         for (int i=0; i< ITERATION_COUNT; i++) {
   225         for (int i=0; i< ITERATION_COUNT; i++) {
   182             if (!sameClient || client == null)
   226             if (!sameClient || client == null)
   183                 client = HttpClient.newBuilder().proxy(NO_PROXY).build();
   227                 client = HttpClient.newBuilder()
       
   228                         .proxy(NO_PROXY)
       
   229                         .sslContext(sslContext)
       
   230                         .build();
   184             HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
   231             HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
   185             try {
   232             try {
   186                 HttpResponse<String> response = client.sendAsync(request, ofString()).get();
   233                 HttpResponse<String> response = client.sendAsync(request, ofString()).get();
   187                 String body = response.body();
   234                 String body = response.body();
   188                 out.println(response + ": " + body);
   235                 out.println(response + ": " + body);
   207         public int read() throws IOException {
   254         public int read() throws IOException {
   208             return 1;
   255             return 1;
   209         }
   256         }
   210     }
   257     }
   211 
   258 
       
   259     // POST tests are racy in what may be received before writing may cause a
       
   260     // broken pipe or reset exception, before all the received data can be read.
       
   261     // Any message up to, and including, the "expected" error message can occur.
       
   262     // Strictly ordered list, in order of possible occurrence.
       
   263     static final List<String> MSGS_ORDER =
       
   264             List.of("no bytes", "status line", "header");
       
   265 
       
   266 
   212     @Test(dataProvider = "uris")
   267     @Test(dataProvider = "uris")
   213     void testSynchronousPOST(String url, String unused, boolean sameClient)
   268     void testSynchronousPOST(String url, String expectedMsg, boolean sameClient)
   214         throws Exception
   269         throws Exception
   215     {
   270     {
   216         out.print("---\n");
   271         out.print("---\n");
   217         HttpClient client = null;
   272         HttpClient client = null;
   218         for (int i=0; i< ITERATION_COUNT; i++) {
   273         for (int i=0; i< ITERATION_COUNT; i++) {
   219             if (!sameClient || client == null)
   274             if (!sameClient || client == null)
   220                 client = HttpClient.newBuilder().proxy(NO_PROXY).build();
   275                 client = HttpClient.newBuilder()
       
   276                         .proxy(NO_PROXY)
       
   277                         .sslContext(sslContext)
       
   278                         .build();
   221             HttpRequest request = HttpRequest.newBuilder(URI.create(url))
   279             HttpRequest request = HttpRequest.newBuilder(URI.create(url))
   222                     .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
   280                     .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
   223                     .build();
   281                     .build();
   224             try {
   282             try {
   225                 HttpResponse<String> response = client.send(request, ofString());
   283                 HttpResponse<String> response = client.send(request, ofString());
   226                 String body = response.body();
   284                 String body = response.body();
   227                 out.println(response + ": " + body);
   285                 out.println(response + ": " + body);
   228                 fail("UNEXPECTED RESPONSE: " + response);
   286                 fail("UNEXPECTED RESPONSE: " + response);
   229             } catch (IOException ioe) {
   287             } catch (IOException ioe) {
   230                 out.println("Caught expected exception:" + ioe);
   288                 out.println("Caught expected exception:" + ioe);
   231                 String msg = ioe.getMessage();
   289                 String msg = ioe.getMessage();
   232                 // "incomplete" since the chunked request body is not completely sent
   290 
   233                 assertTrue(msg.contains("incomplete"), "exception msg:[" + msg + "]");
   291                 List<String> expectedMessages = new ArrayList<>();
       
   292                 expectedMessages.add(expectedMsg);
       
   293                 MSGS_ORDER.stream().takeWhile(s -> !s.equals(expectedMsg))
       
   294                                    .forEach(expectedMessages::add);
       
   295 
       
   296                 assertTrue(expectedMessages.stream().anyMatch(s -> msg.indexOf(s) != -1),
       
   297                            "exception msg:[" + msg + "], not in [" + expectedMessages);
   234                 // synchronous API must have the send method on the stack
   298                 // synchronous API must have the send method on the stack
   235                 assertSendMethodOnStack(ioe);
   299                 assertSendMethodOnStack(ioe);
   236                 assertNoConnectionExpiredException(ioe);
   300                 assertNoConnectionExpiredException(ioe);
   237             }
   301             }
   238         }
   302         }
   239     }
   303     }
   240 
   304 
   241     @Test(dataProvider = "uris")
   305     @Test(dataProvider = "uris")
   242     void testAsynchronousPOST(String url, String unused, boolean sameClient)
   306     void testAsynchronousPOST(String url, String expectedMsg, boolean sameClient)
   243         throws Exception
   307         throws Exception
   244     {
   308     {
   245         out.print("---\n");
   309         out.print("---\n");
   246         HttpClient client = null;
   310         HttpClient client = null;
   247         for (int i=0; i< ITERATION_COUNT; i++) {
   311         for (int i=0; i< ITERATION_COUNT; i++) {
   248             if (!sameClient || client == null)
   312             if (!sameClient || client == null)
   249                 client = HttpClient.newBuilder().proxy(NO_PROXY).build();
   313                 client = HttpClient.newBuilder()
       
   314                         .proxy(NO_PROXY)
       
   315                         .sslContext(sslContext)
       
   316                         .build();
   250             HttpRequest request = HttpRequest.newBuilder(URI.create(url))
   317             HttpRequest request = HttpRequest.newBuilder(URI.create(url))
   251                     .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
   318                     .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
   252                     .build();
   319                     .build();
   253             try {
   320             try {
   254                 HttpResponse<String> response = client.sendAsync(request, ofString()).get();
   321                 HttpResponse<String> response = client.sendAsync(request, ofString()).get();
   255                 String body = response.body();
   322                 String body = response.body();
   256                 out.println(response + ": " + body);
   323                 out.println(response + ": " + body);
   258             } catch (ExecutionException ee) {
   325             } catch (ExecutionException ee) {
   259                 if (ee.getCause() instanceof IOException) {
   326                 if (ee.getCause() instanceof IOException) {
   260                     IOException ioe = (IOException) ee.getCause();
   327                     IOException ioe = (IOException) ee.getCause();
   261                     out.println("Caught expected exception:" + ioe);
   328                     out.println("Caught expected exception:" + ioe);
   262                     String msg = ioe.getMessage();
   329                     String msg = ioe.getMessage();
   263                     // "incomplete" since the chunked request body is not completely sent
   330 
   264                     assertTrue(msg.contains("incomplete"), "exception msg:[" + msg + "]");
   331                     List<String> expectedMessages = new ArrayList<>();
       
   332                     expectedMessages.add(expectedMsg);
       
   333                     MSGS_ORDER.stream().takeWhile(s -> !s.equals(expectedMsg))
       
   334                             .forEach(expectedMessages::add);
       
   335 
       
   336                     assertTrue(expectedMessages.stream().anyMatch(s -> msg.indexOf(s) != -1),
       
   337                                "exception msg:[" + msg + "], not in [" + expectedMessages);
   265                     assertNoConnectionExpiredException(ioe);
   338                     assertNoConnectionExpiredException(ioe);
   266                 } else {
   339                 } else {
   267                     throw ee;
   340                     throw ee;
   268                 }
   341                 }
   269             }
   342             }
   307         protected final ServerSocket ss;
   380         protected final ServerSocket ss;
   308         protected volatile boolean closed;
   381         protected volatile boolean closed;
   309 
   382 
   310         Server(String name) throws IOException {
   383         Server(String name) throws IOException {
   311             super(name);
   384             super(name);
   312             ss = new ServerSocket();
   385             ss = newServerSocket();
   313             ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
   386             ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
   314             this.start();
   387             this.start();
       
   388         }
       
   389 
       
   390         protected ServerSocket newServerSocket() throws IOException {
       
   391             return new ServerSocket();
   315         }
   392         }
   316 
   393 
   317         public int getPort() { return ss.getLocalPort(); }
   394         public int getPort() { return ss.getLocalPort(); }
   318 
   395 
   319         @Override
   396         @Override
   330     }
   407     }
   331 
   408 
   332     /**
   409     /**
   333      * A server that closes the connection immediately, without reading or writing.
   410      * A server that closes the connection immediately, without reading or writing.
   334      */
   411      */
   335     static final class CloseImmediatelyServer extends Server {
   412     static class PlainCloseImmediatelyServer extends Server {
   336         CloseImmediatelyServer() throws IOException {
   413         PlainCloseImmediatelyServer() throws IOException {
   337             super("CloseImmediateServer");
   414             super("PlainCloseImmediatelyServer");
       
   415         }
       
   416 
       
   417         protected PlainCloseImmediatelyServer(String name) throws IOException {
       
   418             super(name);
   338         }
   419         }
   339 
   420 
   340         @Override
   421         @Override
   341         public void run() {
   422         public void run() {
   342             while (!closed) {
   423             while (!closed) {
   343                 try (Socket s = ss.accept()) {
   424                 try (Socket s = ss.accept()) {
       
   425                     if (s instanceof SSLSocket) {
       
   426                         ((SSLSocket)s).startHandshake();
       
   427                     }
   344                     out.println("Server: got connection, closing immediately ");
   428                     out.println("Server: got connection, closing immediately ");
   345                 } catch (IOException e) {
   429                 } catch (IOException e) {
   346                     if (!closed)
   430                     if (!closed)
   347                         throw new UncheckedIOException("Unexpected", e);
   431                         throw new UncheckedIOException("Unexpected", e);
   348                 }
   432                 }
   349             }
   433             }
       
   434         }
       
   435     }
       
   436 
       
   437     /**
       
   438      * A server that closes the connection immediately, without reading or writing,
       
   439      * after completing the SSL handshake.
       
   440      */
       
   441     static final class SSLCloseImmediatelyServer extends PlainCloseImmediatelyServer {
       
   442         SSLCloseImmediatelyServer() throws IOException {
       
   443             super("SSLCloseImmediatelyServer");
       
   444         }
       
   445         @Override
       
   446         public ServerSocket newServerSocket() throws IOException {
       
   447             return SSLServerSocketFactory.getDefault().createServerSocket();
   350         }
   448         }
   351     }
   449     }
   352 
   450 
   353     /**
   451     /**
   354      * A server that replies with headers and a, possibly partial, reply, before
   452      * A server that replies with headers and a, possibly partial, reply, before
   388                     } else {
   486                     } else {
   389                         len = Integer.parseInt(query.split("=")[1]);
   487                         len = Integer.parseInt(query.split("=")[1]);
   390                     }
   488                     }
   391 
   489 
   392                     OutputStream os = s.getOutputStream();
   490                     OutputStream os = s.getOutputStream();
   393                     out.println("Server: writing " + len  + " bytes");
   491                     out.println(name + ": writing " + len  + " bytes");
   394                     byte[] responseBytes = response().getBytes(US_ASCII);
   492                     byte[] responseBytes = response().getBytes(US_ASCII);
   395                     for (int i = 0; i< len; i++) {
   493                     for (int i = 0; i< len; i++) {
   396                         os.write(responseBytes[i]);
   494                         os.write(responseBytes[i]);
       
   495                         os.flush();
   397                     }
   496                     }
   398                 } catch (IOException e) {
   497                 } catch (IOException e) {
   399                     if (!closed)
   498                     if (!closed)
   400                         throw new UncheckedIOException("Unexpected", e);
   499                         throw new UncheckedIOException("Unexpected", e);
   401                 }
   500                 }
   438                 }
   537                 }
   439             }
   538             }
   440         }
   539         }
   441     }
   540     }
   442 
   541 
   443     /** A server that issues a chunked reply. */
   542     /** A server that issues a, possibly-partial, chunked reply. */
   444     static final class VariableLengthServer extends ReplyingServer {
   543     static class PlainVariableLengthServer extends ReplyingServer {
   445 
   544 
   446         static final String CHUNKED_RESPONSE_BODY =
   545         static final String CHUNKED_RESPONSE_BODY =
   447                 "6\r\n"+ "<html>\r\n" +
   546                 "6\r\n"+ "<html>\r\n" +
   448                 "6\r\n"+ "<body>\r\n" +
   547                 "6\r\n"+ "<body>\r\n" +
   449                 "10\r\n"+ "<h1>Heading</h1>\r\n" +
   548                 "10\r\n"+ "<h1>Heading</h1>\r\n" +
   458                 "Transfer-Encoding: chunked\r\n" +
   557                 "Transfer-Encoding: chunked\r\n" +
   459                 "Connection: close\r\n\r\n";
   558                 "Connection: close\r\n\r\n";
   460 
   559 
   461         static final String RESPONSE = RESPONSE_HEADERS + CHUNKED_RESPONSE_BODY;
   560         static final String RESPONSE = RESPONSE_HEADERS + CHUNKED_RESPONSE_BODY;
   462 
   561 
   463         VariableLengthServer() throws IOException {
   562         PlainVariableLengthServer() throws IOException {
   464             super("VariableLengthServer");
   563             super("PlainVariableLengthServer");
       
   564         }
       
   565 
       
   566         protected PlainVariableLengthServer(String name) throws IOException {
       
   567             super(name);
   465         }
   568         }
   466 
   569 
   467         @Override
   570         @Override
   468         String response( ) { return RESPONSE; }
   571         String response( ) { return RESPONSE; }
       
   572     }
       
   573 
       
   574     /** A server that issues a, possibly-partial, chunked reply over SSL. */
       
   575     static final class SSLVariableLengthServer extends PlainVariableLengthServer {
       
   576         SSLVariableLengthServer() throws IOException {
       
   577             super("SSLVariableLengthServer");
       
   578         }
       
   579         @Override
       
   580         public ServerSocket newServerSocket() throws IOException {
       
   581             return SSLServerSocketFactory.getDefault().createServerSocket();
       
   582         }
   469     }
   583     }
   470 
   584 
   471     /** A server that issues a fixed-length reply. */
   585     /** A server that issues a fixed-length reply. */
   472     static final class FixedLengthServer extends ReplyingServer {
   586     static final class FixedLengthServer extends ReplyingServer {
   473 
   587 
   494                 + server.getPort();
   608                 + server.getPort();
   495     }
   609     }
   496 
   610 
   497     @BeforeTest
   611     @BeforeTest
   498     public void setup() throws Exception {
   612     public void setup() throws Exception {
   499         closeImmediatelyServer = new CloseImmediatelyServer();
   613         sslContext = new SimpleSSLContext().get();
       
   614         if (sslContext == null)
       
   615             throw new AssertionError("Unexpected null sslContext");
       
   616         SSLContext.setDefault(sslContext);
       
   617 
       
   618         closeImmediatelyServer = new PlainCloseImmediatelyServer();
   500         httpURIClsImed = "http://" + serverAuthority(closeImmediatelyServer)
   619         httpURIClsImed = "http://" + serverAuthority(closeImmediatelyServer)
   501                 + "/http1/closeImmediately/foo";
   620                 + "/http1/closeImmediately/foo";
   502 
   621 
   503         variableLengthServer = new VariableLengthServer();
   622         closeImmediatelyHttpsServer = new SSLCloseImmediatelyServer();
       
   623         httpsURIClsImed = "https://" + serverAuthority(closeImmediatelyHttpsServer)
       
   624                 + "/https1/closeImmediately/foo";
       
   625 
       
   626         variableLengthServer = new PlainVariableLengthServer();
   504         httpURIVarLen = "http://" + serverAuthority(variableLengthServer)
   627         httpURIVarLen = "http://" + serverAuthority(variableLengthServer)
   505                 + "/http1/variable/bar";
   628                 + "/http1/variable/bar";
       
   629 
       
   630         variableLengthHttpsServer = new SSLVariableLengthServer();
       
   631         httpsURIVarLen = "https://" + serverAuthority(variableLengthHttpsServer)
       
   632                 + "/https1/variable/bar";
   506 
   633 
   507         fixedLengthServer = new FixedLengthServer();
   634         fixedLengthServer = new FixedLengthServer();
   508         httpURIFixLen = "http://" + serverAuthority(fixedLengthServer)
   635         httpURIFixLen = "http://" + serverAuthority(fixedLengthServer)
   509                 + "/http1/fixed/baz";
   636                 + "/http1/fixed/baz";
   510     }
   637     }
   511 
   638 
   512     @AfterTest
   639     @AfterTest
   513     public void teardown() throws Exception {
   640     public void teardown() throws Exception {
   514         closeImmediatelyServer.close();
   641         closeImmediatelyServer.close();
       
   642         closeImmediatelyHttpsServer.close();
   515         variableLengthServer.close();
   643         variableLengthServer.close();
       
   644         variableLengthHttpsServer.close();
   516         fixedLengthServer.close();
   645         fixedLengthServer.close();
   517     }
   646     }
   518 }
   647 }