mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-24 04:54:40 +02:00
Merge
This commit is contained in:
commit
31d05a3363
5 changed files with 949 additions and 293 deletions
|
@ -2485,55 +2485,45 @@ public final class Formatter implements Closeable, Flushable {
|
||||||
|
|
||||||
private static Pattern fsPattern = Pattern.compile(formatSpecifier);
|
private static Pattern fsPattern = Pattern.compile(formatSpecifier);
|
||||||
|
|
||||||
// Look for format specifiers in the format string.
|
/**
|
||||||
|
* Finds format specifiers in the format string.
|
||||||
|
*/
|
||||||
private FormatString[] parse(String s) {
|
private FormatString[] parse(String s) {
|
||||||
ArrayList al = new ArrayList();
|
ArrayList<FormatString> al = new ArrayList<FormatString>();
|
||||||
Matcher m = fsPattern.matcher(s);
|
Matcher m = fsPattern.matcher(s);
|
||||||
int i = 0;
|
for (int i = 0, len = s.length(); i < len; ) {
|
||||||
while (i < s.length()) {
|
|
||||||
if (m.find(i)) {
|
if (m.find(i)) {
|
||||||
// Anything between the start of the string and the beginning
|
// Anything between the start of the string and the beginning
|
||||||
// of the format specifier is either fixed text or contains
|
// of the format specifier is either fixed text or contains
|
||||||
// an invalid format string.
|
// an invalid format string.
|
||||||
if (m.start() != i) {
|
if (m.start() != i) {
|
||||||
// Make sure we didn't miss any invalid format specifiers
|
// Make sure we didn't miss any invalid format specifiers
|
||||||
checkText(s.substring(i, m.start()));
|
checkText(s, i, m.start());
|
||||||
// Assume previous characters were fixed text
|
// Assume previous characters were fixed text
|
||||||
al.add(new FixedString(s.substring(i, m.start())));
|
al.add(new FixedString(s.substring(i, m.start())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect 6 groups in regular expression
|
al.add(new FormatSpecifier(m));
|
||||||
String[] sa = new String[6];
|
|
||||||
for (int j = 0; j < m.groupCount(); j++)
|
|
||||||
{
|
|
||||||
sa[j] = m.group(j + 1);
|
|
||||||
// System.out.print(sa[j] + " ");
|
|
||||||
}
|
|
||||||
// System.out.println();
|
|
||||||
al.add(new FormatSpecifier(this, sa));
|
|
||||||
i = m.end();
|
i = m.end();
|
||||||
} else {
|
} else {
|
||||||
// No more valid format specifiers. Check for possible invalid
|
// No more valid format specifiers. Check for possible invalid
|
||||||
// format specifiers.
|
// format specifiers.
|
||||||
checkText(s.substring(i));
|
checkText(s, i, len);
|
||||||
// The rest of the string is fixed text
|
// The rest of the string is fixed text
|
||||||
al.add(new FixedString(s.substring(i)));
|
al.add(new FixedString(s.substring(i)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FormatString[] fs = new FormatString[al.size()];
|
return al.toArray(new FormatString[al.size()]);
|
||||||
// for (int j = 0; j < al.size(); j++)
|
|
||||||
// System.out.println(((FormatString) al.get(j)).toString());
|
|
||||||
return (FormatString[]) al.toArray(new FormatString[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkText(String s) {
|
private static void checkText(String s, int start, int end) {
|
||||||
int idx;
|
for (int i = start; i < end; i++) {
|
||||||
// If there are any '%' in the given string, we got a bad format
|
// Any '%' found in the region starts an invalid format specifier.
|
||||||
// specifier.
|
if (s.charAt(i) == '%') {
|
||||||
if ((idx = s.indexOf('%')) != -1) {
|
char c = (i == end - 1) ? '%' : s.charAt(i + 1);
|
||||||
char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
|
throw new UnknownFormatConversionException(String.valueOf(c));
|
||||||
throw new UnknownFormatConversionException(String.valueOf(c));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2562,8 +2552,6 @@ public final class Formatter implements Closeable, Flushable {
|
||||||
private boolean dt = false;
|
private boolean dt = false;
|
||||||
private char c;
|
private char c;
|
||||||
|
|
||||||
private Formatter formatter;
|
|
||||||
|
|
||||||
// cache the line separator
|
// cache the line separator
|
||||||
private String ls;
|
private String ls;
|
||||||
|
|
||||||
|
@ -2650,21 +2638,22 @@ public final class Formatter implements Closeable, Flushable {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatSpecifier(Formatter formatter, String[] sa) {
|
FormatSpecifier(Matcher m) {
|
||||||
this.formatter = formatter;
|
int idx = 1;
|
||||||
int idx = 0;
|
|
||||||
|
|
||||||
index(sa[idx++]);
|
index(m.group(idx++));
|
||||||
flags(sa[idx++]);
|
flags(m.group(idx++));
|
||||||
width(sa[idx++]);
|
width(m.group(idx++));
|
||||||
precision(sa[idx++]);
|
precision(m.group(idx++));
|
||||||
|
|
||||||
if (sa[idx] != null) {
|
String tT = m.group(idx++);
|
||||||
|
if (tT != null) {
|
||||||
dt = true;
|
dt = true;
|
||||||
if (sa[idx].equals("T"))
|
if (tT.equals("T"))
|
||||||
f.add(Flags.UPPERCASE);
|
f.add(Flags.UPPERCASE);
|
||||||
}
|
}
|
||||||
conversion(sa[++idx]);
|
|
||||||
|
conversion(m.group(idx));
|
||||||
|
|
||||||
if (dt)
|
if (dt)
|
||||||
checkDateTime();
|
checkDateTime();
|
||||||
|
@ -2819,9 +2808,9 @@ public final class Formatter implements Closeable, Flushable {
|
||||||
|
|
||||||
private void printString(Object arg, Locale l) throws IOException {
|
private void printString(Object arg, Locale l) throws IOException {
|
||||||
if (arg instanceof Formattable) {
|
if (arg instanceof Formattable) {
|
||||||
Formatter fmt = formatter;
|
Formatter fmt = Formatter.this;
|
||||||
if (formatter.locale() != l)
|
if (fmt.locale() != l)
|
||||||
fmt = new Formatter(formatter.out(), l);
|
fmt = new Formatter(fmt.out(), l);
|
||||||
((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
|
((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
|
||||||
} else {
|
} else {
|
||||||
if (f.contains(Flags.ALTERNATE))
|
if (f.contains(Flags.ALTERNATE))
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,7 @@ package sun.nio.ch;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manipulates a native array of epoll_event structs on Linux:
|
* Manipulates a native array of epoll_event structs on Linux:
|
||||||
|
@ -200,12 +201,9 @@ class EPollArrayWrapper {
|
||||||
void release(SelChImpl channel) {
|
void release(SelChImpl channel) {
|
||||||
synchronized (updateList) {
|
synchronized (updateList) {
|
||||||
// flush any pending updates
|
// flush any pending updates
|
||||||
int i = 0;
|
for (Iterator<Updator> it = updateList.iterator(); it.hasNext();) {
|
||||||
while (i < updateList.size()) {
|
if (it.next().channel == channel) {
|
||||||
if (updateList.get(i).channel == channel) {
|
it.remove();
|
||||||
updateList.remove(i);
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
292
jdk/test/java/nio/channels/Selector/LotsOfCancels.java
Normal file
292
jdk/test/java/nio/channels/Selector/LotsOfCancels.java
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Google 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.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reproduces O(N^2) behavior of JDK6/7 select() call. This happens when
|
||||||
|
* a selector has many unprocessed updates to its interest set (e.g. adding
|
||||||
|
* OP_READ on a bunch of newly accepted sockets). The O(N^2) is triggered
|
||||||
|
* by cancelling a number of selection keys (or just closing a few sockets).
|
||||||
|
* In this case, select() will first go through the list of cancelled keys
|
||||||
|
* and try to deregister them. That deregistration is O(N^2) over the list
|
||||||
|
* of unprocessed updates to the interest set.
|
||||||
|
*
|
||||||
|
* <p> This O(N^2) behavior is a BUG in JVM and should be fixed.
|
||||||
|
*
|
||||||
|
* <p> The test first creates initCount connections, and adds them
|
||||||
|
* to the server epoll set. It then creates massCount connections,
|
||||||
|
* registers interest (causing updateList to be populated with massCount*2
|
||||||
|
* elements), but does not add them to epoll set (that would've cleared
|
||||||
|
* updateList). The test then closes initCount connections, thus populating
|
||||||
|
* deregistration queue. The subsequent call to selectNow() will first process
|
||||||
|
* deregistration queue, performing O(N^2) over updateList size,
|
||||||
|
* equal to massCount * 2.
|
||||||
|
*
|
||||||
|
* <p> Note that connect rate is artificially slowed down to compensate
|
||||||
|
* for what I believe is a Linux bug, where too high of a connection rate
|
||||||
|
* ends up in SYN's being dropped and then slow retransmits.
|
||||||
|
*
|
||||||
|
* @author Igor Chernyshev
|
||||||
|
*/
|
||||||
|
public class LotsOfCancels {
|
||||||
|
|
||||||
|
static long testStartTime;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// the final select should run in less than 1000ms.
|
||||||
|
runTest(500, 2700, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log(String msg) {
|
||||||
|
System.out.println(getLogPrefix() + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getLogPrefix() {
|
||||||
|
return durationMillis(testStartTime) + ": ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the elapsed time since startNanos, in milliseconds.
|
||||||
|
* @param startNanos the start time; this must be a value returned
|
||||||
|
* by {@link System.nanoTime}
|
||||||
|
*/
|
||||||
|
static long durationMillis(long startNanos) {
|
||||||
|
return (System.nanoTime() - startNanos) / (1000L * 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runTest(int initCount, int massCount, int maxSelectTime)
|
||||||
|
throws Exception {
|
||||||
|
testStartTime = System.nanoTime();
|
||||||
|
|
||||||
|
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 7359);
|
||||||
|
|
||||||
|
// Create server channel, add it to selector and run epoll_ctl.
|
||||||
|
log("Setting up server");
|
||||||
|
Selector serverSelector = Selector.open();
|
||||||
|
ServerSocketChannel server = ServerSocketChannel.open();
|
||||||
|
server.configureBlocking(false);
|
||||||
|
server.socket().bind(address, 5000);
|
||||||
|
server.register(serverSelector, SelectionKey.OP_ACCEPT);
|
||||||
|
serverSelector.selectNow();
|
||||||
|
|
||||||
|
log("Setting up client");
|
||||||
|
ClientThread client = new ClientThread(address);
|
||||||
|
client.start();
|
||||||
|
Thread.sleep(100);
|
||||||
|
|
||||||
|
// Set up initial set of client sockets.
|
||||||
|
log("Starting initial client connections");
|
||||||
|
client.connectClients(initCount);
|
||||||
|
Thread.sleep(500); // Wait for client connections to arrive
|
||||||
|
|
||||||
|
// Accept all initial client sockets, add to selector and run
|
||||||
|
// epoll_ctl.
|
||||||
|
log("Accepting initial connections");
|
||||||
|
List<SocketChannel> serverChannels1 =
|
||||||
|
acceptAndAddAll(serverSelector, server, initCount);
|
||||||
|
if (serverChannels1.size() != initCount) {
|
||||||
|
throw new Exception("Accepted " + serverChannels1.size() +
|
||||||
|
" instead of " + initCount);
|
||||||
|
}
|
||||||
|
serverSelector.selectNow();
|
||||||
|
|
||||||
|
// Set up mass set of client sockets.
|
||||||
|
log("Requesting mass client connections");
|
||||||
|
client.connectClients(massCount);
|
||||||
|
Thread.sleep(500); // Wait for client connections to arrive
|
||||||
|
|
||||||
|
// Accept all mass client sockets, add to selector and do NOT
|
||||||
|
// run epoll_ctl.
|
||||||
|
log("Accepting mass connections");
|
||||||
|
List<SocketChannel> serverChannels2 =
|
||||||
|
acceptAndAddAll(serverSelector, server, massCount);
|
||||||
|
if (serverChannels2.size() != massCount) {
|
||||||
|
throw new Exception("Accepted " + serverChannels2.size() +
|
||||||
|
" instead of " + massCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close initial set of sockets.
|
||||||
|
log("Closing initial connections");
|
||||||
|
closeAll(serverChannels1);
|
||||||
|
|
||||||
|
// Now get the timing of select() call.
|
||||||
|
log("Running the final select call");
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
serverSelector.selectNow();
|
||||||
|
long duration = durationMillis(startTime);
|
||||||
|
log("Init count = " + initCount +
|
||||||
|
", mass count = " + massCount +
|
||||||
|
", duration = " + duration + "ms");
|
||||||
|
|
||||||
|
if (duration > maxSelectTime) {
|
||||||
|
System.out.println
|
||||||
|
("\n\n\n\n\nFAILURE: The final selectNow() took " +
|
||||||
|
duration + "ms " +
|
||||||
|
"- seems like O(N^2) bug is still here\n\n");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<SocketChannel> acceptAndAddAll(Selector selector,
|
||||||
|
ServerSocketChannel server,
|
||||||
|
int expected)
|
||||||
|
throws Exception {
|
||||||
|
int retryCount = 0;
|
||||||
|
int acceptCount = 0;
|
||||||
|
List<SocketChannel> channels = new ArrayList<SocketChannel>();
|
||||||
|
while (channels.size() < expected) {
|
||||||
|
SocketChannel channel = server.accept();
|
||||||
|
if (channel == null) {
|
||||||
|
log("accept() returned null " +
|
||||||
|
"after accepting " + acceptCount + " more connections");
|
||||||
|
acceptCount = 0;
|
||||||
|
if (retryCount < 10) {
|
||||||
|
// See if more new sockets got stacked behind.
|
||||||
|
retryCount++;
|
||||||
|
Thread.sleep(500);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retryCount = 0;
|
||||||
|
acceptCount++;
|
||||||
|
channel.configureBlocking(false);
|
||||||
|
channel.register(selector, SelectionKey.OP_READ);
|
||||||
|
channels.add(channel);
|
||||||
|
}
|
||||||
|
// Cause an additional updateList entry per channel.
|
||||||
|
for (SocketChannel channel : channels) {
|
||||||
|
channel.register(selector, SelectionKey.OP_WRITE);
|
||||||
|
}
|
||||||
|
return channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void closeAll(List<SocketChannel> channels)
|
||||||
|
throws Exception {
|
||||||
|
for (SocketChannel channel : channels) {
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ClientThread extends Thread {
|
||||||
|
private final SocketAddress address;
|
||||||
|
private final Selector selector;
|
||||||
|
private int connectionsNeeded;
|
||||||
|
private int totalCreated;
|
||||||
|
|
||||||
|
ClientThread(SocketAddress address) throws Exception {
|
||||||
|
this.address = address;
|
||||||
|
selector = Selector.open();
|
||||||
|
setDaemon(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectClients(int count) throws Exception {
|
||||||
|
synchronized (this) {
|
||||||
|
connectionsNeeded += count;
|
||||||
|
}
|
||||||
|
selector.wakeup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
handleClients();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleClients() throws Exception {
|
||||||
|
int selectCount = 0;
|
||||||
|
while (true) {
|
||||||
|
int createdCount = 0;
|
||||||
|
synchronized (this) {
|
||||||
|
if (connectionsNeeded > 0) {
|
||||||
|
|
||||||
|
while (connectionsNeeded > 0 && createdCount < 20) {
|
||||||
|
connectionsNeeded--;
|
||||||
|
createdCount++;
|
||||||
|
totalCreated++;
|
||||||
|
|
||||||
|
SocketChannel channel = SocketChannel.open();
|
||||||
|
channel.configureBlocking(false);
|
||||||
|
channel.connect(address);
|
||||||
|
if (!channel.finishConnect()) {
|
||||||
|
channel.register(selector,
|
||||||
|
SelectionKey.OP_CONNECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Started total of " +
|
||||||
|
totalCreated + " client connections");
|
||||||
|
Thread.sleep(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdCount > 0) {
|
||||||
|
selector.selectNow();
|
||||||
|
} else {
|
||||||
|
selectCount++;
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
selector.select();
|
||||||
|
long duration = durationMillis(startTime);
|
||||||
|
log("Exited clientSelector.select(), loop #"
|
||||||
|
+ selectCount + ", duration = " + duration + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyCount = -1;
|
||||||
|
Iterator<SelectionKey> keys =
|
||||||
|
selector.selectedKeys().iterator();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
SelectionKey key = keys.next();
|
||||||
|
synchronized (key) {
|
||||||
|
keyCount++;
|
||||||
|
keys.remove();
|
||||||
|
if (!key.isValid()) {
|
||||||
|
log("Ignoring client key #" + keyCount);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int readyOps = key.readyOps();
|
||||||
|
if (readyOps == SelectionKey.OP_CONNECT) {
|
||||||
|
key.interestOps(0);
|
||||||
|
((SocketChannel) key.channel()).finishConnect();
|
||||||
|
} else {
|
||||||
|
log("readyOps() on client key #" + keyCount +
|
||||||
|
" returned " + readyOps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -421,8 +421,11 @@ public class MOAT {
|
||||||
|
|
||||||
private static void testQueue(Queue<Integer> q) {
|
private static void testQueue(Queue<Integer> q) {
|
||||||
q.clear();
|
q.clear();
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++) {
|
||||||
|
testQueueAddRemove(q, null);
|
||||||
|
testQueueAddRemove(q, 537);
|
||||||
q.add(i);
|
q.add(i);
|
||||||
|
}
|
||||||
equal(q.size(), 5);
|
equal(q.size(), 5);
|
||||||
checkFunctionalInvariants(q);
|
checkFunctionalInvariants(q);
|
||||||
q.poll();
|
q.poll();
|
||||||
|
@ -435,6 +438,216 @@ public class MOAT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testQueueAddRemove(final Queue<Integer> q,
|
||||||
|
final Integer e) {
|
||||||
|
final List<Integer> originalContents = new ArrayList<Integer>(q);
|
||||||
|
final boolean isEmpty = q.isEmpty();
|
||||||
|
final boolean isList = (q instanceof List);
|
||||||
|
final List asList = isList ? (List) q : null;
|
||||||
|
check(!q.contains(e));
|
||||||
|
try {
|
||||||
|
q.add(e);
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
check(e == null);
|
||||||
|
return; // Null elements not supported
|
||||||
|
}
|
||||||
|
check(q.contains(e));
|
||||||
|
check(q.remove(e));
|
||||||
|
check(!q.contains(e));
|
||||||
|
equal(new ArrayList<Integer>(q), originalContents);
|
||||||
|
|
||||||
|
if (q instanceof Deque<?>) {
|
||||||
|
final Deque<Integer> deq = (Deque<Integer>) q;
|
||||||
|
final List<Integer> singleton = Collections.singletonList(e);
|
||||||
|
|
||||||
|
// insert, query, remove element at head
|
||||||
|
if (isEmpty) {
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ deq.getFirst(); }},
|
||||||
|
new Fun(){void f(){ deq.element(); }},
|
||||||
|
new Fun(){void f(){ deq.iterator().next(); }});
|
||||||
|
check(deq.peekFirst() == null);
|
||||||
|
check(deq.peek() == null);
|
||||||
|
} else {
|
||||||
|
check(deq.getFirst() != e);
|
||||||
|
check(deq.element() != e);
|
||||||
|
check(deq.iterator().next() != e);
|
||||||
|
check(deq.peekFirst() != e);
|
||||||
|
check(deq.peek() != e);
|
||||||
|
}
|
||||||
|
check(!deq.contains(e));
|
||||||
|
check(!deq.removeFirstOccurrence(e));
|
||||||
|
check(!deq.removeLastOccurrence(e));
|
||||||
|
if (isList) {
|
||||||
|
check(asList.indexOf(e) == -1);
|
||||||
|
check(asList.lastIndexOf(e) == -1);
|
||||||
|
}
|
||||||
|
switch (rnd.nextInt(isList ? 4 : 3)) {
|
||||||
|
case 0: deq.addFirst(e); break;
|
||||||
|
case 1: check(deq.offerFirst(e)); break;
|
||||||
|
case 2: deq.push(e); break;
|
||||||
|
case 3: asList.add(0, e); break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
check(deq.peekFirst() == e);
|
||||||
|
check(deq.getFirst() == e);
|
||||||
|
check(deq.element() == e);
|
||||||
|
check(deq.peek() == e);
|
||||||
|
check(deq.iterator().next() == e);
|
||||||
|
check(deq.contains(e));
|
||||||
|
if (isList) {
|
||||||
|
check(asList.get(0) == e);
|
||||||
|
check(asList.indexOf(e) == 0);
|
||||||
|
check(asList.lastIndexOf(e) == 0);
|
||||||
|
check(asList.subList(0, 1).equals(singleton));
|
||||||
|
}
|
||||||
|
switch (rnd.nextInt(isList ? 11 : 9)) {
|
||||||
|
case 0: check(deq.pollFirst() == e); break;
|
||||||
|
case 1: check(deq.removeFirst() == e); break;
|
||||||
|
case 2: check(deq.remove() == e); break;
|
||||||
|
case 3: check(deq.pop() == e); break;
|
||||||
|
case 4: check(deq.removeFirstOccurrence(e)); break;
|
||||||
|
case 5: check(deq.removeLastOccurrence(e)); break;
|
||||||
|
case 6: check(deq.remove(e)); break;
|
||||||
|
case 7: check(deq.removeAll(singleton)); break;
|
||||||
|
case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
|
||||||
|
case 9: asList.remove(0); break;
|
||||||
|
case 10: asList.subList(0, 1).clear(); break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
if (isEmpty) {
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ deq.getFirst(); }},
|
||||||
|
new Fun(){void f(){ deq.element(); }},
|
||||||
|
new Fun(){void f(){ deq.iterator().next(); }});
|
||||||
|
check(deq.peekFirst() == null);
|
||||||
|
check(deq.peek() == null);
|
||||||
|
} else {
|
||||||
|
check(deq.getFirst() != e);
|
||||||
|
check(deq.element() != e);
|
||||||
|
check(deq.iterator().next() != e);
|
||||||
|
check(deq.peekFirst() != e);
|
||||||
|
check(deq.peek() != e);
|
||||||
|
}
|
||||||
|
check(!deq.contains(e));
|
||||||
|
check(!deq.removeFirstOccurrence(e));
|
||||||
|
check(!deq.removeLastOccurrence(e));
|
||||||
|
if (isList) {
|
||||||
|
check(isEmpty || asList.get(0) != e);
|
||||||
|
check(asList.indexOf(e) == -1);
|
||||||
|
check(asList.lastIndexOf(e) == -1);
|
||||||
|
}
|
||||||
|
equal(new ArrayList<Integer>(deq), originalContents);
|
||||||
|
|
||||||
|
// insert, query, remove element at tail
|
||||||
|
if (isEmpty) {
|
||||||
|
check(deq.peekLast() == null);
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ deq.getLast(); }});
|
||||||
|
} else {
|
||||||
|
check(deq.peekLast() != e);
|
||||||
|
check(deq.getLast() != e);
|
||||||
|
}
|
||||||
|
switch (rnd.nextInt(isList ? 6 : 4)) {
|
||||||
|
case 0: deq.addLast(e); break;
|
||||||
|
case 1: check(deq.offerLast(e)); break;
|
||||||
|
case 2: check(deq.add(e)); break;
|
||||||
|
case 3: deq.addAll(singleton); break;
|
||||||
|
case 4: asList.addAll(deq.size(), singleton); break;
|
||||||
|
case 5: asList.add(deq.size(), e); break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
check(deq.peekLast() == e);
|
||||||
|
check(deq.getLast() == e);
|
||||||
|
check(deq.contains(e));
|
||||||
|
if (isList) {
|
||||||
|
ListIterator it = asList.listIterator(asList.size());
|
||||||
|
check(it.previous() == e);
|
||||||
|
check(asList.get(asList.size() - 1) == e);
|
||||||
|
check(asList.indexOf(e) == asList.size() - 1);
|
||||||
|
check(asList.lastIndexOf(e) == asList.size() - 1);
|
||||||
|
int size = asList.size();
|
||||||
|
check(asList.subList(size - 1, size).equals(singleton));
|
||||||
|
}
|
||||||
|
switch (rnd.nextInt(isList ? 8 : 6)) {
|
||||||
|
case 0: check(deq.pollLast() == e); break;
|
||||||
|
case 1: check(deq.removeLast() == e); break;
|
||||||
|
case 2: check(deq.removeFirstOccurrence(e)); break;
|
||||||
|
case 3: check(deq.removeLastOccurrence(e)); break;
|
||||||
|
case 4: check(deq.remove(e)); break;
|
||||||
|
case 5: check(deq.removeAll(singleton)); break;
|
||||||
|
case 6: asList.remove(asList.size() - 1); break;
|
||||||
|
case 7:
|
||||||
|
ListIterator it = asList.listIterator(asList.size());
|
||||||
|
it.previous();
|
||||||
|
it.remove();
|
||||||
|
break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
if (isEmpty) {
|
||||||
|
check(deq.peekLast() == null);
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ deq.getLast(); }});
|
||||||
|
} else {
|
||||||
|
check(deq.peekLast() != e);
|
||||||
|
check(deq.getLast() != e);
|
||||||
|
}
|
||||||
|
check(!deq.contains(e));
|
||||||
|
equal(new ArrayList<Integer>(deq), originalContents);
|
||||||
|
|
||||||
|
// Test operations on empty deque
|
||||||
|
switch (rnd.nextInt(isList ? 4 : 2)) {
|
||||||
|
case 0: deq.clear(); break;
|
||||||
|
case 1:
|
||||||
|
Iterator it = deq.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: asList.subList(0, asList.size()).clear(); break;
|
||||||
|
case 3:
|
||||||
|
ListIterator lit = asList.listIterator(asList.size());
|
||||||
|
while (lit.hasPrevious()) {
|
||||||
|
lit.previous();
|
||||||
|
lit.remove();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
testEmptyCollection(deq);
|
||||||
|
check(!deq.iterator().hasNext());
|
||||||
|
if (isList) {
|
||||||
|
check(!asList.listIterator().hasPrevious());
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ asList.listIterator().previous(); }});
|
||||||
|
}
|
||||||
|
THROWS(NoSuchElementException.class,
|
||||||
|
new Fun(){void f(){ deq.iterator().next(); }},
|
||||||
|
new Fun(){void f(){ deq.element(); }},
|
||||||
|
new Fun(){void f(){ deq.getFirst(); }},
|
||||||
|
new Fun(){void f(){ deq.getLast(); }},
|
||||||
|
new Fun(){void f(){ deq.pop(); }},
|
||||||
|
new Fun(){void f(){ deq.remove(); }},
|
||||||
|
new Fun(){void f(){ deq.removeFirst(); }},
|
||||||
|
new Fun(){void f(){ deq.removeLast(); }});
|
||||||
|
|
||||||
|
check(deq.poll() == null);
|
||||||
|
check(deq.pollFirst() == null);
|
||||||
|
check(deq.pollLast() == null);
|
||||||
|
check(deq.peek() == null);
|
||||||
|
check(deq.peekFirst() == null);
|
||||||
|
check(deq.peekLast() == null);
|
||||||
|
check(!deq.removeFirstOccurrence(e));
|
||||||
|
check(!deq.removeLastOccurrence(e));
|
||||||
|
|
||||||
|
check(deq.addAll(originalContents) == !isEmpty);
|
||||||
|
equal(new ArrayList<Integer>(deq), originalContents);
|
||||||
|
check(!deq.addAll(Collections.<Integer>emptyList()));
|
||||||
|
equal(new ArrayList<Integer>(deq), originalContents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void testQueueIteratorRemove(Queue<Integer> q) {
|
private static void testQueueIteratorRemove(Queue<Integer> q) {
|
||||||
System.err.printf("testQueueIteratorRemove %s%n",
|
System.err.printf("testQueueIteratorRemove %s%n",
|
||||||
q.getClass().getSimpleName());
|
q.getClass().getSimpleName());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue