mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
Merge
This commit is contained in:
commit
b12d27166f
250 changed files with 9035 additions and 3846 deletions
81
jdk/test/java/io/FileOutputStream/AtomicAppend.java
Normal file
81
jdk/test/java/io/FileOutputStream/AtomicAppend.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6631352
|
||||
* @summary Check that appends are atomic
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AtomicAppend {
|
||||
// Before the fix for
|
||||
// 6631352: Implement atomic append mode using FILE_APPEND_DATA (win)
|
||||
// this would fail intermittently on windows
|
||||
void test(String[] args) throws Throwable {
|
||||
final int nThreads = 10;
|
||||
final int writes = 1000;
|
||||
final File file = new File("foo");
|
||||
file.delete();
|
||||
try {
|
||||
final ExecutorService es = Executors.newFixedThreadPool(nThreads);
|
||||
for (int i = 0; i < nThreads; i++)
|
||||
es.execute(new Runnable() { public void run() {
|
||||
try {
|
||||
FileOutputStream s = new FileOutputStream(file, true);
|
||||
for (int j = 0; j < 1000; j++) {
|
||||
s.write((int) 'x');
|
||||
s.flush();
|
||||
}
|
||||
s.close();
|
||||
} catch (Throwable t) { unexpected(t); }}});
|
||||
es.shutdown();
|
||||
es.awaitTermination(10L, TimeUnit.MINUTES);
|
||||
equal(file.length(), (long) (nThreads * writes));
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new AtomicAppend().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
|
@ -25,12 +25,15 @@
|
|||
* @test
|
||||
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
|
||||
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
|
||||
* 6464154 6523983 6206031
|
||||
* 6464154 6523983 6206031 4960438 6631352 6631966
|
||||
* @summary Basic tests for Process and Environment Variable code
|
||||
* @run main/othervm Basic
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import static java.lang.ProcessBuilder.Redirect.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
|
@ -257,7 +260,29 @@ public class Basic {
|
|||
public static class JavaChild {
|
||||
public static void main(String args[]) throws Throwable {
|
||||
String action = args[0];
|
||||
if (action.equals("System.getenv(String)")) {
|
||||
if (action.equals("testIO")) {
|
||||
String expected = "standard input";
|
||||
char[] buf = new char[expected.length()+1];
|
||||
int n = new InputStreamReader(System.in).read(buf,0,buf.length);
|
||||
if (n != expected.length())
|
||||
System.exit(5);
|
||||
if (! new String(buf,0,n).equals(expected))
|
||||
System.exit(5);
|
||||
System.err.print("standard error");
|
||||
System.out.print("standard output");
|
||||
} else if (action.equals("testInheritIO")) {
|
||||
List<String> childArgs = new ArrayList<String>(javaChildArgs);
|
||||
childArgs.add("testIO");
|
||||
ProcessBuilder pb = new ProcessBuilder(childArgs);
|
||||
pb.inheritIO();
|
||||
ProcessResults r = run(pb);
|
||||
if (! r.out().equals(""))
|
||||
System.exit(7);
|
||||
if (! r.err().equals(""))
|
||||
System.exit(8);
|
||||
if (r.exitValue() != 0)
|
||||
System.exit(9);
|
||||
} else if (action.equals("System.getenv(String)")) {
|
||||
String val = System.getenv(args[1]);
|
||||
printUTF8(val == null ? "null" : val);
|
||||
} else if (action.equals("System.getenv(\\u1234)")) {
|
||||
|
@ -599,6 +624,333 @@ public class Basic {
|
|||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
static void checkRedirects(ProcessBuilder pb,
|
||||
Redirect in, Redirect out, Redirect err) {
|
||||
equal(pb.redirectInput(), in);
|
||||
equal(pb.redirectOutput(), out);
|
||||
equal(pb.redirectError(), err);
|
||||
}
|
||||
|
||||
static void redirectIO(ProcessBuilder pb,
|
||||
Redirect in, Redirect out, Redirect err) {
|
||||
pb.redirectInput(in);
|
||||
pb.redirectOutput(out);
|
||||
pb.redirectError(err);
|
||||
}
|
||||
|
||||
static void setFileContents(File file, String contents) {
|
||||
try {
|
||||
Writer w = new FileWriter(file);
|
||||
w.write(contents);
|
||||
w.close();
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
static String fileContents(File file) {
|
||||
try {
|
||||
Reader r = new FileReader(file);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] buffer = new char[1024];
|
||||
int n;
|
||||
while ((n = r.read(buffer)) != -1)
|
||||
sb.append(buffer,0,n);
|
||||
r.close();
|
||||
return new String(sb);
|
||||
} catch (Throwable t) { unexpected(t); return ""; }
|
||||
}
|
||||
|
||||
static void testIORedirection() throws Throwable {
|
||||
final File ifile = new File("ifile");
|
||||
final File ofile = new File("ofile");
|
||||
final File efile = new File("efile");
|
||||
ifile.delete();
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Check mutual inequality of different types of Redirect
|
||||
//----------------------------------------------------------------
|
||||
Redirect[] redirects =
|
||||
{ PIPE,
|
||||
INHERIT,
|
||||
Redirect.from(ifile),
|
||||
Redirect.to(ifile),
|
||||
Redirect.appendTo(ifile),
|
||||
Redirect.from(ofile),
|
||||
Redirect.to(ofile),
|
||||
Redirect.appendTo(ofile),
|
||||
};
|
||||
for (int i = 0; i < redirects.length; i++)
|
||||
for (int j = 0; j < redirects.length; j++)
|
||||
equal(redirects[i].equals(redirects[j]), (i == j));
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Check basic properties of different types of Redirect
|
||||
//----------------------------------------------------------------
|
||||
equal(PIPE.type(), Redirect.Type.PIPE);
|
||||
equal(PIPE.toString(), "PIPE");
|
||||
equal(PIPE.file(), null);
|
||||
|
||||
equal(INHERIT.type(), Redirect.Type.INHERIT);
|
||||
equal(INHERIT.toString(), "INHERIT");
|
||||
equal(INHERIT.file(), null);
|
||||
|
||||
equal(Redirect.from(ifile).type(), Redirect.Type.READ);
|
||||
equal(Redirect.from(ifile).toString(),
|
||||
"redirect to read from file \"ifile\"");
|
||||
equal(Redirect.from(ifile).file(), ifile);
|
||||
equal(Redirect.from(ifile),
|
||||
Redirect.from(ifile));
|
||||
equal(Redirect.from(ifile).hashCode(),
|
||||
Redirect.from(ifile).hashCode());
|
||||
|
||||
equal(Redirect.to(ofile).type(), Redirect.Type.WRITE);
|
||||
equal(Redirect.to(ofile).toString(),
|
||||
"redirect to write to file \"ofile\"");
|
||||
equal(Redirect.to(ofile).file(), ofile);
|
||||
equal(Redirect.to(ofile),
|
||||
Redirect.to(ofile));
|
||||
equal(Redirect.to(ofile).hashCode(),
|
||||
Redirect.to(ofile).hashCode());
|
||||
|
||||
equal(Redirect.appendTo(ofile).type(), Redirect.Type.APPEND);
|
||||
equal(Redirect.appendTo(efile).toString(),
|
||||
"redirect to append to file \"efile\"");
|
||||
equal(Redirect.appendTo(efile).file(), efile);
|
||||
equal(Redirect.appendTo(efile),
|
||||
Redirect.appendTo(efile));
|
||||
equal(Redirect.appendTo(efile).hashCode(),
|
||||
Redirect.appendTo(efile).hashCode());
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Check initial values of redirects
|
||||
//----------------------------------------------------------------
|
||||
List<String> childArgs = new ArrayList<String>(javaChildArgs);
|
||||
childArgs.add("testIO");
|
||||
final ProcessBuilder pb = new ProcessBuilder(childArgs);
|
||||
checkRedirects(pb, PIPE, PIPE, PIPE);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Check inheritIO
|
||||
//----------------------------------------------------------------
|
||||
pb.inheritIO();
|
||||
checkRedirects(pb, INHERIT, INHERIT, INHERIT);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Check setters and getters agree
|
||||
//----------------------------------------------------------------
|
||||
pb.redirectInput(ifile);
|
||||
equal(pb.redirectInput().file(), ifile);
|
||||
equal(pb.redirectInput(), Redirect.from(ifile));
|
||||
|
||||
pb.redirectOutput(ofile);
|
||||
equal(pb.redirectOutput().file(), ofile);
|
||||
equal(pb.redirectOutput(), Redirect.to(ofile));
|
||||
|
||||
pb.redirectError(efile);
|
||||
equal(pb.redirectError().file(), efile);
|
||||
equal(pb.redirectError(), Redirect.to(efile));
|
||||
|
||||
THROWS(IllegalArgumentException.class,
|
||||
new Fun(){void f() {
|
||||
pb.redirectInput(Redirect.to(ofile)); }},
|
||||
new Fun(){void f() {
|
||||
pb.redirectInput(Redirect.appendTo(ofile)); }},
|
||||
new Fun(){void f() {
|
||||
pb.redirectOutput(Redirect.from(ifile)); }},
|
||||
new Fun(){void f() {
|
||||
pb.redirectError(Redirect.from(ifile)); }});
|
||||
|
||||
THROWS(IOException.class,
|
||||
// Input file does not exist
|
||||
new Fun(){void f() throws Throwable { pb.start(); }});
|
||||
setFileContents(ifile, "standard input");
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Writing to non-existent files
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(fileContents(ofile), "standard output");
|
||||
equal(fileContents(efile), "standard error");
|
||||
equal(r.out(), "");
|
||||
equal(r.err(), "");
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Both redirectErrorStream + redirectError
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
pb.redirectErrorStream(true);
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(fileContents(ofile),
|
||||
"standard error" + "standard output");
|
||||
equal(fileContents(efile), "");
|
||||
equal(r.out(), "");
|
||||
equal(r.err(), "");
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Appending to existing files
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
setFileContents(ofile, "ofile-contents");
|
||||
setFileContents(efile, "efile-contents");
|
||||
pb.redirectOutput(Redirect.appendTo(ofile));
|
||||
pb.redirectError(Redirect.appendTo(efile));
|
||||
pb.redirectErrorStream(false);
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(fileContents(ofile),
|
||||
"ofile-contents" + "standard output");
|
||||
equal(fileContents(efile),
|
||||
"efile-contents" + "standard error");
|
||||
equal(r.out(), "");
|
||||
equal(r.err(), "");
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Replacing existing files
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
setFileContents(ofile, "ofile-contents");
|
||||
setFileContents(efile, "efile-contents");
|
||||
pb.redirectOutput(ofile);
|
||||
pb.redirectError(Redirect.to(efile));
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(fileContents(ofile), "standard output");
|
||||
equal(fileContents(efile), "standard error");
|
||||
equal(r.out(), "");
|
||||
equal(r.err(), "");
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Appending twice to the same file?
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
setFileContents(ofile, "ofile-contents");
|
||||
setFileContents(efile, "efile-contents");
|
||||
Redirect appender = Redirect.appendTo(ofile);
|
||||
pb.redirectOutput(appender);
|
||||
pb.redirectError(appender);
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(fileContents(ofile),
|
||||
"ofile-contents" +
|
||||
"standard error" +
|
||||
"standard output");
|
||||
equal(fileContents(efile), "efile-contents");
|
||||
equal(r.out(), "");
|
||||
equal(r.err(), "");
|
||||
ifile.delete();
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Testing INHERIT is harder.
|
||||
// Note that this requires __FOUR__ nested JVMs involved in one test,
|
||||
// if you count the harness JVM.
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
redirectIO(pb, PIPE, PIPE, PIPE);
|
||||
List<String> command = pb.command();
|
||||
command.set(command.size() - 1, "testInheritIO");
|
||||
Process p = pb.start();
|
||||
new PrintStream(p.getOutputStream()).print("standard input");
|
||||
p.getOutputStream().close();
|
||||
ProcessResults r = run(p);
|
||||
equal(r.exitValue(), 0);
|
||||
equal(r.out(), "standard output");
|
||||
equal(r.err(), "standard error");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Test security implications of I/O redirection
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Read access to current directory is always granted;
|
||||
// So create a tmpfile for input instead.
|
||||
final File tmpFile = File.createTempFile("Basic", "tmp");
|
||||
setFileContents(tmpFile, "standard input");
|
||||
|
||||
final Policy policy = new Policy();
|
||||
Policy.setPolicy(policy);
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
try {
|
||||
final Permission xPermission
|
||||
= new FilePermission("<<ALL FILES>>", "execute");
|
||||
final Permission rxPermission
|
||||
= new FilePermission("<<ALL FILES>>", "read,execute");
|
||||
final Permission wxPermission
|
||||
= new FilePermission("<<ALL FILES>>", "write,execute");
|
||||
final Permission rwxPermission
|
||||
= new FilePermission("<<ALL FILES>>", "read,write,execute");
|
||||
|
||||
THROWS(SecurityException.class,
|
||||
new Fun() { void f() throws IOException {
|
||||
policy.setPermissions(xPermission);
|
||||
redirectIO(pb, from(tmpFile), PIPE, PIPE);
|
||||
pb.start();}},
|
||||
new Fun() { void f() throws IOException {
|
||||
policy.setPermissions(rxPermission);
|
||||
redirectIO(pb, PIPE, to(ofile), PIPE);
|
||||
pb.start();}},
|
||||
new Fun() { void f() throws IOException {
|
||||
policy.setPermissions(rxPermission);
|
||||
redirectIO(pb, PIPE, PIPE, to(efile));
|
||||
pb.start();}});
|
||||
|
||||
{
|
||||
policy.setPermissions(rxPermission);
|
||||
redirectIO(pb, from(tmpFile), PIPE, PIPE);
|
||||
ProcessResults r = run(pb);
|
||||
equal(r.out(), "standard output");
|
||||
equal(r.err(), "standard error");
|
||||
}
|
||||
|
||||
{
|
||||
policy.setPermissions(wxPermission);
|
||||
redirectIO(pb, PIPE, to(ofile), to(efile));
|
||||
Process p = pb.start();
|
||||
new PrintStream(p.getOutputStream()).print("standard input");
|
||||
p.getOutputStream().close();
|
||||
ProcessResults r = run(p);
|
||||
policy.setPermissions(rwxPermission);
|
||||
equal(fileContents(ofile), "standard output");
|
||||
equal(fileContents(efile), "standard error");
|
||||
}
|
||||
|
||||
{
|
||||
policy.setPermissions(rwxPermission);
|
||||
redirectIO(pb, from(tmpFile), to(ofile), to(efile));
|
||||
ProcessResults r = run(pb);
|
||||
policy.setPermissions(rwxPermission);
|
||||
equal(fileContents(ofile), "standard output");
|
||||
equal(fileContents(efile), "standard error");
|
||||
}
|
||||
|
||||
} finally {
|
||||
policy.setPermissions(new RuntimePermission("setSecurityManager"));
|
||||
System.setSecurityManager(null);
|
||||
tmpFile.delete();
|
||||
ifile.delete();
|
||||
ofile.delete();
|
||||
efile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
if (Windows.is())
|
||||
System.out.println("This appears to be a Windows system.");
|
||||
|
@ -607,6 +959,9 @@ public class Basic {
|
|||
if (UnicodeOS.is())
|
||||
System.out.println("This appears to be a Unicode-based OS.");
|
||||
|
||||
try { testIORedirection(); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Basic tests for setting, replacing and deleting envvars
|
||||
//----------------------------------------------------------------
|
||||
|
@ -1354,7 +1709,8 @@ public class Basic {
|
|||
execPermission);
|
||||
ProcessBuilder pb = new ProcessBuilder("env");
|
||||
pb.environment().put("foo","bar");
|
||||
pb.start();
|
||||
Process p = pb.start();
|
||||
closeStreams(p);
|
||||
} catch (IOException e) { // OK
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
|
||||
|
@ -1378,6 +1734,14 @@ public class Basic {
|
|||
|
||||
}
|
||||
|
||||
static void closeStreams(Process p) {
|
||||
try {
|
||||
p.getOutputStream().close();
|
||||
p.getInputStream().close();
|
||||
p.getErrorStream().close();
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// A Policy class designed to make permissions fiddling very easy.
|
||||
//----------------------------------------------------------------
|
||||
|
@ -1432,10 +1796,19 @@ public class Basic {
|
|||
}
|
||||
} catch (Throwable t) {
|
||||
throwable = t;
|
||||
} finally {
|
||||
try { is.close(); }
|
||||
catch (Throwable t) { throwable = t; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ProcessResults run(ProcessBuilder pb) {
|
||||
try {
|
||||
return run(pb.start());
|
||||
} catch (Throwable t) { unexpected(t); return null; }
|
||||
}
|
||||
|
||||
private static ProcessResults run(Process p) {
|
||||
Throwable throwable = null;
|
||||
int exitValue = -1;
|
||||
|
|
83
jdk/test/java/nio/channels/Channels/ShortWrite.java
Normal file
83
jdk/test/java/nio/channels/Channels/ShortWrite.java
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6448457
|
||||
* @summary Test Channels.newOutputStream returns OutputStream that handles
|
||||
* short writes from the underlying channel
|
||||
*/
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class ShortWrite {
|
||||
|
||||
static Random rand = new Random();
|
||||
static int bytesWritten = 0;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
WritableByteChannel wbc = new WritableByteChannel() {
|
||||
public int write(ByteBuffer src) {
|
||||
int rem = src.remaining();
|
||||
if (rem > 0) {
|
||||
// short write
|
||||
int n = rand.nextInt(rem) + 1;
|
||||
src.position(src.position() + n);
|
||||
bytesWritten += n;
|
||||
return n;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public void close() throws IOException {
|
||||
throw new RuntimeException("not implemented");
|
||||
}
|
||||
public boolean isOpen() {
|
||||
throw new RuntimeException("not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
// wrap Channel with OutputStream
|
||||
OutputStream out = Channels.newOutputStream(wbc);
|
||||
|
||||
|
||||
// write 100, 99, 98, ... 1
|
||||
// and check that the expected number of bytes is written
|
||||
int expected = 0;
|
||||
byte[] buf = new byte[100];
|
||||
for (int i=0; i<buf.length; i++) {
|
||||
int len = buf.length-i;
|
||||
out.write(buf, i, len);
|
||||
expected += len;
|
||||
}
|
||||
System.out.format("Bytes written: %d, expected: %d\n", bytesWritten,
|
||||
expected);
|
||||
if (bytesWritten != expected)
|
||||
throw new RuntimeException("incorrect number of bytes written");
|
||||
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ public class TestUtil {
|
|||
// Test hosts used by the channels tests - change these when
|
||||
// executing in a different network.
|
||||
public static final String HOST = "javaweb.sfbay.sun.com";
|
||||
public static final String REFUSING_HOST = "jano.sfbay.sun.com";
|
||||
public static final String REFUSING_HOST = "jano1.sfbay.sun.com";
|
||||
public static final String FAR_HOST = "theclub.ireland.sun.com";
|
||||
public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah";
|
||||
|
||||
|
|
127
jdk/test/java/util/Map/LockStep.java
Normal file
127
jdk/test/java/util/Map/LockStep.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6612102
|
||||
* @summary Test Map implementations for mutual compatibility
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Based on the strange scenario required to reproduce
|
||||
* (coll) IdentityHashMap.iterator().remove() might decrement size twice
|
||||
*
|
||||
* It would be good to add more "Lockstep-style" tests to this file.
|
||||
*/
|
||||
public class LockStep {
|
||||
void mapsEqual(Map m1, Map m2) {
|
||||
equal(m1, m2);
|
||||
equal(m2, m1);
|
||||
equal(m1.size(), m2.size());
|
||||
equal(m1.isEmpty(), m2.isEmpty());
|
||||
equal(m1.keySet(), m2.keySet());
|
||||
equal(m2.keySet(), m1.keySet());
|
||||
}
|
||||
|
||||
void mapsEqual(List<Map> maps) {
|
||||
Map first = maps.get(0);
|
||||
for (Map map : maps)
|
||||
mapsEqual(first, map);
|
||||
}
|
||||
|
||||
void put(List<Map> maps, Object key, Object val) {
|
||||
for (Map map : maps)
|
||||
map.put(key, val);
|
||||
mapsEqual(maps);
|
||||
}
|
||||
|
||||
void removeLastTwo(List<Map> maps) {
|
||||
Map first = maps.get(0);
|
||||
int size = first.size();
|
||||
Iterator fit = first.keySet().iterator();
|
||||
for (int j = 0; j < size - 2; j++)
|
||||
fit.next();
|
||||
Object x1 = fit.next();
|
||||
Object x2 = fit.next();
|
||||
|
||||
for (Map map : maps) {
|
||||
Iterator it = map.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Object x = it.next();
|
||||
if (x == x1 || x == x2)
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
mapsEqual(maps);
|
||||
}
|
||||
|
||||
void remove(Map m, Iterator it) {
|
||||
int size = m.size();
|
||||
it.remove();
|
||||
if (m.size() != size-1)
|
||||
throw new Error(String.format("Incorrect size!%nmap=%s, size=%d%n",
|
||||
m.toString(), m.size()));
|
||||
}
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
final int iterations = 100;
|
||||
final Random r = new Random();
|
||||
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
List<Map> maps = Arrays.asList(
|
||||
new Map[] {
|
||||
new IdentityHashMap(11),
|
||||
new HashMap(16),
|
||||
new LinkedHashMap(16),
|
||||
new WeakHashMap(16),
|
||||
new Hashtable(16),
|
||||
new TreeMap(),
|
||||
new ConcurrentHashMap(16),
|
||||
new ConcurrentSkipListMap() });
|
||||
|
||||
for (int j = 0; j < 10; j++)
|
||||
put(maps, r.nextInt(100), r.nextInt(100));
|
||||
removeLastTwo(maps);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new LockStep().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
61
jdk/test/java/util/concurrent/DelayQueue/Stress.java
Normal file
61
jdk/test/java/util/concurrent/DelayQueue/Stress.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
|
||||
/**
|
||||
* This is not a regression test, but a stress benchmark test for
|
||||
* 6609775: Reduce context switches in DelayQueue due to signalAll
|
||||
*
|
||||
* This runs in the same wall clock time, but much reduced cpu time,
|
||||
* with the changes for 6609775.
|
||||
*/
|
||||
public class Stress {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
final DelayQueue<Delayed> q = new DelayQueue<Delayed>();
|
||||
final long t0 = System.nanoTime();
|
||||
for (long i = 0; i < 1000; i++) {
|
||||
final long expiry = t0 + i*10L*1000L*1000L;
|
||||
q.add(new Delayed() {
|
||||
public long getDelay(TimeUnit unit) {
|
||||
return unit.convert(expiry - System.nanoTime(),
|
||||
NANOSECONDS);
|
||||
}
|
||||
public int compareTo(Delayed x) {
|
||||
long d = getDelay(NANOSECONDS)
|
||||
- x.getDelay(NANOSECONDS);
|
||||
return d < 0 ? -1 : d > 0 ? 1 : 0; }});
|
||||
}
|
||||
|
||||
for (int i = 0; i < 300; i++)
|
||||
new Thread() { public void run() {
|
||||
try {
|
||||
while (!q.isEmpty())
|
||||
q.poll(10L, TimeUnit.SECONDS);
|
||||
} catch (Throwable t) { t.printStackTrace(); }
|
||||
}}.start();
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6316155
|
||||
* @bug 6316155 6595669
|
||||
* @summary Test concurrent offer vs. remove
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
@ -50,15 +50,18 @@ public class OfferRemoveLoops {
|
|||
private static void testQueue(final BlockingQueue<String> q) throws Throwable {
|
||||
System.out.println(q.getClass());
|
||||
final int count = 10000;
|
||||
final long quittingTime = System.nanoTime() + 1L * 1000L * 1000L * 1000L;
|
||||
Thread t1 = new ControlledThread() {
|
||||
protected void realRun() {
|
||||
for (int i = 0, j = 0; i < count; i++)
|
||||
while (! q.remove(String.valueOf(i)))
|
||||
while (! q.remove(String.valueOf(i))
|
||||
&& System.nanoTime() - quittingTime < 0)
|
||||
Thread.yield();}};
|
||||
Thread t2 = new ControlledThread() {
|
||||
protected void realRun() {
|
||||
for (int i = 0, j = 0; i < count; i++)
|
||||
while (! q.offer(String.valueOf(i)))
|
||||
while (! q.offer(String.valueOf(i))
|
||||
&& System.nanoTime() - quittingTime < 0)
|
||||
Thread.yield();}};
|
||||
t1.setDaemon(true); t2.setDaemon(true);
|
||||
t1.start(); t2.start();
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6602600
|
||||
* @run main/othervm -Xmx8m BasicCancelTest
|
||||
* @summary Check effectiveness of RemoveOnCancelPolicy
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Simple timer cancellation test. Submits tasks to a scheduled executor
|
||||
* service and immediately cancels them.
|
||||
*/
|
||||
public class BasicCancelTest {
|
||||
|
||||
void checkShutdown(final ExecutorService es) {
|
||||
final Runnable nop = new Runnable() {public void run() {}};
|
||||
try {
|
||||
if (new Random().nextBoolean()) {
|
||||
check(es.isShutdown());
|
||||
if (es instanceof ThreadPoolExecutor)
|
||||
check(((ThreadPoolExecutor) es).isTerminating()
|
||||
|| es.isTerminated());
|
||||
THROWS(RejectedExecutionException.class,
|
||||
new F(){void f(){es.execute(nop);}});
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
void checkTerminated(final ThreadPoolExecutor tpe) {
|
||||
try {
|
||||
checkShutdown(tpe);
|
||||
check(tpe.getQueue().isEmpty());
|
||||
check(tpe.isTerminated());
|
||||
check(! tpe.isTerminating());
|
||||
equal(tpe.getActiveCount(), 0);
|
||||
equal(tpe.getPoolSize(), 0);
|
||||
equal(tpe.getTaskCount(), tpe.getCompletedTaskCount());
|
||||
check(tpe.awaitTermination(0, TimeUnit.SECONDS));
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
|
||||
final ScheduledThreadPoolExecutor pool =
|
||||
new ScheduledThreadPoolExecutor(1);
|
||||
|
||||
// Needed to avoid OOME
|
||||
pool.setRemoveOnCancelPolicy(true);
|
||||
|
||||
final long moreThanYouCanChew = Runtime.getRuntime().freeMemory() / 4;
|
||||
System.out.printf("moreThanYouCanChew=%d%n", moreThanYouCanChew);
|
||||
|
||||
Runnable noopTask = new Runnable() { public void run() {}};
|
||||
|
||||
for (long i = 0; i < moreThanYouCanChew; i++)
|
||||
pool.schedule(noopTask, 10, TimeUnit.MINUTES).cancel(true);
|
||||
|
||||
pool.shutdown();
|
||||
check(pool.awaitTermination(1L, TimeUnit.DAYS));
|
||||
checkTerminated(pool);
|
||||
equal(pool.getTaskCount(), 0L);
|
||||
equal(pool.getCompletedTaskCount(), 0L);
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new BasicCancelTest().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
abstract class F {abstract void f() throws Throwable;}
|
||||
void THROWS(Class<? extends Throwable> k, F... fs) {
|
||||
for (F f : fs)
|
||||
try {f.f(); fail("Expected " + k.getName() + " not thrown");}
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* This is not a regression test, but a stress benchmark test for
|
||||
* 6602600: Fast removal of cancelled scheduled thread pool tasks
|
||||
*
|
||||
* This runs in the same wall clock time, but much reduced cpu time,
|
||||
* with the changes for 6602600.
|
||||
*/
|
||||
public class Stress {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
final CountDownLatch count = new CountDownLatch(1000);
|
||||
|
||||
final ScheduledThreadPoolExecutor pool =
|
||||
new ScheduledThreadPoolExecutor(100);
|
||||
pool.prestartAllCoreThreads();
|
||||
|
||||
final Runnable incTask = new Runnable() { public void run() {
|
||||
count.countDown();
|
||||
}};
|
||||
|
||||
pool.scheduleAtFixedRate(incTask, 0, 10, TimeUnit.MILLISECONDS);
|
||||
|
||||
count.await();
|
||||
|
||||
pool.shutdown();
|
||||
pool.awaitTermination(1L, TimeUnit.DAYS);
|
||||
}
|
||||
}
|
|
@ -23,36 +23,49 @@
|
|||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4992438
|
||||
* @compile -source 1.5 Fairness.java
|
||||
* @run main Fairness
|
||||
* @bug 4992438 6633113
|
||||
* @summary Checks that fairness setting is respected.
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
|
||||
public class Fairness {
|
||||
private static void testFairness(boolean fair,
|
||||
final BlockingQueue<Integer> q)
|
||||
throws Exception
|
||||
throws Throwable
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
final Integer I = new Integer(i);
|
||||
new Thread() { public void run() {
|
||||
try { q.put(I); } catch (Exception e) {}
|
||||
}}.start();
|
||||
Thread.currentThread().sleep(100);
|
||||
final ReentrantLock lock = new ReentrantLock();
|
||||
final Condition ready = lock.newCondition();
|
||||
final int threadCount = 10;
|
||||
final Throwable[] badness = new Throwable[1];
|
||||
lock.lock();
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
final Integer I = i;
|
||||
Thread t = new Thread() { public void run() {
|
||||
try {
|
||||
lock.lock();
|
||||
ready.signal();
|
||||
lock.unlock();
|
||||
q.put(I);
|
||||
} catch (Throwable t) { badness[0] = t; }}};
|
||||
t.start();
|
||||
ready.await();
|
||||
// Probably unnecessary, but should be bullet-proof
|
||||
while (t.getState() == Thread.State.RUNNABLE)
|
||||
Thread.yield();
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int j = q.take().intValue();
|
||||
System.err.printf("%d%n",j);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
int j = q.take();
|
||||
// Non-fair queues are lifo in our implementation
|
||||
if (fair ? j != i : j != 2-i)
|
||||
throw new Exception("No fair!");
|
||||
if (fair ? j != i : j != threadCount - 1 - i)
|
||||
throw new Error(String.format("fair=%b i=%d j=%d%n",
|
||||
fair, i, j));
|
||||
}
|
||||
if (badness[0] != null) throw new Error(badness[0]);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
testFairness(false, new SynchronousQueue<Integer>());
|
||||
testFairness(false, new SynchronousQueue<Integer>(false));
|
||||
testFairness(true, new SynchronousQueue<Integer>(true));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
@ -23,21 +23,89 @@
|
|||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6207928 6328220 6378321
|
||||
* @bug 6207928 6328220 6378321 6625723
|
||||
* @summary Recursive lock invariant sanity checks
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
|
||||
// I am the Cownt, and I lahve to cownt.
|
||||
public class Count {
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
final ReentrantLock rl = new ReentrantLock();
|
||||
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
final Random rnd = new Random();
|
||||
|
||||
void lock(Lock lock) {
|
||||
try {
|
||||
switch (rnd.nextInt(4)) {
|
||||
case 0: lock.lock(); break;
|
||||
case 1: lock.lockInterruptibly(); break;
|
||||
case 2: check(lock.tryLock()); break;
|
||||
case 3: check(lock.tryLock(45, TimeUnit.MINUTES)); break;
|
||||
}
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
for (boolean fair : new boolean[] { true, false })
|
||||
for (boolean serialClone : new boolean[] { true, false }) {
|
||||
testReentrantLocks(fair, serialClone);
|
||||
testConcurrentReadLocks(fair, serialClone);
|
||||
}
|
||||
}
|
||||
|
||||
void testConcurrentReadLocks(final boolean fair,
|
||||
final boolean serialClone) throws Throwable {
|
||||
final int nThreads = 10;
|
||||
final CyclicBarrier barrier = new CyclicBarrier(nThreads);
|
||||
final ExecutorService es = Executors.newFixedThreadPool(nThreads);
|
||||
final ReentrantReadWriteLock rwl = serialClone ?
|
||||
serialClone(new ReentrantReadWriteLock(fair)) :
|
||||
new ReentrantReadWriteLock(fair);
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
es.submit(new Runnable() { public void run() {
|
||||
try {
|
||||
int n = 5;
|
||||
for (int i = 0; i < n; i++) {
|
||||
barrier.await();
|
||||
equal(rwl.getReadHoldCount(), i);
|
||||
equal(rwl.getWriteHoldCount(), 0);
|
||||
check(! rwl.isWriteLocked());
|
||||
equal(rwl.getReadLockCount(), nThreads * i);
|
||||
barrier.await();
|
||||
lock(rwl.readLock());
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
rwl.readLock().unlock();
|
||||
barrier.await();
|
||||
equal(rwl.getReadHoldCount(), n-i-1);
|
||||
equal(rwl.getReadLockCount(), nThreads*(n-i-1));
|
||||
equal(rwl.getWriteHoldCount(), 0);
|
||||
check(! rwl.isWriteLocked());
|
||||
barrier.await();
|
||||
}
|
||||
THROWS(IllegalMonitorStateException.class,
|
||||
new F(){void f(){rwl.readLock().unlock();}},
|
||||
new F(){void f(){rwl.writeLock().unlock();}});
|
||||
barrier.await();
|
||||
} catch (Throwable t) { unexpected(t); }}});}
|
||||
es.shutdown();
|
||||
check(es.awaitTermination(10, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
void testReentrantLocks(final boolean fair,
|
||||
final boolean serialClone) throws Throwable {
|
||||
final ReentrantLock rl = serialClone ?
|
||||
serialClone(new ReentrantLock(fair)) :
|
||||
new ReentrantLock(fair);
|
||||
final ReentrantReadWriteLock rwl = serialClone ?
|
||||
serialClone(new ReentrantReadWriteLock(fair)) :
|
||||
new ReentrantReadWriteLock(fair);
|
||||
final int depth = 10;
|
||||
equal(rl.isFair(), fair);
|
||||
equal(rwl.isFair(), fair);
|
||||
check(! rl.isLocked());
|
||||
check(! rwl.isWriteLocked());
|
||||
check(! rl.isHeldByCurrentThread());
|
||||
|
@ -50,28 +118,11 @@ public class Count {
|
|||
equal(rwl.getReadHoldCount(), i);
|
||||
equal(rwl.getWriteHoldCount(), i);
|
||||
equal(rwl.writeLock().getHoldCount(), i);
|
||||
switch (i%4) {
|
||||
case 0:
|
||||
rl.lock();
|
||||
rwl.writeLock().lock();
|
||||
rwl.readLock().lock();
|
||||
break;
|
||||
case 1:
|
||||
rl.lockInterruptibly();
|
||||
rwl.writeLock().lockInterruptibly();
|
||||
rwl.readLock().lockInterruptibly();
|
||||
break;
|
||||
case 2:
|
||||
check(rl.tryLock());
|
||||
check(rwl.writeLock().tryLock());
|
||||
check(rwl.readLock().tryLock());
|
||||
break;
|
||||
case 3:
|
||||
check(rl.tryLock(454, TimeUnit.MILLISECONDS));
|
||||
check(rwl.writeLock().tryLock(454, TimeUnit.NANOSECONDS));
|
||||
check(rwl.readLock().tryLock(454, TimeUnit.HOURS));
|
||||
break;
|
||||
}
|
||||
equal(rl.isLocked(), i > 0);
|
||||
equal(rwl.isWriteLocked(), i > 0);
|
||||
lock(rl);
|
||||
lock(rwl.writeLock());
|
||||
lock(rwl.readLock());
|
||||
}
|
||||
|
||||
for (int i = depth; i > 0; i--) {
|
||||
|
@ -95,20 +146,48 @@ public class Count {
|
|||
rwl.writeLock().unlock();
|
||||
rl.unlock();
|
||||
}
|
||||
THROWS(IllegalMonitorStateException.class,
|
||||
new F(){void f(){rl.unlock();}},
|
||||
new F(){void f(){rwl.readLock().unlock();}},
|
||||
new F(){void f(){rwl.writeLock().unlock();}});
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
new Count().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
abstract class F {abstract void f() throws Throwable;}
|
||||
void THROWS(Class<? extends Throwable> k, F... fs) {
|
||||
for (F f : fs)
|
||||
try {f.f(); fail("Expected " + k.getName() + " not thrown");}
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
|
||||
static byte[] serializedForm(Object obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new ObjectOutputStream(baos).writeObject(obj);
|
||||
return baos.toByteArray();
|
||||
} catch (IOException e) { throw new RuntimeException(e); }}
|
||||
static Object readObject(byte[] bytes)
|
||||
throws IOException, ClassNotFoundException {
|
||||
InputStream is = new ByteArrayInputStream(bytes);
|
||||
return new ObjectInputStream(is).readObject();}
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try { return (T) readObject(serializedForm(obj)); }
|
||||
catch (Exception e) { throw new RuntimeException(e); }}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue