jdk-24/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java
Julia Boes f505396ccc 8277459: Add jwebserver tool
Reviewed-by: michaelm, dfuchs, ihse
2021-12-01 10:37:09 +00:00

246 lines
10 KiB
Java

/*
* 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 Negative tests for java -m jdk.httpserver command
* @library /test/lib
* @modules jdk.httpserver
* @run testng/othervm CommandLineNegativeTest
*/
import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.FileUtils;
import org.testng.SkipException;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static java.lang.System.out;
import static org.testng.Assert.assertFalse;
public class CommandLineNegativeTest {
static final Path JAVA_HOME = Path.of(System.getProperty("java.home"));
static final String JAVA = getJava(JAVA_HOME);
static final Path CWD = Path.of(".").toAbsolutePath().normalize();
static final Path TEST_DIR = CWD.resolve("CommandLineNegativeTest");
static final Path TEST_FILE = TEST_DIR.resolve("file.txt");
static final String LOOPBACK_ADDR = InetAddress.getLoopbackAddress().getHostAddress();
@BeforeTest
public void setup() throws IOException {
if (Files.exists(TEST_DIR)) {
FileUtils.deleteFileTreeWithRetry(TEST_DIR);
}
Files.createDirectories(TEST_DIR);
Files.createFile(TEST_FILE);
}
@DataProvider
public Object[][] unknownOption() {
return new Object[][] {
{"--unknownOption"},
{"null"}
};
}
@Test(dataProvider = "unknownOption")
public void testBadOption(String opt) throws Throwable {
out.println("\n--- testUnknownOption, opt=\"%s\" ".formatted(opt));
simpleserver(JAVA, "-m", "jdk.httpserver", opt)
.shouldNotHaveExitValue(0)
.shouldContain("Error: unknown option: " + opt);
}
@DataProvider
public Object[][] tooManyOptionArgs() {
return new Object[][] {
{"-b", "localhost"},
{"-d", "/some/path"},
{"-o", "none"},
{"-p", "0"},
{"--bind-address", "localhost"},
{"--directory", "/some/path"},
{"--output", "none"},
{"--port", "0"}
// doesn't fail for -h option
};
}
@Test(dataProvider = "tooManyOptionArgs")
public void testTooManyOptionArgs(String opt, String arg) throws Throwable {
out.println("\n--- testTooManyOptionArgs, opt=\"%s\" ".formatted(opt));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, arg, arg)
.shouldNotHaveExitValue(0)
.shouldContain("Error: unknown option: " + arg);
}
@DataProvider
public Object[][] noArg() {
return new Object[][] {
{"-b", """
-b, --bind-address - Address to bind to. Default: %s (loopback).
For all interfaces use "-b 0.0.0.0" or "-b ::".""".formatted(LOOPBACK_ADDR)},
{"-d", "-d, --directory - Directory to serve. Default: current directory."},
{"-o", "-o, --output - Output format. none|info|verbose. Default: info."},
{"-p", "-p, --port - Port to listen on. Default: 8000."},
{"--bind-address", """
-b, --bind-address - Address to bind to. Default: %s (loopback).
For all interfaces use "-b 0.0.0.0" or "-b ::".""".formatted(LOOPBACK_ADDR)},
{"--directory", "-d, --directory - Directory to serve. Default: current directory."},
{"--output", "-o, --output - Output format. none|info|verbose. Default: info."},
{"--port", "-p, --port - Port to listen on. Default: 8000."}
// doesn't fail for -h option
};
}
@Test(dataProvider = "noArg")
public void testNoArg(String opt, String msg) throws Throwable {
out.println("\n--- testNoArg, opt=\"%s\" ".formatted(opt));
simpleserver(JAVA, "-m", "jdk.httpserver", opt)
.shouldNotHaveExitValue(0)
.shouldContain("Error: no value given for " + opt)
.shouldContain(msg);
}
@DataProvider
public Object[][] invalidValue() {
return new Object[][] {
{"-b", "[127.0.0.1]"},
{"-b", "badhost"},
{"--bind-address", "192.168.1.220..."},
{"-o", "bad-output-level"},
{"--output", "bad-output-level"},
{"-p", "+-"},
{"--port", "+-"}
};
}
@Test(dataProvider = "invalidValue")
public void testInvalidValue(String opt, String val) throws Throwable {
out.println("\n--- testInvalidValue, opt=\"%s\" ".formatted(opt));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, val)
.shouldNotHaveExitValue(0)
.shouldContain("Error: invalid value given for " + opt + ": " + val);
}
@DataProvider
public Object[][] portOptions() { return new Object[][] {{"-p"}, {"--port"}}; }
@Test(dataProvider = "portOptions")
public void testPortOutOfRange(String opt) throws Throwable {
out.println("\n--- testPortOutOfRange, opt=\"%s\" ".formatted(opt));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, "65536") // range 0 to 65535
.shouldNotHaveExitValue(0)
.shouldContain("Error: server config failed: " + "port out of range:65536");
}
@DataProvider
public Object[][] directoryOptions() { return new Object[][] {{"-d"}, {"--directory"}}; }
@Test(dataProvider = "directoryOptions")
public void testRootNotAbsolute(String opt) throws Throwable {
out.println("\n--- testRootNotAbsolute, opt=\"%s\" ".formatted(opt));
var root = Path.of(".");
assertFalse(root.isAbsolute());
simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString())
.shouldNotHaveExitValue(0)
.shouldContain("Error: server config failed: " + "Path is not absolute:");
}
@Test(dataProvider = "directoryOptions")
public void testRootNotADirectory(String opt) throws Throwable {
out.println("\n--- testRootNotADirectory, opt=\"%s\" ".formatted(opt));
var file = TEST_FILE.toString();
assertFalse(Files.isDirectory(TEST_FILE));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, file)
.shouldNotHaveExitValue(0)
.shouldContain("Error: server config failed: " + "Path is not a directory: " + file);
}
@Test(dataProvider = "directoryOptions")
public void testRootDoesNotExist(String opt) throws Throwable {
out.println("\n--- testRootDoesNotExist, opt=\"%s\" ".formatted(opt));
Path root = TEST_DIR.resolve("not/existent/dir");
assertFalse(Files.exists(root));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString())
.shouldNotHaveExitValue(0)
.shouldContain("Error: server config failed: " + "Path does not exist: " + root.toString());
}
@Test(dataProvider = "directoryOptions")
public void testRootNotReadable(String opt) throws Throwable {
out.println("\n--- testRootNotReadable, opt=\"%s\" ".formatted(opt));
if (Platform.isWindows()) {
// Not applicable to Windows. Reason: cannot revoke an owner's read
// access to a directory that was created by that owner
throw new SkipException("cannot run on Windows");
}
Path root = Files.createDirectories(TEST_DIR.resolve("not/readable/dir"));
try {
root.toFile().setReadable(false, false);
assertFalse(Files.isReadable(root));
simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString())
.shouldNotHaveExitValue(0)
.shouldContain("Error: server config failed: " + "Path is not readable: " + root.toString());
} finally {
root.toFile().setReadable(true, false);
}
}
@AfterTest
public void teardown() throws IOException {
if (Files.exists(TEST_DIR)) {
FileUtils.deleteFileTreeWithRetry(TEST_DIR);
}
}
// --- infra ---
static String getJava(Path image) {
boolean isWindows = System.getProperty("os.name").startsWith("Windows");
Path java = image.resolve("bin").resolve(isWindows ? "java.exe" : "java");
if (Files.notExists(java))
throw new RuntimeException(java + " not found");
return java.toAbsolutePath().toString();
}
static OutputAnalyzer simpleserver(String... args) throws Throwable {
var pb = new ProcessBuilder(args)
.directory(TEST_DIR.toFile());
var outputAnalyser = ProcessTools.executeCommand(pb)
.outputTo(System.out)
.errorTo(System.out);
return outputAnalyser;
}
}