0N/A/*
3261N/A * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
2981N/A * @bug 6488669 6595324 6993490
0N/A * @run main/othervm ChunkedErrorStream
0N/A * @summary Chunked ErrorStream tests
0N/A */
0N/A
0N/Aimport java.net.*;
0N/Aimport java.io.*;
0N/Aimport com.sun.net.httpserver.*;
0N/A
0N/A/**
0N/A * Part 1: 6488669
0N/A * 1) Http server that responds with an error code (>=400)
0N/A * and a chunked response body. It also indicates that
0N/A * the connection will be closed.
0N/A * 2) Client sends request to server and tries to
0N/A * getErrorStream(). Some data must be able to be read
0N/A * from the errorStream.
0N/A *
0N/A * Part 2: 6595324
0N/A * 1) Http server that responds with an error code (>=400)
0N/A * and a chunked response body greater than
0N/A * sun.net.http.errorstream.bufferSize, 4K + 10 bytes.
0N/A * 2) Client sends request to server and tries to
0N/A * getErrorStream(). 4K + 10 bytes must be read from
0N/A * the errorStream.
2981N/A *
2981N/A * Part 3: 6993490
2981N/A * Reuse persistent connection from part 2, the error stream
2981N/A * buffering will have set a reduced timeout on the socket and
2981N/A * tried to reset it to the default, infinity. Client must not
2981N/A * throw a timeout exception. If it does, it indicates that the
2981N/A * default timeout was not reset correctly.
2981N/A * If no timeout exception is thrown, it does not guarantee that
2981N/A * the timeout was reset correctly, as there is a potential race
2981N/A * between the sleeping server and the client thread. Typically,
2981N/A * 1000 millis has been enought to reliable reproduce this problem
2981N/A * since the error stream buffering sets the timeout to 60 millis.
0N/A */
0N/A
0N/Apublic class ChunkedErrorStream
0N/A{
0N/A com.sun.net.httpserver.HttpServer httpServer;
0N/A
0N/A static {
0N/A // Enable ErrorStream buffering
0N/A System.getProperties().setProperty("sun.net.http.errorstream.enableBuffering", "true");
0N/A
0N/A // No need to set this as 4K is the default
0N/A // System.getProperties().setProperty("sun.net.http.errorstream.bufferSize", "4096");
0N/A }
0N/A
0N/A public static void main(String[] args) {
0N/A new ChunkedErrorStream();
0N/A }
0N/A
0N/A public ChunkedErrorStream() {
0N/A try {
0N/A startHttpServer();
0N/A doClient();
0N/A } catch (IOException ioe) {
0N/A ioe.printStackTrace();
0N/A } finally {
0N/A httpServer.stop(1);
0N/A }
0N/A }
0N/A
0N/A void doClient() {
2981N/A for (int times=0; times<3; times++) {
0N/A HttpURLConnection uc = null;
0N/A try {
0N/A InetSocketAddress address = httpServer.getAddress();
0N/A String URLStr = "http://localhost:" + address.getPort() + "/test/";
0N/A if (times == 0) {
2981N/A URLStr += "first";
0N/A } else {
2981N/A URLStr += "second";
0N/A }
0N/A
0N/A System.out.println("Trying " + URLStr);
0N/A URL url = new URL(URLStr);
0N/A uc = (HttpURLConnection)url.openConnection();
0N/A uc.getInputStream();
0N/A
0N/A throw new RuntimeException("Failed: getInputStream should throw and IOException");
0N/A } catch (IOException e) {
2981N/A if (e instanceof SocketTimeoutException) {
2981N/A e.printStackTrace();
2981N/A throw new RuntimeException("Failed: SocketTimeoutException should not happen");
2981N/A }
2981N/A
0N/A // This is what we expect to happen.
0N/A InputStream es = uc.getErrorStream();
0N/A byte[] ba = new byte[1024];
0N/A int count = 0, ret;
0N/A try {
0N/A while ((ret = es.read(ba)) != -1)
0N/A count += ret;
0N/A es.close();
0N/A } catch (IOException ioe) {
0N/A ioe.printStackTrace();
0N/A }
0N/A
0N/A if (count == 0)
0N/A throw new RuntimeException("Failed: ErrorStream returning 0 bytes");
0N/A
2981N/A if (times >= 1 && count != (4096+10))
0N/A throw new RuntimeException("Failed: ErrorStream returning " + count +
0N/A " bytes. Expecting " + (4096+10));
0N/A
0N/A System.out.println("Read " + count + " bytes from the errorStream");
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Http Server
0N/A */
0N/A void startHttpServer() throws IOException {
0N/A httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
0N/A
0N/A // create HttpServer context
2981N/A httpServer.createContext("/test/first", new FirstHandler());
2981N/A httpServer.createContext("/test/second", new SecondHandler());
0N/A
0N/A httpServer.start();
0N/A }
0N/A
2981N/A class FirstHandler implements HttpHandler {
0N/A public void handle(HttpExchange t) throws IOException {
0N/A InputStream is = t.getRequestBody();
0N/A byte[] ba = new byte[1024];
0N/A while (is.read(ba) != -1);
0N/A is.close();
0N/A
0N/A Headers resHeaders = t.getResponseHeaders();
0N/A resHeaders.add("Connection", "close");
0N/A t.sendResponseHeaders(404, 0);
0N/A OutputStream os = t.getResponseBody();
0N/A
0N/A // actual data doesn't matter. Just send 2K worth.
0N/A byte b = 'a';
0N/A for (int i=0; i<2048; i++)
0N/A os.write(b);
0N/A
0N/A os.close();
0N/A t.close();
0N/A }
0N/A }
0N/A
2981N/A static class SecondHandler implements HttpHandler {
2981N/A /* count greater than 0, slow response */
2981N/A static int count = 0;
2981N/A
0N/A public void handle(HttpExchange t) throws IOException {
0N/A InputStream is = t.getRequestBody();
0N/A byte[] ba = new byte[1024];
0N/A while (is.read(ba) != -1);
0N/A is.close();
0N/A
2981N/A if (count > 0) {
2981N/A System.out.println("server sleeping...");
2981N/A try { Thread.sleep(1000); } catch(InterruptedException e) {}
2981N/A }
2981N/A count++;
2981N/A
0N/A t.sendResponseHeaders(404, 0);
0N/A OutputStream os = t.getResponseBody();
0N/A
0N/A // actual data doesn't matter. Just send more than 4K worth
0N/A byte b = 'a';
0N/A for (int i=0; i<(4096+10); i++)
0N/A os.write(b);
0N/A
0N/A os.close();
0N/A t.close();
0N/A }
0N/A }
0N/A}