--- a/jdk/.hgtags Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/.hgtags Tue Mar 21 08:48:14 2017 -0700
@@ -403,3 +403,4 @@
c476ca73750698fa5654e101af699ee45db38e2a jdk-9+158
49b54a4d9e84b7ba956b8c27fced5035465146ae jdk-9+159
cac788454598b95d8b0153c021a7fae3cd7e6fda jdk-9+160
+09b92d3067a38ee07bc14efa336b14790c93f7e7 jdk-9+161
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Tue Mar 21 08:48:14 2017 -0700
@@ -2771,7 +2771,7 @@
* In all other cases, it requires RuntimePermission("accessDeclaredMembers")
* permission.
*/
- final ClassLoader ccl = caller.getClassLoader0();
+ final ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (which != Member.PUBLIC) {
final ClassLoader cl = getClassLoader0();
if (ccl != cl) {
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java Tue Mar 21 08:48:14 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -24,6 +24,7 @@
*/
package java.lang;
+import java.lang.annotation.Native;
import java.security.PrivilegedAction;
import java.time.Duration;
import java.time.Instant;
@@ -57,6 +58,12 @@
private static long REAPER_DEFAULT_STACKSIZE = 128 * 1024;
/**
+ * Return value from waitForProcessExit0 indicating the process is not a child.
+ */
+ @Native
+ private static final int NOT_A_CHILD = -2;
+
+ /**
* Cache the ProcessHandle of this process.
*/
private static final ProcessHandleImpl current;
@@ -131,6 +138,29 @@
// spawn a thread to wait for and deliver the exit value
processReaperExecutor.execute(() -> {
int exitValue = waitForProcessExit0(pid, shouldReap);
+ if (exitValue == NOT_A_CHILD) {
+ // pid not alive or not a child of this process
+ // If it is alive wait for it to terminate
+ long sleep = 300; // initial milliseconds to sleep
+ int incr = 30; // increment to the sleep time
+
+ long startTime = isAlive0(pid);
+ long origStart = startTime;
+ while (startTime >= 0) {
+ try {
+ Thread.sleep(Math.min(sleep, 5000L)); // no more than 5 sec
+ sleep += incr;
+ } catch (InterruptedException ie) {
+ // ignore and retry
+ }
+ startTime = isAlive0(pid); // recheck if is alive
+ if (origStart > 0 && startTime != origStart) {
+ // start time changed, pid is not the same process
+ break;
+ }
+ }
+ exitValue = 0;
+ }
newCompletion.complete(exitValue);
// remove from cache afterwards
completions.remove(pid, newCompletion);
--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java Tue Mar 21 08:48:14 2017 -0700
@@ -1337,14 +1337,12 @@
int oSize = ob.version().size();
int min = Math.min(size, oSize);
for (int i = 0; i < min; i++) {
- Integer val = version.get(i);
- Integer oVal = ob.version().get(i);
+ int val = version.get(i);
+ int oVal = ob.version().get(i);
if (val != oVal)
return val - oVal;
}
- if (size != oSize)
- return size - oSize;
- return 0;
+ return size - oSize;
}
private int comparePre(Version ob) {
--- a/jdk/src/java.base/share/classes/java/util/Date.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Date.java Tue Mar 21 08:48:14 2017 -0700
@@ -728,7 +728,6 @@
* @see java.util.Calendar
* @deprecated As of JDK version 1.1,
* replaced by {@code Calendar.get(Calendar.DAY_OF_MONTH)}.
- * @deprecated
*/
@Deprecated
public int getDate() {
--- a/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c Tue Mar 21 08:48:14 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -244,7 +244,8 @@
int status;
while (waitpid(pid, &status, 0) < 0) {
switch (errno) {
- case ECHILD: return 0;
+ case ECHILD:
+ return java_lang_ProcessHandleImpl_NOT_A_CHILD; // No child
case EINTR: break;
default: return -1;
}
@@ -269,9 +270,10 @@
memset(&siginfo, 0, sizeof siginfo);
while (waitid(P_PID, pid, &siginfo, options) < 0) {
switch (errno) {
- case ECHILD: return 0;
- case EINTR: break;
- default: return -1;
+ case ECHILD:
+ return java_lang_ProcessHandleImpl_NOT_A_CHILD; // No child
+ case EINTR: break;
+ default: return -1;
}
}
--- a/jdk/src/java.transaction/share/classes/module-info.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/java.transaction/share/classes/module-info.java Tue Mar 21 08:48:14 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -31,6 +31,7 @@
*
* @since 9
*/
+@Deprecated(since="9", forRemoval=true)
module java.transaction {
requires transitive java.rmi;
exports javax.transaction;
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Tue Mar 21 08:48:14 2017 -0700
@@ -95,7 +95,7 @@
tool.xflag = true;
}
},
- new Option(false, OptionType.MAIN_OPERATION, "--print-module-descriptor", "-d") {
+ new Option(false, OptionType.MAIN_OPERATION, "--describe-module", "-d") {
void process(Main tool, String opt, String arg) throws BadArgs {
if (tool.cflag || tool.iflag || tool.tflag || tool.uflag || tool.xflag)
throw new BadArgs("error.multiple.main.operations").showUsage(true);
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Tue Mar 21 08:48:14 2017 -0700
@@ -27,6 +27,7 @@
import java.io.*;
import java.lang.module.Configuration;
+import java.lang.module.FindException;
import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
@@ -407,11 +408,11 @@
boolean found;
if (fname != null) {
try (ZipFile zf = new ZipFile(fname)) {
- found = printModuleDescriptor(zf);
+ found = describeModule(zf);
}
} else {
try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
- found = printModuleDescriptor(fin);
+ found = describeModule(fin);
}
}
if (!found)
@@ -603,7 +604,7 @@
int n = args.length - count;
if (n > 0) {
if (dflag) {
- // "--print-module-descriptor/-d" does not require file argument(s)
+ // "--describe-module/-d" does not require file argument(s)
usageError(formatMsg("error.bad.dflag", args[count]));
return false;
}
@@ -1728,24 +1729,43 @@
.collect(joining(", ", prefix, suffix));
}
- private boolean printModuleDescriptor(ZipFile zipFile)
- throws IOException
- {
+ private boolean describeModule(ZipFile zipFile) throws IOException {
ZipEntry[] zes = zipFile.stream()
.filter(e -> isModuleInfoEntry(e.getName()))
.sorted(Validator.ENTRY_COMPARATOR)
.toArray(ZipEntry[]::new);
- if (zes.length == 0)
- return false;
- for (ZipEntry ze : zes) {
- try (InputStream is = zipFile.getInputStream(ze)) {
- printModuleDescriptor(is, ze.getName());
+
+ if (zes.length == 0) {
+ // No module descriptor found, derive the automatic module name
+ String fn = zipFile.getName();
+ ModuleFinder mf = ModuleFinder.of(Paths.get(fn));
+ try {
+ Set<ModuleReference> mref = mf.findAll();
+ if (mref.isEmpty()) {
+ output(formatMsg("error.unable.derive.automodule", fn));
+ return true;
+ }
+ ModuleDescriptor md = mref.iterator().next().descriptor();
+ output(getMsg("out.automodule"));
+ describeModule(md, null, "automatic");
+ } catch (FindException e) {
+ String msg = formatMsg("error.unable.derive.automodule", fn);
+ Throwable t = e.getCause();
+ if (t != null)
+ msg = msg + "\n" + t.getMessage();
+ output(msg);
+ }
+ } else {
+ for (ZipEntry ze : zes) {
+ try (InputStream is = zipFile.getInputStream(ze)) {
+ describeModule(is, ze.getName());
+ }
}
}
return true;
}
- private boolean printModuleDescriptor(FileInputStream fis)
+ private boolean describeModule(FileInputStream fis)
throws IOException
{
try (BufferedInputStream bis = new BufferedInputStream(fis);
@@ -1764,7 +1784,7 @@
.sorted(Validator.ENTRYNAME_COMPARATOR)
.toArray(String[]::new);
for (String name : names) {
- printModuleDescriptor(new ByteArrayInputStream(moduleInfos.get(name)), name);
+ describeModule(new ByteArrayInputStream(moduleInfos.get(name)), name);
}
return true;
}
@@ -1775,13 +1795,21 @@
.collect(joining(" "));
}
- private void printModuleDescriptor(InputStream entryInputStream, String ename)
+ private void describeModule(InputStream entryInputStream, String ename)
throws IOException
{
ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
ModuleDescriptor md = attrs.descriptor();
ModuleHashes hashes = attrs.recordedHashes();
+ describeModule(md, hashes, ename);
+ }
+
+ private void describeModule(ModuleDescriptor md,
+ ModuleHashes hashes,
+ String ename)
+ throws IOException
+ {
StringBuilder sb = new StringBuilder();
sb.append("\nmodule ")
.append(md.toNameAndVersion())
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Tue Mar 21 08:48:14 2017 -0700
@@ -45,7 +45,7 @@
'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
together!
error.bad.dflag=\
- '-d, --print-module-descriptor' option requires no input file(s) to be specified: {0}
+ '-d, --describe-module' option requires no input file(s) to be specified: {0}
error.bad.reason=\
bad reason: {0}, must be one of deprecated, deprecated-for-removal, or incubating
error.nosuch.fileordir=\
@@ -62,6 +62,8 @@
Hashing module {0} dependences, unable to find module {1} on module path
error.module.options.without.info=\
One of --module-version or --hash-modules without module-info.class
+error.unable.derive.automodule=\
+ Unable to derive module descriptor for: {0}
error.unexpected.module-info=\
Unexpected module descriptor {0}
error.module.descriptor.not.found=\
@@ -129,6 +131,8 @@
added manifest
out.added.module-info=\
added module-info: {0}
+out.automodule=\
+ No module descriptor found. Derived automatic module.
out.update.manifest=\
updated manifest
out.update.module-info=\
@@ -224,8 +228,8 @@
\ -u, --update Update an existing jar archive
main.help.opt.main.extract=\
\ -x, --extract Extract named (or all) files from the archive
-main.help.opt.main.print-module-descriptor=\
-\ -d, --print-module-descriptor Print the module descriptor
+main.help.opt.main.describe-module=\
+\ -d, --describe-module Print the module descriptor, or automatic module name
main.help.opt.any=\
\ Operation modifiers valid in any mode:\n\
\n\
--- a/jdk/test/TEST.groups Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/TEST.groups Tue Mar 21 08:48:14 2017 -0700
@@ -28,8 +28,6 @@
tier1 = \
:jdk_lang \
:jdk_util \
- -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
- -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
sun/nio/cs/ISO8859x.java \
java/nio/Buffer \
com/sun/crypto/provider/Cipher \
@@ -37,8 +35,6 @@
tools/pack200
tier2 = \
- java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
- java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
:jdk_io \
:jdk_nio \
-sun/nio/cs/ISO8859x.java \
--- a/jdk/test/java/lang/ProcessHandle/JavaChild.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java Tue Mar 21 08:48:14 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,6 @@
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
-import java.io.PrintStream;
import java.io.Reader;
import java.io.PrintWriter;
import java.lang.InterruptedException;
@@ -39,9 +38,11 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Optional;
import java.util.function.Consumer;
@@ -437,6 +438,11 @@
case "threaddump":
Thread.dumpStack();
break;
+ case "waitpid":
+ long pid = Long.parseLong(args[nextArg++]);
+ Optional<String> s = ProcessHandle.of(pid).map(ph -> waitAlive(ph));
+ sendResult(action, s.orElse("pid not valid: " + pid));
+ break;
default:
throw new Error("JavaChild action unknown: " + action);
}
@@ -447,6 +453,17 @@
}
}
+ private static String waitAlive(ProcessHandle ph) {
+ String status;
+ try {
+ boolean isAlive = ph.onExit().get().isAlive();
+ status = Boolean.toString(isAlive);
+ } catch (InterruptedException | ExecutionException ex ) {
+ status = "interrupted";
+ }
+ return status;
+ }
+
static synchronized void sendRaw(String s) {
System.out.println(s);
System.out.flush();
@@ -476,6 +493,7 @@
System.err.println(" spawn <n> command... - spawn n new children and send command");
System.err.println(" child command... - send command to all live children");
System.err.println(" child_eof - send eof to all live children");
+ System.err.println(" waitpid <pid> - wait for the pid to exit");
System.err.println(" exit <exitcode>");
System.err.println(" out arg...");
System.err.println(" err arg...");
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Tue Mar 21 08:48:14 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -26,9 +26,11 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
import jdk.test.lib.Utils;
@@ -196,4 +198,95 @@
}
}
+ /**
+ * Verify that onExit completes for a non-child process only when
+ * the process has exited.
+ * Spawn a child (A) waiting to be commanded to exit.
+ * Spawn a child (B) to wait for that process to exit.
+ * Command (A) to exit.
+ * Check that (B) does not complete until (A) has exited.
+ */
+ @Test
+ public static void peerOnExitTest() {
+ String line = null;
+ ArrayBlockingQueue<String> alines = new ArrayBlockingQueue<>(100);
+ ArrayBlockingQueue<String> blines = new ArrayBlockingQueue<>(100);
+ JavaChild A = null;
+ try {
+ String[] split;
+ A = JavaChild.spawnJavaChild("stdin");
+ A.forEachOutputLine(l -> alines.add(l));
+
+ // Verify A is running
+ A.sendAction("pid");
+ do {
+ split = getSplitLine(alines);
+ } while (!"pid".equals(split[1]));
+
+ JavaChild B = null;
+ try {
+ B = JavaChild.spawnJavaChild("stdin");
+ B.forEachOutputLine(l -> blines.add(l));
+
+ // Verify B is running
+ B.sendAction("pid");
+ do {
+ split = getSplitLine(blines);
+ } while (!"pid".equals(split[1]));
+
+ // Tell B to wait for A's pid
+ B.sendAction("waitpid", A.getPid());
+
+ // Wait a bit to see if B will prematurely report the termination of A
+ try {
+ line = blines.poll(5L, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ Assert.fail("interrupted", ie);
+ }
+ Assert.assertNull(line, "waitpid didn't wait");
+
+ A.sendAction("exit", 0L);
+
+ // Look for B to report that A has exited
+ do {
+ split = getSplitLine(blines);
+ } while (!"waitpid".equals(split[1]));
+
+ Assert.assertEquals(split[2], "false", "Process A should not be alive");
+
+ B.sendAction("exit", 0L);
+ } catch (IOException ioe) {
+ Assert.fail("unable to start JavaChild B", ioe);
+ } finally {
+ B.destroyForcibly();
+ }
+ } catch (IOException ioe2) {
+ Assert.fail("unable to start JavaChild A", ioe2);
+ } finally {
+ A.destroyForcibly();
+ }
+ }
+
+ private static boolean DEBUG = true;
+
+ /**
+ * Get a line from the queue and split into words on whitespace.
+ * Log to stdout if requested.
+ * @param queue a queue of strings
+ * @return the words split from the line.
+ */
+ private static String[] getSplitLine(ArrayBlockingQueue<String> queue) {
+ try {
+ String line = queue.take();
+ String[] split = line.split("\\s");
+ if (DEBUG) {
+ System.out.printf(" Child Output: %s%n", line);
+ }
+ return split;
+ } catch (InterruptedException ie) {
+ Assert.fail("interrupted", ie);
+ return null;
+ }
+ }
+
}
--- a/jdk/test/java/lang/Runtime/Version/Basic.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/java/lang/Runtime/Version/Basic.java Tue Mar 21 08:48:14 2017 -0700
@@ -129,6 +129,9 @@
testEHC("9", "10", false, false, -1, -1);
testEHC("9", "8", false, false, 1, 1);
+ testEHC("10.512.1", "10.512.2", false, false, -1, -1);
+ testEHC("512.10.1", "512.11.1", false, false, -1, -1);
+
// $OPT comparison
testEHC("9", "9+-oink", false, true, -1, 0);
testEHC("9+-ribbit", "9+-moo", false, true, 1, 0);
--- a/jdk/test/java/nio/channels/FileChannel/Transfer.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java Tue Mar 21 08:48:14 2017 -0700
@@ -22,8 +22,7 @@
*/
/* @test
- * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
- * 6984545
+ * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545
* @key intermittent
* @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed)
* @library ..
@@ -34,18 +33,13 @@
*/
import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.io.Reader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
@@ -55,8 +49,6 @@
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
-import java.nio.file.StandardOpenOption;
-import java.nio.file.FileAlreadyExistsException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@@ -67,8 +59,6 @@
public class Transfer {
private static Random generator = RandomFactory.getRandom();
- private static PrintStream err = System.err;
- private static PrintStream out = System.out;
@Test
public void testFileChannel() throws Exception {
@@ -242,116 +232,7 @@
dest.delete();
}
- // Test transferTo with large file
- @Test
- public void xferTest04() throws Exception { // for bug 4638365
- // Windows and Linux can't handle the really large file sizes for a
- // truncate or a positional write required by the test for 4563125
- String osName = System.getProperty("os.name");
- if (!(osName.startsWith("SunOS") || osName.contains("OS X")))
- return;
- File source = File.createTempFile("blah", null);
- source.deleteOnExit();
- long testSize = ((long)Integer.MAX_VALUE) * 2;
- initTestFile(source, 10);
- RandomAccessFile raf = new RandomAccessFile(source, "rw");
- FileChannel fc = raf.getChannel();
- out.println(" Writing large file...");
- long t0 = System.nanoTime();
- fc.write(ByteBuffer.wrap("Use the source!".getBytes()), testSize - 40);
- long t1 = System.nanoTime();
- out.printf(" Wrote large file in %d ns (%d ms) %n",
- t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
-
- fc.close();
- raf.close();
-
- File sink = File.createTempFile("sink", null);
- sink.deleteOnExit();
-
- FileInputStream fis = new FileInputStream(source);
- FileChannel sourceChannel = fis.getChannel();
-
- raf = new RandomAccessFile(sink, "rw");
- FileChannel sinkChannel = raf.getChannel();
-
- long bytesWritten = sourceChannel.transferTo(testSize -40, 10,
- sinkChannel);
- if (bytesWritten != 10) {
- throw new RuntimeException("Transfer test 4 failed " +
- bytesWritten);
- }
- sourceChannel.close();
- sinkChannel.close();
-
- source.delete();
- sink.delete();
- }
-
- // Test transferFrom with large file
- @Test
- public void xferTest05() throws Exception { // for bug 4638365
- // Create a source file & large sink file for the test
- File source = File.createTempFile("blech", null);
- source.deleteOnExit();
- initTestFile(source, 100);
-
- // Create the sink file as a sparse file if possible
- File sink = null;
- FileChannel fc = null;
- while (fc == null) {
- sink = File.createTempFile("sink", null);
- // re-create as a sparse file
- sink.delete();
- try {
- fc = FileChannel.open(sink.toPath(),
- StandardOpenOption.CREATE_NEW,
- StandardOpenOption.WRITE,
- StandardOpenOption.SPARSE);
- } catch (FileAlreadyExistsException ignore) {
- // someone else got it
- }
- }
- sink.deleteOnExit();
-
- long testSize = ((long)Integer.MAX_VALUE) * 2;
- try {
- out.println(" Writing large file...");
- long t0 = System.nanoTime();
- fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
- testSize - 40);
- long t1 = System.nanoTime();
- out.printf(" Wrote large file in %d ns (%d ms) %n",
- t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
- } catch (IOException e) {
- // Can't set up the test, abort it
- err.println("xferTest05 was aborted.");
- return;
- } finally {
- fc.close();
- }
-
- // Get new channels for the source and sink and attempt transfer
- FileChannel sourceChannel = new FileInputStream(source).getChannel();
- try {
- FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
- try {
- long bytesWritten = sinkChannel.transferFrom(sourceChannel,
- testSize - 40, 10);
- if (bytesWritten != 10) {
- throw new RuntimeException("Transfer test 5 failed " +
- bytesWritten);
- }
- } finally {
- sinkChannel.close();
- }
- } finally {
- sourceChannel.close();
- }
-
- source.delete();
- sink.delete();
- }
+ // xferTest04() and xferTest05() moved to Transfer4GBFile.java
static void checkFileData(File file, String expected) throws Exception {
FileInputStream fis = new FileInputStream(file);
@@ -436,118 +317,7 @@
source.delete();
}
-
- // Test transferTo with file positions larger than 2 and 4GB
- @Test
- public void xferTest08() throws Exception { // for bug 6253145
- // Creating a sparse 6GB file on Windows takes too long
- String osName = System.getProperty("os.name");
- if (osName.startsWith("Windows"))
- return;
-
- final long G = 1024L * 1024L * 1024L;
-
- // Create 6GB file
-
- File file = File.createTempFile("source", null);
- file.deleteOnExit();
-
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- FileChannel fc = raf.getChannel();
-
- out.println(" Writing large file...");
- long t0 = System.nanoTime();
- try {
- fc.write(ByteBuffer.wrap("0123456789012345".getBytes("UTF-8")), 6*G);
- long t1 = System.nanoTime();
- out.printf(" Wrote large file in %d ns (%d ms) %n",
- t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
- } catch (IOException x) {
- err.println(" Unable to create test file:" + x);
- fc.close();
- return;
- }
-
- // Setup looback connection and echo server
-
- ServerSocketChannel ssc = ServerSocketChannel.open();
- ssc.socket().bind(new InetSocketAddress(0));
-
- InetAddress lh = InetAddress.getLocalHost();
- InetSocketAddress isa = new InetSocketAddress(lh, ssc.socket().getLocalPort());
- SocketChannel source = SocketChannel.open(isa);
- SocketChannel sink = ssc.accept();
-
- Thread thr = new Thread(new EchoServer(sink));
- thr.start();
-
- // Test data is array of positions and counts
-
- long testdata[][] = {
- { 2*G-1, 1 },
- { 2*G-1, 10 }, // across 2GB boundary
- { 2*G, 1 },
- { 2*G, 10 },
- { 2*G+1, 1 },
- { 4*G-1, 1 },
- { 4*G-1, 10 }, // across 4GB boundary
- { 4*G, 1 },
- { 4*G, 10 },
- { 4*G+1, 1 },
- { 5*G-1, 1 },
- { 5*G-1, 10 },
- { 5*G, 1 },
- { 5*G, 10 },
- { 5*G+1, 1 },
- { 6*G, 1 },
- };
-
- ByteBuffer sendbuf = ByteBuffer.allocateDirect(100);
- ByteBuffer readbuf = ByteBuffer.allocateDirect(100);
-
- try {
- byte value = 0;
- for (int i=0; i<testdata.length; i++) {
- long position = testdata[(int)i][0];
- long count = testdata[(int)i][1];
-
- // generate bytes
- for (long j=0; j<count; j++) {
- sendbuf.put(++value);
- }
- sendbuf.flip();
-
- // write to file and transfer to echo server
- fc.write(sendbuf, position);
- t0 = System.nanoTime();
- fc.transferTo(position, count, source);
- out.printf(" transferTo(%d, %2d, source): %d ns%n",
- position, count, System.nanoTime() - t0);
-
- // read from echo server
- long nread = 0;
- while (nread < count) {
- int n = source.read(readbuf);
- if (n < 0)
- throw new RuntimeException("Premature EOF!");
- nread += n;
- }
-
- // check reply from echo server
- readbuf.flip();
- sendbuf.flip();
- if (!readbuf.equals(sendbuf))
- throw new RuntimeException("Echoed bytes do not match!");
- readbuf.clear();
- sendbuf.clear();
- }
- } finally {
- source.close();
- ssc.close();
- fc.close();
- file.delete();
- }
- }
+ // xferTest08() moved to TransferTo6GBFile.java
// Test that transferFrom with FileChannel source that is not readable
// throws NonReadableChannelException
@@ -570,56 +340,4 @@
fc2.close();
}
}
-
- /**
- * Creates file blah of specified size in bytes.
- */
- private static void initTestFile(File blah, long size) throws Exception {
- if (blah.exists())
- blah.delete();
- FileOutputStream fos = new FileOutputStream(blah);
- BufferedWriter awriter
- = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
-
- for(int i=0; i<size; i++) {
- awriter.write("e");
- }
- awriter.flush();
- awriter.close();
- }
-
- /**
- * Simple in-process server to echo bytes read by a given socket channel
- */
- static class EchoServer implements Runnable {
- private SocketChannel sc;
-
- public EchoServer(SocketChannel sc) {
- this.sc = sc;
- }
-
- public void run() {
- ByteBuffer bb = ByteBuffer.allocateDirect(1024);
- try {
- for (;;) {
- int n = sc.read(bb);
- if (n < 0)
- break;
-
- bb.flip();
- while (bb.remaining() > 0) {
- sc.write(bb);
- }
- bb.clear();
- }
- } catch (IOException x) {
- x.printStackTrace();
- } finally {
- try {
- sc.close();
- } catch (IOException ignore) { }
- }
- }
- }
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java Tue Mar 21 08:48:14 2017 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2001, 2017, 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
+ * @bug 4638365
+ * @key intermittent
+ * @summary Test FileChannel.transferFrom and transferTo for 4GB files
+ * @run testng/timeout=300 Transfer4GBFile
+ */
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.FileAlreadyExistsException;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+
+public class Transfer4GBFile {
+
+ private static PrintStream err = System.err;
+ private static PrintStream out = System.out;
+
+ // Test transferTo with large file
+ @Test
+ public void xferTest04() throws Exception { // for bug 4638365
+ // Windows and Linux can't handle the really large file sizes for a
+ // truncate or a positional write required by the test for 4563125
+ String osName = System.getProperty("os.name");
+ if (!(osName.startsWith("SunOS") || osName.contains("OS X")))
+ return;
+ File source = File.createTempFile("blah", null);
+ source.deleteOnExit();
+ long testSize = ((long)Integer.MAX_VALUE) * 2;
+ initTestFile(source, 10);
+ RandomAccessFile raf = new RandomAccessFile(source, "rw");
+ FileChannel fc = raf.getChannel();
+ out.println(" Writing large file...");
+ long t0 = System.nanoTime();
+ fc.write(ByteBuffer.wrap("Use the source!".getBytes()), testSize - 40);
+ long t1 = System.nanoTime();
+ out.printf(" Wrote large file in %d ns (%d ms) %n",
+ t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
+
+ fc.close();
+ raf.close();
+
+ File sink = File.createTempFile("sink", null);
+ sink.deleteOnExit();
+
+ FileInputStream fis = new FileInputStream(source);
+ FileChannel sourceChannel = fis.getChannel();
+
+ raf = new RandomAccessFile(sink, "rw");
+ FileChannel sinkChannel = raf.getChannel();
+
+ long bytesWritten = sourceChannel.transferTo(testSize -40, 10,
+ sinkChannel);
+ if (bytesWritten != 10) {
+ throw new RuntimeException("Transfer test 4 failed " +
+ bytesWritten);
+ }
+ sourceChannel.close();
+ sinkChannel.close();
+
+ source.delete();
+ sink.delete();
+ }
+
+ // Test transferFrom with large file
+ @Test
+ public void xferTest05() throws Exception { // for bug 4638365
+ // Create a source file & large sink file for the test
+ File source = File.createTempFile("blech", null);
+ source.deleteOnExit();
+ initTestFile(source, 100);
+
+ // Create the sink file as a sparse file if possible
+ File sink = null;
+ FileChannel fc = null;
+ while (fc == null) {
+ sink = File.createTempFile("sink", null);
+ // re-create as a sparse file
+ sink.delete();
+ try {
+ fc = FileChannel.open(sink.toPath(),
+ StandardOpenOption.CREATE_NEW,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.SPARSE);
+ } catch (FileAlreadyExistsException ignore) {
+ // someone else got it
+ }
+ }
+ sink.deleteOnExit();
+
+ long testSize = ((long)Integer.MAX_VALUE) * 2;
+ try {
+ out.println(" Writing large file...");
+ long t0 = System.nanoTime();
+ fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
+ testSize - 40);
+ long t1 = System.nanoTime();
+ out.printf(" Wrote large file in %d ns (%d ms) %n",
+ t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
+ } catch (IOException e) {
+ // Can't set up the test, abort it
+ err.println("xferTest05 was aborted.");
+ return;
+ } finally {
+ fc.close();
+ }
+
+ // Get new channels for the source and sink and attempt transfer
+ FileChannel sourceChannel = new FileInputStream(source).getChannel();
+ try {
+ FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
+ try {
+ long bytesWritten = sinkChannel.transferFrom(sourceChannel,
+ testSize - 40, 10);
+ if (bytesWritten != 10) {
+ throw new RuntimeException("Transfer test 5 failed " +
+ bytesWritten);
+ }
+ } finally {
+ sinkChannel.close();
+ }
+ } finally {
+ sourceChannel.close();
+ }
+
+ source.delete();
+ sink.delete();
+ }
+
+ /**
+ * Creates file blah of specified size in bytes.
+ */
+ private static void initTestFile(File blah, long size) throws Exception {
+ if (blah.exists())
+ blah.delete();
+ FileOutputStream fos = new FileOutputStream(blah);
+ BufferedWriter awriter
+ = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
+
+ for(int i=0; i<size; i++) {
+ awriter.write("e");
+ }
+ awriter.flush();
+ awriter.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java Tue Mar 21 08:48:14 2017 -0700
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2001, 2017, 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
+ * @bug 6253145
+ * @key intermittent
+ * @summary Test FileChannel.transferTo with file positions up to 8GB
+ * @run testng/timeout=300 TransferTo6GBFile
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.RandomAccessFile;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+
+public class TransferTo6GBFile {
+
+ private static PrintStream err = System.err;
+ private static PrintStream out = System.out;
+
+ // Test transferTo with file positions larger than 2 and 4GB
+ @Test
+ public void xferTest08() throws Exception { // for bug 6253145
+ // Creating a sparse 6GB file on Windows takes too long
+ String osName = System.getProperty("os.name");
+ if (osName.startsWith("Windows"))
+ return;
+
+ final long G = 1024L * 1024L * 1024L;
+
+ // Create 6GB file
+
+ File file = File.createTempFile("source", null);
+ file.deleteOnExit();
+
+ RandomAccessFile raf = new RandomAccessFile(file, "rw");
+ FileChannel fc = raf.getChannel();
+
+ out.println(" Writing large file...");
+ long t0 = System.nanoTime();
+ try {
+ fc.write(ByteBuffer.wrap("0123456789012345".getBytes("UTF-8")), 6*G);
+ long t1 = System.nanoTime();
+ out.printf(" Wrote large file in %d ns (%d ms) %n",
+ t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
+ } catch (IOException x) {
+ err.println(" Unable to create test file:" + x);
+ fc.close();
+ return;
+ }
+
+ // Setup looback connection and echo server
+
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(0));
+
+ InetAddress lh = InetAddress.getLocalHost();
+ InetSocketAddress isa = new InetSocketAddress(lh, ssc.socket().getLocalPort());
+ SocketChannel source = SocketChannel.open(isa);
+ SocketChannel sink = ssc.accept();
+
+ Thread thr = new Thread(new EchoServer(sink));
+ thr.start();
+
+ // Test data is array of positions and counts
+
+ long testdata[][] = {
+ { 2*G-1, 1 },
+ { 2*G-1, 10 }, // across 2GB boundary
+ { 2*G, 1 },
+ { 2*G, 10 },
+ { 2*G+1, 1 },
+ { 4*G-1, 1 },
+ { 4*G-1, 10 }, // across 4GB boundary
+ { 4*G, 1 },
+ { 4*G, 10 },
+ { 4*G+1, 1 },
+ { 5*G-1, 1 },
+ { 5*G-1, 10 },
+ { 5*G, 1 },
+ { 5*G, 10 },
+ { 5*G+1, 1 },
+ { 6*G, 1 },
+ };
+
+ ByteBuffer sendbuf = ByteBuffer.allocateDirect(100);
+ ByteBuffer readbuf = ByteBuffer.allocateDirect(100);
+
+ try {
+ byte value = 0;
+ for (int i=0; i<testdata.length; i++) {
+ long position = testdata[(int)i][0];
+ long count = testdata[(int)i][1];
+
+ // generate bytes
+ for (long j=0; j<count; j++) {
+ sendbuf.put(++value);
+ }
+ sendbuf.flip();
+
+ // write to file and transfer to echo server
+ fc.write(sendbuf, position);
+ t0 = System.nanoTime();
+ fc.transferTo(position, count, source);
+ out.printf(" transferTo(%d, %2d, source): %d ns%n",
+ position, count, System.nanoTime() - t0);
+
+ // read from echo server
+ long nread = 0;
+ while (nread < count) {
+ int n = source.read(readbuf);
+ if (n < 0)
+ throw new RuntimeException("Premature EOF!");
+ nread += n;
+ }
+
+ // check reply from echo server
+ readbuf.flip();
+ sendbuf.flip();
+ if (!readbuf.equals(sendbuf))
+ throw new RuntimeException("Echoed bytes do not match!");
+ readbuf.clear();
+ sendbuf.clear();
+ }
+ } finally {
+ source.close();
+ ssc.close();
+ fc.close();
+ file.delete();
+ }
+ }
+
+ /**
+ * Simple in-process server to echo bytes read by a given socket channel
+ */
+ static class EchoServer implements Runnable {
+ private SocketChannel sc;
+
+ public EchoServer(SocketChannel sc) {
+ this.sc = sc;
+ }
+
+ public void run() {
+ ByteBuffer bb = ByteBuffer.allocateDirect(1024);
+ try {
+ for (;;) {
+ int n = sc.read(bb);
+ if (n < 0)
+ break;
+
+ bb.flip();
+ while (bb.remaining() > 0) {
+ sc.write(bb);
+ }
+ bb.clear();
+ }
+ } catch (IOException x) {
+ x.printStackTrace();
+ } finally {
+ try {
+ sc.close();
+ } catch (IOException ignore) { }
+ }
+ }
+ }
+}
--- a/jdk/test/sun/net/www/http/HttpClient/B8025710.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/sun/net/www/http/HttpClient/B8025710.java Tue Mar 21 08:48:14 2017 -0700
@@ -37,6 +37,7 @@
* @test
* @bug 8025710
* @summary Proxied https connection reuse by HttpClient can send CONNECT to the server
+ * @run main/othervm B8025710
*/
public class B8025710 {
--- a/jdk/test/tools/jar/modularJar/Basic.java Thu Mar 16 22:03:08 2017 +0300
+++ b/jdk/test/tools/jar/modularJar/Basic.java Tue Mar 21 08:48:14 2017 -0700
@@ -39,6 +39,7 @@
import jdk.testlibrary.FileUtils;
import jdk.testlibrary.JDKToolFinder;
import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static java.lang.String.format;
@@ -46,7 +47,7 @@
/*
* @test
- * @bug 8167328 8171830 8165640 8174248
+ * @bug 8167328 8171830 8165640 8174248 8176772
* @library /lib/testlibrary
* @modules jdk.compiler
* jdk.jartool
@@ -754,7 +755,7 @@
.assertSuccess();
- for (String option : new String[] {"--print-module-descriptor", "-d" }) {
+ for (String option : new String[] {"--describe-module", "-d" }) {
jar(option,
"--file=" + modularJar.toString())
@@ -801,8 +802,8 @@
}
@Test
- public void printModuleDescriptorFoo() throws IOException {
- Path mp = Paths.get("printModuleDescriptorFoo");
+ public void describeModuleFoo() throws IOException {
+ Path mp = Paths.get("describeModuleFoo");
createTestDir(mp);
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
@@ -815,7 +816,7 @@
"-C", modClasses.toString(), ".")
.assertSuccess();
- for (String option : new String[] {"--print-module-descriptor", "-d" }) {
+ for (String option : new String[] {"--describe-module", "-d" }) {
jar(option,
"--file=" + modularJar.toString())
.assertSuccess()
@@ -836,8 +837,8 @@
}
@Test
- public void printModuleDescriptorFooFromStdin() throws IOException {
- Path mp = Paths.get("printModuleDescriptorFooFromStdin");
+ public void describeModuleFooFromStdin() throws IOException {
+ Path mp = Paths.get("describeModuleFooFromStdin");
createTestDir(mp);
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
@@ -850,7 +851,7 @@
"-C", modClasses.toString(), ".")
.assertSuccess();
- for (String option : new String[] {"--print-module-descriptor", "-d" }) {
+ for (String option : new String[] {"--describe-module", "-d" }) {
jarWithStdin(modularJar.toFile(),
option)
.assertSuccess()
@@ -862,6 +863,50 @@
}
}
+
+ @DataProvider(name = "autoNames")
+ public Object[][] autoNames() {
+ return new Object[][] {
+ // JAR file name module-name[@version]
+ { "foo.jar", "foo" },
+ { "foo4j.jar", "foo4j", },
+ { "foo1.2.3.jar", "foo" },
+ { "foo-1.2.3.4.jar", "foo@1.2.3.4" },
+ { "foo-bar.jar", "foo.bar" },
+ { "foo-1.2-SNAPSHOT.jar", "foo@1.2-SNAPSHOT" },
+ };
+ }
+
+ @Test(dataProvider = "autoNames")
+ public void describeAutomaticModule(String jarName, String mid)
+ throws IOException
+ {
+ Path mp = Paths.get("describeAutomaticModule");
+ createTestDir(mp);
+ Path regularJar = mp.resolve(jarName);
+ Path t = Paths.get("t");
+ if (Files.notExists(t))
+ Files.createFile(t);
+
+ jar("--create",
+ "--file=" + regularJar.toString(),
+ t.toString())
+ .assertSuccess();
+
+ for (String option : new String[] {"--describe-module", "-d" }) {
+ jar(option,
+ "--file=" + regularJar.toString())
+ .assertSuccess()
+ .resultChecker(r -> {
+ assertTrue(r.output.contains("No module descriptor found"));
+ assertTrue(r.output.contains("Derived automatic module"));
+ assertTrue(r.output.contains("module " + mid),
+ "Expected [", "module " + mid,"] in [", r.output, "]");
+ }
+ );
+ }
+ }
+
// -- Infrastructure
static Result jarWithStdin(File stdinSource, String... args) {