changeset 15289:eee43c66c298

Merge
author amurillo
date Mon, 01 Feb 2016 10:07:37 -0800
parents 7a5fb0aa1e8d efd8dc147138
children 20069883ae86
files
diffstat 103 files changed, 66303 insertions(+), 209 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatException.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatException.java	Mon Feb 01 10:07:37 2016 -0800
@@ -26,6 +26,8 @@
 /**
  * StringConcatException is thrown by {@link StringConcatFactory} when linkage
  * invariants are violated.
+ *
+ * @since 9
  */
 public class StringConcatException extends Exception {
     private static final long serialVersionUID = 292L + 9L;
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Mon Feb 01 10:07:37 2016 -0800
@@ -96,6 +96,8 @@
  * more than 200 argument slots. Users requiring more than 200 argument slots in
  * concatenation are expected to split the large concatenation in smaller
  * expressions.
+ *
+ * @since 9
  */
 public final class StringConcatFactory {
 
--- a/src/java.base/share/classes/java/net/URI.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/net/URI.java	Mon Feb 01 10:07:37 2016 -0800
@@ -1080,11 +1080,8 @@
      *          If a protocol handler for the URL could not be found,
      *          or if some other error occurred while constructing the URL
      */
-    public URL toURL()
-        throws MalformedURLException {
-        if (!isAbsolute())
-            throw new IllegalArgumentException("URI is not absolute");
-        return new URL(toString());
+    public URL toURL() throws MalformedURLException {
+        return URL.fromURI(this);
     }
 
     // -- Component access methods --
--- a/src/java.base/share/classes/java/net/URL.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/net/URL.java	Mon Feb 01 10:07:37 2016 -0800
@@ -659,6 +659,44 @@
         }
     }
 
+    /**
+     * Creates a URL from a URI, as if by invoking {@code uri.toURL()}.
+     *
+     * @see java.net.URI#toURL()
+     */
+    static URL fromURI(URI uri) throws MalformedURLException {
+        if (!uri.isAbsolute()) {
+            throw new IllegalArgumentException("URI is not absolute");
+        }
+        String protocol = uri.getScheme();
+
+        // In general we need to go via Handler.parseURL, but for the jrt
+        // protocol we enforce that the Handler is not overrideable and can
+        // optimize URI to URL conversion.
+        //
+        // Case-sensitive comparison for performance; malformed protocols will
+        // be handled correctly by the slow path.
+        if (protocol.equals("jrt") && !uri.isOpaque()
+                && uri.getRawFragment() == null) {
+
+            String query = uri.getRawQuery();
+            String path = uri.getRawPath();
+            String file = (query == null) ? path : path + "?" + query;
+
+            // URL represent undefined host as empty string while URI use null
+            String host = uri.getHost();
+            if (host == null) {
+                host = "";
+            }
+
+            int port = uri.getPort();
+
+            return new URL("jrt", host, port, file, null);
+        } else {
+            return new URL((URL)null, uri.toString(), null);
+        }
+    }
+
     /*
      * Returns true if specified string is a valid protocol name.
      */
@@ -1275,11 +1313,28 @@
         }
     }
 
