/* * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @summary Tests for FileServerHandler * @run testng FileServerHandlerTest */ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; import java.nio.file.Path; import java.util.List; import java.util.Map; import com.sun.net.httpserver.Authenticator; import com.sun.net.httpserver.Filter; 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.HttpPrincipal; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.SimpleFileServer; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; public class FileServerHandlerTest { static final Path CWD = Path.of(".").toAbsolutePath(); static final Class RE = RuntimeException.class; @DataProvider public Object[][] notAllowedMethods() { var l = List.of("POST", "PUT", "DELETE", "TRACE", "OPTIONS"); return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } @Test(dataProvider = "notAllowedMethods") public void testNotAllowedRequestMethod(String requestMethod) throws Exception { var handler = SimpleFileServer.createFileHandler(CWD); var exchange = new MethodHttpExchange(requestMethod); handler.handle(exchange); assertEquals(exchange.rCode, 405); assertEquals(exchange.getResponseHeaders().getFirst("allow"), "HEAD, GET"); } @DataProvider public Object[][] notImplementedMethods() { var l = List.of("GARBAGE", "RUBBISH", "TRASH", "FOO", "BAR"); return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } @Test(dataProvider = "notImplementedMethods") public void testNotImplementedRequestMethod(String requestMethod) throws Exception { var handler = SimpleFileServer.createFileHandler(CWD); var exchange = new MethodHttpExchange(requestMethod); handler.handle(exchange); assertEquals(exchange.rCode, 501); } // 301 and 404 response codes tested in SimpleFileServerTest @Test public void testThrowingExchange() { var h = SimpleFileServer.createFileHandler(CWD); { var exchange = new ThrowingHttpExchange("GET") { public InputStream getRequestBody() { throw new RuntimeException("getRequestBody"); } }; var t = expectThrows(RE, () -> h.handle(exchange)); assertEquals(t.getMessage(), "getRequestBody"); } { var exchange = new ThrowingHttpExchange("GET") { public Headers getResponseHeaders() { throw new RuntimeException("getResponseHeaders"); } }; var t = expectThrows(RE, () -> h.handle(exchange)); assertEquals(t.getMessage(), "getResponseHeaders"); } { var exchange = new ThrowingHttpExchange("GET") { public void sendResponseHeaders(int rCode, long responseLength) { throw new RuntimeException("sendResponseHeaders"); } }; var t = expectThrows(RE, () -> h.handle(exchange)); assertEquals(t.getMessage(), "sendResponseHeaders"); } { var exchange = new ThrowingHttpExchange("GET") { public OutputStream getResponseBody() { throw new RuntimeException("getResponseBody"); } }; var t = expectThrows(RE, () -> h.handle(exchange)); assertEquals(t.getMessage(), "getResponseBody"); } { var exchange = new ThrowingHttpExchange("GET") { public void close() { throw new RuntimeException("close"); } }; var t = expectThrows(RE, () -> h.handle(exchange)); assertEquals(t.getMessage(), "close"); } } static class ThrowingHttpExchange extends StubHttpExchange { private final String method; volatile int rCode; volatile long responseLength; volatile Headers responseHeaders; volatile Headers requestHeaders; volatile InputStream requestBody; ThrowingHttpExchange(String method) { this.method = method; responseHeaders = new Headers(); requestHeaders = new Headers(); requestBody = new ByteArrayInputStream(new byte[]{}); } @Override public String getRequestMethod() { return method; } @Override public Headers getResponseHeaders() { return responseHeaders; } @Override public Headers getRequestHeaders() { return requestHeaders; } @Override public InputStream getRequestBody() { return requestBody; } @Override public URI getRequestURI() { return URI.create("/"); } @Override public OutputStream getResponseBody() { return OutputStream.nullOutputStream(); } @Override public void sendResponseHeaders(int rCode, long responseLength) { this.rCode = rCode; this.responseLength = responseLength; } @Override public HttpContext getHttpContext() { return new HttpContext() { @Override public HttpHandler getHandler() { return null; } @Override public void setHandler(HttpHandler handler) { } @Override public String getPath() { return "/"; } @Override public HttpServer getServer() { return null; } @Override public Map getAttributes() { return null; } @Override public List getFilters() { return null; } @Override public Authenticator setAuthenticator(Authenticator auth) { return null; } @Override public Authenticator getAuthenticator() { return null; } }; } } static class MethodHttpExchange extends StubHttpExchange { private final String method; volatile int rCode; volatile long responseLength; volatile Headers responseHeaders; volatile InputStream requestBody; MethodHttpExchange(String method) { this.method = method; responseHeaders = new Headers(); requestBody = InputStream.nullInputStream(); } @Override public String getRequestMethod() { return method; } @Override public Headers getResponseHeaders() { return responseHeaders; } @Override public InputStream getRequestBody() { return requestBody; } @Override public void sendResponseHeaders(int rCode, long responseLength) { this.rCode = rCode; this.responseLength = responseLength; } } static class StubHttpExchange extends HttpExchange { @Override public Headers getRequestHeaders() { return null; } @Override public Headers getResponseHeaders() { return null; } @Override public URI getRequestURI() { return null; } @Override public String getRequestMethod() { return null; } @Override public void close() { } @Override public InputStream getRequestBody() { return null; } @Override public OutputStream getResponseBody() { return null; } @Override public HttpContext getHttpContext() { return null; } @Override public void sendResponseHeaders(int rCode, long responseLength) { } @Override public InetSocketAddress getRemoteAddress() { return null; } @Override public int getResponseCode() { return 0; } @Override public InetSocketAddress getLocalAddress() { return null; } @Override public String getProtocol() { return null; } @Override public Object getAttribute(String name) { return null; } @Override public void setAttribute(String name, Object value) { } @Override public void setStreams(InputStream i, OutputStream o) { } @Override public HttpPrincipal getPrincipal() { return null; } } }