< prev index next >

test/jdk/java/net/httpclient/SmokeTest.java

Print this page

        

@@ -30,27 +30,27 @@
  * @library /lib/testlibrary/ /
  * @build jdk.testlibrary.SimpleSSLContext ProxyServer
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
  * @compile ../../../com/sun/net/httpserver/EchoHandler.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
- * @run main/othervm -Djdk.httpclient.HttpClient.log=errors,trace SmokeTest
+ * @run main/othervm -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=errors,trace SmokeTest
  */
 
 import com.sun.net.httpserver.Headers;
 import com.sun.net.httpserver.HttpContext;
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
 import com.sun.net.httpserver.HttpServer;
 import com.sun.net.httpserver.HttpsConfigurator;
 import com.sun.net.httpserver.HttpsParameters;
 import com.sun.net.httpserver.HttpsServer;
+import java.net.Proxy;
+import java.net.SocketAddress;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.net.InetSocketAddress;
 import java.net.PasswordAuthentication;
 import java.net.ProxySelector;
-import java.net.ServerSocket;
-import java.net.Socket;
 import java.net.URI;
 import jdk.incubator.http.HttpClient;
 import jdk.incubator.http.HttpRequest;
 import jdk.incubator.http.HttpResponse;
 import java.nio.file.StandardOpenOption;

@@ -79,13 +79,13 @@
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Random;
 import jdk.testlibrary.SimpleSSLContext;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromFile;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromInputStream;
-import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromFile;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromInputStream;
+import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString;
 import static jdk.incubator.http.HttpResponse.*;
 import static jdk.incubator.http.HttpResponse.BodyHandler.asFile;
 import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
 import java.util.concurrent.CountDownLatch;
 import java.util.logging.ConsoleHandler;

@@ -170,11 +170,10 @@
                            .sslParameters(sslparams)
                            .followRedirects(HttpClient.Redirect.ALWAYS)
                            .build();
 
         try {
-
             test1(httproot + "files/foo.txt", true);
             test1(httproot + "files/foo.txt", false);
             test1(httpsroot + "files/foo.txt", true);
             test1(httpsroot + "files/foo.txt", false);
 

@@ -253,11 +252,14 @@
 
         HttpResponse<String> response = client.send(request, asString());
 
         String body = response.body();
         if (!body.equals("This is foo.txt\r\n")) {
-            throw new RuntimeException();
+            throw new RuntimeException("Did not get expected body: "
+                + "\n\t expected \"This is foo.txt\\r\\n\""
+                + "\n\t received \""
+                + body.replace("\r", "\\r").replace("\n","\\n") + "\"");
         }
 
         // repeat async
         HttpResponse<String> response1 = client.sendAsync(request, asString())
                                                .join();

@@ -294,18 +296,17 @@
 
     // POST use echo to check reply
     static void test2a(String s) throws Exception {
         System.out.print("test2a: " + s);
         URI uri = new URI(s);
-        Path p = Util.getTempFile(128 * 1024);
-        //Path p = Util.getTempFile(1 * 1024);
+        Path p = getTempFile(128 * 1024);
 
         HttpRequest request = HttpRequest.newBuilder(uri)
                                          .POST(fromFile(p))
                                          .build();
 
-        Path resp = Util.getTempFile(1); // will be overwritten
+        Path resp = getTempFile(1); // will be overwritten
 
         HttpResponse<Path> response =
                 client.send(request,
                             BodyHandler.asFile(resp,
                                                StandardOpenOption.TRUNCATE_EXISTING,

@@ -313,10 +314,15 @@
 
         if (response.statusCode() != 200) {
             throw new RuntimeException(
                 "Expected 200, got [ " + response.statusCode() + " ]");
         }
+        // no redirection, etc, should be no previous response
+        if (response.previousResponse().isPresent()) {
+            throw new RuntimeException(
+                "Unexpected previous response: " + response.previousResponse().get());
+        }
         Path reply = response.body();
         //System.out.println("Reply stored in " + reply.toString());
         cmpFileContent(reply, p);
         System.out.println(" OK");
     }

@@ -345,11 +351,11 @@
 
         Path downloaded = Paths.get("redir1.txt");
         if (Files.size(downloaded) != Files.size(midSizedFile)) {
             throw new RuntimeException("Size mismatch");
         }
-
+        checkPreviousRedirectResponses(request, response);
         System.out.printf(" (count: %d) ", handler.count());
         // repeat with async api
 
         handler.reset();
 

@@ -366,43 +372,114 @@
 
         downloaded = Paths.get("redir2.txt");
         if (Files.size(downloaded) != Files.size(midSizedFile)) {
             throw new RuntimeException("Size mismatch 2");
         }
+
+        checkPreviousRedirectResponses(request, response);
         System.out.printf(" (count: %d) ", handler.count());
         System.out.println(" OK");
     }
 
+    static void checkPreviousRedirectResponses(HttpRequest initialRequest,
+                                               HttpResponse<?> finalResponse) {
+        // there must be at least one previous response
+        finalResponse.previousResponse()
+                .orElseThrow(() -> new RuntimeException("no previous response"));
+
+        HttpResponse<?> response = finalResponse;
+        do {
+            URI uri = response.uri();
+            response = response.previousResponse().get();
+            check(300 <= response.statusCode() && response.statusCode() <= 309,
+                  "Expected 300 <= code <= 309, got:" + response.statusCode());
+            check(response.body() == null, "Unexpected body: " + response.body());
+            String locationHeader = response.headers().firstValue("Location")
+                    .orElseThrow(() -> new RuntimeException("no previous Location"));
+            check(uri.toString().endsWith(locationHeader),
+                  "URI: " + uri + ", Location: " + locationHeader);
+        } while (response.previousResponse().isPresent());
+
+        // initial
+        check(initialRequest.equals(response.request()),
+              "Expected initial request [%s] to equal last prev req [%s]",
+              initialRequest, response.request());
+    }
+
+    static void check(boolean cond, Object... msg) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : msg)
+            sb.append(o);
+        throw new RuntimeException(sb.toString());
+    }
+
+    /**
+     * A Proxy Selector that wraps a ProxySelector.of(), and counts the number
+     * of times its select method has been invoked. This can be used to ensure
+     * that the Proxy Selector is invoked only once per HttpClient.sendXXX
+     * invocation.
+     */
+    static class CountingProxySelector extends ProxySelector {
+        private final ProxySelector proxySelector;
+        private volatile int count; // 0
+        private CountingProxySelector(InetSocketAddress proxyAddress) {
+            proxySelector = ProxySelector.of(proxyAddress);
+        }
+
+        public static CountingProxySelector of(InetSocketAddress proxyAddress) {
+            return new CountingProxySelector(proxyAddress);
+        }
+
+        int count() { return count; }
+
+        @Override
+        public List<Proxy> select(URI uri) {
+            count++;
+            return proxySelector.select(uri);
+        }
+
+        @Override
+        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+            proxySelector.connectFailed(uri, sa, ioe);
+        }
+    }
+
     // Proxies
     static void test4(String s) throws Exception {
         System.out.print("test4: " + s);
         URI uri = new URI(s);
         InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort);
         String filename = fileroot + uri.getPath();
 
         ExecutorService e = Executors.newCachedThreadPool();
 
+        CountingProxySelector ps = CountingProxySelector.of(proxyAddr);
         HttpClient cl = HttpClient.newBuilder()
                                   .executor(e)
-                                  .proxy(ProxySelector.of(proxyAddr))
+                                  .proxy(ps)
                                   .sslContext(ctx)
                                   .sslParameters(sslparams)
                                   .build();
 
         HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
 
-        CompletableFuture<String> fut = client.sendAsync(request, asString())
+        CompletableFuture<String> fut = cl.sendAsync(request, asString())
                 .thenApply((response) -> response.body());
 
         String body = fut.get(5, TimeUnit.HOURS);
 
         String fc = getFileContent(filename);
 
         if (!body.equals(fc)) {
             throw new RuntimeException(
                     "Body mismatch: expected [" + body + "], got [" + fc + "]");
         }
+        if (ps.count() != 1) {
+            throw new RuntimeException("CountingProxySelector. Expected 1, got " + ps.count());
+        }
         e.shutdownNow();
         System.out.println(" OK");
     }
 
     // 100 Continue: use echo target

@@ -463,11 +540,11 @@
     }
 
     @SuppressWarnings("rawtypes")
     static void test7(String target) throws Exception {
         System.out.print("test7: " + target);
-        Path requestBody = Util.getTempFile(128 * 1024);
+        Path requestBody = getTempFile(128 * 1024);
         // First test
         URI uri = new URI(target);
         HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build();
 
         for (int i=0; i<4; i++) {

@@ -642,11 +719,11 @@
         ConsoleHandler ch = new ConsoleHandler();
         logger.setLevel(Level.SEVERE);
         ch.setLevel(Level.SEVERE);
         logger.addHandler(ch);
 
-        String root = System.getProperty ("test.src")+ "/docs";
+        String root = System.getProperty ("test.src", ".")+ "/docs";
         InetSocketAddress addr = new InetSocketAddress (0);
         s1 = HttpServer.create (addr, 0);
         if (s1 instanceof HttpsServer) {
             throw new RuntimeException ("should not be httpsserver");
         }

@@ -688,97 +765,21 @@
 
         proxy = new ProxyServer(0, false);
         proxyPort = proxy.getPort();
         System.out.println("Proxy port = " + proxyPort);
     }
-}
-
-class Configurator extends HttpsConfigurator {
-    public Configurator(SSLContext ctx) {
-        super(ctx);
-    }
 
-    public void configure (HttpsParameters params) {
-        params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
-    }
-}
-
-class UploadServer extends Thread {
-    int statusCode;
-    ServerSocket ss;
-    int port;
-    int size;
-    Object lock;
-    boolean failed = false;
-
-    UploadServer(int size) throws IOException {
-        this.statusCode = statusCode;
-        this.size = size;
-        ss = new ServerSocket(0);
-        port = ss.getLocalPort();
-        lock = new Object();
-    }
-
-    int port() {
-          return port;
-    }
-
-    int size() {
-          return size;
-    }
-
-    // wait a sec before calling this
-    boolean failed() {
-        synchronized(lock) {
-            return failed;
-        }
-    }
-
-    @Override
-    public void run () {
-        int nbytes = 0;
-        Socket s = null;
-
-        synchronized(lock) {
-            try {
-                s = ss.accept();
-
-                InputStream is = s.getInputStream();
-                OutputStream os = s.getOutputStream();
-                os.write("HTTP/1.1 201 OK\r\nContent-length: 0\r\n\r\n".getBytes());
-                int n;
-                byte[] buf = new byte[8000];
-                while ((n=is.read(buf)) != -1) {
-                    nbytes += n;
-                }
-            } catch (IOException e) {
-                System.out.println ("read " + nbytes);
-                System.out.println ("size " + size);
-                failed = nbytes >= size;
-            } finally {
-                try {
-                    ss.close();
-                    if (s != null)
-                        s.close();
-                } catch (IOException e) {}
-            }
-        }
-    }
-}
-
-class RedirectHandler implements HttpHandler {
-    String root;
-    volatile int count = 0;
+    static class RedirectHandler implements HttpHandler {
+        private final String root;
+        private volatile int count = 0;
 
     RedirectHandler(String root) {
         this.root = root;
     }
 
     @Override
-    public synchronized void handle(HttpExchange t)
-        throws IOException
-    {
+        public synchronized void handle(HttpExchange t) throws IOException {
         byte[] buf = new byte[2048];
         try (InputStream is = t.getRequestBody()) {
             while (is.read(buf) != -1) ;
         }
 

@@ -787,26 +788,32 @@
         if (count++ < 1) {
             responseHeaders.add("Location", root + "/foo/" + count);
         } else {
             responseHeaders.add("Location", SmokeTest.midSizedFilename);
         }
-        t.sendResponseHeaders(301, -1);
+            t.sendResponseHeaders(301, 64 * 1024);
+            byte[] bb = new byte[1024];
+            OutputStream os = t.getResponseBody();
+            for (int i=0; i<64; i++) {
+                os.write(bb);
+            }
+            os.close();
         t.close();
     }
 
     int count() {
         return count;
     }
 
     void reset() {
         count = 0;
     }
-}
+    }
 
-class RedirectErrorHandler implements HttpHandler {
-    String root;
-    volatile int count = 1;
+    static class RedirectErrorHandler implements HttpHandler {
+        private final String root;
+        private volatile int count = 1;
 
     RedirectErrorHandler(String root) {
         this.root = root;
     }
 

@@ -817,64 +824,25 @@
     synchronized void increment() {
         count++;
     }
 
     @Override
-    public synchronized void handle (HttpExchange t)
-        throws IOException
-    {
-        byte[] buf = new byte[2048];
+        public synchronized void handle(HttpExchange t) throws IOException {
         try (InputStream is = t.getRequestBody()) {
-            while (is.read(buf) != -1) ;
+                is.readAllBytes();
         }
 
         Headers map = t.getResponseHeaders();
         String redirect = root + "/foo/" + Integer.toString(count);
         increment();
         map.add("Location", redirect);
         t.sendResponseHeaders(301, -1);
         t.close();
     }
-}
-
-class Util {
-    static byte[] readAll(InputStream is) throws IOException {
-        byte[] buf = new byte[1024];
-        byte[] result = new byte[0];
-
-        while (true) {
-            int n = is.read(buf);
-            if (n > 0) {
-                byte[] b1 = new byte[result.length + n];
-                System.arraycopy(result, 0, b1, 0, result.length);
-                System.arraycopy(buf, 0, b1, result.length, n);
-                result = b1;
-            } else if (n == -1) {
-                return result;
-            }
-        }
-    }
-
-    static Path getTempFile(int size) throws IOException {
-        File f = File.createTempFile("test", "txt");
-        f.deleteOnExit();
-        byte[] buf = new byte[2048];
-        for (int i=0; i<buf.length; i++)
-            buf[i] = (byte)i;
-
-        FileOutputStream fos = new FileOutputStream(f);
-        while (size > 0) {
-            int amount = Math.min(size, buf.length);
-            fos.write(buf, 0, amount);
-            size -= amount;
-        }
-        fos.close();
-        return f.toPath();
     }
-}
 
-class DelayHandler implements HttpHandler {
+    static class DelayHandler implements HttpHandler {
 
     CyclicBarrier bar1 = new CyclicBarrier(2);
     CyclicBarrier bar2 = new CyclicBarrier(2);
     CyclicBarrier bar3 = new CyclicBarrier(2);
 

@@ -886,19 +854,46 @@
         return bar2;
     }
 
     @Override
     public synchronized void handle(HttpExchange he) throws IOException {
-        byte[] buf = Util.readAll(he.getRequestBody());
+            he.getRequestBody().readAllBytes();
         try {
             bar1.await();
             bar2.await();
-        } catch (Exception e) {}
+            } catch (Exception e) { }
         he.sendResponseHeaders(200, -1); // will probably fail
         he.close();
     }
+    }
 
+    static class Configurator extends HttpsConfigurator {
+        public Configurator(SSLContext ctx) {
+            super(ctx);
+        }
+
+        public void configure (HttpsParameters params) {
+            params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+        }
+    }
+
+    static Path getTempFile(int size) throws IOException {
+        File f = File.createTempFile("test", "txt");
+        f.deleteOnExit();
+        byte[] buf = new byte[2048];
+        for (int i = 0; i < buf.length; i++)
+            buf[i] = (byte) i;
+
+        FileOutputStream fos = new FileOutputStream(f);
+        while (size > 0) {
+            int amount = Math.min(size, buf.length);
+            fos.write(buf, 0, amount);
+            size -= amount;
+        }
+        fos.close();
+        return f.toPath();
+    }
 }
 
 // check for simple hardcoded sequence and use remote address
 // to check.
 // First 4 requests executed in sequence (should use same connection/address)
< prev index next >