-    private static final String[] NON_OVERRIDEABLE_PROTOCOLS = {"file", "jrt"};
-    private static boolean isOverrideable(String protocol) {
-        for (String p : NON_OVERRIDEABLE_PROTOCOLS)
-            if (protocol.equalsIgnoreCase(p))
+
+    /**
+     * Non-overrideable protocols: "jrt" and "file"
+     *
+     * Character-based comparison for performance reasons; also ensures
+     * case-insensitive comparison in a locale-independent fashion.
+     */
+    static boolean isOverrideable(String protocol) {
+        if (protocol.length() == 3) {
+            if ((Character.toLowerCase(protocol.charAt(0)) == 'j') &&
+                    (Character.toLowerCase(protocol.charAt(1)) == 'r') &&
+                    (Character.toLowerCase(protocol.charAt(2)) == 't')) {
                 return false;
+            }
+        } else if (protocol.length() == 4) {
+            if ((Character.toLowerCase(protocol.charAt(0)) == 'f') &&
+                    (Character.toLowerCase(protocol.charAt(1)) == 'i') &&
+                    (Character.toLowerCase(protocol.charAt(2)) == 'l') &&
+                    (Character.toLowerCase(protocol.charAt(3)) == 'e')) {
+                return false;
+            }
+        }
         return true;
     }
 
--- a/src/java.base/share/classes/java/time/LocalDate.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/time/LocalDate.java	Mon Feb 01 10:07:37 2016 -0800
@@ -100,6 +100,8 @@
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
 
 /**
  * A date without a time-zone in the ISO-8601 calendar system,
@@ -1716,6 +1718,89 @@
     }
 
     /**
+     * Returns a sequential ordered stream of dates. The returned stream starts from this date
+     * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.
+     * <p>
+     * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if end date is before this date
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive) {
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        if (end < start) {
+            throw new IllegalArgumentException(endExclusive + " < " + this);
+        }
+        return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay);
+    }
+
+    /**
+     * Returns a sequential ordered stream of dates by given incremental step. The returned stream
+     * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive).
+     * <p>
+     * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))}
+     * (but the result of step multiplication never overflows). For example, if this date is
+     * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the
+     * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and
+     * {@code 2015-04-30}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @param step  the non-zero, non-negative {@code Period} which represents the step.
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and
+     *             {@code step.toTotalMonths()} have opposite sign, or end date is before this date
+     *             and step is positive, or end date is after this date and step is negative
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {
+        if (step.isZero()) {
+            throw new IllegalArgumentException("step is zero");
+        }
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        long until = end - start;
+        long months = step.toTotalMonths();
+        long days = step.getDays();
+        if ((months < 0 && days > 0) || (months > 0 && days < 0)) {
+            throw new IllegalArgumentException("period months and days are of opposite sign");
+        }
+        if (until == 0) {
+            return Stream.empty();
+        }
+        int sign = months > 0 || days > 0 ? 1 : -1;
+        if (sign < 0 ^ until < 0) {
+            throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this);
+        }
+        if (months == 0) {
+            long steps = (until - sign) / days; // non-negative
+            return LongStream.rangeClosed(0, steps).mapToObj(
+                    n -> LocalDate.ofEpochDay(start + n * days));
+        }
+        // 48699/1600 = 365.2425/12, no overflow, non-negative result
+        long steps = until * 1600 / (months * 48699 + days * 1600) + 1;
+        long addMonths = months * steps;
+        long addDays = days * steps;
+        long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth()
+                : getProlepticMonth() - MIN.getProlepticMonth();
+        // adjust steps estimation
+        if (addMonths * sign > maxAddMonths
+                || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+            steps--;
+            addMonths -= months;
+            addDays -= days;
+            if (addMonths * sign > maxAddMonths
+                    || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+                steps--;
+            }
+        }
+        return LongStream.rangeClosed(0, steps).mapToObj(
+                n -> this.plusMonths(months * n).plusDays(days * n));
+    }
+
+    /**
      * Formats this date using the specified formatter.
      * <p>
      * This date will be passed to the formatter to produce a string.
--- a/src/java.base/share/classes/java/util/Map.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/util/Map.java	Mon Feb 01 10:07:37 2016 -0800
@@ -649,7 +649,7 @@
             try {
                 k = entry.getKey();
                 v = entry.getValue();
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -704,7 +704,7 @@
             try {
                 k = entry.getKey();
                 v = entry.getValue();
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -714,7 +714,7 @@
 
             try {
                 entry.setValue(v);
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -887,7 +887,7 @@
      * or atomicity properties of this method. Any implementation providing
      * atomicity guarantees must override this method and document its
      * concurrency properties.
-      *
+     *
      * @param key key with which the specified value is associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -984,6 +984,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V computeIfAbsent(K key,
@@ -1058,6 +1061,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V computeIfPresent(K key,
@@ -1103,7 +1109,7 @@
      * <pre> {@code
      * V oldValue = map.get(key);
      * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
+     * if (oldValue != null) {
      *    if (newValue != null)
      *       map.put(key, newValue);
      *    else
@@ -1147,6 +1153,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V compute(K key,
@@ -1239,6 +1248,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified key is null and this map
      *         does not support null keys or the value or remappingFunction is
      *         null
@@ -1251,7 +1263,7 @@
         V oldValue = get(key);
         V newValue = (oldValue == null) ? value :
                    remappingFunction.apply(oldValue, value);
-        if(newValue == null) {
+        if (newValue == null) {
             remove(key);
         } else {
             put(key, newValue);
--- a/src/java.base/share/classes/java/util/Queue.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/util/Queue.java	Mon Feb 01 10:07:37 2016 -0800
@@ -129,14 +129,6 @@
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
- * @see java.util.Collection
- * @see LinkedList
- * @see PriorityQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.BlockingQueue
- * @see java.util.concurrent.ArrayBlockingQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.PriorityBlockingQueue
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Mon Feb 01 10:07:37 2016 -0800
@@ -301,19 +301,15 @@
      *
      * @implSpec
      * The default implementation is equivalent to the following steps for this
-     * {@code map}, then returning the current value or {@code null} if now
-     * absent:
+     * {@code map}:
      *
      * <pre> {@code
-     * if (map.get(key) == null) {
-     *   V newValue = mappingFunction.apply(key);
-     *   if (newValue != null)
-     *     return map.putIfAbsent(key, newValue);
-     * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the mapping
-     * function multiple times.
+     * V oldValue, newValue;
+     * return ((oldValue = map.get(key)) == null
+     *         && (newValue = mappingFunction.apply(key)) != null
+     *         && (oldValue = map.putIfAbsent(key, newValue)) == null)
+     *   ? newValue
+     *   : oldValue;}</pre>
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -323,16 +319,19 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V computeIfAbsent(K key,
             Function<? super K, ? extends V> mappingFunction) {
         Objects.requireNonNull(mappingFunction);
-        V v, newValue;
-        return ((v = get(key)) == null &&
-                (newValue = mappingFunction.apply(key)) != null &&
-                (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
+        V oldValue, newValue;
+        return ((oldValue = get(key)) == null
+                && (newValue = mappingFunction.apply(key)) != null
+                && (oldValue = putIfAbsent(key, newValue)) == null)
+            ? newValue
+            : oldValue;
     }
 
     /**
@@ -340,22 +339,19 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if now absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * if (map.get(key) != null) {
-     *   V oldValue = map.get(key);
+     * for (V oldValue; (oldValue = map.get(key)) != null; ) {
      *   V newValue = remappingFunction.apply(key, oldValue);
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple threads
-     * attempt updates including potentially calling the remapping function
-     * multiple times.
+     *   if ((newValue == null)
+     *       ? map.remove(key, oldValue)
+     *       : map.replace(key, oldValue, newValue))
+     *     return newValue;
+     * }
+     * return null;}</pre>
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -365,22 +361,21 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V computeIfPresent(K key,
             BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
         Objects.requireNonNull(remappingFunction);
-        V oldValue;
-        while ((oldValue = get(key)) != null) {
+        for (V oldValue; (oldValue = get(key)) != null; ) {
             V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue != null) {
-                if (replace(key, oldValue, newValue))
-                    return newValue;
-            } else if (remove(key, oldValue))
-                return null;
+            if ((newValue == null)
+                ? remove(key, oldValue)
+                : replace(key, oldValue, newValue))
+                return newValue;
         }
-        return oldValue;
+        return null;
     }
 
     /**
@@ -388,27 +383,23 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * } else {
-     *   if (newValue != null)
-     *     map.putIfAbsent(key, newValue);
-     *   else
+     * for (;;) {
+     *   V oldValue = map.get(key);
+     *   V newValue = remappingFunction.apply(key, oldValue);
+     *   if (newValue != null) {
+     *     if ((oldValue != null)
+     *       ? map.replace(key, oldValue, newValue)
+     *       : map.putIfAbsent(key, newValue) == null)
+     *       return newValue;
+     *   } else if (oldValue == null || map.remove(key, oldValue)) {
      *     return null;
+     *   }
      * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the remapping
-     * function multiple times.
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -418,50 +409,29 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V compute(K key,
-            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        V oldValue = get(key);
-        for (;;) {
-            V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue == null) {
-                // delete mapping
-                if (oldValue != null || containsKey(key)) {
-                    // something to remove
-                    if (remove(key, oldValue)) {
-                        // removed the old value as expected
-                        return null;
+                      BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        retry: for (;;) {
+            V oldValue = get(key);
+            // if putIfAbsent fails, opportunistically use its return value
+            haveOldValue: for (;;) {
+                V newValue = remappingFunction.apply(key, oldValue);
+                if (newValue != null) {
+                    if (oldValue != null) {
+                        if (replace(key, oldValue, newValue))
+                            return newValue;
                     }
-
-                    // some other value replaced old value. try again.
-                    oldValue = get(key);
-                } else {
-                    // nothing to do. Leave things as they were.
+                    else if ((oldValue = putIfAbsent(key, newValue)) == null)
+                        return newValue;
+                    else continue haveOldValue;
+                } else if (oldValue == null || remove(key, oldValue)) {
                     return null;
                 }
-            } else {
-                // add or replace old mapping
-                if (oldValue != null) {
-                    // replace
-                    if (replace(key, oldValue, newValue)) {
-                        // replaced as expected.
-                        return newValue;
-                    }
-
-                    // some other value replaced old value. try again.
-                    oldValue = get(key);
-                } else {
-                    // add (replace if oldValue was null)
-                    if ((oldValue = putIfAbsent(key, newValue)) == null) {
-                        // replaced
-                        return newValue;
-                    }
-
-                    // some other value replaced old value. try again.
-                }
+                continue retry;
             }
         }
     }
@@ -471,21 +441,25 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = (oldValue == null) ? value :
-     *     remappingFunction.apply(oldValue, value);
-     * if (newValue == null)
-     *   map.remove(key);
-     * else
-     *   map.put(key, newValue);}</pre>
-     *
-     * <p>The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the remapping
-     * function multiple times.
+     * for (;;) {
+     *   V oldValue = map.get(key);
+     *   if (oldValue != null) {
+     *     V newValue = remappingFunction.apply(oldValue, value);
+     *     if (newValue != null) {
+     *       if (map.replace(key, oldValue, newValue))
+     *         return newValue;
+     *     } else if (map.remove(key, oldValue)) {
+     *       return null;
+     *     }
+     *   } else if (map.putIfAbsent(key, value) == null) {
+     *     return value;
+     *   }
+     * }}</pre>
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -495,6 +469,7 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
@@ -502,20 +477,23 @@
             BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
         Objects.requireNonNull(remappingFunction);
         Objects.requireNonNull(value);
-        V oldValue = get(key);
-        for (;;) {
-            if (oldValue != null) {
-                V newValue = remappingFunction.apply(oldValue, value);
-                if (newValue != null) {
-                    if (replace(key, oldValue, newValue))
-                        return newValue;
-                } else if (remove(key, oldValue)) {
-                    return null;
-                }
-                oldValue = get(key);
-            } else {
-                if ((oldValue = putIfAbsent(key, value)) == null) {
-                    return value;
+        retry: for (;;) {
+            V oldValue = get(key);
+            // if putIfAbsent fails, opportunistically use its return value
+            haveOldValue: for (;;) {
+                if (oldValue != null) {
+                    V newValue = remappingFunction.apply(oldValue, value);
+                    if (newValue != null) {
+                        if (replace(key, oldValue, newValue))
+                            return newValue;
+                    } else if (remove(key, oldValue)) {
+                        return null;
+                    }
+                    continue retry;
+                } else {
+                    if ((oldValue = putIfAbsent(key, value)) == null)
+                        return value;
+                    continue haveOldValue;
                 }
             }
         }
--- a/test/java/lang/ref/CleanerTest.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/test/java/lang/ref/CleanerTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -41,14 +41,17 @@
 
 import sun.hotspot.WhiteBox;
 
+import jdk.test.lib.Utils;
+
 import org.testng.Assert;
 import org.testng.TestNG;
 import org.testng.annotations.Test;
 
 /*
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib/share/classes /lib/testlibrary /test/lib
  * @build sun.hotspot.WhiteBox
+ * @build jdk.test.lib.Utils
  * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run testng/othervm
@@ -88,8 +91,7 @@
 
         CleanableCase s = setupPhantom(COMMON, cleaner);
         cleaner = null;
-        Assert.assertTrue(checkCleaned(s.getSemaphore()),
-                "Cleaner cleanup should have occurred");
+        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
     }
 
     /**
@@ -124,8 +126,7 @@
 
         CleanableCase s = setupPhantom(COMMON, cleaner);
         cleaner = null;
-        Assert.assertTrue(checkCleaned(s.getSemaphore()),
-                "Cleaner cleanup should have occurred");
+        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
     }
 
     /**
@@ -213,16 +214,11 @@
         CleanableCase cc = setupPhantom(COMMON, test.getCleanable());
         test.clearCleanable();        // release this hard reference
 
-        boolean result = checkCleaned(test.getSemaphore());
-        if (result) {
-            Assert.assertEquals(r, CleanableCase.EV_CLEAN,
-                    "cleaned; but not expected");
-        } else {
-            Assert.assertNotEquals(r, CleanableCase.EV_CLEAN,
-                    "not cleaned; expected cleaning");
-        }
-        Assert.assertTrue(checkCleaned(cc.getSemaphore()),
-                "The reference to the Cleanable should have been freed");
+        checkCleaned(test.getSemaphore(),
+                r == CleanableCase.EV_CLEAN,
+                "Cleanable was cleaned:");
+        checkCleaned(cc.getSemaphore(), true,
+                "The reference to the Cleanable was freed:");
     }
 
     /**
@@ -278,27 +274,32 @@
      * Check a semaphore having been released by cleanup handler.
      * Force a number of GC cycles to give the GC a chance to process
      * the Reference and for the cleanup action to be run.
+     * Use a larger number of cycles to wait for an expected cleaning to occur.
      *
      * @param semaphore a Semaphore
-     * @return true if the semaphores has 1 permit, false otherwise.
+     * @param expectCleaned true if cleaning should occur
+     * @param msg a message to explain the error
      */
-    static boolean checkCleaned(Semaphore semaphore) {
-        int cycle = 0;
-        for (; cycle < 3; cycle++) {
+    static void checkCleaned(Semaphore semaphore, boolean expectCleaned,
+                             String msg) {
+        long max_cycles = expectCleaned ? 10 : 3;
+        long cycle = 0;
+        for (; cycle < max_cycles; cycle++) {
+            // Force GC
+            whitebox.fullGC();
+
             try {
-                if (semaphore.tryAcquire(10L, TimeUnit.MILLISECONDS)) {
+                if (semaphore.tryAcquire(Utils.adjustTimeout(10L), TimeUnit.MILLISECONDS)) {
                     System.out.printf(" Cleanable cleaned in cycle: %d%n", cycle);
-                    return true;
+                    Assert.assertEquals(true, expectCleaned, msg);
+                    return;
                 }
             } catch (InterruptedException ie) {
                 // retry in outer loop
             }
-            // Force GC
-            whitebox.fullGC();
         }
         // Object has not been cleaned
-        System.out.printf(" Cleanable not cleaned%n");
-        return false;   // Failing result
+        Assert.assertEquals(false, expectCleaned, msg);
     }
 
     /**
@@ -622,7 +623,7 @@
         System.gc();
         Assert.assertNotEquals(map.get(k2), data, "value should not be found in the map");
 
-        final int CYCLE_MAX = 30;
+        final long CYCLE_MAX = Utils.adjustTimeout(30L);
         for (int i = 1; map.size() > 0 && i < CYCLE_MAX; i++) {
             map.forEach( (k, v) -> System.out.printf("    k: %s, v: %s%n", k, v));
             try {
@@ -699,7 +700,7 @@
         }
 
         obj = null;
-        Assert.assertTrue(checkCleaned(s1), "reference should be cleaned;");
+        checkCleaned(s1, true, "reference was cleaned:");
         cleaner = null;
     }
 
@@ -713,7 +714,7 @@
         Object obj = new Object();
         CleanableCase s = setupPhantom(cleaner, obj);
         obj = null;
-        Assert.assertTrue(checkCleaned(s.getSemaphore()),
-                "Object cleaning should have occurred using CleanerFactor.cleaner()");
+        checkCleaned(s.getSemaphore(), true,
+                "Object was cleaned using CleanerFactor.cleaner():");
     }
 }
--- a/test/java/net/URI/URItoURLTest.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/test/java/net/URI/URItoURLTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -23,13 +23,16 @@
 
 /**
  * @test
- * @bug  4768755 4677045
- * @summary URL.equal(URL) is inconsistant for opaque URI.toURL()
- *                      and new URL(URI.toString)
+ * @bug  4768755 4677045 8147462
+ * @summary URL.equal(URL) is inconsistent for opaque URI.toURL()
+ *              and new URL(URI.toString)
  *          URI.toURL() does not always work as specified
+ *          Ensure URIs representing invalid/malformed URLs throw similar
+ *              exception with new URL(URI.toString()) and URI.toURL()
  */
 
 import java.net.*;
+import java.util.Objects;
 
 public class URItoURLTest {
 
@@ -39,19 +42,43 @@
         URL classUrl = testClass.getClass().
                                     getResource("/java/lang/Object.class");
 
-        String[] uris = { "mailto:xyz@abc.de",
+        String[] uris = {
+                        "mailto:xyz@abc.de",
                         "file:xyz#ab",
                         "http:abc/xyz/pqr",
+                        "http:abc/xyz/pqr?id=x%0a&ca=true",
                         "file:/C:/v700/dev/unitTesting/tests/apiUtil/uri",
                         "http:///p",
+                        "file:/C:/v700/dev/unitTesting/tests/apiUtil/uri",
+                        "file:/C:/v700/dev%20src/unitTesting/tests/apiUtil/uri",
+                        "file:/C:/v700/dev%20src/./unitTesting/./tests/apiUtil/uri",
+                        "http://localhost:80/abc/./xyz/../pqr?id=x%0a&ca=true",
+                        "file:./test/./x",
+                        "file:./././%20#i=3",
+                        "file:?hmm",
+                        "file:.#hmm",
                         classUrl.toExternalForm(),
                         };
 
+        // Strings that represent valid URIs but invalid URLs that should throw
+        // MalformedURLException both when calling toURL and new URL(String)
+        String[] malformedUrls = {
+                        "test:/test",
+                        "fiel:test",
+                        };
+
+        // Non-absolute URIs should throw IAE when calling toURL but will throw
+        // MalformedURLException when calling new URL
+        String[] illegalUris = {
+                        "./test",
+                        "/test",
+                        };
+
         boolean isTestFailed = false;
         boolean isURLFailed = false;
 
-        for (int i = 0; i < uris.length; i++) {
-            URI uri = URI.create(uris[i]);
+        for (String uriString : uris) {
+            URI uri = URI.create(uriString);
 
             URL url1 = new URL(uri.toString());
             URL url2 = uri.toURL();
@@ -107,6 +134,42 @@
             System.out.println();
             isURLFailed = false;
         }
+        for (String malformedUrl : malformedUrls) {
+            Exception toURLEx = null;
+            Exception newURLEx = null;
+            try {
+                new URI(malformedUrl).toURL();
+            } catch (Exception e) {
+                // expected
+                toURLEx = e;
+            }
+            try {
+                new URL(new URI(malformedUrl).toString());
+            } catch (Exception e) {
+                // expected
+                newURLEx = e;
+            }
+            if (!(toURLEx instanceof MalformedURLException) ||
+                    !(newURLEx instanceof MalformedURLException) ||
+                    !toURLEx.getMessage().equals(newURLEx.getMessage())) {
+                isTestFailed = true;
+                System.out.println("Expected the same MalformedURLException: " +
+                    newURLEx + " vs " + toURLEx);
+            }
+        }
+        for (String illegalUri : illegalUris) {
+             try {
+                 new URI(illegalUri).toURL();
+             } catch (IllegalArgumentException e) {
+                 // pass
+             }
+
+             try {
+                 new URL(illegalUri);
+             } catch (MalformedURLException e) {
+                 // pass
+             }
+        }
         if (isTestFailed) {
             throw new Exception("URI.toURL() test failed");
         }
--- a/test/java/time/tck/java/time/TCKLocalDate.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/test/java/time/tck/java/time/TCKLocalDate.java	Mon Feb 01 10:07:37 2016 -0800
@@ -119,6 +119,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
@@ -2385,4 +2387,204 @@
         assertSame(isoEra,IsoEra.CE);
         assertSame(LocalDate.MIN.getEra(),IsoEra.BCE);
     }
+
+    //-----------------------------------------------------------------
+    // datesUntil()
+    // ----------------------------------------------------------------
+    @Test
+    public void test_datesUntil() {
+        assertEquals(
+                date(2015, 9, 29).datesUntil(date(2015, 10, 3)).collect(
+                        Collectors.toList()), Arrays.asList(date(2015, 9, 29),
+                        date(2015, 9, 30), date(2015, 10, 1), date(2015, 10, 2)));
+        assertEquals(date(2015, 9, 29).datesUntil(date(2015, 10, 3), Period.ofDays(2))
+                .collect(Collectors.toList()), Arrays.asList(date(2015, 9, 29),
+                date(2015, 10, 1)));
+        assertEquals(date(2015, 1, 31).datesUntil(date(2015, 6, 1), Period.ofMonths(1))
+                .collect(Collectors.toList()), Arrays.asList(date(2015, 1, 31),
+                date(2015, 2, 28), date(2015, 3, 31), date(2015, 4, 30),
+                date(2015, 5, 31)));
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullEnd() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullEndStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(null, Period.ofDays(1));
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endBeforeStart() {
+        date(2015, 1, 31).datesUntil(date(2015, 1, 30));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endBeforeStartPositiveStep() {
+        date(2015, 1, 31).datesUntil(date(2015, 1, 30), Period.of(1, 0, 0));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endAfterStartNegativeStep() {
+        date(2015, 1, 30).datesUntil(date(2015, 1, 31), Period.of(0, -1, -1));
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_zeroStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.ZERO);
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_oppositeSign() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.of(1, 0, -1));
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_oppositeSign2() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.of(0, -1, 1));
+    }
+
+    @DataProvider(name="datesUntil")
+    public Object[][] provider_datesUntil() {
+        return new Object[][] {
+                {MIN_DATE, MIN_DATE},
+                {MIN_DATE, MAX_DATE},
+                {MAX_DATE, MAX_DATE},
+                {date(2015,10,1), date(2015,10,2)},
+                {date(2015,10,1), date(2015,11,1)},
+                {date(2015,10,31), date(2015,11,1)},
+                {date(2015,10,1), MAX_DATE},
+                {MIN_DATE, date(2015,10,1)}
+        };
+    }
+
+    @Test(dataProvider = "datesUntil")
+    public void test_datesUntil_count(LocalDate start, LocalDate end) {
+        assertEquals(start.datesUntil(end).count(), start.until(end, ChronoUnit.DAYS));
+        assertEquals(start.datesUntil(end, Period.ofDays(1)).count(),
+                start.until(end, ChronoUnit.DAYS));
+    }
+
+    @DataProvider(name="datesUntilSteps")
+    public Object[][] provider_datesUntil_steps() {
+        List<Object[]> data = new ArrayList<>(Arrays.asList(new Object[][] {
+            {MIN_DATE, MAX_DATE, Period.ofYears(Year.MAX_VALUE)},
+            {MIN_DATE, MAX_DATE, Period.ofDays(2)},
+            {MIN_DATE, MAX_DATE, Period.of(1,2,3)},
+            {MIN_DATE, MAX_DATE, Period.of(1,2,1000000)},
+            {MIN_DATE, MAX_DATE, Period.of(1,1000000,3)},
+            {MIN_DATE, MAX_DATE, Period.of(1000000,2,3)},
+            {MIN_DATE, MIN_DATE.plusMonths(1), Period.ofMonths(1)},
+            {MIN_DATE, date(Year.MIN_VALUE, 2, 2), Period.ofMonths(1)},
+            {MIN_DATE, date(Year.MIN_VALUE, 8, 9), Period.of(0, 1, 1)},
+            {MIN_DATE, MAX_DATE.minusYears(1), Period.ofYears(Year.MAX_VALUE)},
+            {MAX_DATE.minusMonths(1), MAX_DATE, Period.ofMonths(1)},
+            {date(Year.MAX_VALUE, 2, 20), MAX_DATE, Period.of(0, 1, 1)},
+            {date(2015,1,1), date(2016,1,1), Period.ofYears(1)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(365)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(366)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(4)},
+            {date(2015,1,1), date(2016,1,1), Period.of(0,1,2)},
+            {date(2015,1,1), date(2016,1,1), Period.ofMonths(1)},
+            {date(2015,1,1), date(2016,1,1), Period.ofMonths(12)},
+            {date(2015,1,1), date(2016,1,2), Period.ofMonths(12)},
+            {date(2015,1,1), date(2016,1,1), Period.of(0, 11, 30)},
+            {date(2015,1,1), date(2015,12,31), Period.of(0, 11, 30)},
+            {date(2015,1,31), date(2015,12,31), Period.ofMonths(2)},
+            {date(2015,1,31), date(2015,12,1), Period.ofMonths(2)},
+            {date(2015,1,31), date(2015,11,30), Period.ofMonths(2)},
+            {date(2015,1,31), date(2030,11,30), Period.of(1,30,365)},
+            {date(2015,1,31), date(2043,1,31), Period.of(4,0,0)},
+            {date(2015,1,31), date(2043,2,1), Period.of(4,0,0)},
+            {date(2015,1,31), date(2043,1,31), Period.of(3,11,30)},
+            {date(2015,1,31), date(2043,2,1), Period.of(3,11,30)},
+            {date(2015,1,31), date(2043,1,31), Period.of(0,0,1460)},
+            {date(2015,1,31), date(2043,1,31), Period.of(0,0,1461)},
+            {date(2015,1,31), date(2043,2,1), Period.of(0,0,1461)},
+            {date(2015,1,31), MAX_DATE, Period.of(10,100,1000)},
+            {date(2015,1,31), MAX_DATE, Period.of(1000000,10000,100000)},
+            {date(2015,1,31), MAX_DATE, Period.ofDays(10000000)},
+            {date(2015,1,31), MAX_DATE, Period.ofDays(Integer.MAX_VALUE)},
+            {date(2015,1,31), MAX_DATE, Period.ofMonths(Integer.MAX_VALUE)},
+            {date(2015,1,31), MAX_DATE, Period.ofYears(Integer.MAX_VALUE)}
+        }));
+        LocalDate start = date(2014, 1, 15);
+        LocalDate end = date(2015, 3, 4);
+        for (int months : new int[] { 0, 1, 2, 3, 5, 7, 12, 13 }) {
+            for (int days : new int[] { 0, 1, 2, 3, 5, 10, 17, 27, 28, 29, 30, 31, 32, 57, 58, 59,
+                    60, 61, 62, 70, 80, 90 }) {
+                if (months > 0 || days > 0)
+                    data.add(new Object[] { start, end, Period.of(0, months, days) });
+            }
+        }
+        for (int days = 27; days < 100; days++) {
+            data.add(new Object[] { start, start.plusDays(days), Period.ofMonths(1) });
+        }
+        return data.toArray(new Object[data.size()][]);
+    }
+
+    @Test(dataProvider="datesUntilSteps")
+    public void test_datesUntil_step(LocalDate start, LocalDate end, Period step) {
+        assertEquals(start.datesUntil(start, step).count(), 0);
+        long count = start.datesUntil(end, step).count();
+        assertTrue(count > 0);
+        // the last value must be before the end date
+        assertTrue(start.plusMonths(step.toTotalMonths()*(count-1)).plusDays(step.getDays()*(count-1)).isBefore(end));
+        try {
+            // the next after the last value must be either invalid or not before the end date
+            assertFalse(start.plusMonths(step.toTotalMonths()*count).plusDays(step.getDays()*count).isBefore(end));
+        } catch (ArithmeticException | DateTimeException e) {
+            // ignore: possible overflow for the next value is ok
+        }
+        if(count < 1000) {
+            assertTrue(start.datesUntil(end, step).allMatch(date -> !date.isBefore(start) && date.isBefore(end)));
+            List<LocalDate> list = new ArrayList<>();
+            for(long i=0; i<count; i++) {
+                list.add(start.plusMonths(step.toTotalMonths()*i).plusDays(step.getDays()*i));
+            }
+            assertEquals(start.datesUntil(end, step).collect(Collectors.toList()), list);
+        }
+
+        // swap end and start and negate the Period
+        count = end.datesUntil(start, step.negated()).count();
+        assertTrue(count > 0);
+        // the last value must be after the start date
+        assertTrue(end.minusMonths(step.toTotalMonths()*(count-1)).minusDays(step.getDays()*(count-1)).isAfter(start));
+        try {
+            // the next after the last value must be either invalid or not after the start date
+            assertFalse(end.minusMonths(step.toTotalMonths()*count).minusDays(step.getDays()*count).isAfter(start));
+        } catch (ArithmeticException | DateTimeException e) {
+            // ignore: possible overflow for the next value is ok
+        }
+        if(count < 1000) {
+            assertTrue(end.datesUntil(start, step.negated()).allMatch(date -> date.isAfter(start) && !date.isAfter(end)));
+            List<LocalDate> list = new ArrayList<>();
+            for(long i=0; i<count; i++) {
+                list.add(end.minusMonths(step.toTotalMonths()*i).minusDays(step.getDays()*i));
+            }
+            assertEquals(end.datesUntil(start, step.negated()).collect(Collectors.toList()), list);
+        }
+    }
+
+    @Test
+    public void test_datesUntil_staticType() {
+        // Test the types of the Stream and elements of the stream
+        LocalDate date = date(2015, 2, 10);
+        Stream<LocalDate> stream = date.datesUntil(date.plusDays(5));
+        long sum = stream.mapToInt(LocalDate::getDayOfMonth).sum();
+        assertEquals(sum, 60, "sum of 10, 11, 12, 13, 14 is wrong");
+    }
 }
--- a/test/java/util/Map/Defaults.java	Thu Jan 28 16:30:39 2016 -0800
+++ b/test/java/util/Map/Defaults.java	Mon Feb 01 10:07:37 2016 -0800
@@ -48,11 +48,14 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.BiFunction;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 import org.testng.annotations.Test;
 import org.testng.annotations.DataProvider;
+import static java.util.Objects.requireNonNull;
 import static org.testng.Assert.fail;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -533,6 +536,191 @@
                 "Should throw NPE");
     }
 
+    /** A function that flipflops between running two other functions. */
+    static <T,U,V> BiFunction<T,U,V> twoStep(AtomicBoolean b,
+                                             BiFunction<T,U,V> first,
+                                             BiFunction<T,U,V> second) {
+        return (t, u) -> {
+            boolean bb = b.get();
+            try {
+                return (b.get() ? first : second).apply(t, u);
+            } finally {
+                b.set(!bb);
+            }};
+    }
+
+    /**
+     * Simulates races by modifying the map within the mapping function.
+     */
+    @Test
+    public void testConcurrentMap_computeIfAbsent_racy() {
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        Function<Long,Long> f, g;
+
+        // race not detected if function returns null
+        f = (k) -> { map.put(two, 42L); return null; };
+        assertNull(map.computeIfAbsent(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        map.clear();
+        f = (k) -> { map.put(two, 42L); return 86L; };
+        assertEquals(42L, (long)map.computeIfAbsent(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        // mapping function ignored if value already exists
+        map.put(two, 99L);
+        assertEquals(99L, (long)map.computeIfAbsent(two, f));
+        assertEquals(99L, (long)map.get(two));
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_computeIfPresent_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            // Function not invoked if no mapping exists
+            f = (k, v) -> { map.put(two, 42L); return val; };
+            assertNull(map.computeIfPresent(two, f));
+            assertNull(map.get(two));
+
+            map.put(two, 42L);
+            f = (k, v) -> { map.put(two, 86L); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(86L, (long)v);
+                return null;
+            };
+            assertNull(map.computeIfPresent(two, twoStep(b, f, g)));
+            assertFalse(map.containsKey(two));
+            assertTrue(b.get());
+
+            map.put(two, 42L);
+            f = (k, v) -> { map.put(two, 86L); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(86L, (long)v);
+                return 99L;
+            };
+            assertEquals(99L, (long)map.computeIfPresent(two, twoStep(b, f, g)));
+            assertTrue(map.containsKey(two));
+            assertTrue(b.get());
+        }
+    }
+
+    @Test
+    public void testConcurrentMap_compute_simple() {
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        BiFunction<Long,Long,Long> fun = (k, v) -> ((v == null) ? 0L : k + v);
+        assertEquals(Long.valueOf(0L), map.compute(3L, fun));
+        assertEquals(Long.valueOf(3L), map.compute(3L, fun));
+        assertEquals(Long.valueOf(6L), map.compute(3L, fun));
+        assertNull(map.compute(3L, (k, v) -> null));
+        assertTrue(map.isEmpty());
+
+        assertEquals(Long.valueOf(0L), map.compute(new Long(3L), fun));
+        assertEquals(Long.valueOf(3L), map.compute(new Long(3L), fun));
+        assertEquals(Long.valueOf(6L), map.compute(new Long(3L), fun));
+        assertNull(map.compute(3L, (k, v) -> null));
+        assertTrue(map.isEmpty());
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_compute_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        // null -> null is a no-op; race not detected
+        f = (k, v) -> { map.put(two, 42L); return null; };
+        assertNull(map.compute(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            f = (k, v) -> { map.put(two, 42L); return 86L; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(42L, (long)v);
+                return k + v;
+            };
+            assertEquals(44L, (long)map.compute(two, twoStep(b, f, g)));
+            assertEquals(44L, (long)map.get(two));
+            assertTrue(b.get());
+
+            f = (k, v) -> { map.remove(two); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertNull(v);
+                return 44L;
+            };
+            assertEquals(44L, (long)map.compute(two, twoStep(b, f, g)));
+            assertEquals(44L, (long)map.get(two));
+            assertTrue(map.containsKey(two));
+            assertTrue(b.get());
+
+            f = (k, v) -> { map.remove(two); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertNull(v);
+                return null;
+            };
+            assertNull(map.compute(two, twoStep(b, f, g)));
+            assertNull(map.get(two));
+            assertFalse(map.containsKey(two));
+            assertTrue(b.get());
+        }
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_merge_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            f = (v, w) -> { throw new AssertionError(); };
+            assertEquals(99L, (long)map.merge(two, 99L, f));
+            assertEquals(99L, (long)map.get(two));
+
+            f = (v, w) -> { map.put(two, 42L); return val; };
+            g = (v, w) -> {
+                assertEquals(42L, (long)v);
+                assertEquals(3L, (long)w);
+                return v + w;
+            };
+            assertEquals(45L, (long)map.merge(two, 3L, twoStep(b, f, g)));
+            assertEquals(45L, (long)map.get(two));
+            assertTrue(b.get());
+
+            f = (v, w) -> { map.remove(two); return val; };
+            g = (k, v) -> { throw new AssertionError(); };
+            assertEquals(55L, (long)map.merge(two, 55L, twoStep(b, f, g)));
+            assertEquals(55L, (long)map.get(two));
+            assertTrue(map.containsKey(two));
+            assertFalse(b.get()); b.set(true);
+        }
+    }
+
     public enum IntegerEnum {
 
         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
@@ -838,13 +1026,13 @@
 
         protected ExtendsAbstractMap(M map) { this.map = map; }
 
-        public Set<Map.Entry<K,V>> entrySet() {
+        @Override public Set<Map.Entry<K,V>> entrySet() {
             return new AbstractSet<Map.Entry<K,V>>() {
-                public int size() {
+                @Override public int size() {
                     return map.size();
                 }
 
-                public Iterator<Map.Entry<K,V>> iterator() {
+                @Override public Iterator<Map.Entry<K,V>> iterator() {
                     final Iterator<Map.Entry<K,V>> source = map.entrySet().iterator();
                     return new Iterator<Map.Entry<K,V>>() {
                        public boolean hasNext() { return source.hasNext(); }
@@ -853,20 +1041,20 @@
                     };
                 }
 
-                public boolean add(Map.Entry<K,V> e) {
+                @Override public boolean add(Map.Entry<K,V> e) {
                     return map.entrySet().add(e);
                 }
             };
         }
 
-        public V put(K key, V value) {
+        @Override public V put(K key, V value) {
             return map.put(key, value);
         }
     }
 
     /**
      * A simple mutable concurrent map implementation that provides only default
-     * implementations of all methods. ie. none of the ConcurrentMap interface
+     * implementations of all methods, i.e. none of the ConcurrentMap interface
      * default methods have overridden implementations.
      *
      * @param <K> Type of keys
@@ -875,14 +1063,26 @@
     public static class ImplementsConcurrentMap<K,V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
         public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
 
-        // ConcurrentMap reabstracts these methods
+        // ConcurrentMap reabstracts these methods.
+        //
+        // Unlike ConcurrentHashMap, we have zero tolerance for null values.
 
-        public V replace(K k, V v) { return map.replace(k, v); };
+        @Override public V replace(K k, V v) {
+            return map.replace(requireNonNull(k), requireNonNull(v));
+        }
 
-        public boolean replace(K k, V v, V vv) { return map.replace(k, v, vv); };
+        @Override public boolean replace(K k, V v, V vv) {
+            return map.replace(requireNonNull(k),
+                               requireNonNull(v),
+                               requireNonNull(vv));
+        }
 
-        public boolean remove(Object k, Object v) { return map.remove(k, v); }
+        @Override public boolean remove(Object k, Object v) {
+            return map.remove(requireNonNull(k), requireNonNull(v));
+        }
 
-        public V putIfAbsent(K k, V v) { return map.putIfAbsent(k, v); }
+        @Override public V putIfAbsent(K k, V v) {
+            return map.putIfAbsent(requireNonNull(k), requireNonNull(v));
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,635 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractExecutorServiceTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AbstractExecutorServiceTest.class);
+    }
+
+    /**
+     * A no-frills implementation of AbstractExecutorService, designed
+     * to test the submit methods only.
+     */
+    static class DirectExecutorService extends AbstractExecutorService {
+        public void execute(Runnable r) { r.run(); }
+        public void shutdown() { shutdown = true; }
+        public List<Runnable> shutdownNow() {
+            shutdown = true;
+            return Collections.EMPTY_LIST;
+        }
+        public boolean isShutdown() { return shutdown; }
+        public boolean isTerminated() { return isShutdown(); }
+        public boolean awaitTermination(long timeout, TimeUnit unit) {
+            return isShutdown();
+        }
+        private volatile boolean shutdown = false;
+    }
+
+    /**
+     * execute(runnable) runs it to completion
+     */
+    public void testExecuteRunnable() throws Exception {
+        ExecutorService e = new DirectExecutorService();
+        final AtomicBoolean done = new AtomicBoolean(false);
+        Future<?> future = e.submit(new CheckedRunnable() {
+            public void realRun() {
+                done.set(true);
+            }});
+        assertNull(future.get());
+        assertNull(future.get(0, MILLISECONDS));
+        assertTrue(done.get());
+        assertTrue(future.isDone());
+        assertFalse(future.isCancelled());
+    }
+
+    /**
+     * Completed submit(callable) returns result
+     */
+    public void testSubmitCallable() throws Exception {
+        ExecutorService e = new DirectExecutorService();
+        Future<String> future = e.submit(new StringTask());
+        String result = future.get();
+        assertSame(TEST_STRING, result);
+    }
+
+    /**
+     * Completed submit(runnable) returns successfully
+     */
+    public void testSubmitRunnable() throws Exception {
+        ExecutorService e = new DirectExecutorService();
+        Future<?> future = e.submit(new NoOpRunnable());
+        future.get();
+        assertTrue(future.isDone());
+    }
+
+    /**
+     * Completed submit(runnable, result) returns result
+     */
+    public void testSubmitRunnable2() throws Exception {
+        ExecutorService e = new DirectExecutorService();
+        Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
+        String result = future.get();
+        assertSame(TEST_STRING, result);
+    }
+
+    /**
+     * A submitted privileged action runs to completion
+     */
+    public void testSubmitPrivilegedAction() throws Exception {
+        Runnable r = new CheckedRunnable() {
+            public void realRun() throws Exception {
+                ExecutorService e = new DirectExecutorService();
+                Future future = e.submit(Executors.callable(new PrivilegedAction() {
+                    public Object run() {
+                        return TEST_STRING;
+                    }}));
+
+                assertSame(TEST_STRING, future.get());
+            }};
+
+        runWithPermissions(r,
+                           new RuntimePermission("getClassLoader"),
+                           new RuntimePermission("setContextClassLoader"),
+                           new RuntimePermission("modifyThread"));
+    }
+
+    /**
+     * A submitted privileged exception action runs to completion
+     */
+    public void testSubmitPrivilegedExceptionAction() throws Exception {
+        Runnable r = new CheckedRunnable() {
+            public void realRun() throws Exception {
+                ExecutorService e = new DirectExecutorService();
+                Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+                    public Object run() {
+                        return TEST_STRING;
+                    }}));
+
+                assertSame(TEST_STRING, future.get());
+            }};
+
+        runWithPermissions(r);
+    }
+
+    /**
+     * A submitted failed privileged exception action reports exception
+     */
+    public void testSubmitFailedPrivilegedExceptionAction() throws Exception {
+        Runnable r = new CheckedRunnable() {
+            public void realRun() throws Exception {
+                ExecutorService e = new DirectExecutorService();
+                Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+                    public Object run() throws Exception {
+                        throw new IndexOutOfBoundsException();
+                    }}));
+
+                try {
+                    future.get();
+                    shouldThrow();
+                } catch (ExecutionException success) {
+                    assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
+                }}};
+
+        runWithPermissions(r);
+    }
+
+    /**
+     * execute(null runnable) throws NPE
+     */
+    public void testExecuteNullRunnable() {
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.submit((Runnable) null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * submit(null callable) throws NPE
+     */
+    public void testSubmitNullCallable() {
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.submit((Callable) null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * submit(callable).get() throws InterruptedException if interrupted
+     */
+    public void testInterruptedSubmit() throws InterruptedException {
+        final CountDownLatch submitted    = new CountDownLatch(1);
+        final CountDownLatch quittingTime = new CountDownLatch(1);
+        final Callable<Void> awaiter = new CheckedCallable<Void>() {
+            public Void realCall() throws InterruptedException {
+                assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS));
+                return null;
+            }};
+        final ExecutorService p
+            = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
+                                     new ArrayBlockingQueue<Runnable>(10));
+        try (PoolCleaner cleaner = cleaner(p, quittingTime)) {
+            Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+                public void realRun() throws Exception {
+                    Future<Void> future = p.submit(awaiter);
+                    submitted.countDown();
+                    future.get();
+                }});
+
+            await(submitted);
+            t.interrupt();
+            awaitTermination(t);
+        }
+    }
+
+    /**
+     * get of submit(callable) throws ExecutionException if callable
+     * throws exception
+     */
+    public void testSubmitEE() throws InterruptedException {
+        final ThreadPoolExecutor p =
+            new ThreadPoolExecutor(1, 1,
+                                   60, TimeUnit.SECONDS,
+                                   new ArrayBlockingQueue<Runnable>(10));
+        try (PoolCleaner cleaner = cleaner(p)) {
+            Callable c = new Callable() {
+                public Object call() { throw new ArithmeticException(); }};
+            try {
+                p.submit(c).get();
+                shouldThrow();
+            } catch (ExecutionException success) {
+                assertTrue(success.getCause() instanceof ArithmeticException);
+            }
+        }
+    }
+
+    /**
+     * invokeAny(null) throws NPE
+     */
+    public void testInvokeAny1() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAny(null);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * invokeAny(empty collection) throws IAE
+     */
+    public void testInvokeAny2() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAny(new ArrayList<Callable<String>>());
+                shouldThrow();
+            } catch (IllegalArgumentException success) {}
+        }
+    }
+
+    /**
+     * invokeAny(c) throws NPE if c has null elements
+     */
+    public void testInvokeAny3() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+            l.add(new Callable<Long>() {
+                      public Long call() { throw new ArithmeticException(); }});
+            l.add(null);
+            try {
+                e.invokeAny(l);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * invokeAny(c) throws ExecutionException if no task in c completes
+     */
+    public void testInvokeAny4() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new NPETask());
+            try {
+                e.invokeAny(l);
+                shouldThrow();
+            } catch (ExecutionException success) {
+                assertTrue(success.getCause() instanceof NullPointerException);
+            }
+        }
+    }
+
+    /**
+     * invokeAny(c) returns result of some task in c if at least one completes
+     */
+    public void testInvokeAny5() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(new StringTask());
+            String result = e.invokeAny(l);
+            assertSame(TEST_STRING, result);
+        }
+    }
+
+    /**
+     * invokeAll(null) throws NPE
+     */
+    public void testInvokeAll1() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAll(null);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * invokeAll(empty collection) returns empty collection
+     */
+    public void testInvokeAll2() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
+            assertTrue(r.isEmpty());
+        }
+    }
+
+    /**
+     * invokeAll(c) throws NPE if c has null elements
+     */
+    public void testInvokeAll3() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(null);
+            try {
+                e.invokeAll(l);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * get of returned element of invokeAll(c) throws exception on failed task
+     */
+    public void testInvokeAll4() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new NPETask());
+            List<Future<String>> futures = e.invokeAll(l);
+            assertEquals(1, futures.size());
+            try {
+                futures.get(0).get();
+                shouldThrow();
+            } catch (ExecutionException success) {
+                assertTrue(success.getCause() instanceof NullPointerException);
+            }
+        }
+    }
+
+    /**
+     * invokeAll(c) returns results of all completed tasks in c
+     */
+    public void testInvokeAll5() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(new StringTask());
+            List<Future<String>> futures = e.invokeAll(l);
+            assertEquals(2, futures.size());
+            for (Future<String> future : futures)
+                assertSame(TEST_STRING, future.get());
+        }
+    }
+
+    /**
+     * timed invokeAny(null) throws NPE
+     */
+    public void testTimedInvokeAny1() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAny(null time unit) throws NPE
+     */
+    public void testTimedInvokeAnyNullTimeUnit() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            try {
+                e.invokeAny(l, MEDIUM_DELAY_MS, null);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAny(empty collection) throws IAE
+     */
+    public void testTimedInvokeAny2() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAny(new ArrayList<Callable<String>>(),
+                            MEDIUM_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (IllegalArgumentException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAny(c) throws NPE if c has null elements
+     */
+    public void testTimedInvokeAny3() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+            l.add(new Callable<Long>() {
+                      public Long call() { throw new ArithmeticException(); }});
+            l.add(null);
+            try {
+                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAny(c) throws ExecutionException if no task completes
+     */
+    public void testTimedInvokeAny4() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            long startTime = System.nanoTime();
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new NPETask());
+            try {
+                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (ExecutionException success) {
+                assertTrue(success.getCause() instanceof NullPointerException);
+            }
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+    }
+
+    /**
+     * timed invokeAny(c) returns result of some task in c
+     */
+    public void testTimedInvokeAny5() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            long startTime = System.nanoTime();
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(new StringTask());
+            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            assertSame(TEST_STRING, result);
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+    }
+
+    /**
+     * timed invokeAll(null) throws NPE
+     */
+    public void testTimedInvokeAll1() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            try {
+                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAll(null time unit) throws NPE
+     */
+    public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            try {
+                e.invokeAll(l, MEDIUM_DELAY_MS, null);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * timed invokeAll(empty collection) returns empty collection
+     */
+    public void testTimedInvokeAll2() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            assertTrue(r.isEmpty());
+        }
+    }
+
+    /**
+     * timed invokeAll(c) throws NPE if c has null elements
+     */
+    public void testTimedInvokeAll3() throws InterruptedException {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(null);
+            try {
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+                shouldThrow();
+            } catch (NullPointerException success) {}
+        }
+    }
+
+    /**
+     * get of returned element of invokeAll(c) throws exception on failed task
+     */
+    public void testTimedInvokeAll4() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new NPETask());
+            List<Future<String>> futures =
+                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+            assertEquals(1, futures.size());
+            try {
+                futures.get(0).get();
+                shouldThrow();
+            } catch (ExecutionException success) {
+                assertTrue(success.getCause() instanceof NullPointerException);
+            }
+        }
+    }
+
+    /**
+     * timed invokeAll(c) returns results of all completed tasks in c
+     */
+    public void testTimedInvokeAll5() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+            assertEquals(2, futures.size());
+            for (Future<String> future : futures)
+                assertSame(TEST_STRING, future.get());
+        }
+    }
+
+    /**
+     * timed invokeAll cancels tasks not completed by timeout
+     */
+    public void testTimedInvokeAll6() throws Exception {
+        final ExecutorService e = new DirectExecutorService();
+        try (PoolCleaner cleaner = cleaner(e)) {
+            for (long timeout = timeoutMillis();;) {
+                List<Callable<String>> tasks = new ArrayList<>();
+                tasks.add(new StringTask("0"));
+                tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout),
+                                             TEST_STRING));
+                tasks.add(new StringTask("2"));
+                long startTime = System.nanoTime();
+                List<Future<String>> futures =
+                    e.invokeAll(tasks, timeout, MILLISECONDS);
+                assertEquals(tasks.size(), futures.size());
+                assertTrue(millisElapsedSince(startTime) >= timeout);
+                for (Future future : futures)
+                    assertTrue(future.isDone());
+                try {
+                    assertEquals("0", futures.get(0).get());
+                    assertEquals(TEST_STRING, futures.get(1).get());
+                } catch (CancellationException retryWithLongerTimeout) {
+                    // unusual delay before starting second task
+                    timeout *= 2;
+                    if (timeout >= LONG_DELAY_MS / 2)
+                        fail("expected exactly one task to be cancelled");
+                    continue;
+                }
+                assertTrue(futures.get(2).isCancelled());
+                break;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AbstractQueueTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.AbstractQueue;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueueTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AbstractQueueTest.class);
+    }
+
+    static class Succeed extends AbstractQueue<Integer> {
+        public boolean offer(Integer x) {
+            if (x == null) throw new NullPointerException();
+            return true;
+        }
+        public Integer peek() { return one; }
+        public Integer poll() { return one; }
+        public int size() { return 0; }
+        public Iterator iterator() { return null; } // not needed
+    }
+
+    static class Fail extends AbstractQueue<Integer> {
+        public boolean offer(Integer x) {
+            if (x == null) throw new NullPointerException();
+            return false;
+        }
+        public Integer peek() { return null; }
+        public Integer poll() { return null; }
+        public int size() { return 0; }
+        public Iterator iterator() { return null; } // not needed
+    }
+
+    /**
+     * add returns true if offer succeeds
+     */
+    public void testAddS() {
+        Succeed q = new Succeed();
+        assertTrue(q.add(two));
+    }
+
+    /**
+     * add throws ISE true if offer fails
+     */
+    public void testAddF() {
+        Fail q = new Fail();
+        try {
+            q.add(one);
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * add throws NPE if offer does
+     */
+    public void testAddNPE() {
+        Succeed q = new Succeed();
+        try {
+            q.add(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * remove returns normally if poll succeeds
+     */
+    public void testRemoveS() {
+        Succeed q = new Succeed();
+        q.remove();
+    }
+
+    /**
+     * remove throws NSEE if poll returns null
+     */
+    public void testRemoveF() {
+        Fail q = new Fail();
+        try {
+            q.remove();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * element returns normally if peek succeeds
+     */
+    public void testElementS() {
+        Succeed q = new Succeed();
+        q.element();
+    }
+
+    /**
+     * element throws NSEE if peek returns null
+     */
+    public void testElementF() {
+        Fail q = new Fail();
+        try {
+            q.element();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * addAll(null) throws NPE
+     */
+    public void testAddAll1() {
+        Succeed q = new Succeed();
+        try {
+            q.addAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll(this) throws IAE
+     */
+    public void testAddAllSelf() {
+        Succeed q = new Succeed();
+        try {
+            q.addAll(q);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * addAll of a collection with null elements throws NPE
+     */
+    public void testAddAll2() {
+        Succeed q = new Succeed();
+        Integer[] ints = new Integer[SIZE];
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll of a collection with any null elements throws NPE after
+     * possibly adding some elements
+     */
+    public void testAddAll3() {
+        Succeed q = new Succeed();
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE - 1; ++i)
+            ints[i] = new Integer(i);
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll throws ISE if an add fails
+     */
+    public void testAddAll4() {
+        Fail q = new Fail();
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = new Integer(i);
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,1280 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
+import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
+    }
+
+    /**
+     * A simple mutex class, adapted from the class javadoc.  Exclusive
+     * acquire tests exercise this as a sample user extension.
+     */
+    static class Mutex extends AbstractQueuedLongSynchronizer {
+        /** An eccentric value > 32 bits for locked synchronizer state. */
+        static final long LOCKED = (1L << 63) | (1L << 15);
+
+        static final long UNLOCKED = 0;
+
+        public boolean isHeldExclusively() {
+            long state = getState();
+            assertTrue(state == UNLOCKED || state == LOCKED);
+            return state == LOCKED;
+        }
+
+        public boolean tryAcquire(long acquires) {
+            assertEquals(LOCKED, acquires);
+            return compareAndSetState(UNLOCKED, LOCKED);
+        }
+
+        public boolean tryRelease(long releases) {
+            if (getState() != LOCKED) throw new IllegalMonitorStateException();
+            setState(UNLOCKED);
+            return true;
+        }
+
+        public boolean tryAcquireNanos(long nanos) throws InterruptedException {
+            return tryAcquireNanos(LOCKED, nanos);
+        }
+
+        public boolean tryAcquire() {
+            return tryAcquire(LOCKED);
+        }
+
+        public boolean tryRelease() {
+            return tryRelease(LOCKED);
+        }
+
+        public void acquire() {
+            acquire(LOCKED);
+        }
+
+        public void acquireInterruptibly() throws InterruptedException {
+            acquireInterruptibly(LOCKED);
+        }
+
+        public void release() {
+            release(LOCKED);
+        }
+
+        public ConditionObject newCondition() {
+            return new ConditionObject();
+        }
+    }
+
+    /**
+     * A simple latch class, to test shared mode.
+     */
+    static class BooleanLatch extends AbstractQueuedLongSynchronizer {
+        public boolean isSignalled() { return getState() != 0; }
+
+        public long tryAcquireShared(long ignore) {
+            return isSignalled() ? 1 : -1;
+        }
+
+        public boolean tryReleaseShared(long ignore) {
+            setState(1L << 62);
+            return true;
+        }
+    }
+
+    /**
+     * A runnable calling acquireInterruptibly that does not expect to
+     * be interrupted.
+     */
+    class InterruptibleSyncRunnable extends CheckedRunnable {
+        final Mutex sync;
+        InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; }
+        public void realRun() throws InterruptedException {
+            sync.acquireInterruptibly();
+        }
+    }
+
+    /**
+     * A runnable calling acquireInterruptibly that expects to be
+     * interrupted.
+     */
+    class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
+        final Mutex sync;
+        InterruptedSyncRunnable(Mutex sync) { this.sync = sync; }
+        public void realRun() throws InterruptedException {
+            sync.acquireInterruptibly();
+        }
+    }
+
+    /** A constant to clarify calls to checking methods below. */
+    static final Thread[] NO_THREADS = new Thread[0];
+
+    /**
+     * Spin-waits until sync.isQueued(t) becomes true.
+     */
+    void waitForQueuedThread(AbstractQueuedLongSynchronizer sync,
+                             Thread t) {
+        long startTime = System.nanoTime();
+        while (!sync.isQueued(t)) {
+            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+                throw new AssertionFailedError("timed out");
+            Thread.yield();
+        }
+        assertTrue(t.isAlive());
+    }
+
+    /**
+     * Checks that sync has exactly the given queued threads.
+     */
+    void assertHasQueuedThreads(AbstractQueuedLongSynchronizer sync,
+                                Thread... expected) {
+        Collection<Thread> actual = sync.getQueuedThreads();
+        assertEquals(expected.length > 0, sync.hasQueuedThreads());
+        assertEquals(expected.length, sync.getQueueLength());
+        assertEquals(expected.length, actual.size());
+        assertEquals(expected.length == 0, actual.isEmpty());
+        assertEquals(new HashSet<Thread>(actual),
+                     new HashSet<Thread>(Arrays.asList(expected)));
+    }
+
+    /**
+     * Checks that sync has exactly the given (exclusive) queued threads.
+     */
+    void assertHasExclusiveQueuedThreads(AbstractQueuedLongSynchronizer sync,
+                                         Thread... expected) {
+        assertHasQueuedThreads(sync, expected);
+        assertEquals(new HashSet<Thread>(sync.getExclusiveQueuedThreads()),
+                     new HashSet<Thread>(sync.getQueuedThreads()));
+        assertEquals(0, sync.getSharedQueuedThreads().size());
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+    }
+
+    /**
+     * Checks that sync has exactly the given (shared) queued threads.
+     */
+    void assertHasSharedQueuedThreads(AbstractQueuedLongSynchronizer sync,
+                                      Thread... expected) {
+        assertHasQueuedThreads(sync, expected);
+        assertEquals(new HashSet<Thread>(sync.getSharedQueuedThreads()),
+                     new HashSet<Thread>(sync.getQueuedThreads()));
+        assertEquals(0, sync.getExclusiveQueuedThreads().size());
+        assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+    }
+
+    /**
+     * Checks that condition c has exactly the given waiter threads,
+     * after acquiring mutex.
+     */
+    void assertHasWaitersUnlocked(Mutex sync, ConditionObject c,
+                                 Thread... threads) {
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, threads);
+        sync.release();
+    }
+
+    /**
+     * Checks that condition c has exactly the given waiter threads.
+     */
+    void assertHasWaitersLocked(Mutex sync, ConditionObject c,
+                                Thread... threads) {
+        assertEquals(threads.length > 0, sync.hasWaiters(c));
+        assertEquals(threads.length, sync.getWaitQueueLength(c));
+        assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty());
+        assertEquals(threads.length, sync.getWaitingThreads(c).size());
+        assertEquals(new HashSet<Thread>(sync.getWaitingThreads(c)),
+                     new HashSet<Thread>(Arrays.asList(threads)));
+    }
+
+    enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
+
+    /**
+     * Awaits condition using the specified AwaitMethod.
+     */
+    void await(ConditionObject c, AwaitMethod awaitMethod)
+            throws InterruptedException {
+        long timeoutMillis = 2 * LONG_DELAY_MS;
+        switch (awaitMethod) {
+        case await:
+            c.await();
+            break;
+        case awaitTimed:
+            assertTrue(c.await(timeoutMillis, MILLISECONDS));
+            break;
+        case awaitNanos:
+            long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+            long nanosRemaining = c.awaitNanos(nanosTimeout);
+            assertTrue(nanosRemaining > 0);
+            break;
+        case awaitUntil:
+            assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
+            break;
+        default:
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Checks that awaiting the given condition times out (using the
+     * default timeout duration).
+     */
+    void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
+        long timeoutMillis = timeoutMillis();
+        long startTime;
+        try {
+            switch (awaitMethod) {
+            case awaitTimed:
+                startTime = System.nanoTime();
+                assertFalse(c.await(timeoutMillis, MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+                break;
+            case awaitNanos:
+                startTime = System.nanoTime();
+                long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+                long nanosRemaining = c.awaitNanos(nanosTimeout);
+                assertTrue(nanosRemaining <= 0);
+                assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+                break;
+            case awaitUntil:
+                // We shouldn't assume that nanoTime and currentTimeMillis
+                // use the same time source, so don't use nanoTime here.
+                java.util.Date delayedDate = delayedDate(timeoutMillis());
+                assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
+                assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+                break;
+            default:
+                throw new UnsupportedOperationException();
+            }
+        } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+    }
+
+    /**
+     * isHeldExclusively is false upon construction
+     */
+    public void testIsHeldExclusively() {
+        Mutex sync = new Mutex();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * acquiring released sync succeeds
+     */
+    public void testAcquire() {
+        Mutex sync = new Mutex();
+        sync.acquire();
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * tryAcquire on a released sync succeeds
+     */
+    public void testTryAcquire() {
+        Mutex sync = new Mutex();
+        assertTrue(sync.tryAcquire());
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * hasQueuedThreads reports whether there are waiting threads
+     */
+    public void testHasQueuedThreads() {
+        final Mutex sync = new Mutex();
+        assertFalse(sync.hasQueuedThreads());
+        sync.acquire();
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.hasQueuedThreads());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.hasQueuedThreads());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.hasQueuedThreads());
+        sync.release();
+        awaitTermination(t2);
+        assertFalse(sync.hasQueuedThreads());
+    }
+
+    /**
+     * isQueued(null) throws NullPointerException
+     */
+    public void testIsQueuedNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.isQueued(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * isQueued reports whether a thread is queued
+     */
+    public void testIsQueued() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertFalse(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+        sync.acquire();
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.isQueued(t1));
+        assertTrue(sync.isQueued(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertFalse(sync.isQueued(t1));
+        assertTrue(sync.isQueued(t2));
+        sync.release();
+        awaitTermination(t2);
+        assertFalse(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+    }
+
+    /**
+     * getFirstQueuedThread returns first waiting thread or null if none
+     */
+    public void testGetFirstQueuedThread() {
+        final Mutex sync = new Mutex();
+        assertNull(sync.getFirstQueuedThread());
+        sync.acquire();
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertEquals(t1, sync.getFirstQueuedThread());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertEquals(t1, sync.getFirstQueuedThread());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertEquals(t2, sync.getFirstQueuedThread());
+        sync.release();
+        awaitTermination(t2);
+        assertNull(sync.getFirstQueuedThread());
+    }
+
+    /**
+     * hasContended reports false if no thread has ever blocked, else true
+     */
+    public void testHasContended() {
+        final Mutex sync = new Mutex();
+        assertFalse(sync.hasContended());
+        sync.acquire();
+        assertFalse(sync.hasContended());
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.hasContended());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.hasContended());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.hasContended());
+        sync.release();
+        awaitTermination(t2);
+        assertTrue(sync.hasContended());
+    }
+
+    /**
+     * getQueuedThreads returns all waiting threads
+     */
+    public void testGetQueuedThreads() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        sync.acquire();
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertHasExclusiveQueuedThreads(sync, t1);
+        assertTrue(sync.getQueuedThreads().contains(t1));
+        assertFalse(sync.getQueuedThreads().contains(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertTrue(sync.getQueuedThreads().contains(t1));
+        assertTrue(sync.getQueuedThreads().contains(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasExclusiveQueuedThreads(sync, t2);
+        sync.release();
+        awaitTermination(t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+    }
+
+    /**
+     * getExclusiveQueuedThreads returns all exclusive waiting threads
+     */
+    public void testGetExclusiveQueuedThreads() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        sync.acquire();
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertHasExclusiveQueuedThreads(sync, t1);
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+        assertFalse(sync.getExclusiveQueuedThreads().contains(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasExclusiveQueuedThreads(sync, t2);
+        sync.release();
+        awaitTermination(t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+    }
+
+    /**
+     * getSharedQueuedThreads does not include exclusively waiting threads
+     */
+    public void testGetSharedQueuedThreads_Exclusive() {
+        final Mutex sync = new Mutex();
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        sync.acquire();
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        sync.release();
+        awaitTermination(t2);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+    }
+
+    /**
+     * getSharedQueuedThreads returns all shared waiting threads
+     */
+    public void testGetSharedQueuedThreads_Shared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertHasSharedQueuedThreads(l, NO_THREADS);
+        Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                l.acquireSharedInterruptibly(0);
+            }});
+        waitForQueuedThread(l, t1);
+        assertHasSharedQueuedThreads(l, t1);
+        Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                l.acquireSharedInterruptibly(0);
+            }});
+        waitForQueuedThread(l, t2);
+        assertHasSharedQueuedThreads(l, t1, t2);
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasSharedQueuedThreads(l, t2);
+        assertTrue(l.releaseShared(0));
+        awaitTermination(t2);
+        assertHasSharedQueuedThreads(l, NO_THREADS);
+    }
+
+    /**
+     * tryAcquireNanos is interruptible
+     */
+    public void testTryAcquireNanos_Interruptible() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
+            }});
+
+        waitForQueuedThread(sync, t);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * tryAcquire on exclusively held sync fails
+     */
+    public void testTryAcquireWhenSynced() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                assertFalse(sync.tryAcquire());
+            }});
+
+        awaitTermination(t);
+        sync.release();
+    }
+
+    /**
+     * tryAcquireNanos on an exclusively held sync times out
+     */
+    public void testAcquireNanos_Timeout() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                long startTime = System.nanoTime();
+                long nanos = MILLISECONDS.toNanos(timeoutMillis());
+                assertFalse(sync.tryAcquireNanos(nanos));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            }});
+
+        awaitTermination(t);
+        sync.release();
+    }
+
+    /**
+     * getState is true when acquired and false when not
+     */
+    public void testGetState() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+
+        final BooleanLatch acquired = new BooleanLatch();
+        final BooleanLatch done = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(acquired.releaseShared(0));
+                done.acquireShared(0);
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        assertTrue(sync.isHeldExclusively());
+        assertTrue(done.releaseShared(0));
+        awaitTermination(t);
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * acquireInterruptibly succeeds when released, else is interruptible
+     */
+    public void testAcquireInterruptibly() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final BooleanLatch threadStarted = new BooleanLatch();
+        sync.acquireInterruptibly();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertTrue(threadStarted.releaseShared(0));
+                sync.acquireInterruptibly();
+            }});
+
+        threadStarted.acquireShared(0);
+        waitForQueuedThread(sync, t);
+        t.interrupt();
+        awaitTermination(t);
+        assertTrue(sync.isHeldExclusively());
+    }
+
+    /**
+     * owns is true for a condition created by sync else false
+     */
+    public void testOwns() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        assertTrue(sync.owns(c));
+        assertFalse(sync2.owns(c));
+    }
+
+    /**
+     * Calling await without holding sync throws IllegalMonitorStateException
+     */
+    public void testAwait_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        for (AwaitMethod awaitMethod : AwaitMethod.values()) {
+            long startTime = System.nanoTime();
+            try {
+                await(c, awaitMethod);
+                shouldThrow();
+            } catch (IllegalMonitorStateException success) {
+            } catch (InterruptedException e) { threadUnexpectedException(e); }
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+    }
+
+    /**
+     * Calling signal without holding sync throws IllegalMonitorStateException
+     */
+    public void testSignal_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            c.signal();
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * Calling signalAll without holding sync throws IllegalMonitorStateException
+     */
+    public void testSignalAll_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            c.signalAll();
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil without a signal times out
+     */
+    public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); }
+    public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); }
+    public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); }
+    public void testAwait_Timeout(AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertAwaitTimesOut(c, awaitMethod);
+        sync.release();
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil returns when signalled
+     */
+    public void testSignal_await()      { testSignal(AwaitMethod.await); }
+    public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); }
+    public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); }
+    public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); }
+    public void testSignal(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(acquired.releaseShared(0));
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        sync.release();
+        awaitTermination(t);
+    }
+
+    /**
+     * hasWaiters(null) throws NullPointerException
+     */
+    public void testHasWaitersNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.hasWaiters(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * getWaitQueueLength(null) throws NullPointerException
+     */
+    public void testGetWaitQueueLengthNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.getWaitQueueLength(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * getWaitingThreads throws NPE if null
+     */
+    public void testGetWaitingThreadsNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.getWaitingThreads(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * hasWaiters throws IllegalArgumentException if not owned
+     */
+    public void testHasWaitersIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.hasWaiters(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * hasWaiters throws IllegalMonitorStateException if not synced
+     */
+    public void testHasWaitersIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.hasWaiters(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength throws IllegalArgumentException if not owned
+     */
+    public void testGetWaitQueueLengthIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.getWaitQueueLength(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength throws IllegalMonitorStateException if not synced
+     */
+    public void testGetWaitQueueLengthIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.getWaitQueueLength(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads throws IllegalArgumentException if not owned
+     */
+    public void testGetWaitingThreadsIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.getWaitingThreads(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads throws IllegalMonitorStateException if not synced
+     */
+    public void testGetWaitingThreadsIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.getWaitingThreads(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * hasWaiters returns true when a thread is waiting, else false
+     */
+    public void testHasWaiters() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertFalse(sync.hasWaiters(c));
+                assertTrue(acquired.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertTrue(sync.hasWaiters(c));
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        assertFalse(sync.hasWaiters(c));
+        sync.release();
+
+        awaitTermination(t);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength returns number of waiting threads
+     */
+    public void testGetWaitQueueLength() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        final Thread t1 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertEquals(0, sync.getWaitQueueLength(c));
+                assertTrue(acquired1.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+        acquired1.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1);
+        assertEquals(1, sync.getWaitQueueLength(c));
+        sync.release();
+
+        final Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, t1);
+                assertEquals(1, sync.getWaitQueueLength(c));
+                assertTrue(acquired2.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertEquals(2, sync.getWaitQueueLength(c));
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertEquals(0, sync.getWaitQueueLength(c));
+        sync.release();
+
+        awaitTermination(t1);
+        awaitTermination(t2);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads returns only and all waiting threads
+     */
+    public void testGetWaitingThreads() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        final Thread t1 = new Thread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertTrue(sync.getWaitingThreads(c).isEmpty());
+                assertTrue(acquired1.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        final Thread t2 = new Thread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, t1);
+                assertTrue(sync.getWaitingThreads(c).contains(t1));
+                assertFalse(sync.getWaitingThreads(c).isEmpty());
+                assertEquals(1, sync.getWaitingThreads(c).size());
+                assertTrue(acquired2.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertFalse(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertTrue(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(0, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        t1.start();
+        acquired1.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1);
+        assertTrue(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertFalse(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(1, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        t2.start();
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertTrue(sync.getWaitingThreads(c).contains(t1));
+        assertTrue(sync.getWaitingThreads(c).contains(t2));
+        assertFalse(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(2, sync.getWaitingThreads(c).size());
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertFalse(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertTrue(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(0, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        awaitTermination(t1);
+        awaitTermination(t2);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * awaitUninterruptibly is uninterruptible
+     */
+    public void testAwaitUninterruptibly() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch pleaseInterrupt = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                sync.acquire();
+                assertTrue(pleaseInterrupt.releaseShared(0));
+                c.awaitUninterruptibly();
+                assertTrue(Thread.interrupted());
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                sync.release();
+            }});
+
+        pleaseInterrupt.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        sync.release();
+        t.interrupt();
+        assertHasWaitersUnlocked(sync, c, t);
+        assertThreadStaysAlive(t);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        sync.release();
+        awaitTermination(t);
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil is interruptible
+     */
+    public void testInterruptible_await()      { testInterruptible(AwaitMethod.await); }
+    public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); }
+    public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); }
+    public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); }
+    public void testInterruptible(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch pleaseInterrupt = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(pleaseInterrupt.releaseShared(0));
+                await(c, awaitMethod);
+            }});
+
+        pleaseInterrupt.acquireShared(0);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * signalAll wakes up all threads
+     */
+    public void testSignalAll_await()      { testSignalAll(AwaitMethod.await); }
+    public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); }
+    public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); }
+    public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); }
+    public void testSignalAll(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        Thread t1 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                acquired1.releaseShared(0);
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                acquired2.releaseShared(0);
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        acquired1.acquireShared(0);
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        sync.release();
+        awaitTermination(t1);
+        awaitTermination(t2);
+    }
+
+    /**
+     * toString indicates current state
+     */
+    public void testToString() {
+        Mutex sync = new Mutex();
+        assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED));
+        sync.acquire();
+        assertTrue(sync.toString().contains("State = " + Mutex.LOCKED));
+    }
+
+    /**
+     * A serialized AQS deserializes with current state, but no queued threads
+     */
+    public void testSerialization() {
+        Mutex sync = new Mutex();
+        assertFalse(serialClone(sync).isHeldExclusively());
+        sync.acquire();
+        Thread t = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t);
+        assertTrue(sync.isHeldExclusively());
+
+        Mutex clone = serialClone(sync);
+        assertTrue(clone.isHeldExclusively());
+        assertHasExclusiveQueuedThreads(sync, t);
+        assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+        t.interrupt();
+        awaitTermination(t);
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+        assertTrue(clone.isHeldExclusively());
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+    }
+
+    /**
+     * tryReleaseShared setting state changes getState
+     */
+    public void testGetStateWithReleaseShared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertFalse(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+    }
+
+    /**
+     * releaseShared has no effect when already signalled
+     */
+    public void testReleaseShared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertFalse(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+    }
+
+    /**
+     * acquireSharedInterruptibly returns after release, but not before
+     */
+    public void testAcquireSharedInterruptibly() {
+        final BooleanLatch l = new BooleanLatch();
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+                assertTrue(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+                assertTrue(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        assertThreadStaysAlive(t);
+        assertHasSharedQueuedThreads(l, t);
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        awaitTermination(t);
+    }
+
+    /**
+     * tryAcquireSharedNanos returns after release, but not before
+     */
+    public void testTryAcquireSharedNanos() {
+        final BooleanLatch l = new BooleanLatch();
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+                assertTrue(l.tryAcquireSharedNanos(0, nanos));
+                assertTrue(l.isSignalled());
+                assertTrue(l.tryAcquireSharedNanos(0, nanos));
+                assertTrue(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        assertThreadStaysAlive(t);
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        awaitTermination(t);
+    }
+
+    /**
+     * acquireSharedInterruptibly is interruptible
+     */
+    public void testAcquireSharedInterruptibly_Interruptible() {
+        final BooleanLatch l = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        t.interrupt();
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * tryAcquireSharedNanos is interruptible
+     */
+    public void testTryAcquireSharedNanos_Interruptible() {
+        final BooleanLatch l = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+                l.tryAcquireSharedNanos(0, nanos);
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        t.interrupt();
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * tryAcquireSharedNanos times out if not released before timeout
+     */
+    public void testTryAcquireSharedNanos_Timeout() {
+        final BooleanLatch l = new BooleanLatch();
+        final BooleanLatch observedQueued = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                for (long millis = timeoutMillis();
+                     !observedQueued.isSignalled();
+                     millis *= 2) {
+                    long nanos = MILLISECONDS.toNanos(millis);
+                    long startTime = System.nanoTime();
+                    assertFalse(l.tryAcquireSharedNanos(0, nanos));
+                    assertTrue(millisElapsedSince(startTime) >= millis);
+                }
+                assertFalse(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        observedQueued.releaseShared(0);
+        assertFalse(l.isSignalled());
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * awaitNanos/timed await with 0 wait times out immediately
+     */
+    public void testAwait_Zero() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertTrue(c.awaitNanos(0L) <= 0);
+        assertFalse(c.await(0L, NANOSECONDS));
+        sync.release();
+    }
+
+    /**
+     * awaitNanos/timed await with maximum negative wait times does not underflow
+     */
+    public void testAwait_NegativeInfinity() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
+        assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
+        sync.release();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,1283 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AbstractQueuedSynchronizerTest.class);
+    }
+
+    /**
+     * A simple mutex class, adapted from the class javadoc.  Exclusive
+     * acquire tests exercise this as a sample user extension.  Other
+     * methods/features of AbstractQueuedSynchronizer are tested via
+     * other test classes, including those for ReentrantLock,
+     * ReentrantReadWriteLock, and Semaphore.
+     */
+    static class Mutex extends AbstractQueuedSynchronizer {
+        /** An eccentric value for locked synchronizer state. */
+        static final int LOCKED = (1 << 31) | (1 << 15);
+
+        static final int UNLOCKED = 0;
+
+        @Override public boolean isHeldExclusively() {
+            int state = getState();
+            assertTrue(state == UNLOCKED || state == LOCKED);
+            return state == LOCKED;
+        }
+
+        @Override public boolean tryAcquire(int acquires) {
+            assertEquals(LOCKED, acquires);
+            return compareAndSetState(UNLOCKED, LOCKED);
+        }
+
+        @Override public boolean tryRelease(int releases) {
+            if (getState() != LOCKED) throw new IllegalMonitorStateException();
+            assertEquals(LOCKED, releases);
+            setState(UNLOCKED);
+            return true;
+        }
+
+        public boolean tryAcquireNanos(long nanos) throws InterruptedException {
+            return tryAcquireNanos(LOCKED, nanos);
+        }
+
+        public boolean tryAcquire() {
+            return tryAcquire(LOCKED);
+        }
+
+        public boolean tryRelease() {
+            return tryRelease(LOCKED);
+        }
+
+        public void acquire() {
+            acquire(LOCKED);
+        }
+
+        public void acquireInterruptibly() throws InterruptedException {
+            acquireInterruptibly(LOCKED);
+        }
+
+        public void release() {
+            release(LOCKED);
+        }
+
+        public ConditionObject newCondition() {
+            return new ConditionObject();
+        }
+    }
+
+    /**
+     * A simple latch class, to test shared mode.
+     */
+    static class BooleanLatch extends AbstractQueuedSynchronizer {
+        public boolean isSignalled() { return getState() != 0; }
+
+        public int tryAcquireShared(int ignore) {
+            return isSignalled() ? 1 : -1;
+        }
+
+        public boolean tryReleaseShared(int ignore) {
+            setState(1);
+            return true;
+        }
+    }
+
+    /**
+     * A runnable calling acquireInterruptibly that does not expect to
+     * be interrupted.
+     */
+    class InterruptibleSyncRunnable extends CheckedRunnable {
+        final Mutex sync;
+        InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; }
+        public void realRun() throws InterruptedException {
+            sync.acquireInterruptibly();
+        }
+    }
+
+    /**
+     * A runnable calling acquireInterruptibly that expects to be
+     * interrupted.
+     */
+    class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
+        final Mutex sync;
+        InterruptedSyncRunnable(Mutex sync) { this.sync = sync; }
+        public void realRun() throws InterruptedException {
+            sync.acquireInterruptibly();
+        }
+    }
+
+    /** A constant to clarify calls to checking methods below. */
+    static final Thread[] NO_THREADS = new Thread[0];
+
+    /**
+     * Spin-waits until sync.isQueued(t) becomes true.
+     */
+    void waitForQueuedThread(AbstractQueuedSynchronizer sync, Thread t) {
+        long startTime = System.nanoTime();
+        while (!sync.isQueued(t)) {
+            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+                throw new AssertionFailedError("timed out");
+            Thread.yield();
+        }
+        assertTrue(t.isAlive());
+    }
+
+    /**
+     * Checks that sync has exactly the given queued threads.
+     */
+    void assertHasQueuedThreads(AbstractQueuedSynchronizer sync,
+                                Thread... expected) {
+        Collection<Thread> actual = sync.getQueuedThreads();
+        assertEquals(expected.length > 0, sync.hasQueuedThreads());
+        assertEquals(expected.length, sync.getQueueLength());
+        assertEquals(expected.length, actual.size());
+        assertEquals(expected.length == 0, actual.isEmpty());
+        assertEquals(new HashSet<Thread>(actual),
+                     new HashSet<Thread>(Arrays.asList(expected)));
+    }
+
+    /**
+     * Checks that sync has exactly the given (exclusive) queued threads.
+     */
+    void assertHasExclusiveQueuedThreads(AbstractQueuedSynchronizer sync,
+                                         Thread... expected) {
+        assertHasQueuedThreads(sync, expected);
+        assertEquals(new HashSet<Thread>(sync.getExclusiveQueuedThreads()),
+                     new HashSet<Thread>(sync.getQueuedThreads()));
+        assertEquals(0, sync.getSharedQueuedThreads().size());
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+    }
+
+    /**
+     * Checks that sync has exactly the given (shared) queued threads.
+     */
+    void assertHasSharedQueuedThreads(AbstractQueuedSynchronizer sync,
+                                      Thread... expected) {
+        assertHasQueuedThreads(sync, expected);
+        assertEquals(new HashSet<Thread>(sync.getSharedQueuedThreads()),
+                     new HashSet<Thread>(sync.getQueuedThreads()));
+        assertEquals(0, sync.getExclusiveQueuedThreads().size());
+        assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+    }
+
+    /**
+     * Checks that condition c has exactly the given waiter threads,
+     * after acquiring mutex.
+     */
+    void assertHasWaitersUnlocked(Mutex sync, ConditionObject c,
+                                 Thread... threads) {
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, threads);
+        sync.release();
+    }
+
+    /**
+     * Checks that condition c has exactly the given waiter threads.
+     */
+    void assertHasWaitersLocked(Mutex sync, ConditionObject c,
+                                Thread... threads) {
+        assertEquals(threads.length > 0, sync.hasWaiters(c));
+        assertEquals(threads.length, sync.getWaitQueueLength(c));
+        assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty());
+        assertEquals(threads.length, sync.getWaitingThreads(c).size());
+        assertEquals(new HashSet<Thread>(sync.getWaitingThreads(c)),
+                     new HashSet<Thread>(Arrays.asList(threads)));
+    }
+
+    enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
+
+    /**
+     * Awaits condition using the specified AwaitMethod.
+     */
+    void await(ConditionObject c, AwaitMethod awaitMethod)
+            throws InterruptedException {
+        long timeoutMillis = 2 * LONG_DELAY_MS;
+        switch (awaitMethod) {
+        case await:
+            c.await();
+            break;
+        case awaitTimed:
+            assertTrue(c.await(timeoutMillis, MILLISECONDS));
+            break;
+        case awaitNanos:
+            long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+            long nanosRemaining = c.awaitNanos(nanosTimeout);
+            assertTrue(nanosRemaining > 0);
+            break;
+        case awaitUntil:
+            assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
+            break;
+        default:
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Checks that awaiting the given condition times out (using the
+     * default timeout duration).
+     */
+    void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
+        long timeoutMillis = timeoutMillis();
+        long startTime;
+        try {
+            switch (awaitMethod) {
+            case awaitTimed:
+                startTime = System.nanoTime();
+                assertFalse(c.await(timeoutMillis, MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+                break;
+            case awaitNanos:
+                startTime = System.nanoTime();
+                long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+                long nanosRemaining = c.awaitNanos(nanosTimeout);
+                assertTrue(nanosRemaining <= 0);
+                assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+                break;
+            case awaitUntil:
+                // We shouldn't assume that nanoTime and currentTimeMillis
+                // use the same time source, so don't use nanoTime here.
+                java.util.Date delayedDate = delayedDate(timeoutMillis());
+                assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
+                assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+                break;
+            default:
+                throw new UnsupportedOperationException();
+            }
+        } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+    }
+
+    /**
+     * isHeldExclusively is false upon construction
+     */
+    public void testIsHeldExclusively() {
+        Mutex sync = new Mutex();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * acquiring released sync succeeds
+     */
+    public void testAcquire() {
+        Mutex sync = new Mutex();
+        sync.acquire();
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * tryAcquire on a released sync succeeds
+     */
+    public void testTryAcquire() {
+        Mutex sync = new Mutex();
+        assertTrue(sync.tryAcquire());
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * hasQueuedThreads reports whether there are waiting threads
+     */
+    public void testHasQueuedThreads() {
+        final Mutex sync = new Mutex();
+        assertFalse(sync.hasQueuedThreads());
+        sync.acquire();
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.hasQueuedThreads());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.hasQueuedThreads());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.hasQueuedThreads());
+        sync.release();
+        awaitTermination(t2);
+        assertFalse(sync.hasQueuedThreads());
+    }
+
+    /**
+     * isQueued(null) throws NullPointerException
+     */
+    public void testIsQueuedNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.isQueued(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * isQueued reports whether a thread is queued
+     */
+    public void testIsQueued() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertFalse(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+        sync.acquire();
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.isQueued(t1));
+        assertTrue(sync.isQueued(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertFalse(sync.isQueued(t1));
+        assertTrue(sync.isQueued(t2));
+        sync.release();
+        awaitTermination(t2);
+        assertFalse(sync.isQueued(t1));
+        assertFalse(sync.isQueued(t2));
+    }
+
+    /**
+     * getFirstQueuedThread returns first waiting thread or null if none
+     */
+    public void testGetFirstQueuedThread() {
+        final Mutex sync = new Mutex();
+        assertNull(sync.getFirstQueuedThread());
+        sync.acquire();
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertEquals(t1, sync.getFirstQueuedThread());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertEquals(t1, sync.getFirstQueuedThread());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertEquals(t2, sync.getFirstQueuedThread());
+        sync.release();
+        awaitTermination(t2);
+        assertNull(sync.getFirstQueuedThread());
+    }
+
+    /**
+     * hasContended reports false if no thread has ever blocked, else true
+     */
+    public void testHasContended() {
+        final Mutex sync = new Mutex();
+        assertFalse(sync.hasContended());
+        sync.acquire();
+        assertFalse(sync.hasContended());
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.hasContended());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.hasContended());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.hasContended());
+        sync.release();
+        awaitTermination(t2);
+        assertTrue(sync.hasContended());
+    }
+
+    /**
+     * getQueuedThreads returns all waiting threads
+     */
+    public void testGetQueuedThreads() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        sync.acquire();
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertHasExclusiveQueuedThreads(sync, t1);
+        assertTrue(sync.getQueuedThreads().contains(t1));
+        assertFalse(sync.getQueuedThreads().contains(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertTrue(sync.getQueuedThreads().contains(t1));
+        assertTrue(sync.getQueuedThreads().contains(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasExclusiveQueuedThreads(sync, t2);
+        sync.release();
+        awaitTermination(t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+    }
+
+    /**
+     * getExclusiveQueuedThreads returns all exclusive waiting threads
+     */
+    public void testGetExclusiveQueuedThreads() {
+        final Mutex sync = new Mutex();
+        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        sync.acquire();
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        t1.start();
+        waitForQueuedThread(sync, t1);
+        assertHasExclusiveQueuedThreads(sync, t1);
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+        assertFalse(sync.getExclusiveQueuedThreads().contains(t2));
+        t2.start();
+        waitForQueuedThread(sync, t2);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+        assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasExclusiveQueuedThreads(sync, t2);
+        sync.release();
+        awaitTermination(t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+    }
+
+    /**
+     * getSharedQueuedThreads does not include exclusively waiting threads
+     */
+    public void testGetSharedQueuedThreads_Exclusive() {
+        final Mutex sync = new Mutex();
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        sync.acquire();
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t1);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+        waitForQueuedThread(sync, t2);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        t1.interrupt();
+        awaitTermination(t1);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+        sync.release();
+        awaitTermination(t2);
+        assertTrue(sync.getSharedQueuedThreads().isEmpty());
+    }
+
+    /**
+     * getSharedQueuedThreads returns all shared waiting threads
+     */
+    public void testGetSharedQueuedThreads_Shared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertHasSharedQueuedThreads(l, NO_THREADS);
+        Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                l.acquireSharedInterruptibly(0);
+            }});
+        waitForQueuedThread(l, t1);
+        assertHasSharedQueuedThreads(l, t1);
+        Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                l.acquireSharedInterruptibly(0);
+            }});
+        waitForQueuedThread(l, t2);
+        assertHasSharedQueuedThreads(l, t1, t2);
+        t1.interrupt();
+        awaitTermination(t1);
+        assertHasSharedQueuedThreads(l, t2);
+        assertTrue(l.releaseShared(0));
+        awaitTermination(t2);
+        assertHasSharedQueuedThreads(l, NO_THREADS);
+    }
+
+    /**
+     * tryAcquireNanos is interruptible
+     */
+    public void testTryAcquireNanos_Interruptible() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
+            }});
+
+        waitForQueuedThread(sync, t);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * tryAcquire on exclusively held sync fails
+     */
+    public void testTryAcquireWhenSynced() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                assertFalse(sync.tryAcquire());
+            }});
+
+        awaitTermination(t);
+        sync.release();
+    }
+
+    /**
+     * tryAcquireNanos on an exclusively held sync times out
+     */
+    public void testAcquireNanos_Timeout() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                long startTime = System.nanoTime();
+                long nanos = MILLISECONDS.toNanos(timeoutMillis());
+                assertFalse(sync.tryAcquireNanos(nanos));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            }});
+
+        awaitTermination(t);
+        sync.release();
+    }
+
+    /**
+     * getState is true when acquired and false when not
+     */
+    public void testGetState() {
+        final Mutex sync = new Mutex();
+        sync.acquire();
+        assertTrue(sync.isHeldExclusively());
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+
+        final BooleanLatch acquired = new BooleanLatch();
+        final BooleanLatch done = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(acquired.releaseShared(0));
+                done.acquireShared(0);
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        assertTrue(sync.isHeldExclusively());
+        assertTrue(done.releaseShared(0));
+        awaitTermination(t);
+        assertFalse(sync.isHeldExclusively());
+    }
+
+    /**
+     * acquireInterruptibly succeeds when released, else is interruptible
+     */
+    public void testAcquireInterruptibly() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final BooleanLatch threadStarted = new BooleanLatch();
+        sync.acquireInterruptibly();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertTrue(threadStarted.releaseShared(0));
+                sync.acquireInterruptibly();
+            }});
+
+        threadStarted.acquireShared(0);
+        waitForQueuedThread(sync, t);
+        t.interrupt();
+        awaitTermination(t);
+        assertTrue(sync.isHeldExclusively());
+    }
+
+    /**
+     * owns is true for a condition created by sync else false
+     */
+    public void testOwns() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        assertTrue(sync.owns(c));
+        assertFalse(sync2.owns(c));
+    }
+
+    /**
+     * Calling await without holding sync throws IllegalMonitorStateException
+     */
+    public void testAwait_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        for (AwaitMethod awaitMethod : AwaitMethod.values()) {
+            long startTime = System.nanoTime();
+            try {
+                await(c, awaitMethod);
+                shouldThrow();
+            } catch (IllegalMonitorStateException success) {
+            } catch (InterruptedException e) { threadUnexpectedException(e); }
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+    }
+
+    /**
+     * Calling signal without holding sync throws IllegalMonitorStateException
+     */
+    public void testSignal_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            c.signal();
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * Calling signalAll without holding sync throws IllegalMonitorStateException
+     */
+    public void testSignalAll_IMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            c.signalAll();
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil without a signal times out
+     */
+    public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); }
+    public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); }
+    public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); }
+    public void testAwait_Timeout(AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertAwaitTimesOut(c, awaitMethod);
+        sync.release();
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil returns when signalled
+     */
+    public void testSignal_await()      { testSignal(AwaitMethod.await); }
+    public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); }
+    public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); }
+    public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); }
+    public void testSignal(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(acquired.releaseShared(0));
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        sync.release();
+        awaitTermination(t);
+    }
+
+    /**
+     * hasWaiters(null) throws NullPointerException
+     */
+    public void testHasWaitersNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.hasWaiters(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * getWaitQueueLength(null) throws NullPointerException
+     */
+    public void testGetWaitQueueLengthNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.getWaitQueueLength(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * getWaitingThreads(null) throws NullPointerException
+     */
+    public void testGetWaitingThreadsNPE() {
+        final Mutex sync = new Mutex();
+        try {
+            sync.getWaitingThreads(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * hasWaiters throws IllegalArgumentException if not owned
+     */
+    public void testHasWaitersIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.hasWaiters(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * hasWaiters throws IllegalMonitorStateException if not synced
+     */
+    public void testHasWaitersIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.hasWaiters(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength throws IllegalArgumentException if not owned
+     */
+    public void testGetWaitQueueLengthIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.getWaitQueueLength(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength throws IllegalMonitorStateException if not synced
+     */
+    public void testGetWaitQueueLengthIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.getWaitQueueLength(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads throws IllegalArgumentException if not owned
+     */
+    public void testGetWaitingThreadsIAE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final Mutex sync2 = new Mutex();
+        try {
+            sync2.getWaitingThreads(c);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads throws IllegalMonitorStateException if not synced
+     */
+    public void testGetWaitingThreadsIMSE() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        try {
+            sync.getWaitingThreads(c);
+            shouldThrow();
+        } catch (IllegalMonitorStateException success) {}
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * hasWaiters returns true when a thread is waiting, else false
+     */
+    public void testHasWaiters() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertFalse(sync.hasWaiters(c));
+                assertTrue(acquired.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        acquired.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertTrue(sync.hasWaiters(c));
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        assertFalse(sync.hasWaiters(c));
+        sync.release();
+
+        awaitTermination(t);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitQueueLength returns number of waiting threads
+     */
+    public void testGetWaitQueueLength() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        final Thread t1 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertEquals(0, sync.getWaitQueueLength(c));
+                assertTrue(acquired1.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+        acquired1.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1);
+        assertEquals(1, sync.getWaitQueueLength(c));
+        sync.release();
+
+        final Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, t1);
+                assertEquals(1, sync.getWaitQueueLength(c));
+                assertTrue(acquired2.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertEquals(2, sync.getWaitQueueLength(c));
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertEquals(0, sync.getWaitQueueLength(c));
+        sync.release();
+
+        awaitTermination(t1);
+        awaitTermination(t2);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * getWaitingThreads returns only and all waiting threads
+     */
+    public void testGetWaitingThreads() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        final Thread t1 = new Thread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                assertTrue(sync.getWaitingThreads(c).isEmpty());
+                assertTrue(acquired1.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        final Thread t2 = new Thread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertHasWaitersLocked(sync, c, t1);
+                assertTrue(sync.getWaitingThreads(c).contains(t1));
+                assertFalse(sync.getWaitingThreads(c).isEmpty());
+                assertEquals(1, sync.getWaitingThreads(c).size());
+                assertTrue(acquired2.releaseShared(0));
+                c.await();
+                sync.release();
+            }});
+
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertFalse(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertTrue(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(0, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        t1.start();
+        acquired1.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1);
+        assertTrue(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertFalse(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(1, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        t2.start();
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertTrue(sync.getWaitingThreads(c).contains(t1));
+        assertTrue(sync.getWaitingThreads(c).contains(t2));
+        assertFalse(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(2, sync.getWaitingThreads(c).size());
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        assertFalse(sync.getWaitingThreads(c).contains(t1));
+        assertFalse(sync.getWaitingThreads(c).contains(t2));
+        assertTrue(sync.getWaitingThreads(c).isEmpty());
+        assertEquals(0, sync.getWaitingThreads(c).size());
+        sync.release();
+
+        awaitTermination(t1);
+        awaitTermination(t2);
+        assertHasWaitersUnlocked(sync, c, NO_THREADS);
+    }
+
+    /**
+     * awaitUninterruptibly is uninterruptible
+     */
+    public void testAwaitUninterruptibly() {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch pleaseInterrupt = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                sync.acquire();
+                assertTrue(pleaseInterrupt.releaseShared(0));
+                c.awaitUninterruptibly();
+                assertTrue(Thread.interrupted());
+                assertHasWaitersLocked(sync, c, NO_THREADS);
+                sync.release();
+            }});
+
+        pleaseInterrupt.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        sync.release();
+        t.interrupt();
+        assertHasWaitersUnlocked(sync, c, t);
+        assertThreadStaysAlive(t);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signal();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t);
+        sync.release();
+        awaitTermination(t);
+    }
+
+    /**
+     * await/awaitNanos/awaitUntil is interruptible
+     */
+    public void testInterruptible_await()      { testInterruptible(AwaitMethod.await); }
+    public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); }
+    public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); }
+    public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); }
+    public void testInterruptible(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch pleaseInterrupt = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                assertTrue(pleaseInterrupt.releaseShared(0));
+                await(c, awaitMethod);
+            }});
+
+        pleaseInterrupt.acquireShared(0);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * signalAll wakes up all threads
+     */
+    public void testSignalAll_await()      { testSignalAll(AwaitMethod.await); }
+    public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); }
+    public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); }
+    public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); }
+    public void testSignalAll(final AwaitMethod awaitMethod) {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        final BooleanLatch acquired1 = new BooleanLatch();
+        final BooleanLatch acquired2 = new BooleanLatch();
+        Thread t1 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                acquired1.releaseShared(0);
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                sync.acquire();
+                acquired2.releaseShared(0);
+                await(c, awaitMethod);
+                sync.release();
+            }});
+
+        acquired1.acquireShared(0);
+        acquired2.acquireShared(0);
+        sync.acquire();
+        assertHasWaitersLocked(sync, c, t1, t2);
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        c.signalAll();
+        assertHasWaitersLocked(sync, c, NO_THREADS);
+        assertHasExclusiveQueuedThreads(sync, t1, t2);
+        sync.release();
+        awaitTermination(t1);
+        awaitTermination(t2);
+    }
+
+    /**
+     * toString indicates current state
+     */
+    public void testToString() {
+        Mutex sync = new Mutex();
+        assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED));
+        sync.acquire();
+        assertTrue(sync.toString().contains("State = " + Mutex.LOCKED));
+    }
+
+    /**
+     * A serialized AQS deserializes with current state, but no queued threads
+     */
+    public void testSerialization() {
+        Mutex sync = new Mutex();
+        assertFalse(serialClone(sync).isHeldExclusively());
+        sync.acquire();
+        Thread t = newStartedThread(new InterruptedSyncRunnable(sync));
+        waitForQueuedThread(sync, t);
+        assertTrue(sync.isHeldExclusively());
+
+        Mutex clone = serialClone(sync);
+        assertTrue(clone.isHeldExclusively());
+        assertHasExclusiveQueuedThreads(sync, t);
+        assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+        t.interrupt();
+        awaitTermination(t);
+        sync.release();
+        assertFalse(sync.isHeldExclusively());
+        assertTrue(clone.isHeldExclusively());
+        assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+        assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+    }
+
+    /**
+     * tryReleaseShared setting state changes getState
+     */
+    public void testGetStateWithReleaseShared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertFalse(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+    }
+
+    /**
+     * releaseShared has no effect when already signalled
+     */
+    public void testReleaseShared() {
+        final BooleanLatch l = new BooleanLatch();
+        assertFalse(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+    }
+
+    /**
+     * acquireSharedInterruptibly returns after release, but not before
+     */
+    public void testAcquireSharedInterruptibly() {
+        final BooleanLatch l = new BooleanLatch();
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+                assertTrue(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+                assertTrue(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        assertThreadStaysAlive(t);
+        assertHasSharedQueuedThreads(l, t);
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        awaitTermination(t);
+    }
+
+    /**
+     * tryAcquireSharedNanos returns after release, but not before
+     */
+    public void testTryAcquireSharedNanos() {
+        final BooleanLatch l = new BooleanLatch();
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+                assertTrue(l.tryAcquireSharedNanos(0, nanos));
+                assertTrue(l.isSignalled());
+                assertTrue(l.tryAcquireSharedNanos(0, nanos));
+                assertTrue(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        assertThreadStaysAlive(t);
+        assertTrue(l.releaseShared(0));
+        assertTrue(l.isSignalled());
+        awaitTermination(t);
+    }
+
+    /**
+     * acquireSharedInterruptibly is interruptible
+     */
+    public void testAcquireSharedInterruptibly_Interruptible() {
+        final BooleanLatch l = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                l.acquireSharedInterruptibly(0);
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        t.interrupt();
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * tryAcquireSharedNanos is interruptible
+     */
+    public void testTryAcquireSharedNanos_Interruptible() {
+        final BooleanLatch l = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+                l.tryAcquireSharedNanos(0, nanos);
+            }});
+
+        waitForQueuedThread(l, t);
+        assertFalse(l.isSignalled());
+        t.interrupt();
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * tryAcquireSharedNanos times out if not released before timeout
+     */
+    public void testTryAcquireSharedNanos_Timeout() {
+        final BooleanLatch l = new BooleanLatch();
+        final BooleanLatch observedQueued = new BooleanLatch();
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(l.isSignalled());
+                for (long millis = timeoutMillis();
+                     !observedQueued.isSignalled();
+                     millis *= 2) {
+                    long nanos = MILLISECONDS.toNanos(millis);
+                    long startTime = System.nanoTime();
+                    assertFalse(l.tryAcquireSharedNanos(0, nanos));
+                    assertTrue(millisElapsedSince(startTime) >= millis);
+                }
+                assertFalse(l.isSignalled());
+            }});
+
+        waitForQueuedThread(l, t);
+        observedQueued.releaseShared(0);
+        assertFalse(l.isSignalled());
+        awaitTermination(t);
+        assertFalse(l.isSignalled());
+    }
+
+    /**
+     * awaitNanos/timed await with 0 wait times out immediately
+     */
+    public void testAwait_Zero() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertTrue(c.awaitNanos(0L) <= 0);
+        assertFalse(c.await(0L, NANOSECONDS));
+        sync.release();
+    }
+
+    /**
+     * awaitNanos/timed await with maximum negative wait times does not underflow
+     */
+    public void testAwait_NegativeInfinity() throws InterruptedException {
+        final Mutex sync = new Mutex();
+        final ConditionObject c = sync.newCondition();
+        sync.acquire();
+        assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
+        assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
+        sync.release();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,955 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+
+import junit.framework.Test;
+
+public class ArrayBlockingQueueTest extends JSR166TestCase {
+
+    public static class Fair extends BlockingQueueTest {
+        protected BlockingQueue emptyCollection() {
+            return new ArrayBlockingQueue(SIZE, true);
+        }
+    }
+
+    public static class NonFair extends BlockingQueueTest {
+        protected BlockingQueue emptyCollection() {
+            return new ArrayBlockingQueue(SIZE, false);
+        }
+    }
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        return newTestSuite(ArrayBlockingQueueTest.class,
+                            new Fair().testSuite(),
+                            new NonFair().testSuite());
+    }
+
+    /**
+     * Returns a new queue of given size containing consecutive
+     * Integers 0 ... n.
+     */
+    private ArrayBlockingQueue<Integer> populatedQueue(int n) {
+        ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(n);
+        assertTrue(q.isEmpty());
+        for (int i = 0; i < n; i++)
+            assertTrue(q.offer(new Integer(i)));
+        assertFalse(q.isEmpty());
+        assertEquals(0, q.remainingCapacity());
+        assertEquals(n, q.size());
+        return q;
+    }
+
+    /**
+     * A new queue has the indicated capacity
+     */
+    public void testConstructor1() {
+        assertEquals(SIZE, new ArrayBlockingQueue(SIZE).remainingCapacity());
+    }
+
+    /**
+     * Constructor throws IAE if capacity argument nonpositive
+     */
+    public void testConstructor2() {
+        try {
+            new ArrayBlockingQueue(0);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * Initializing from null Collection throws NPE
+     */
+    public void testConstructor3() {
+        try {
+            new ArrayBlockingQueue(1, true, null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Initializing from Collection of null elements throws NPE
+     */
+    public void testConstructor4() {
+        Collection<Integer> elements = Arrays.asList(new Integer[SIZE]);
+        try {
+            new ArrayBlockingQueue(SIZE, false, elements);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Initializing from Collection with some null elements throws NPE
+     */
+    public void testConstructor5() {
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE - 1; ++i)
+            ints[i] = i;
+        Collection<Integer> elements = Arrays.asList(ints);
+        try {
+            new ArrayBlockingQueue(SIZE, false, elements);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Initializing from too large collection throws IAE
+     */
+    public void testConstructor6() {
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = i;
+        Collection<Integer> elements = Arrays.asList(ints);
+        try {
+            new ArrayBlockingQueue(SIZE - 1, false, elements);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * Queue contains all elements of collection used to initialize
+     */
+    public void testConstructor7() {
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = i;
+        Collection<Integer> elements = Arrays.asList(ints);
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, true, elements);
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(ints[i], q.poll());
+    }
+
+    /**
+     * Queue transitions from empty to full when elements added
+     */
+    public void testEmptyFull() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+        assertTrue(q.isEmpty());
+        assertEquals(2, q.remainingCapacity());
+        q.add(one);
+        assertFalse(q.isEmpty());
+        q.add(two);
+        assertFalse(q.isEmpty());
+        assertEquals(0, q.remainingCapacity());
+        assertFalse(q.offer(three));
+    }
+
+    /**
+     * remainingCapacity decreases on add, increases on remove
+     */
+    public void testRemainingCapacity() {
+        BlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.remainingCapacity());
+            assertEquals(SIZE, q.size() + q.remainingCapacity());
+            assertEquals(i, q.remove());
+        }
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(SIZE - i, q.remainingCapacity());
+            assertEquals(SIZE, q.size() + q.remainingCapacity());
+            assertTrue(q.add(i));
+        }
+    }
+
+    /**
+     * Offer succeeds if not full; fails if full
+     */
+    public void testOffer() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(1);
+        assertTrue(q.offer(zero));
+        assertFalse(q.offer(one));
+    }
+
+    /**
+     * add succeeds if not full; throws ISE if full
+     */
+    public void testAdd() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(q.add(new Integer(i)));
+        }
+        assertEquals(0, q.remainingCapacity());
+        try {
+            q.add(new Integer(SIZE));
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * addAll(this) throws IAE
+     */
+    public void testAddAllSelf() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        try {
+            q.addAll(q);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * addAll of a collection with any null elements throws NPE after
+     * possibly adding some elements
+     */
+    public void testAddAll3() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE - 1; ++i)
+            ints[i] = new Integer(i);
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll throws ISE if not enough room
+     */
+    public void testAddAll4() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(1);
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = new Integer(i);
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * Queue contains all elements, in traversal order, of successful addAll
+     */
+    public void testAddAll5() {
+        Integer[] empty = new Integer[0];
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = new Integer(i);
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        assertFalse(q.addAll(Arrays.asList(empty)));
+        assertTrue(q.addAll(Arrays.asList(ints)));
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(ints[i], q.poll());
+    }
+
+    /**
+     * all elements successfully put are contained
+     */
+    public void testPut() throws InterruptedException {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            Integer x = new Integer(i);
+            q.put(x);
+            assertTrue(q.contains(x));
+        }
+        assertEquals(0, q.remainingCapacity());
+    }
+
+    /**
+     * put blocks interruptibly if full
+     */
+    public void testBlockingPut() throws InterruptedException {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                for (int i = 0; i < SIZE; ++i)
+                    q.put(i);
+                assertEquals(SIZE, q.size());
+                assertEquals(0, q.remainingCapacity());
+
+                Thread.currentThread().interrupt();
+                try {
+                    q.put(99);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+
+                pleaseInterrupt.countDown();
+                try {
+                    q.put(99);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+            }});
+
+        await(pleaseInterrupt);
+        assertThreadStaysAlive(t);
+        t.interrupt();
+        awaitTermination(t);
+        assertEquals(SIZE, q.size());
+        assertEquals(0, q.remainingCapacity());
+    }
+
+    /**
+     * put blocks interruptibly waiting for take when full
+     */
+    public void testPutWithTake() throws InterruptedException {
+        final int capacity = 2;
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(capacity);
+        final CountDownLatch pleaseTake = new CountDownLatch(1);
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                for (int i = 0; i < capacity; i++)
+                    q.put(i);
+                pleaseTake.countDown();
+                q.put(86);
+
+                pleaseInterrupt.countDown();
+                try {
+                    q.put(99);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+            }});
+
+        await(pleaseTake);
+        assertEquals(0, q.remainingCapacity());
+        assertEquals(0, q.take());
+
+        await(pleaseInterrupt);
+        assertThreadStaysAlive(t);
+        t.interrupt();
+        awaitTermination(t);
+        assertEquals(0, q.remainingCapacity());
+    }
+
+    /**
+     * timed offer times out if full and elements not taken
+     */
+    public void testTimedOffer() throws InterruptedException {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                q.put(new Object());
+                q.put(new Object());
+                long startTime = System.nanoTime();
+                assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+                pleaseInterrupt.countDown();
+                try {
+                    q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+            }});
+
+        await(pleaseInterrupt);
+        assertThreadStaysAlive(t);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * take retrieves elements in FIFO order
+     */
+    public void testTake() throws InterruptedException {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.take());
+        }
+    }
+
+    /**
+     * Take removes existing elements until empty, then blocks interruptibly
+     */
+    public void testBlockingTake() throws InterruptedException {
+        final ArrayBlockingQueue q = populatedQueue(SIZE);
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                for (int i = 0; i < SIZE; ++i) {
+                    assertEquals(i, q.take());
+                }
+
+                Thread.currentThread().interrupt();
+                try {
+                    q.take();
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+
+                pleaseInterrupt.countDown();
+                try {
+                    q.take();
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+            }});
+
+        await(pleaseInterrupt);
+        assertThreadStaysAlive(t);
+        t.interrupt();
+        awaitTermination(t);
+    }
+
+    /**
+     * poll succeeds unless empty
+     */
+    public void testPoll() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.poll());
+        }
+        assertNull(q.poll());
+    }
+
+    /**
+     * timed poll with zero timeout succeeds when non-empty, else times out
+     */
+    public void testTimedPoll0() throws InterruptedException {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.poll(0, MILLISECONDS));
+        }
+        assertNull(q.poll(0, MILLISECONDS));
+        checkEmpty(q);
+    }
+
+    /**
+     * timed poll with nonzero timeout succeeds when non-empty, else times out
+     */
+    public void testTimedPoll() throws InterruptedException {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            long startTime = System.nanoTime();
+            assertEquals(i, q.poll(LONG_DELAY_MS, MILLISECONDS));
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+        long startTime = System.nanoTime();
+        assertNull(q.poll(timeoutMillis(), MILLISECONDS));
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        checkEmpty(q);
+    }
+
+    /**
+     * Interrupted timed poll throws InterruptedException instead of
+     * returning timeout status
+     */
+    public void testInterruptedTimedPoll() throws InterruptedException {
+        final BlockingQueue<Integer> q = populatedQueue(SIZE);
+        final CountDownLatch aboutToWait = new CountDownLatch(1);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                long startTime = System.nanoTime();
+                for (int i = 0; i < SIZE; ++i) {
+                    assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                }
+                aboutToWait.countDown();
+                try {
+                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    shouldThrow();
+                } catch (InterruptedException success) {
+                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                }
+            }});
+
+        await(aboutToWait);
+        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        t.interrupt();
+        awaitTermination(t);
+        checkEmpty(q);
+    }
+
+    /**
+     * peek returns next element, or null if empty
+     */
+    public void testPeek() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.peek());
+            assertEquals(i, q.poll());
+            assertTrue(q.peek() == null ||
+                       !q.peek().equals(i));
+        }
+        assertNull(q.peek());
+    }
+
+    /**
+     * element returns next element, or throws NSEE if empty
+     */
+    public void testElement() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.element());
+            assertEquals(i, q.poll());
+        }
+        try {
+            q.element();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * remove removes next element, or throws NSEE if empty
+     */
+    public void testRemove() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.remove());
+        }
+        try {
+            q.remove();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * contains(x) reports true when elements added but not yet removed
+     */
+    public void testContains() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(q.contains(new Integer(i)));
+            assertEquals(i, q.poll());
+            assertFalse(q.contains(new Integer(i)));
+        }
+    }
+
+    /**
+     * clear removes all elements
+     */
+    public void testClear() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        q.clear();
+        assertTrue(q.isEmpty());
+        assertEquals(0, q.size());
+        assertEquals(SIZE, q.remainingCapacity());
+        q.add(one);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(one));
+        q.clear();
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * containsAll(c) is true when c contains a subset of elements
+     */
+    public void testContainsAll() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        ArrayBlockingQueue p = new ArrayBlockingQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(q.containsAll(p));
+            assertFalse(p.containsAll(q));
+            p.add(new Integer(i));
+        }
+        assertTrue(p.containsAll(q));
+    }
+
+    /**
+     * retainAll(c) retains only those elements of c and reports true if changed
+     */
+    public void testRetainAll() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        ArrayBlockingQueue p = populatedQueue(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            boolean changed = q.retainAll(p);
+            if (i == 0)
+                assertFalse(changed);
+            else
+                assertTrue(changed);
+
+            assertTrue(q.containsAll(p));
+            assertEquals(SIZE - i, q.size());
+            p.remove();
+        }
+    }
+
+    /**
+     * removeAll(c) removes only those elements of c and reports true if changed
+     */
+    public void testRemoveAll() {
+        for (int i = 1; i < SIZE; ++i) {
+            ArrayBlockingQueue q = populatedQueue(SIZE);
+            ArrayBlockingQueue p = populatedQueue(i);
+            assertTrue(q.removeAll(p));
+            assertEquals(SIZE - i, q.size());
+            for (int j = 0; j < i; ++j) {
+                Integer x = (Integer)(p.remove());
+                assertFalse(q.contains(x));
+            }
+        }
+    }
+
+    void checkToArray(ArrayBlockingQueue q) {
+        int size = q.size();
+        Object[] o = q.toArray();
+        assertEquals(size, o.length);
+        Iterator it = q.iterator();
+        for (int i = 0; i < size; i++) {
+            Integer x = (Integer) it.next();
+            assertEquals((Integer)o[0] + i, (int) x);
+            assertSame(o[i], x);
+        }
+    }
+
+    /**
+     * toArray() contains all elements in FIFO order
+     */
+    public void testToArray() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            q.add(i);
+        }
+        // Provoke wraparound
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            assertEquals(i, q.poll());
+            checkToArray(q);
+            q.add(SIZE + i);
+        }
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            assertEquals(SIZE + i, q.poll());
+        }
+    }
+
+    void checkToArray2(ArrayBlockingQueue q) {
+        int size = q.size();
+        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
+        Integer[] a2 = new Integer[size];
+        Integer[] a3 = new Integer[size + 2];
+        if (size > 0) Arrays.fill(a1, 42);
+        Arrays.fill(a2, 42);
+        Arrays.fill(a3, 42);
+        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
+        Integer[] b2 = (Integer[]) q.toArray(a2);
+        Integer[] b3 = (Integer[]) q.toArray(a3);
+        assertSame(a2, b2);
+        assertSame(a3, b3);
+        Iterator it = q.iterator();
+        for (int i = 0; i < size; i++) {
+            Integer x = (Integer) it.next();
+            assertSame(b1[i], x);
+            assertEquals(b1[0] + i, (int) x);
+            assertSame(b2[i], x);
+            assertSame(b3[i], x);
+        }
+        assertNull(a3[size]);
+        assertEquals(42, (int) a3[size + 1]);
+        if (size > 0) {
+            assertNotSame(a1, b1);
+            assertEquals(size, b1.length);
+            for (int i = 0; i < a1.length; i++) {
+                assertEquals(42, (int) a1[i]);
+            }
+        }
+    }
+
+    /**
+     * toArray(a) contains all elements in FIFO order
+     */
+    public void testToArray2() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            q.add(i);
+        }
+        // Provoke wraparound
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            assertEquals(i, q.poll());
+            checkToArray2(q);
+            q.add(SIZE + i);
+        }
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            assertEquals(SIZE + i, q.poll());
+        }
+    }
+
+    /**
+     * toArray(incompatible array type) throws ArrayStoreException
+     */
+    public void testToArray1_BadArg() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        try {
+            q.toArray(new String[10]);
+            shouldThrow();
+        } catch (ArrayStoreException success) {}
+    }
+
+    /**
+     * iterator iterates through all elements
+     */
+    public void testIterator() throws InterruptedException {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        Iterator it = q.iterator();
+        int i;
+        for (i = 0; it.hasNext(); i++)
+            assertTrue(q.contains(it.next()));
+        assertEquals(i, SIZE);
+        assertIteratorExhausted(it);
+
+        it = q.iterator();
+        for (i = 0; it.hasNext(); i++)
+            assertEquals(it.next(), q.take());
+        assertEquals(i, SIZE);
+        assertIteratorExhausted(it);
+    }
+
+    /**
+     * iterator of empty collection has no elements
+     */
+    public void testEmptyIterator() {
+        assertIteratorExhausted(new ArrayBlockingQueue(SIZE).iterator());
+    }
+
+    /**
+     * iterator.remove removes current element
+     */
+    public void testIteratorRemove() {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+        q.add(two);
+        q.add(one);
+        q.add(three);
+
+        Iterator it = q.iterator();
+        it.next();
+        it.remove();
+
+        it = q.iterator();
+        assertSame(it.next(), one);
+        assertSame(it.next(), three);
+        assertFalse(it.hasNext());
+    }
+
+    /**
+     * iterator ordering is FIFO
+     */
+    public void testIteratorOrdering() {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+        q.add(one);
+        q.add(two);
+        q.add(three);
+
+        assertEquals("queue should be full", 0, q.remainingCapacity());
+
+        int k = 0;
+        for (Iterator it = q.iterator(); it.hasNext();) {
+            assertEquals(++k, it.next());
+        }
+        assertEquals(3, k);
+    }
+
+    /**
+     * Modifications do not cause iterators to fail
+     */
+    public void testWeaklyConsistentIteration() {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+        q.add(one);
+        q.add(two);
+        q.add(three);
+        for (Iterator it = q.iterator(); it.hasNext();) {
+            q.remove();
+            it.next();
+        }
+        assertEquals(0, q.size());
+    }
+
+    /**
+     * toString contains toStrings of elements
+     */
+    public void testToString() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        String s = q.toString();
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(s.contains(String.valueOf(i)));
+        }
+    }
+
+    /**
+     * offer transfers elements across Executor tasks
+     */
+    public void testOfferInExecutor() {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+        q.add(one);
+        q.add(two);
+        final CheckedBarrier threadsStarted = new CheckedBarrier(2);
+        final ExecutorService executor = Executors.newFixedThreadPool(2);
+        try (PoolCleaner cleaner = cleaner(executor)) {
+            executor.execute(new CheckedRunnable() {
+                public void realRun() throws InterruptedException {
+                    assertFalse(q.offer(three));
+                    threadsStarted.await();
+                    assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
+                    assertEquals(0, q.remainingCapacity());
+                }});
+
+            executor.execute(new CheckedRunnable() {
+                public void realRun() throws InterruptedException {
+                    threadsStarted.await();
+                    assertEquals(0, q.remainingCapacity());
+                    assertSame(one, q.take());
+                }});
+        }
+    }
+
+    /**
+     * timed poll retrieves elements across Executor threads
+     */
+    public void testPollInExecutor() {
+        final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+        final CheckedBarrier threadsStarted = new CheckedBarrier(2);
+        final ExecutorService executor = Executors.newFixedThreadPool(2);
+        try (PoolCleaner cleaner = cleaner(executor)) {
+            executor.execute(new CheckedRunnable() {
+                public void realRun() throws InterruptedException {
+                    assertNull(q.poll());
+                    threadsStarted.await();
+                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    checkEmpty(q);
+                }});
+
+            executor.execute(new CheckedRunnable() {
+                public void realRun() throws InterruptedException {
+                    threadsStarted.await();
+                    q.put(one);
+                }});
+        }
+    }
+
+    /**
+     * A deserialized serialized queue has same elements in same order
+     */
+    public void testSerialization() throws Exception {
+        Queue x = populatedQueue(SIZE);
+        Queue y = serialClone(x);
+
+        assertNotSame(x, y);
+        assertEquals(x.size(), y.size());
+        assertEquals(x.toString(), y.toString());
+        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
+        while (!x.isEmpty()) {
+            assertFalse(y.isEmpty());
+            assertEquals(x.remove(), y.remove());
+        }
+        assertTrue(y.isEmpty());
+    }
+
+    /**
+     * drainTo(c) empties queue into another collection c
+     */
+    public void testDrainTo() {
+        ArrayBlockingQueue q = populatedQueue(SIZE);
+        ArrayList l = new ArrayList();
+        q.drainTo(l);
+        assertEquals(0, q.size());
+        assertEquals(SIZE, l.size());
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(l.get(i), new Integer(i));
+        q.add(zero);
+        q.add(one);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(zero));
+        assertTrue(q.contains(one));
+        l.clear();
+        q.drainTo(l);
+        assertEquals(0, q.size());
+        assertEquals(2, l.size());
+        for (int i = 0; i < 2; ++i)
+            assertEquals(l.get(i), new Integer(i));
+    }
+
+    /**
+     * drainTo empties full queue, unblocking a waiting put.
+     */
+    public void testDrainToWithActivePut() throws InterruptedException {
+        final ArrayBlockingQueue q = populatedQueue(SIZE);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                q.put(new Integer(SIZE + 1));
+            }});
+
+        t.start();
+        ArrayList l = new ArrayList();
+        q.drainTo(l);
+        assertTrue(l.size() >= SIZE);
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(l.get(i), new Integer(i));
+        t.join();
+        assertTrue(q.size() + l.size() >= SIZE);
+    }
+
+    /**
+     * drainTo(c, n) empties first min(n, size) elements of queue into c
+     */
+    public void testDrainToN() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE * 2);
+        for (int i = 0; i < SIZE + 2; ++i) {
+            for (int j = 0; j < SIZE; j++)
+                assertTrue(q.offer(new Integer(j)));
+            ArrayList l = new ArrayList();
+            q.drainTo(l, i);
+            int k = (i < SIZE) ? i : SIZE;
+            assertEquals(k, l.size());
+            assertEquals(SIZE - k, q.size());
+            for (int j = 0; j < k; ++j)
+                assertEquals(l.get(j), new Integer(j));
+            do {} while (q.poll() != null);
+        }
+    }
+
+    /**
+     * remove(null), contains(null) always return false
+     */
+    public void testNeverContainsNull() {
+        Collection<?>[] qs = {
+            new ArrayBlockingQueue<Object>(10),
+            populatedQueue(2),
+        };
+
+        for (Collection<?> q : qs) {
+            assertFalse(q.contains(null));
+            assertFalse(q.remove(null));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/ArrayDequeTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,945 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Random;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class ArrayDequeTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        return new TestSuite(ArrayDequeTest.class);
+    }
+
+    /**
+     * Returns a new deque of given size containing consecutive
+     * Integers 0 ... n.
+     */
+    private ArrayDeque<Integer> populatedDeque(int n) {
+        ArrayDeque<Integer> q = new ArrayDeque<Integer>();
+        assertTrue(q.isEmpty());
+        for (int i = 0; i < n; ++i)
+            assertTrue(q.offerLast(new Integer(i)));
+        assertFalse(q.isEmpty());
+        assertEquals(n, q.size());
+        return q;
+    }
+
+    /**
+     * new deque is empty
+     */
+    public void testConstructor1() {
+        assertEquals(0, new ArrayDeque().size());
+    }
+
+    /**
+     * Initializing from null Collection throws NPE
+     */
+    public void testConstructor3() {
+        try {
+            new ArrayDeque((Collection)null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Initializing from Collection of null elements throws NPE
+     */
+    public void testConstructor4() {
+        try {
+            new ArrayDeque(Arrays.asList(new Integer[SIZE]));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Initializing from Collection with some null elements throws NPE
+     */
+    public void testConstructor5() {
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE - 1; ++i)
+            ints[i] = new Integer(i);
+        try {
+            new ArrayDeque(Arrays.asList(ints));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Deque contains all elements of collection used to initialize
+     */
+    public void testConstructor6() {
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = new Integer(i);
+        ArrayDeque q = new ArrayDeque(Arrays.asList(ints));
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(ints[i], q.pollFirst());
+    }
+
+    /**
+     * isEmpty is true before add, false after
+     */
+    public void testEmpty() {
+        ArrayDeque q = new ArrayDeque();
+        assertTrue(q.isEmpty());
+        q.add(new Integer(1));
+        assertFalse(q.isEmpty());
+        q.add(new Integer(2));
+        q.removeFirst();
+        q.removeFirst();
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * size changes when elements added and removed
+     */
+    public void testSize() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(SIZE - i, q.size());
+            q.removeFirst();
+        }
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.size());
+            q.add(new Integer(i));
+        }
+    }
+
+    /**
+     * push(null) throws NPE
+     */
+    public void testPushNull() {
+        ArrayDeque q = new ArrayDeque(1);
+        try {
+            q.push(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * peekFirst() returns element inserted with push
+     */
+    public void testPush() {
+        ArrayDeque q = populatedDeque(3);
+        q.pollLast();
+        q.push(four);
+        assertSame(four, q.peekFirst());
+    }
+
+    /**
+     * pop() removes next element, or throws NSEE if empty
+     */
+    public void testPop() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.pop());
+        }
+        try {
+            q.pop();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * offer(null) throws NPE
+     */
+    public void testOfferNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.offer(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * offerFirst(null) throws NPE
+     */
+    public void testOfferFirstNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.offerFirst(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * offerLast(null) throws NPE
+     */
+    public void testOfferLastNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.offerLast(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * offer(x) succeeds
+     */
+    public void testOffer() {
+        ArrayDeque q = new ArrayDeque();
+        assertTrue(q.offer(zero));
+        assertTrue(q.offer(one));
+        assertSame(zero, q.peekFirst());
+        assertSame(one, q.peekLast());
+    }
+
+    /**
+     * offerFirst(x) succeeds
+     */
+    public void testOfferFirst() {
+        ArrayDeque q = new ArrayDeque();
+        assertTrue(q.offerFirst(zero));
+        assertTrue(q.offerFirst(one));
+        assertSame(one, q.peekFirst());
+        assertSame(zero, q.peekLast());
+    }
+
+    /**
+     * offerLast(x) succeeds
+     */
+    public void testOfferLast() {
+        ArrayDeque q = new ArrayDeque();
+        assertTrue(q.offerLast(zero));
+        assertTrue(q.offerLast(one));
+        assertSame(zero, q.peekFirst());
+        assertSame(one, q.peekLast());
+    }
+
+    /**
+     * add(null) throws NPE
+     */
+    public void testAddNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.add(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addFirst(null) throws NPE
+     */
+    public void testAddFirstNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.addFirst(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addLast(null) throws NPE
+     */
+    public void testAddLastNull() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.addLast(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * add(x) succeeds
+     */
+    public void testAdd() {
+        ArrayDeque q = new ArrayDeque();
+        assertTrue(q.add(zero));
+        assertTrue(q.add(one));
+        assertSame(zero, q.peekFirst());
+        assertSame(one, q.peekLast());
+    }
+
+    /**
+     * addFirst(x) succeeds
+     */
+    public void testAddFirst() {
+        ArrayDeque q = new ArrayDeque();
+        q.addFirst(zero);
+        q.addFirst(one);
+        assertSame(one, q.peekFirst());
+        assertSame(zero, q.peekLast());
+    }
+
+    /**
+     * addLast(x) succeeds
+     */
+    public void testAddLast() {
+        ArrayDeque q = new ArrayDeque();
+        q.addLast(zero);
+        q.addLast(one);
+        assertSame(zero, q.peekFirst());
+        assertSame(one, q.peekLast());
+    }
+
+    /**
+     * addAll(null) throws NPE
+     */
+    public void testAddAll1() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.addAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll of a collection with null elements throws NPE
+     */
+    public void testAddAll2() {
+        ArrayDeque q = new ArrayDeque();
+        try {
+            q.addAll(Arrays.asList(new Integer[SIZE]));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * addAll of a collection with any null elements throws NPE after
+     * possibly adding some elements
+     */
+    public void testAddAll3() {
+        ArrayDeque q = new ArrayDeque();
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE - 1; ++i)
+            ints[i] = new Integer(i);
+        try {
+            q.addAll(Arrays.asList(ints));
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * Deque contains all elements, in traversal order, of successful addAll
+     */
+    public void testAddAll5() {
+        Integer[] empty = new Integer[0];
+        Integer[] ints = new Integer[SIZE];
+        for (int i = 0; i < SIZE; ++i)
+            ints[i] = new Integer(i);
+        ArrayDeque q = new ArrayDeque();
+        assertFalse(q.addAll(Arrays.asList(empty)));
+        assertTrue(q.addAll(Arrays.asList(ints)));
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(ints[i], q.pollFirst());
+    }
+
+    /**
+     * pollFirst() succeeds unless empty
+     */
+    public void testPollFirst() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.pollFirst());
+        }
+        assertNull(q.pollFirst());
+    }
+
+    /**
+     * pollLast() succeeds unless empty
+     */
+    public void testPollLast() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = SIZE - 1; i >= 0; --i) {
+            assertEquals(i, q.pollLast());
+        }
+        assertNull(q.pollLast());
+    }
+
+    /**
+     * poll() succeeds unless empty
+     */
+    public void testPoll() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.poll());
+        }
+        assertNull(q.poll());
+    }
+
+    /**
+     * remove() removes next element, or throws NSEE if empty
+     */
+    public void testRemove() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.remove());
+        }
+        try {
+            q.remove();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * remove(x) removes x and returns true if present
+     */
+    public void testRemoveElement() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 1; i < SIZE; i += 2) {
+            assertTrue(q.contains(i));
+            assertTrue(q.remove(i));
+            assertFalse(q.contains(i));
+            assertTrue(q.contains(i - 1));
+        }
+        for (int i = 0; i < SIZE; i += 2) {
+            assertTrue(q.contains(i));
+            assertTrue(q.remove(i));
+            assertFalse(q.contains(i));
+            assertFalse(q.remove(i + 1));
+            assertFalse(q.contains(i + 1));
+        }
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * peekFirst() returns next element, or null if empty
+     */
+    public void testPeekFirst() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.peekFirst());
+            assertEquals(i, q.pollFirst());
+            assertTrue(q.peekFirst() == null ||
+                       !q.peekFirst().equals(i));
+        }
+        assertNull(q.peekFirst());
+    }
+
+    /**
+     * peek() returns next element, or null if empty
+     */
+    public void testPeek() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.peek());
+            assertEquals(i, q.poll());
+            assertTrue(q.peek() == null ||
+                       !q.peek().equals(i));
+        }
+        assertNull(q.peek());
+    }
+
+    /**
+     * peekLast() returns next element, or null if empty
+     */
+    public void testPeekLast() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = SIZE - 1; i >= 0; --i) {
+            assertEquals(i, q.peekLast());
+            assertEquals(i, q.pollLast());
+            assertTrue(q.peekLast() == null ||
+                       !q.peekLast().equals(i));
+        }
+        assertNull(q.peekLast());
+    }
+
+    /**
+     * element() returns first element, or throws NSEE if empty
+     */
+    public void testElement() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.element());
+            assertEquals(i, q.poll());
+        }
+        try {
+            q.element();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * getFirst() returns first element, or throws NSEE if empty
+     */
+    public void testFirstElement() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.getFirst());
+            assertEquals(i, q.pollFirst());
+        }
+        try {
+            q.getFirst();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * getLast() returns last element, or throws NSEE if empty
+     */
+    public void testLastElement() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = SIZE - 1; i >= 0; --i) {
+            assertEquals(i, q.getLast());
+            assertEquals(i, q.pollLast());
+        }
+        try {
+            q.getLast();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+        assertNull(q.peekLast());
+    }
+
+    /**
+     * removeFirst() removes first element, or throws NSEE if empty
+     */
+    public void testRemoveFirst() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertEquals(i, q.removeFirst());
+        }
+        try {
+            q.removeFirst();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+        assertNull(q.peekFirst());
+    }
+
+    /**
+     * removeLast() removes last element, or throws NSEE if empty
+     */
+    public void testRemoveLast() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = SIZE - 1; i >= 0; --i) {
+            assertEquals(i, q.removeLast());
+        }
+        try {
+            q.removeLast();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+        assertNull(q.peekLast());
+    }
+
+    /**
+     * removeFirstOccurrence(x) removes x and returns true if present
+     */
+    public void testRemoveFirstOccurrence() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 1; i < SIZE; i += 2) {
+            assertTrue(q.removeFirstOccurrence(new Integer(i)));
+        }
+        for (int i = 0; i < SIZE; i += 2) {
+            assertTrue(q.removeFirstOccurrence(new Integer(i)));
+            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+        }
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * removeLastOccurrence(x) removes x and returns true if present
+     */
+    public void testRemoveLastOccurrence() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 1; i < SIZE; i += 2) {
+            assertTrue(q.removeLastOccurrence(new Integer(i)));
+        }
+        for (int i = 0; i < SIZE; i += 2) {
+            assertTrue(q.removeLastOccurrence(new Integer(i)));
+            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+        }
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * contains(x) reports true when elements added but not yet removed
+     */
+    public void testContains() {
+        ArrayDeque q = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(q.contains(new Integer(i)));
+            assertEquals(i, q.pollFirst());
+            assertFalse(q.contains(new Integer(i)));
+        }
+    }
+
+    /**
+     * clear removes all elements
+     */
+    public void testClear() {
+        ArrayDeque q = populatedDeque(SIZE);
+        q.clear();
+        assertTrue(q.isEmpty());
+        assertEquals(0, q.size());
+        assertTrue(q.add(new Integer(1)));
+        assertFalse(q.isEmpty());
+        q.clear();
+        assertTrue(q.isEmpty());
+    }
+
+    /**
+     * containsAll(c) is true when c contains a subset of elements
+     */
+    public void testContainsAll() {
+        ArrayDeque q = populatedDeque(SIZE);
+        ArrayDeque p = new ArrayDeque();
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(q.containsAll(p));
+            assertFalse(p.containsAll(q));
+            assertTrue(p.add(new Integer(i)));
+        }
+        assertTrue(p.containsAll(q));
+    }
+
+    /**
+     * retainAll(c) retains only those elements of c and reports true if changed
+     */
+    public void testRetainAll() {
+        ArrayDeque q = populatedDeque(SIZE);
+        ArrayDeque p = populatedDeque(SIZE);
+        for (int i = 0; i < SIZE; ++i) {
+            boolean changed = q.retainAll(p);
+            assertEquals(changed, (i > 0));
+            assertTrue(q.containsAll(p));
+            assertEquals(SIZE - i, q.size());
+            p.removeFirst();
+        }
+    }
+
+    /**
+     * removeAll(c) removes only those elements of c and reports true if changed
+     */
+    public void testRemoveAll() {
+        for (int i = 1; i < SIZE; ++i) {
+            ArrayDeque q = populatedDeque(SIZE);
+            ArrayDeque p = populatedDeque(i);
+            assertTrue(q.removeAll(p));
+            assertEquals(SIZE - i, q.size());
+            for (int j = 0; j < i; ++j) {
+                assertFalse(q.contains(p.removeFirst()));
+            }
+        }
+    }
+
+    void checkToArray(ArrayDeque q) {
+        int size = q.size();
+        Object[] o = q.toArray();
+        assertEquals(size, o.length);
+        Iterator it = q.iterator();
+        for (int i = 0; i < size; i++) {
+            Integer x = (Integer) it.next();
+            assertEquals((Integer)o[0] + i, (int) x);
+            assertSame(o[i], x);
+        }
+    }
+
+    /**
+     * toArray() contains all elements in FIFO order
+     */
+    public void testToArray() {
+        ArrayDeque q = new ArrayDeque();
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            q.addLast(i);
+        }
+        // Provoke wraparound
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            assertEquals(i, q.poll());
+            q.addLast(SIZE + i);
+        }
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray(q);
+            assertEquals(SIZE + i, q.poll());
+        }
+    }
+
+    void checkToArray2(ArrayDeque q) {
+        int size = q.size();
+        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
+        Integer[] a2 = new Integer[size];
+        Integer[] a3 = new Integer[size + 2];
+        if (size > 0) Arrays.fill(a1, 42);
+        Arrays.fill(a2, 42);
+        Arrays.fill(a3, 42);
+        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
+        Integer[] b2 = (Integer[]) q.toArray(a2);
+        Integer[] b3 = (Integer[]) q.toArray(a3);
+        assertSame(a2, b2);
+        assertSame(a3, b3);
+        Iterator it = q.iterator();
+        for (int i = 0; i < size; i++) {
+            Integer x = (Integer) it.next();
+            assertSame(b1[i], x);
+            assertEquals(b1[0] + i, (int) x);
+            assertSame(b2[i], x);
+            assertSame(b3[i], x);
+        }
+        assertNull(a3[size]);
+        assertEquals(42, (int) a3[size + 1]);
+        if (size > 0) {
+            assertNotSame(a1, b1);
+            assertEquals(size, b1.length);
+            for (int i = 0; i < a1.length; i++) {
+                assertEquals(42, (int) a1[i]);
+            }
+        }
+    }
+
+    /**
+     * toArray(a) contains all elements in FIFO order
+     */
+    public void testToArray2() {
+        ArrayDeque q = new ArrayDeque();
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            q.addLast(i);
+        }
+        // Provoke wraparound
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            assertEquals(i, q.poll());
+            q.addLast(SIZE + i);
+        }
+        for (int i = 0; i < SIZE; i++) {
+            checkToArray2(q);
+            assertEquals(SIZE + i, q.poll());
+        }
+    }
+
+    /**
+     * toArray(null) throws NullPointerException
+     */
+    public void testToArray_NullArg() {
+        ArrayDeque l = new ArrayDeque();
+        l.add(new Object());
+        try {
+            l.toArray(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * toArray(incompatible array type) throws ArrayStoreException
+     */
+    public void testToArray1_BadArg() {
+        ArrayDeque l = new ArrayDeque();
+        l.add(new Integer(5));
+        try {
+            l.toArray(new String[10]);
+            shouldThrow();
+        } catch (ArrayStoreException success) {}
+    }
+
+    /**
+     * Iterator iterates through all elements
+     */
+    public void testIterator() {
+        ArrayDeque q = populatedDeque(SIZE);
+        Iterator it = q.iterator();
+        int i;
+        for (i = 0; it.hasNext(); i++)
+            assertTrue(q.contains(it.next()));
+        assertEquals(i, SIZE);
+        assertIteratorExhausted(it);
+    }
+
+    /**
+     * iterator of empty collection has no elements
+     */
+    public void testEmptyIterator() {
+        Deque c = new ArrayDeque();
+        assertIteratorExhausted(c.iterator());
+        assertIteratorExhausted(c.descendingIterator());
+    }
+
+    /**
+     * Iterator ordering is FIFO
+     */
+    public void testIteratorOrdering() {
+        final ArrayDeque q = new ArrayDeque();
+        q.add(one);
+        q.add(two);
+        q.add(three);
+        int k = 0;
+        for (Iterator it = q.iterator(); it.hasNext();) {
+            assertEquals(++k, it.next());
+        }
+
+        assertEquals(3, k);
+    }
+
+    /**
+     * iterator.remove() removes current element
+     */
+    public void testIteratorRemove() {
+        final ArrayDeque q = new ArrayDeque();
+        final Random rng = new Random();
+        for (int iters = 0; iters < 100; ++iters) {
+            int max = rng.nextInt(5) + 2;
+            int split = rng.nextInt(max - 1) + 1;
+            for (int j = 1; j <= max; ++j)
+                q.add(new Integer(j));
+            Iterator it = q.iterator();
+            for (int j = 1; j <= split; ++j)
+                assertEquals(it.next(), new Integer(j));
+            it.remove();
+            assertEquals(it.next(), new Integer(split + 1));
+            for (int j = 1; j <= split; ++j)
+                q.remove(new Integer(j));
+            it = q.iterator();
+            for (int j = split + 1; j <= max; ++j) {
+                assertEquals(it.next(), new Integer(j));
+                it.remove();
+            }
+            assertFalse(it.hasNext());
+            assertTrue(q.isEmpty());
+        }
+    }
+
+    /**
+     * Descending iterator iterates through all elements
+     */
+    public void testDescendingIterator() {
+        ArrayDeque q = populatedDeque(SIZE);
+        int i = 0;
+        Iterator it = q.descendingIterator();
+        while (it.hasNext()) {
+            assertTrue(q.contains(it.next()));
+            ++i;
+        }
+        assertEquals(i, SIZE);
+        assertFalse(it.hasNext());
+        try {
+            it.next();
+            shouldThrow();
+        } catch (NoSuchElementException success) {}
+    }
+
+    /**
+     * Descending iterator ordering is reverse FIFO
+     */
+    public void testDescendingIteratorOrdering() {
+        final ArrayDeque q = new ArrayDeque();
+        for (int iters = 0; iters < 100; ++iters) {
+            q.add(new Integer(3));
+            q.add(new Integer(2));
+            q.add(new Integer(1));
+            int k = 0;
+            for (Iterator it = q.descendingIterator(); it.hasNext();) {
+                assertEquals(++k, it.next());
+            }
+
+            assertEquals(3, k);
+            q.remove();
+            q.remove();
+            q.remove();
+        }
+    }
+
+    /**
+     * descendingIterator.remove() removes current element
+     */
+    public void testDescendingIteratorRemove() {
+        final ArrayDeque q = new ArrayDeque();
+        final Random rng = new Random();
+        for (int iters = 0; iters < 100; ++iters) {
+            int max = rng.nextInt(5) + 2;
+            int split = rng.nextInt(max - 1) + 1;
+            for (int j = max; j >= 1; --j)
+                q.add(new Integer(j));
+            Iterator it = q.descendingIterator();
+            for (int j = 1; j <= split; ++j)
+                assertEquals(it.next(), new Integer(j));
+            it.remove();
+            assertEquals(it.next(), new Integer(split + 1));
+            for (int j = 1; j <= split; ++j)
+                q.remove(new Integer(j));
+            it = q.descendingIterator();
+            for (int j = split + 1; j <= max; ++j) {
+                assertEquals(it.next(), new Integer(j));
+                it.remove();
+            }
+            assertFalse(it.hasNext());
+            assertTrue(q.isEmpty());
+        }
+    }
+
+    /**
+     * toString() contains toStrings of elements
+     */
+    public void testToString() {
+        ArrayDeque q = populatedDeque(SIZE);
+        String s = q.toString();
+        for (int i = 0; i < SIZE; ++i) {
+            assertTrue(s.contains(String.valueOf(i)));
+        }
+    }
+
+    /**
+     * A deserialized serialized deque has same elements in same order
+     */
+    public void testSerialization() throws Exception {
+        Queue x = populatedDeque(SIZE);
+        Queue y = serialClone(x);
+
+        assertNotSame(y, x);
+        assertEquals(x.size(), y.size());
+        assertEquals(x.toString(), y.toString());
+        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
+        while (!x.isEmpty()) {
+            assertFalse(y.isEmpty());
+            assertEquals(x.remove(), y.remove());
+        }
+        assertTrue(y.isEmpty());
+    }
+
+    /**
+     * remove(null), contains(null) always return false
+     */
+    public void testNeverContainsNull() {
+        Deque<?>[] qs = {
+            new ArrayDeque<Object>(),
+            populatedDeque(2),
+        };
+
+        for (Deque<?> q : qs) {
+            assertFalse(q.contains(null));
+            assertFalse(q.remove(null));
+            assertFalse(q.removeFirstOccurrence(null));
+            assertFalse(q.removeLastOccurrence(null));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/Atomic8Test.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,596 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class Atomic8Test extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(Atomic8Test.class);
+    }
+
+    /*
+     * Tests of atomic class methods accepting lambdas
+     * introduced in JDK8.
+     */
+
+    static long addLong17(long x) { return x + 17; }
+    static int addInt17(int x) { return x + 17; }
+    static Integer addInteger17(Integer x) {
+        return new Integer(x.intValue() + 17);
+    }
+    static Integer sumInteger(Integer x, Integer y) {
+        return new Integer(x.intValue() + y.intValue());
+    }
+
+    volatile long aLongField;
+    volatile int anIntField;
+    volatile Integer anIntegerField;
+
+    AtomicLongFieldUpdater aLongFieldUpdater() {
+        return AtomicLongFieldUpdater.newUpdater
+            (Atomic8Test.class, "aLongField");
+    }
+
+    AtomicIntegerFieldUpdater anIntFieldUpdater() {
+        return AtomicIntegerFieldUpdater.newUpdater
+            (Atomic8Test.class, "anIntField");
+    }
+
+    AtomicReferenceFieldUpdater<Atomic8Test,Integer> anIntegerFieldUpdater() {
+        return AtomicReferenceFieldUpdater.newUpdater
+            (Atomic8Test.class, Integer.class, "anIntegerField");
+    }
+
+    /**
+     * AtomicLong getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testLongGetAndUpdate() {
+        AtomicLong a = new AtomicLong(1L);
+        assertEquals(1L, a.getAndUpdate(Atomic8Test::addLong17));
+        assertEquals(18L, a.getAndUpdate(Atomic8Test::addLong17));
+        assertEquals(35L, a.get());
+    }
+
+    /**
+     * AtomicLong updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testLongUpdateAndGet() {
+        AtomicLong a = new AtomicLong(1L);
+        assertEquals(18L, a.updateAndGet(Atomic8Test::addLong17));
+        assertEquals(35L, a.updateAndGet(Atomic8Test::addLong17));
+    }
+
+    /**
+     * AtomicLong getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testLongGetAndAccumulate() {
+        AtomicLong a = new AtomicLong(1L);
+        assertEquals(1L, a.getAndAccumulate(2L, Long::sum));
+        assertEquals(3L, a.getAndAccumulate(3L, Long::sum));
+        assertEquals(6L, a.get());
+    }
+
+    /**
+     * AtomicLong accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testLongAccumulateAndGet() {
+        AtomicLong a = new AtomicLong(1L);
+        assertEquals(7L, a.accumulateAndGet(6L, Long::sum));
+        assertEquals(10L, a.accumulateAndGet(3L, Long::sum));
+        assertEquals(10L, a.get());
+    }
+
+    /**
+     * AtomicInteger getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testIntGetAndUpdate() {
+        AtomicInteger a = new AtomicInteger(1);
+        assertEquals(1, a.getAndUpdate(Atomic8Test::addInt17));
+        assertEquals(18, a.getAndUpdate(Atomic8Test::addInt17));
+        assertEquals(35, a.get());
+    }
+
+    /**
+     * AtomicInteger updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testIntUpdateAndGet() {
+        AtomicInteger a = new AtomicInteger(1);
+        assertEquals(18, a.updateAndGet(Atomic8Test::addInt17));
+        assertEquals(35, a.updateAndGet(Atomic8Test::addInt17));
+        assertEquals(35, a.get());
+    }
+
+    /**
+     * AtomicInteger getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testIntGetAndAccumulate() {
+        AtomicInteger a = new AtomicInteger(1);
+        assertEquals(1, a.getAndAccumulate(2, Integer::sum));
+        assertEquals(3, a.getAndAccumulate(3, Integer::sum));
+        assertEquals(6, a.get());
+    }
+
+    /**
+     * AtomicInteger accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testIntAccumulateAndGet() {
+        AtomicInteger a = new AtomicInteger(1);
+        assertEquals(7, a.accumulateAndGet(6, Integer::sum));
+        assertEquals(10, a.accumulateAndGet(3, Integer::sum));
+        assertEquals(10, a.get());
+    }
+
+    /**
+     * AtomicReference getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testReferenceGetAndUpdate() {
+        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17));
+        assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.get());
+    }
+
+    /**
+     * AtomicReference updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testReferenceUpdateAndGet() {
+        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.get());
+    }
+
+    /**
+     * AtomicReference getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testReferenceGetAndAccumulate() {
+        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        assertEquals(new Integer(1), a.getAndAccumulate(2, Atomic8Test::sumInteger));
+        assertEquals(new Integer(3), a.getAndAccumulate(3, Atomic8Test::sumInteger));
+        assertEquals(new Integer(6), a.get());
+    }
+
+    /**
+     * AtomicReference accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testReferenceAccumulateAndGet() {
+        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        assertEquals(new Integer(7), a.accumulateAndGet(6, Atomic8Test::sumInteger));
+        assertEquals(new Integer(10), a.accumulateAndGet(3, Atomic8Test::sumInteger));
+        assertEquals(new Integer(10), a.get());
+    }
+
+    /**
+     * AtomicLongArray getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testLongArrayGetAndUpdate() {
+        AtomicLongArray a = new AtomicLongArray(1);
+        a.set(0, 1);
+        assertEquals(1L, a.getAndUpdate(0, Atomic8Test::addLong17));
+        assertEquals(18L, a.getAndUpdate(0, Atomic8Test::addLong17));
+        assertEquals(35L, a.get(0));
+    }
+
+    /**
+     * AtomicLongArray updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testLongArrayUpdateAndGet() {
+        AtomicLongArray a = new AtomicLongArray(1);
+        a.set(0, 1);
+        assertEquals(18L, a.updateAndGet(0, Atomic8Test::addLong17));
+        assertEquals(35L, a.updateAndGet(0, Atomic8Test::addLong17));
+        assertEquals(35L, a.get(0));
+    }
+
+    /**
+     * AtomicLongArray getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testLongArrayGetAndAccumulate() {
+        AtomicLongArray a = new AtomicLongArray(1);
+        a.set(0, 1);
+        assertEquals(1L, a.getAndAccumulate(0, 2L, Long::sum));
+        assertEquals(3L, a.getAndAccumulate(0, 3L, Long::sum));
+        assertEquals(6L, a.get(0));
+    }
+
+    /**
+     * AtomicLongArray accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testLongArrayAccumulateAndGet() {
+        AtomicLongArray a = new AtomicLongArray(1);
+        a.set(0, 1);
+        assertEquals(7L, a.accumulateAndGet(0, 6L, Long::sum));
+        assertEquals(10L, a.accumulateAndGet(0, 3L, Long::sum));
+        assertEquals(10L, a.get(0));
+    }
+
+    /**
+     * AtomicIntegerArray getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testIntArrayGetAndUpdate() {
+        AtomicIntegerArray a = new AtomicIntegerArray(1);
+        a.set(0, 1);
+        assertEquals(1, a.getAndUpdate(0, Atomic8Test::addInt17));
+        assertEquals(18, a.getAndUpdate(0, Atomic8Test::addInt17));
+        assertEquals(35, a.get(0));
+    }
+
+    /**
+     * AtomicIntegerArray updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testIntArrayUpdateAndGet() {
+        AtomicIntegerArray a = new AtomicIntegerArray(1);
+        a.set(0, 1);
+        assertEquals(18, a.updateAndGet(0, Atomic8Test::addInt17));
+        assertEquals(35, a.updateAndGet(0, Atomic8Test::addInt17));
+        assertEquals(35, a.get(0));
+    }
+
+    /**
+     * AtomicIntegerArray getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testIntArrayGetAndAccumulate() {
+        AtomicIntegerArray a = new AtomicIntegerArray(1);
+        a.set(0, 1);
+        assertEquals(1, a.getAndAccumulate(0, 2, Integer::sum));
+        assertEquals(3, a.getAndAccumulate(0, 3, Integer::sum));
+        assertEquals(6, a.get(0));
+    }
+
+    /**
+     * AtomicIntegerArray accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testIntArrayAccumulateAndGet() {
+        AtomicIntegerArray a = new AtomicIntegerArray(1);
+        a.set(0, 1);
+        assertEquals(7, a.accumulateAndGet(0, 6, Integer::sum));
+        assertEquals(10, a.accumulateAndGet(0, 3, Integer::sum));
+    }
+
+    /**
+     * AtomicReferenceArray getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testReferenceArrayGetAndUpdate() {
+        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+        a.set(0, one);
+        assertEquals(new Integer(1), a.getAndUpdate(0, Atomic8Test::addInteger17));
+        assertEquals(new Integer(18), a.getAndUpdate(0, Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.get(0));
+    }
+
+    /**
+     * AtomicReferenceArray updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testReferenceArrayUpdateAndGet() {
+        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+        a.set(0, one);
+        assertEquals(new Integer(18), a.updateAndGet(0, Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.updateAndGet(0, Atomic8Test::addInteger17));
+    }
+
+    /**
+     * AtomicReferenceArray getAndAccumulate returns previous value and updates
+     * with supplied function.
+     */
+    public void testReferenceArrayGetAndAccumulate() {
+        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+        a.set(0, one);
+        assertEquals(new Integer(1), a.getAndAccumulate(0, 2, Atomic8Test::sumInteger));
+        assertEquals(new Integer(3), a.getAndAccumulate(0, 3, Atomic8Test::sumInteger));
+        assertEquals(new Integer(6), a.get(0));
+    }
+
+    /**
+     * AtomicReferenceArray accumulateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testReferenceArrayAccumulateAndGet() {
+        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+        a.set(0, one);
+        assertEquals(new Integer(7), a.accumulateAndGet(0, 6, Atomic8Test::sumInteger));
+        assertEquals(new Integer(10), a.accumulateAndGet(0, 3, Atomic8Test::sumInteger));
+    }
+
+    /**
+     * AtomicLongFieldUpdater getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testLongFieldUpdaterGetAndUpdate() {
+        AtomicLongFieldUpdater a = aLongFieldUpdater();
+        a.set(this, 1);
+        assertEquals(1L, a.getAndUpdate(this, Atomic8Test::addLong17));
+        assertEquals(18L, a.getAndUpdate(this, Atomic8Test::addLong17));
+        assertEquals(35L, a.get(this));
+        assertEquals(35L, aLongField);
+    }
+
+    /**
+     * AtomicLongFieldUpdater updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testLongFieldUpdaterUpdateAndGet() {
+        AtomicLongFieldUpdater a = aLongFieldUpdater();
+        a.set(this, 1);
+        assertEquals(18L, a.updateAndGet(this, Atomic8Test::addLong17));
+        assertEquals(35L, a.updateAndGet(this, Atomic8Test::addLong17));
+        assertEquals(35L, a.get(this));
+        assertEquals(35L, aLongField);
+    }
+
+    /**
+     * AtomicLongFieldUpdater getAndAccumulate returns previous value
+     * and updates with supplied function.
+     */
+    public void testLongFieldUpdaterGetAndAccumulate() {
+        AtomicLongFieldUpdater a = aLongFieldUpdater();
+        a.set(this, 1);
+        assertEquals(1L, a.getAndAccumulate(this, 2L, Long::sum));
+        assertEquals(3L, a.getAndAccumulate(this, 3L, Long::sum));
+        assertEquals(6L, a.get(this));
+        assertEquals(6L, aLongField);
+    }
+
+    /**
+     * AtomicLongFieldUpdater accumulateAndGet updates with supplied
+     * function and returns result.
+     */
+    public void testLongFieldUpdaterAccumulateAndGet() {
+        AtomicLongFieldUpdater a = aLongFieldUpdater();
+        a.set(this, 1);
+        assertEquals(7L, a.accumulateAndGet(this, 6L, Long::sum));
+        assertEquals(10L, a.accumulateAndGet(this, 3L, Long::sum));
+        assertEquals(10L, a.get(this));
+        assertEquals(10L, aLongField);
+    }
+
+    /**
+     * AtomicIntegerFieldUpdater getAndUpdate returns previous value and updates
+     * result of supplied function
+     */
+    public void testIntegerFieldUpdaterGetAndUpdate() {
+        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
+        a.set(this, 1);
+        assertEquals(1, a.getAndUpdate(this, Atomic8Test::addInt17));
+        assertEquals(18, a.getAndUpdate(this, Atomic8Test::addInt17));
+        assertEquals(35, a.get(this));
+        assertEquals(35, anIntField);
+    }
+
+    /**
+     * AtomicIntegerFieldUpdater updateAndGet updates with supplied function and
+     * returns result.
+     */
+    public void testIntegerFieldUpdaterUpdateAndGet() {
+        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
+        a.set(this, 1);
+        assertEquals(18, a.updateAndGet(this, Atomic8Test::addInt17));
+        assertEquals(35, a.updateAndGet(this, Atomic8Test::addInt17));
+        assertEquals(35, a.get(this));
+        assertEquals(35, anIntField);
+    }
+
+    /**
+     * AtomicIntegerFieldUpdater getAndAccumulate returns previous value
+     * and updates with supplied function.
+     */
+    public void testIntegerFieldUpdaterGetAndAccumulate() {
+        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
+        a.set(this, 1);
+        assertEquals(1, a.getAndAccumulate(this, 2, Integer::sum));
+        assertEquals(3, a.getAndAccumulate(this, 3, Integer::sum));
+        assertEquals(6, a.get(this));
+        assertEquals(6, anIntField);
+    }
+
+    /**
+     * AtomicIntegerFieldUpdater accumulateAndGet updates with supplied
+     * function and returns result.
+     */
+    public void testIntegerFieldUpdaterAccumulateAndGet() {
+        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
+        a.set(this, 1);
+        assertEquals(7, a.accumulateAndGet(this, 6, Integer::sum));
+        assertEquals(10, a.accumulateAndGet(this, 3, Integer::sum));
+        assertEquals(10, a.get(this));
+        assertEquals(10, anIntField);
+    }
+
+    /**
+     * AtomicReferenceFieldUpdater getAndUpdate returns previous value
+     * and updates result of supplied function
+     */
+    public void testReferenceFieldUpdaterGetAndUpdate() {
+        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
+        a.set(this, one);
+        assertEquals(new Integer(1), a.getAndUpdate(this, Atomic8Test::addInteger17));
+        assertEquals(new Integer(18), a.getAndUpdate(this, Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.get(this));
+        assertEquals(new Integer(35), anIntegerField);
+    }
+
+    /**
+     * AtomicReferenceFieldUpdater updateAndGet updates with supplied
+     * function and returns result.
+     */
+    public void testReferenceFieldUpdaterUpdateAndGet() {
+        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
+        a.set(this, one);
+        assertEquals(new Integer(18), a.updateAndGet(this, Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.updateAndGet(this, Atomic8Test::addInteger17));
+        assertEquals(new Integer(35), a.get(this));
+        assertEquals(new Integer(35), anIntegerField);
+    }
+
+    /**
+     * AtomicReferenceFieldUpdater returns previous value and updates
+     * with supplied function.
+     */
+    public void testReferenceFieldUpdaterGetAndAccumulate() {
+        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
+        a.set(this, one);
+        assertEquals(new Integer(1), a.getAndAccumulate(this, 2, Atomic8Test::sumInteger));
+        assertEquals(new Integer(3), a.getAndAccumulate(this, 3, Atomic8Test::sumInteger));
+        assertEquals(new Integer(6), a.get(this));
+        assertEquals(new Integer(6), anIntegerField);
+    }
+
+    /**
+     * AtomicReferenceFieldUpdater accumulateAndGet updates with
+     * supplied function and returns result.
+     */
+    public void testReferenceFieldUpdaterAccumulateAndGet() {
+        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
+        a.set(this, one);
+        assertEquals(new Integer(7), a.accumulateAndGet(this, 6, Atomic8Test::sumInteger));
+        assertEquals(new Integer(10), a.accumulateAndGet(this, 3, Atomic8Test::sumInteger));
+        assertEquals(new Integer(10), a.get(this));
+        assertEquals(new Integer(10), anIntegerField);
+    }
+
+    /**
+     * All Atomic getAndUpdate methods throw NullPointerException on
+     * null function argument
+     */
+    public void testGetAndUpdateNPE() {
+        Runnable[] throwingActions = {
+            () -> new AtomicLong().getAndUpdate(null),
+            () -> new AtomicInteger().getAndUpdate(null),
+            () -> new AtomicReference().getAndUpdate(null),
+            () -> new AtomicLongArray(1).getAndUpdate(0, null),
+            () -> new AtomicIntegerArray(1).getAndUpdate(0, null),
+            () -> new AtomicReferenceArray(1).getAndUpdate(0, null),
+            () -> aLongFieldUpdater().getAndUpdate(this, null),
+            () -> anIntFieldUpdater().getAndUpdate(this, null),
+            () -> anIntegerFieldUpdater().getAndUpdate(this, null),
+            ////() -> aLongFieldUpdater().getAndUpdate(null, Atomic8Test::addLong17),
+            ////() -> anIntFieldUpdater().getAndUpdate(null, Atomic8Test::addInt17),
+            ////() -> anIntegerFieldUpdater().getAndUpdate(null, Atomic8Test::addInteger17),
+        };
+        assertThrows(NullPointerException.class, throwingActions);
+    }
+
+    /**
+     * All Atomic updateAndGet methods throw NullPointerException on null function argument
+     */
+    public void testUpdateAndGetNPE() {
+        Runnable[] throwingActions = {
+            () -> new AtomicLong().updateAndGet(null),
+            () -> new AtomicInteger().updateAndGet(null),
+            () -> new AtomicReference().updateAndGet(null),
+            () -> new AtomicLongArray(1).updateAndGet(0, null),
+            () -> new AtomicIntegerArray(1).updateAndGet(0, null),
+            () -> new AtomicReferenceArray(1).updateAndGet(0, null),
+            () -> aLongFieldUpdater().updateAndGet(this, null),
+            () -> anIntFieldUpdater().updateAndGet(this, null),
+            () -> anIntegerFieldUpdater().updateAndGet(this, null),
+        };
+        assertThrows(NullPointerException.class, throwingActions);
+    }
+
+    /**
+     * All Atomic getAndAccumulate methods throw NullPointerException
+     * on null function argument
+     */
+    public void testGetAndAccumulateNPE() {
+        Runnable[] throwingActions = {
+            () -> new AtomicLong().getAndAccumulate(1L, null),
+            () -> new AtomicInteger().getAndAccumulate(1, null),
+            () -> new AtomicReference().getAndAccumulate(one, null),
+            () -> new AtomicLongArray(1).getAndAccumulate(0, 1L, null),
+            () -> new AtomicIntegerArray(1).getAndAccumulate(0, 1, null),
+            () -> new AtomicReferenceArray(1).getAndAccumulate(0, one, null),
+            () -> aLongFieldUpdater().getAndAccumulate(this, 1L, null),
+            () -> anIntFieldUpdater().getAndAccumulate(this, 1, null),
+            () -> anIntegerFieldUpdater().getAndAccumulate(this, one, null),
+        };
+        assertThrows(NullPointerException.class, throwingActions);
+    }
+
+    /**
+     * All Atomic accumulateAndGet methods throw NullPointerException
+     * on null function argument
+     */
+    public void testAccumulateAndGetNPE() {
+        Runnable[] throwingActions = {
+            () -> new AtomicLong().accumulateAndGet(1L, null),
+            () -> new AtomicInteger().accumulateAndGet(1, null),
+            () -> new AtomicReference().accumulateAndGet(one, null),
+            () -> new AtomicLongArray(1).accumulateAndGet(0, 1L, null),
+            () -> new AtomicIntegerArray(1).accumulateAndGet(0, 1, null),
+            () -> new AtomicReferenceArray(1).accumulateAndGet(0, one, null),
+            () -> aLongFieldUpdater().accumulateAndGet(this, 1L, null),
+            () -> anIntFieldUpdater().accumulateAndGet(this, 1, null),
+            () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null),
+        };
+        assertThrows(NullPointerException.class, throwingActions);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicBooleanTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicBooleanTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicBooleanTest.class);
+    }
+
+    /**
+     * constructor initializes to given value
+     */
+    public void testConstructor() {
+        assertTrue(new AtomicBoolean(true).get());
+        assertFalse(new AtomicBoolean(false).get());
+    }
+
+    /**
+     * default constructed initializes to false
+     */
+    public void testConstructor2() {
+        AtomicBoolean ai = new AtomicBoolean();
+        assertFalse(ai.get());
+    }
+
+    /**
+     * get returns the last value set
+     */
+    public void testGetSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertTrue(ai.get());
+        ai.set(false);
+        assertFalse(ai.get());
+        ai.set(true);
+        assertTrue(ai.get());
+    }
+
+    /**
+     * get returns the last value lazySet in same thread
+     */
+    public void testGetLazySet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertTrue(ai.get());
+        ai.lazySet(false);
+        assertFalse(ai.get());
+        ai.lazySet(true);
+        assertTrue(ai.get());
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertTrue(ai.compareAndSet(true, false));
+        assertFalse(ai.get());
+        assertTrue(ai.compareAndSet(false, false));
+        assertFalse(ai.get());
+        assertFalse(ai.compareAndSet(true, false));
+        assertFalse(ai.get());
+        assertTrue(ai.compareAndSet(false, true));
+        assertTrue(ai.get());
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        final AtomicBoolean ai = new AtomicBoolean(true);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!ai.compareAndSet(false, true)) Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(ai.compareAndSet(true, false));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSet(true, false));
+        assertFalse(ai.get());
+        do {} while (!ai.weakCompareAndSet(false, false));
+        assertFalse(ai.get());
+        do {} while (!ai.weakCompareAndSet(false, true));
+        assertTrue(ai.get());
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value
+     */
+    public void testGetAndSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getAndSet(false));
+        assertEquals(false, ai.getAndSet(false));
+        assertEquals(false, ai.getAndSet(true));
+        assertTrue(ai.get());
+    }
+
+    /**
+     * a deserialized serialized atomic holds same value
+     */
+    public void testSerialization() throws Exception {
+        AtomicBoolean x = new AtomicBoolean();
+        AtomicBoolean y = serialClone(x);
+        x.set(true);
+        AtomicBoolean z = serialClone(x);
+        assertTrue(x.get());
+        assertFalse(y.get());
+        assertTrue(z.get());
+    }
+
+    /**
+     * toString returns current value.
+     */
+    public void testToString() {
+        AtomicBoolean ai = new AtomicBoolean();
+        assertEquals(Boolean.toString(false), ai.toString());
+        ai.set(true);
+        assertEquals(Boolean.toString(true), ai.toString());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,370 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicIntegerArrayTest extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicIntegerArrayTest.class);
+    }
+
+    /**
+     * constructor creates array of given size with all elements zero
+     */
+    public void testConstructor() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++)
+            assertEquals(0, aa.get(i));
+    }
+
+    /**
+     * constructor with null array throws NPE
+     */
+    public void testConstructor2NPE() {
+        try {
+            int[] a = null;
+            new AtomicIntegerArray(a);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * constructor with array is of same size and has all elements
+     */
+    public void testConstructor2() {
+        int[] a = { 17, 3, -42, 99, -7 };
+        AtomicIntegerArray aa = new AtomicIntegerArray(a);
+        assertEquals(a.length, aa.length());
+        for (int i = 0; i < a.length; i++)
+            assertEquals(a[i], aa.get(i));
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            try {
+                aa.get(index);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.set(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.lazySet(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.compareAndSet(index, 1, 2);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.weakCompareAndSet(index, 1, 2);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.getAndAdd(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.addAndGet(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+        }
+    }
+
+    /**
+     * get returns the last value set at index
+     */
+    public void testGetSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value lazySet at index by same thread
+     */
+    public void testGetLazySet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.lazySet(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.lazySet(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.lazySet(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertTrue(aa.compareAndSet(i, 1, 2));
+            assertTrue(aa.compareAndSet(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertFalse(aa.compareAndSet(i, -5, 7));
+            assertEquals(-4, aa.get(i));
+            assertTrue(aa.compareAndSet(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        final AtomicIntegerArray a = new AtomicIntegerArray(1);
+        a.set(0, 1);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!a.compareAndSet(0, 2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(a.compareAndSet(0, 1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, a.get(0));
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSet(i, 1, 2));
+            do {} while (!aa.weakCompareAndSet(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSet(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value at given index
+     */
+    public void testGetAndSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndSet(i, 0));
+            assertEquals(0, aa.getAndSet(i, -10));
+            assertEquals(-10, aa.getAndSet(i, 1));
+        }
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndAdd(i, 2));
+            assertEquals(3, aa.get(i));
+            assertEquals(3, aa.getAndAdd(i, -4));
+            assertEquals(-1, aa.get(i));
+        }
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndDecrement(i));
+            assertEquals(0, aa.getAndDecrement(i));
+            assertEquals(-1, aa.getAndDecrement(i));
+        }
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndIncrement(i));
+            assertEquals(2, aa.get(i));
+            aa.set(i, -2);
+            assertEquals(-2, aa.getAndIncrement(i));
+            assertEquals(-1, aa.getAndIncrement(i));
+            assertEquals(0, aa.getAndIncrement(i));
+            assertEquals(1, aa.get(i));
+        }
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(3, aa.addAndGet(i, 2));
+            assertEquals(3, aa.get(i));
+            assertEquals(-1, aa.addAndGet(i, -4));
+            assertEquals(-1, aa.get(i));
+        }
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(0, aa.decrementAndGet(i));
+            assertEquals(-1, aa.decrementAndGet(i));
+            assertEquals(-2, aa.decrementAndGet(i));
+            assertEquals(-2, aa.get(i));
+        }
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(2, aa.incrementAndGet(i));
+            assertEquals(2, aa.get(i));
+            aa.set(i, -2);
+            assertEquals(-1, aa.incrementAndGet(i));
+            assertEquals(0, aa.incrementAndGet(i));
+            assertEquals(1, aa.incrementAndGet(i));
+            assertEquals(1, aa.get(i));
+        }
+    }
+
+    class Counter extends CheckedRunnable {
+        final AtomicIntegerArray aa;
+        volatile int counts;
+        Counter(AtomicIntegerArray a) { aa = a; }
+        public void realRun() {
+            for (;;) {
+                boolean done = true;
+                for (int i = 0; i < aa.length(); i++) {
+                    int v = aa.get(i);
+                    assertTrue(v >= 0);
+                    if (v != 0) {
+                        done = false;
+                        if (aa.compareAndSet(i, v, v - 1))
+                            ++counts;
+                    }
+                }
+                if (done)
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Multiple threads using same array of counters successfully
+     * update a number of times equal to total count
+     */
+    public void testCountingInMultipleThreads() throws InterruptedException {
+        final AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        int countdown = 10000;
+        for (int i = 0; i < SIZE; i++)
+            aa.set(i, countdown);
+        Counter c1 = new Counter(aa);
+        Counter c2 = new Counter(aa);
+        Thread t1 = new Thread(c1);
+        Thread t2 = new Thread(c2);
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+        assertEquals(c1.counts+c2.counts, SIZE * countdown);
+    }
+
+    /**
+     * a deserialized serialized array holds same values
+     */
+    public void testSerialization() throws Exception {
+        AtomicIntegerArray x = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++)
+            x.set(i, -i);
+        AtomicIntegerArray y = serialClone(x);
+        assertNotSame(x, y);
+        assertEquals(x.length(), y.length());
+        for (int i = 0; i < SIZE; i++) {
+            assertEquals(x.get(i), y.get(i));
+        }
+    }
+
+    /**
+     * toString returns current value.
+     */
+    public void testToString() {
+        int[] a = { 17, 3, -42, 99, -7 };
+        AtomicIntegerArray aa = new AtomicIntegerArray(a);
+        assertEquals(Arrays.toString(a), aa.toString());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicIntegerFieldUpdaterTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,363 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
+    volatile int x = 0;
+    protected volatile int protectedField;
+    private volatile int privateField;
+    int w;
+    float z;
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicIntegerFieldUpdaterTest.class);
+    }
+
+    // for testing subclass access
+    static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest {
+        public void checkPrivateAccess() {
+            try {
+                AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                    AtomicIntegerFieldUpdater.newUpdater
+                    (AtomicIntegerFieldUpdaterTest.class, "privateField");
+                shouldThrow();
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+
+        public void checkCompareAndSetProtectedSub() {
+            AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                AtomicIntegerFieldUpdater.newUpdater
+                (AtomicIntegerFieldUpdaterTest.class, "protectedField");
+            this.protectedField = 1;
+            assertTrue(a.compareAndSet(this, 1, 2));
+            assertTrue(a.compareAndSet(this, 2, -4));
+            assertEquals(-4, a.get(this));
+            assertFalse(a.compareAndSet(this, -5, 7));
+            assertEquals(-4, a.get(this));
+            assertTrue(a.compareAndSet(this, -4, 7));
+            assertEquals(7, a.get(this));
+        }
+    }
+
+    static class UnrelatedClass {
+        public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) {
+            obj.x = 72;
+            AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                AtomicIntegerFieldUpdater.newUpdater
+                (AtomicIntegerFieldUpdaterTest.class, "x");
+            assertEquals(72, a.get(obj));
+            assertTrue(a.compareAndSet(obj, 72, 73));
+            assertEquals(73, a.get(obj));
+        }
+
+        public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) {
+            try {
+                AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
+                    AtomicIntegerFieldUpdater.newUpdater
+                    (AtomicIntegerFieldUpdaterTest.class, "privateField");
+                throw new AssertionError("should throw");
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+    }
+
+    AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> updaterFor(String fieldName) {
+        return AtomicIntegerFieldUpdater.newUpdater
+            (AtomicIntegerFieldUpdaterTest.class, fieldName);
+    }
+
+    /**
+     * Construction with non-existent field throws RuntimeException
+     */
+    public void testConstructor() {
+        try {
+            updaterFor("y");
+            shouldThrow();
+        } catch (RuntimeException success) {
+            assertNotNull(success.getCause());
+        }
+    }
+
+    /**
+     * construction with field not of given type throws IllegalArgumentException
+     */
+    public void testConstructor2() {
+        try {
+            updaterFor("z");
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * construction with non-volatile field throws IllegalArgumentException
+     */
+    public void testConstructor3() {
+        try {
+            updaterFor("w");
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * construction using private field from subclass throws RuntimeException
+     */
+    public void testPrivateFieldInSubclass() {
+        AtomicIntegerFieldUpdaterTestSubclass s =
+            new AtomicIntegerFieldUpdaterTestSubclass();
+        s.checkPrivateAccess();
+    }
+
+    /**
+     * construction from unrelated class; package access is allowed,
+     * private access is not
+     */
+    public void testUnrelatedClassAccess() {
+        new UnrelatedClass().checkPackageAccess(this);
+        new UnrelatedClass().checkPrivateAccess(this);
+    }
+
+    /**
+     * get returns the last value set or assigned
+     */
+    public void testGetSet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.get(this));
+        a.set(this, 2);
+        assertEquals(2, a.get(this));
+        a.set(this, -3);
+        assertEquals(-3, a.get(this));
+    }
+
+    /**
+     * get returns the last value lazySet by same thread
+     */
+    public void testGetLazySet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.get(this));
+        a.lazySet(this, 2);
+        assertEquals(2, a.get(this));
+        a.lazySet(this, -3);
+        assertEquals(-3, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertTrue(a.compareAndSet(this, 1, 2));
+        assertTrue(a.compareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        assertFalse(a.compareAndSet(this, -5, 7));
+        assertEquals(-4, a.get(this));
+        assertTrue(a.compareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing protected field value if
+     * equal to expected else fails
+     */
+    public void testCompareAndSetProtected() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("protectedField");
+        protectedField = 1;
+        assertTrue(a.compareAndSet(this, 1, 2));
+        assertTrue(a.compareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        assertFalse(a.compareAndSet(this, -5, 7));
+        assertEquals(-4, a.get(this));
+        assertTrue(a.compareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing protected field value if
+     * equal to expected else fails
+     */
+    public void testCompareAndSetProtectedInSubclass() {
+        AtomicIntegerFieldUpdaterTestSubclass s =
+            new AtomicIntegerFieldUpdaterTestSubclass();
+        s.checkCompareAndSetProtectedSub();
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        x = 1;
+        final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(a.compareAndSet(this, 1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, a.get(this));
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        do {} while (!a.weakCompareAndSet(this, 1, 2));
+        do {} while (!a.weakCompareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        do {} while (!a.weakCompareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value
+     */
+    public void testGetAndSet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndSet(this, 0));
+        assertEquals(0, a.getAndSet(this, -10));
+        assertEquals(-10, a.getAndSet(this, 1));
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndAdd(this, 2));
+        assertEquals(3, a.get(this));
+        assertEquals(3, a.getAndAdd(this, -4));
+        assertEquals(-1, a.get(this));
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndDecrement(this));
+        assertEquals(0, a.getAndDecrement(this));
+        assertEquals(-1, a.getAndDecrement(this));
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndIncrement(this));
+        assertEquals(2, a.get(this));
+        a.set(this, -2);
+        assertEquals(-2, a.getAndIncrement(this));
+        assertEquals(-1, a.getAndIncrement(this));
+        assertEquals(0, a.getAndIncrement(this));
+        assertEquals(1, a.get(this));
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(3, a.addAndGet(this, 2));
+        assertEquals(3, a.get(this));
+        assertEquals(-1, a.addAndGet(this, -4));
+        assertEquals(-1, a.get(this));
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(0, a.decrementAndGet(this));
+        assertEquals(-1, a.decrementAndGet(this));
+        assertEquals(-2, a.decrementAndGet(this));
+        assertEquals(-2, a.get(this));
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(2, a.incrementAndGet(this));
+        assertEquals(2, a.get(this));
+        a.set(this, -2);
+        assertEquals(-1, a.incrementAndGet(this));
+        assertEquals(0, a.incrementAndGet(this));
+        assertEquals(1, a.incrementAndGet(this));
+        assertEquals(1, a.get(this));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicIntegerTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,294 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicIntegerTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicIntegerTest.class);
+    }
+
+    final int[] VALUES = {
+        Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
+    };
+
+    /**
+     * constructor initializes to given value
+     */
+    public void testConstructor() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * default constructed initializes to zero
+     */
+    public void testConstructor2() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals(0, ai.get());
+    }
+
+    /**
+     * get returns the last value set
+     */
+    public void testGetSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.set(2);
+        assertEquals(2, ai.get());
+        ai.set(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value lazySet in same thread
+     */
+    public void testGetLazySet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.lazySet(2);
+        assertEquals(2, ai.get());
+        ai.lazySet(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertTrue(ai.compareAndSet(1, 2));
+        assertTrue(ai.compareAndSet(2, -4));
+        assertEquals(-4, ai.get());
+        assertFalse(ai.compareAndSet(-5, 7));
+        assertEquals(-4, ai.get());
+        assertTrue(ai.compareAndSet(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        final AtomicInteger ai = new AtomicInteger(1);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!ai.compareAndSet(2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(ai.compareAndSet(1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSet(1, 2));
+        do {} while (!ai.weakCompareAndSet(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSet(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value
+     */
+    public void testGetAndSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAndSet(0));
+        assertEquals(0, ai.getAndSet(-10));
+        assertEquals(-10, ai.getAndSet(1));
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAndAdd(2));
+        assertEquals(3, ai.get());
+        assertEquals(3, ai.getAndAdd(-4));
+        assertEquals(-1, ai.get());
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAndDecrement());
+        assertEquals(0, ai.getAndDecrement());
+        assertEquals(-1, ai.getAndDecrement());
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAndIncrement());
+        assertEquals(2, ai.get());
+        ai.set(-2);
+        assertEquals(-2, ai.getAndIncrement());
+        assertEquals(-1, ai.getAndIncrement());
+        assertEquals(0, ai.getAndIncrement());
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(3, ai.addAndGet(2));
+        assertEquals(3, ai.get());
+        assertEquals(-1, ai.addAndGet(-4));
+        assertEquals(-1, ai.get());
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(0, ai.decrementAndGet());
+        assertEquals(-1, ai.decrementAndGet());
+        assertEquals(-2, ai.decrementAndGet());
+        assertEquals(-2, ai.get());
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(2, ai.incrementAndGet());
+        assertEquals(2, ai.get());
+        ai.set(-2);
+        assertEquals(-1, ai.incrementAndGet());
+        assertEquals(0, ai.incrementAndGet());
+        assertEquals(1, ai.incrementAndGet());
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * a deserialized serialized atomic holds same value
+     */
+    public void testSerialization() throws Exception {
+        AtomicInteger x = new AtomicInteger();
+        AtomicInteger y = serialClone(x);
+        assertNotSame(x, y);
+        x.set(22);
+        AtomicInteger z = serialClone(x);
+        assertEquals(22, x.get());
+        assertEquals(0, y.get());
+        assertEquals(22, z.get());
+    }
+
+    /**
+     * toString returns current value.
+     */
+    public void testToString() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals("0", ai.toString());
+        for (int x : VALUES) {
+            ai.set(x);
+            assertEquals(Integer.toString(x), ai.toString());
+        }
+    }
+
+    /**
+     * intValue returns current value.
+     */
+    public void testIntValue() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals(0, ai.intValue());
+        for (int x : VALUES) {
+            ai.set(x);
+            assertEquals(x, ai.intValue());
+        }
+    }
+
+    /**
+     * longValue returns current value.
+     */
+    public void testLongValue() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals(0L, ai.longValue());
+        for (int x : VALUES) {
+            ai.set(x);
+            assertEquals((long)x, ai.longValue());
+        }
+    }
+
+    /**
+     * floatValue returns current value.
+     */
+    public void testFloatValue() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals(0.0f, ai.floatValue());
+        for (int x : VALUES) {
+            ai.set(x);
+            assertEquals((float)x, ai.floatValue());
+        }
+    }
+
+    /**
+     * doubleValue returns current value.
+     */
+    public void testDoubleValue() {
+        AtomicInteger ai = new AtomicInteger();
+        assertEquals(0.0d, ai.doubleValue());
+        for (int x : VALUES) {
+            ai.set(x);
+            assertEquals((double)x, ai.doubleValue());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicLongArrayTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,369 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLongArrayTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLongArrayTest.class);
+    }
+
+    /**
+     * constructor creates array of given size with all elements zero
+     */
+    public void testConstructor() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++)
+            assertEquals(0, aa.get(i));
+    }
+
+    /**
+     * constructor with null array throws NPE
+     */
+    public void testConstructor2NPE() {
+        try {
+            long[] a = null;
+            new AtomicLongArray(a);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * constructor with array is of same size and has all elements
+     */
+    public void testConstructor2() {
+        long[] a = { 17L, 3L, -42L, 99L, -7L };
+        AtomicLongArray aa = new AtomicLongArray(a);
+        assertEquals(a.length, aa.length());
+        for (int i = 0; i < a.length; i++)
+            assertEquals(a[i], aa.get(i));
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            try {
+                aa.get(index);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.set(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.lazySet(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.compareAndSet(index, 1, 2);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.weakCompareAndSet(index, 1, 2);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.getAndAdd(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.addAndGet(index, 1);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+        }
+    }
+
+    /**
+     * get returns the last value set at index
+     */
+    public void testGetSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value lazySet at index by same thread
+     */
+    public void testGetLazySet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.lazySet(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.lazySet(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.lazySet(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertTrue(aa.compareAndSet(i, 1, 2));
+            assertTrue(aa.compareAndSet(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertFalse(aa.compareAndSet(i, -5, 7));
+            assertEquals(-4, aa.get(i));
+            assertTrue(aa.compareAndSet(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws InterruptedException {
+        final AtomicLongArray a = new AtomicLongArray(1);
+        a.set(0, 1);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!a.compareAndSet(0, 2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(a.compareAndSet(0, 1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, a.get(0));
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSet(i, 1, 2));
+            do {} while (!aa.weakCompareAndSet(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSet(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value at given index
+     */
+    public void testGetAndSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndSet(i, 0));
+            assertEquals(0, aa.getAndSet(i, -10));
+            assertEquals(-10, aa.getAndSet(i, 1));
+        }
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndAdd(i, 2));
+            assertEquals(3, aa.get(i));
+            assertEquals(3, aa.getAndAdd(i, -4));
+            assertEquals(-1, aa.get(i));
+        }
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndDecrement(i));
+            assertEquals(0, aa.getAndDecrement(i));
+            assertEquals(-1, aa.getAndDecrement(i));
+        }
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAndIncrement(i));
+            assertEquals(2, aa.get(i));
+            aa.set(i, -2);
+            assertEquals(-2, aa.getAndIncrement(i));
+            assertEquals(-1, aa.getAndIncrement(i));
+            assertEquals(0, aa.getAndIncrement(i));
+            assertEquals(1, aa.get(i));
+        }
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(3, aa.addAndGet(i, 2));
+            assertEquals(3, aa.get(i));
+            assertEquals(-1, aa.addAndGet(i, -4));
+            assertEquals(-1, aa.get(i));
+        }
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(0, aa.decrementAndGet(i));
+            assertEquals(-1, aa.decrementAndGet(i));
+            assertEquals(-2, aa.decrementAndGet(i));
+            assertEquals(-2, aa.get(i));
+        }
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(2, aa.incrementAndGet(i));
+            assertEquals(2, aa.get(i));
+            aa.set(i, -2);
+            assertEquals(-1, aa.incrementAndGet(i));
+            assertEquals(0, aa.incrementAndGet(i));
+            assertEquals(1, aa.incrementAndGet(i));
+            assertEquals(1, aa.get(i));
+        }
+    }
+
+    class Counter extends CheckedRunnable {
+        final AtomicLongArray aa;
+        volatile long counts;
+        Counter(AtomicLongArray a) { aa = a; }
+        public void realRun() {
+            for (;;) {
+                boolean done = true;
+                for (int i = 0; i < aa.length(); i++) {
+                    long v = aa.get(i);
+                    assertTrue(v >= 0);
+                    if (v != 0) {
+                        done = false;
+                        if (aa.compareAndSet(i, v, v - 1))
+                            ++counts;
+                    }
+                }
+                if (done)
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Multiple threads using same array of counters successfully
+     * update a number of times equal to total count
+     */
+    public void testCountingInMultipleThreads() throws InterruptedException {
+        final AtomicLongArray aa = new AtomicLongArray(SIZE);
+        long countdown = 10000;
+        for (int i = 0; i < SIZE; i++)
+            aa.set(i, countdown);
+        Counter c1 = new Counter(aa);
+        Counter c2 = new Counter(aa);
+        Thread t1 = new Thread(c1);
+        Thread t2 = new Thread(c2);
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+        assertEquals(c1.counts+c2.counts, SIZE * countdown);
+    }
+
+    /**
+     * a deserialized serialized array holds same values
+     */
+    public void testSerialization() throws Exception {
+        AtomicLongArray x = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++)
+            x.set(i, -i);
+        AtomicLongArray y = serialClone(x);
+        assertNotSame(x, y);
+        assertEquals(x.length(), y.length());
+        for (int i = 0; i < SIZE; i++) {
+            assertEquals(x.get(i), y.get(i));
+        }
+    }
+
+    /**
+     * toString returns current value.
+     */
+    public void testToString() {
+        long[] a = { 17, 3, -42, 99, -7 };
+        AtomicLongArray aa = new AtomicLongArray(a);
+        assertEquals(Arrays.toString(a), aa.toString());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicLongFieldUpdaterTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,363 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
+    volatile long x = 0;
+    protected volatile long protectedField;
+    private volatile long privateField;
+    long w;
+    float z;
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLongFieldUpdaterTest.class);
+    }
+
+    // for testing subclass access
+    static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
+        public void checkPrivateAccess() {
+            try {
+                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                    AtomicLongFieldUpdater.newUpdater
+                    (AtomicLongFieldUpdaterTest.class, "privateField");
+                shouldThrow();
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+
+        public void checkCompareAndSetProtectedSub() {
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                AtomicLongFieldUpdater.newUpdater
+                (AtomicLongFieldUpdaterTest.class, "protectedField");
+            this.protectedField = 1;
+            assertTrue(a.compareAndSet(this, 1, 2));
+            assertTrue(a.compareAndSet(this, 2, -4));
+            assertEquals(-4, a.get(this));
+            assertFalse(a.compareAndSet(this, -5, 7));
+            assertEquals(-4, a.get(this));
+            assertTrue(a.compareAndSet(this, -4, 7));
+            assertEquals(7, a.get(this));
+        }
+    }
+
+    static class UnrelatedClass {
+        public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
+            obj.x = 72L;
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                AtomicLongFieldUpdater.newUpdater
+                (AtomicLongFieldUpdaterTest.class, "x");
+            assertEquals(72L, a.get(obj));
+            assertTrue(a.compareAndSet(obj, 72L, 73L));
+            assertEquals(73L, a.get(obj));
+        }
+
+        public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
+            try {
+                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
+                    AtomicLongFieldUpdater.newUpdater
+                    (AtomicLongFieldUpdaterTest.class, "privateField");
+                throw new AssertionError("should throw");
+            } catch (RuntimeException success) {
+                assertNotNull(success.getCause());
+            }
+        }
+    }
+
+    AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> updaterFor(String fieldName) {
+        return AtomicLongFieldUpdater.newUpdater
+            (AtomicLongFieldUpdaterTest.class, fieldName);
+    }
+
+    /**
+     * Construction with non-existent field throws RuntimeException
+     */
+    public void testConstructor() {
+        try {
+            updaterFor("y");
+            shouldThrow();
+        } catch (RuntimeException success) {
+            assertNotNull(success.getCause());
+        }
+    }
+
+    /**
+     * construction with field not of given type throws IllegalArgumentException
+     */
+    public void testConstructor2() {
+        try {
+            updaterFor("z");
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * construction with non-volatile field throws IllegalArgumentException
+     */
+    public void testConstructor3() {
+        try {
+            updaterFor("w");
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * construction using private field from subclass throws RuntimeException
+     */
+    public void testPrivateFieldInSubclass() {
+        AtomicLongFieldUpdaterTestSubclass s =
+            new AtomicLongFieldUpdaterTestSubclass();
+        s.checkPrivateAccess();
+    }
+
+    /**
+     * construction from unrelated class; package access is allowed,
+     * private access is not
+     */
+    public void testUnrelatedClassAccess() {
+        new UnrelatedClass().checkPackageAccess(this);
+        new UnrelatedClass().checkPrivateAccess(this);
+    }
+
+    /**
+     * get returns the last value set or assigned
+     */
+    public void testGetSet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.get(this));
+        a.set(this, 2);
+        assertEquals(2, a.get(this));
+        a.set(this, -3);
+        assertEquals(-3, a.get(this));
+    }
+
+    /**
+     * get returns the last value lazySet by same thread
+     */
+    public void testGetLazySet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.get(this));
+        a.lazySet(this, 2);
+        assertEquals(2, a.get(this));
+        a.lazySet(this, -3);
+        assertEquals(-3, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertTrue(a.compareAndSet(this, 1, 2));
+        assertTrue(a.compareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        assertFalse(a.compareAndSet(this, -5, 7));
+        assertEquals(-4, a.get(this));
+        assertTrue(a.compareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing protected field value if
+     * equal to expected else fails
+     */
+    public void testCompareAndSetProtected() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("protectedField");
+        protectedField = 1;
+        assertTrue(a.compareAndSet(this, 1, 2));
+        assertTrue(a.compareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        assertFalse(a.compareAndSet(this, -5, 7));
+        assertEquals(-4, a.get(this));
+        assertTrue(a.compareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * compareAndSet succeeds in changing protected field value if
+     * equal to expected else fails
+     */
+    public void testCompareAndSetProtectedInSubclass() {
+        AtomicLongFieldUpdaterTestSubclass s =
+            new AtomicLongFieldUpdaterTestSubclass();
+        s.checkCompareAndSetProtectedSub();
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        x = 1;
+        final AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(a.compareAndSet(this, 1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, a.get(this));
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        do {} while (!a.weakCompareAndSet(this, 1, 2));
+        do {} while (!a.weakCompareAndSet(this, 2, -4));
+        assertEquals(-4, a.get(this));
+        do {} while (!a.weakCompareAndSet(this, -4, 7));
+        assertEquals(7, a.get(this));
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value
+     */
+    public void testGetAndSet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndSet(this, 0));
+        assertEquals(0, a.getAndSet(this, -10));
+        assertEquals(-10, a.getAndSet(this, 1));
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndAdd(this, 2));
+        assertEquals(3, a.get(this));
+        assertEquals(3, a.getAndAdd(this, -4));
+        assertEquals(-1, a.get(this));
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndDecrement(this));
+        assertEquals(0, a.getAndDecrement(this));
+        assertEquals(-1, a.getAndDecrement(this));
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(1, a.getAndIncrement(this));
+        assertEquals(2, a.get(this));
+        a.set(this, -2);
+        assertEquals(-2, a.getAndIncrement(this));
+        assertEquals(-1, a.getAndIncrement(this));
+        assertEquals(0, a.getAndIncrement(this));
+        assertEquals(1, a.get(this));
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(3, a.addAndGet(this, 2));
+        assertEquals(3, a.get(this));
+        assertEquals(-1, a.addAndGet(this, -4));
+        assertEquals(-1, a.get(this));
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(0, a.decrementAndGet(this));
+        assertEquals(-1, a.decrementAndGet(this));
+        assertEquals(-2, a.decrementAndGet(this));
+        assertEquals(-2, a.get(this));
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
+        a = updaterFor("x");
+        x = 1;
+        assertEquals(2, a.incrementAndGet(this));
+        assertEquals(2, a.get(this));
+        a.set(this, -2);
+        assertEquals(-1, a.incrementAndGet(this));
+        assertEquals(0, a.incrementAndGet(this));
+        assertEquals(1, a.incrementAndGet(this));
+        assertEquals(1, a.get(this));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicLongTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLongTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLongTest.class);
+    }
+
+    final long[] VALUES = {
+        Long.MIN_VALUE,
+        Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
+        Long.MAX_VALUE,
+    };
+
+    /**
+     * constructor initializes to given value
+     */
+    public void testConstructor() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * default constructed initializes to zero
+     */
+    public void testConstructor2() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals(0, ai.get());
+    }
+
+    /**
+     * get returns the last value set
+     */
+    public void testGetSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.set(2);
+        assertEquals(2, ai.get());
+        ai.set(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value lazySet in same thread
+     */
+    public void testGetLazySet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.lazySet(2);
+        assertEquals(2, ai.get());
+        ai.lazySet(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertTrue(ai.compareAndSet(1, 2));
+        assertTrue(ai.compareAndSet(2, -4));
+        assertEquals(-4, ai.get());
+        assertFalse(ai.compareAndSet(-5, 7));
+        assertEquals(-4, ai.get());
+        assertTrue(ai.compareAndSet(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        final AtomicLong ai = new AtomicLong(1);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!ai.compareAndSet(2, 3))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(ai.compareAndSet(1, 2));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertEquals(3, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSet(1, 2));
+        do {} while (!ai.weakCompareAndSet(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSet(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * getAndSet returns previous value and sets to given value
+     */
+    public void testGetAndSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAndSet(0));
+        assertEquals(0, ai.getAndSet(-10));
+        assertEquals(-10, ai.getAndSet(1));
+    }
+
+    /**
+     * getAndAdd returns previous value and adds given value
+     */
+    public void testGetAndAdd() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAndAdd(2));
+        assertEquals(3, ai.get());
+        assertEquals(3, ai.getAndAdd(-4));
+        assertEquals(-1, ai.get());
+    }
+
+    /**
+     * getAndDecrement returns previous value and decrements
+     */
+    public void testGetAndDecrement() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAndDecrement());
+        assertEquals(0, ai.getAndDecrement());
+        assertEquals(-1, ai.getAndDecrement());
+    }
+
+    /**
+     * getAndIncrement returns previous value and increments
+     */
+    public void testGetAndIncrement() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAndIncrement());
+        assertEquals(2, ai.get());
+        ai.set(-2);
+        assertEquals(-2, ai.getAndIncrement());
+        assertEquals(-1, ai.getAndIncrement());
+        assertEquals(0, ai.getAndIncrement());
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * addAndGet adds given value to current, and returns current value
+     */
+    public void testAddAndGet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(3, ai.addAndGet(2));
+        assertEquals(3, ai.get());
+        assertEquals(-1, ai.addAndGet(-4));
+        assertEquals(-1, ai.get());
+    }
+
+    /**
+     * decrementAndGet decrements and returns current value
+     */
+    public void testDecrementAndGet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(0, ai.decrementAndGet());
+        assertEquals(-1, ai.decrementAndGet());
+        assertEquals(-2, ai.decrementAndGet());
+        assertEquals(-2, ai.get());
+    }
+
+    /**
+     * incrementAndGet increments and returns current value
+     */
+    public void testIncrementAndGet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(2, ai.incrementAndGet());
+        assertEquals(2, ai.get());
+        ai.set(-2);
+        assertEquals(-1, ai.incrementAndGet());
+        assertEquals(0, ai.incrementAndGet());
+        assertEquals(1, ai.incrementAndGet());
+        assertEquals(1, ai.get());
+    }
+
+    /**
+     * a deserialized serialized atomic holds same value
+     */
+    public void testSerialization() throws Exception {
+        AtomicLong x = new AtomicLong();
+        AtomicLong y = serialClone(x);
+        assertNotSame(x, y);
+        x.set(-22);
+        AtomicLong z = serialClone(x);
+        assertNotSame(y, z);
+        assertEquals(-22, x.get());
+        assertEquals(0, y.get());
+        assertEquals(-22, z.get());
+    }
+
+    /**
+     * toString returns current value.
+     */
+    public void testToString() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals("0", ai.toString());
+        for (long x : VALUES) {
+            ai.set(x);
+            assertEquals(Long.toString(x), ai.toString());
+        }
+    }
+
+    /**
+     * intValue returns current value.
+     */
+    public void testIntValue() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals(0, ai.intValue());
+        for (long x : VALUES) {
+            ai.set(x);
+            assertEquals((int)x, ai.intValue());
+        }
+    }
+
+    /**
+     * longValue returns current value.
+     */
+    public void testLongValue() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals(0L, ai.longValue());
+        for (long x : VALUES) {
+            ai.set(x);
+            assertEquals(x, ai.longValue());
+        }
+    }
+
+    /**
+     * floatValue returns current value.
+     */
+    public void testFloatValue() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals(0.0f, ai.floatValue());
+        for (long x : VALUES) {
+            ai.set(x);
+            assertEquals((float)x, ai.floatValue());
+        }
+    }
+
+    /**
+     * doubleValue returns current value.
+     */
+    public void testDoubleValue() {
+        AtomicLong ai = new AtomicLong();
+        assertEquals(0.0d, ai.doubleValue());
+        for (long x : VALUES) {
+            ai.set(x);
+            assertEquals((double)x, ai.doubleValue());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicMarkableReferenceTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.concurrent.atomic.AtomicMarkableReference;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicMarkableReferenceTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicMarkableReferenceTest.class);
+    }
+
+    /**
+     * constructor initializes to given reference and mark
+     */
+    public void testConstructor() {
+        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        assertSame(one, ai.getReference());
+        assertFalse(ai.isMarked());
+        AtomicMarkableReference a2 = new AtomicMarkableReference(null, true);
+        assertNull(a2.getReference());
+        assertTrue(a2.isMarked());
+    }
+
+    /**
+     * get returns the last values of reference and mark set
+     */
+    public void testGetSet() {
+        boolean[] mark = new boolean[1];
+        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        assertSame(one, ai.getReference());
+        assertFalse(ai.isMarked());
+        assertSame(one, ai.get(mark));
+        assertFalse(mark[0]);
+        ai.set(two, false);
+        assertSame(two, ai.getReference());
+        assertFalse(ai.isMarked());
+        assertSame(two, ai.get(mark));
+        assertFalse(mark[0]);
+        ai.set(one, true);
+        assertSame(one, ai.getReference());
+        assertTrue(ai.isMarked());
+        assertSame(one, ai.get(mark));
+        assertTrue(mark[0]);
+    }
+
+    /**
+     * attemptMark succeeds in single thread
+     */
+    public void testAttemptMark() {
+        boolean[] mark = new boolean[1];
+        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        assertFalse(ai.isMarked());
+        assertTrue(ai.attemptMark(one, true));
+        assertTrue(ai.isMarked());
+        assertSame(one, ai.get(mark));
+        assertTrue(mark[0]);
+    }
+
+    /**
+     * compareAndSet succeeds in changing values if equal to expected reference
+     * and mark else fails
+     */
+    public void testCompareAndSet() {
+        boolean[] mark = new boolean[1];
+        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        assertSame(one, ai.get(mark));
+        assertFalse(ai.isMarked());
+        assertFalse(mark[0]);
+
+        assertTrue(ai.compareAndSet(one, two, false, false));
+        assertSame(two, ai.get(mark));
+        assertFalse(mark[0]);
+
+        assertTrue(ai.compareAndSet(two, m3, false, true));
+        assertSame(m3, ai.get(mark));
+        assertTrue(mark[0]);
+
+        assertFalse(ai.compareAndSet(two, m3, true, true));
+        assertSame(m3, ai.get(mark));
+        assertTrue(mark[0]);
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for reference value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws Exception {
+        final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!ai.compareAndSet(two, three, false, false))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(ai.compareAndSet(one, two, false, false));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertSame(three, ai.getReference());
+        assertFalse(ai.isMarked());
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for mark value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads2() throws Exception {
+        final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!ai.compareAndSet(one, one, true, false))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(ai.compareAndSet(one, one, false, true));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertSame(one, ai.getReference());
+        assertFalse(ai.isMarked());
+    }
+
+    /**
+     * repeated weakCompareAndSet succeeds in changing values when equal
+     * to expected
+     */
+    public void testWeakCompareAndSet() {
+        boolean[] mark = new boolean[1];
+        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
+        assertSame(one, ai.get(mark));
+        assertFalse(ai.isMarked());
+        assertFalse(mark[0]);
+
+        do {} while (!ai.weakCompareAndSet(one, two, false, false));
+        assertSame(two, ai.get(mark));
+        assertFalse(mark[0]);
+
+        do {} while (!ai.weakCompareAndSet(two, m3, false, true));
+        assertSame(m3, ai.get(mark));
+        assertTrue(mark[0]);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java	Mon Feb 01 10:07:37 2016 -0800
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicReferenceArrayTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicReferenceArrayTest.class);
+    }
+
+    /**
+     * constructor creates array of given size with all elements null
+     */
+    public void testConstructor() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            assertNull(aa.get(i));
+        }
+    }
+
+    /**
+     * constructor with null array throws NPE
+     */
+    public void testConstructor2NPE() {
+        try {
+            Integer[] a = null;
+            new AtomicReferenceArray<Integer>(a);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * constructor with array is of same size and has all elements
+     */
+    public void testConstructor2() {
+        Integer[] a = { two, one, three, four, seven };
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
+        assertEquals(a.length, aa.length());
+        for (int i = 0; i < a.length; i++)
+            assertEquals(a[i], aa.get(i));
+    }
+
+    /**
+     * Initialize AtomicReferenceArray<Class> with SubClass[]
+     */
+    public void testConstructorSubClassArray() {
+        Integer[] a = { two, one, three, four, seven };
+        AtomicReferenceArray<Number> aa = new AtomicReferenceArray<Number>(a);
+        assertEquals(a.length, aa.length());
+        for (int i = 0; i < a.length; i++) {
+            assertSame(a[i], aa.get(i));
+            Long x = Long.valueOf(i);
+            aa.set(i, x);
+            assertSame(x, aa.get(i));
+        }
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            try {
+                aa.get(index);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.set(index, null);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.lazySet(index, null);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.compareAndSet(index, null, null);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+            try {
+                aa.weakCompareAndSet(index, null, null);
+                shouldThrow();
+            } catch (IndexOutOfBoundsException success) {}
+        }
+    }
+
+    /**
+     * get returns the last value set at index
+     */
+    public void testGetSet() {
+        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertSame(one, aa.get(i));
+            aa.set(i, two);
+            assertSame(two, aa.get(i));
+            aa.set(i, m3);
+            assertSame(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value lazySet at index by same thread
+     */
+    public void testGetLazySet() {
+        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.lazySet(i, one);
+            assertSame(one, aa.get(i));
+            aa.lazySet(i, two);
+            assertSame(two, aa.get(i));
+            aa.lazySet(i, m3);
+            assertSame(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet succeeds in changing value if equal to expected else fails
+     */
+    public void testCompareAndSet() {
+        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertTrue(aa.compareAndSet(i, one, two));
+            assertTrue(aa.compareAndSet(i, two, m4));
+            assertSame(m4, aa.get(i));
+            assertFalse(aa.compareAndSet(i, m5, seven));
+            assertSame(m4, aa.get(i));
+            assertTrue(aa.compareAndSet(i, m4, seven));
+            assertSame(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndSet in one thread enables another waiting for value
+     * to succeed
+     */
+    public void testCompareAndSetInMultipleThreads() throws InterruptedException {
+        final AtomicReferenceArray a = new AtomicReferenceArray(1);
+        a.set(0, one);
+        Thread t = new Thread(new CheckedRunnable() {
+            public void realRun() {
+                while (!a.compareAndSet(0, two, three))
+                    Thread.yield();
+            }});
+
+        t.start();
+        assertTrue(a.compareAndSet(0, one, two));
+        t.join(LONG_DELAY_MS);
+        assertFalse(t.isAlive());
+        assertSame(three, a.get(0));
+    }