Merge "java.security.PKCS12Attribute: port class from jdk8u60"
diff --git a/dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java b/dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java
new file mode 100644
index 0000000..316a08f
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.system;
+
+import java.nio.ByteBuffer;
+import sun.misc.Cleaner;
+
+/**
+ * {@link ClassLoader} implementation for loading Dex file from
+ * memory.
+ *
+ * @hide
+ */
+public class InMemoryDexClassLoader extends ClassLoader {
+ private final DexData dexData;
+
+ /**
+ * Creates a new in-memory DEX class loader.
+ *
+ * @param dexBuffer buffer containing DEX file contents between
+ * <tt>buffer.position()</tt> and <tt>buffer.limit()</tt>.
+ * @param parent the parent class loader for delegation.
+ */
+ public InMemoryDexClassLoader(ByteBuffer dexBuffer, ClassLoader parent) {
+ super(parent);
+ if (dexBuffer == null) {
+ throw new NullPointerException("dexData == null");
+ }
+ this.dexData = new DexData(dexBuffer);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ try {
+ return dexData.findClass(name, this);
+ } catch (Exception e) {
+ throw new ClassNotFoundException("Didn't find class \"" + name + "\"", e);
+ }
+ }
+
+ @Override
+ protected synchronized Package getPackage(String name) {
+ // This is duplicated from BaseDexClassLoader.getPackage which
+ // has an extensive comment on why this needs to be defined.
+ if (name == null || name.isEmpty()) {
+ return null;
+ }
+
+ Package pkg = super.getPackage(name);
+ if (pkg == null) {
+ pkg = definePackage(name, "Unknown", "0.0", "Unknown",
+ "Unknown", "0.0", "Unknown", null);
+ }
+ return pkg;
+ }
+
+ /**
+ * Representation of native resources associated with DEX files loaded by
+ * InMemoryDexClassLoader.
+ */
+ private static final class DexData {
+ private final long cookie;
+
+ DexData(ByteBuffer buffer) {
+ if (buffer.isDirect()) {
+ cookie = initializeWithDirectBuffer(buffer, buffer.position(), buffer.limit());
+ } else {
+ cookie = initializeWithArray(buffer.array(), buffer.position(), buffer.limit());
+ }
+
+ if (cookie != 0) {
+ // Register for clean-up when this instance is phantom
+ // reachable. Cleaner instances are inserted in a global
+ // queue to preserve liveness. DexDataDeallocator must not
+ // have a pointer to DexData otherwise it will prevent
+ // cleaning and the freeing of the native resources.
+ Cleaner.create(this, new DexDataDeallocator(cookie));
+ }
+ }
+
+ protected Class<?> findClass(String name, ClassLoader loader) {
+ return findClass(name, loader, cookie);
+ }
+
+ private static native long initializeWithDirectBuffer(ByteBuffer buffer,
+ int start, int end);
+ private static native long initializeWithArray(byte[] array, int start, int end);
+ private static native void uninitialize(long cookie);
+ private native Class findClass(String name, ClassLoader loader, long cookie);
+ }
+
+ /**
+ * Helper class to release native resources associated with DexData instances.
+ */
+ private static final class DexDataDeallocator implements Runnable {
+ private final long cookie;
+
+ DexDataDeallocator(long cookie) {
+ this.cookie = cookie;
+ }
+
+ public void run() {
+ DexData.uninitialize(cookie);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java
index 170c901..5d97393 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java
@@ -21,6 +21,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -34,7 +36,9 @@
import java.security.Security;
import java.util.Arrays;
import java.util.List;
+import java.util.TreeMap;
import java.util.Vector;
+import java.util.function.Function;
public class ClassTest extends junit.framework.TestCase {
@@ -545,47 +549,6 @@
}
}
- /**
- * java.lang.Class#toString()
- */
- public void test_toString() throws ClassNotFoundException {
- assertEquals("Class toString printed wrong value",
- "int", int.class.toString());
- Class<?> clazz = null;
- clazz = Class.forName("[I");
- assertEquals("Class toString printed wrong value",
- "class [I", clazz.toString());
-
- clazz = Class.forName("java.lang.Object");
- assertEquals("Class toString printed wrong value",
- "class java.lang.Object", clazz.toString());
-
- clazz = Class.forName("[Ljava.lang.Object;");
- assertEquals("Class toString printed wrong value",
- "class [Ljava.lang.Object;", clazz.toString());
- }
-
- /**
- * java.lang.Class#getTypeName()
- */
- public void test_getTypeName() throws ClassNotFoundException {
- assertEquals("Class toString printed wrong value",
- "int", int.class.getTypeName());
-
- Class<?> clazz = null;
- clazz = Class.forName("[I");
- assertEquals("Class toString printed wrong value",
- "int[]", clazz.getTypeName());
-
- clazz = Class.forName("java.lang.Object");
- assertEquals("Class toString printed wrong value",
- "java.lang.Object", clazz.getTypeName());
-
- clazz = Class.forName("[Ljava.lang.Object;");
- assertEquals("Class toString printed wrong value",
- "java.lang.Object[]", clazz.getTypeName());
- }
-
// Regression Test for JIRA-2047
public void test_getResourceAsStream_withSharpChar() throws Exception {
// Class.getResourceAsStream() requires a leading "/" for absolute paths.
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index cd2666f..6e3e181 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -201,16 +201,6 @@
return accessFlags;
}
- /**
- * Returns the constructor's signature in non-printable form. This is called
- * (only) from IO native code and needed for deriving the serialVersionUID
- * of the class
- *
- * @return The constructor's signature.
- */
- @SuppressWarnings("unused")
- abstract String getSignature();
-
static final class GenericInfo {
final ListOfTypes genericExceptionTypes;
final ListOfTypes genericParameterTypes;
diff --git a/luni/src/main/java/java/math/BigInt.java b/luni/src/main/java/java/math/BigInt.java
index 2cffee6..5e28a73 100644
--- a/luni/src/main/java/java/math/BigInt.java
+++ b/luni/src/main/java/java/math/BigInt.java
@@ -334,11 +334,11 @@
static BigInt generatePrimeDefault(int bitLength) {
BigInt r = newBigInt();
- NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0);
+ NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0);
return r;
}
boolean isPrime(int certainty) {
- return NativeBN.BN_is_prime_ex(bignum, certainty, 0);
+ return NativeBN.BN_primality_test(bignum, certainty, false);
}
}
diff --git a/luni/src/main/java/java/math/NativeBN.java b/luni/src/main/java/java/math/NativeBN.java
index 64b4468..d269f2e 100644
--- a/luni/src/main/java/java/math/NativeBN.java
+++ b/luni/src/main/java/java/math/NativeBN.java
@@ -120,12 +120,15 @@
public static native void BN_generate_prime_ex(long ret, int bits, boolean safe,
- long add, long rem, long cb);
+ long add, long rem);
// int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
// const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb);
- public static native boolean BN_is_prime_ex(long p, int nchecks, long cb);
- // int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+ public static native boolean BN_primality_test(long candidate, int checks,
+ boolean do_trial_division);
+ // int BN_primality_test(int *is_probably_prime, const BIGNUM *candidate, int checks,
+ // BN_CTX *ctx, int do_trial_division, BN_GENCB *cb);
+ // Returns *is_probably_prime on success and throws an exception on error.
public static native long getNativeFinalizer();
// &BN_free
diff --git a/luni/src/main/java/java/security/security.properties b/luni/src/main/java/java/security/security.properties
index 6b9007b..b5f4d25 100644
--- a/luni/src/main/java/java/security/security.properties
+++ b/luni/src/main/java/java/security/security.properties
@@ -62,3 +62,5 @@
# Disable weak algorithms in CertPathVerifier and CertPathBuilder.
jdk.certpath.disabledAlgorithms=MD2, MD4, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 160
+
+securerandom.strongAlgorithms=SHA1PRNG:AndroidOpenSSL
diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java
index 58afdf9..b746273 100644
--- a/luni/src/main/java/libcore/net/MimeUtils.java
+++ b/luni/src/main/java/libcore/net/MimeUtils.java
@@ -211,6 +211,12 @@
add("application/x-xcf", "xcf");
add("application/x-xfig", "fig");
add("application/xhtml+xml", "xhtml");
+ // Video mime types for 3GPP first so they'll be default for guessMimeTypeFromExtension
+ // See RFC 3839 for 3GPP and RFC 4393 for 3GPP2
+ add("video/3gpp", "3gpp");
+ add("video/3gpp", "3gp");
+ add("video/3gpp2", "3gpp2");
+ add("video/3gpp2", "3g2");
add("audio/3gpp", "3gpp");
add("audio/aac", "aac");
add("audio/aac-adts", "aac");
@@ -354,10 +360,6 @@
add("text/x-tex", "cls");
add("text/x-vcalendar", "vcs");
add("text/x-vcard", "vcf");
- add("video/3gpp", "3gpp");
- add("video/3gpp", "3gp");
- add("video/3gpp2", "3gpp2");
- add("video/3gpp2", "3g2");
add("video/avi", "avi");
add("video/dl", "dl");
add("video/dv", "dif");
diff --git a/luni/src/main/native/canonicalize_path.cpp b/luni/src/main/native/canonicalize_path.cpp
deleted file mode 100644
index b2a2a01..0000000
--- a/luni/src/main/native/canonicalize_path.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The names of the authors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "readlink.h"
-
-#include <string>
-
-#include <errno.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/**
- * This differs from realpath(3) mainly in its behavior when a path element does not exist or can
- * not be searched. realpath(3) treats that as an error and gives up, but we have Java-compatible
- * behavior where we just assume the path element was not a symbolic link. This leads to a textual
- * treatment of ".." from that point in the path, which may actually lead us back to a path we
- * can resolve (as in "/tmp/does-not-exist/../blah.txt" which would be an error for realpath(3)
- * but "/tmp/blah.txt" under the traditional Java interpretation).
- *
- * This implementation also removes all the fixed-length buffers of the C original.
- */
-bool canonicalize_path(const char* path, std::string& resolved) {
- // 'path' must be an absolute path.
- if (path[0] != '/') {
- errno = EINVAL;
- return false;
- }
-
- resolved = "/";
- if (path[1] == '\0') {
- return true;
- }
-
- // Iterate over path components in 'left'.
- int symlinkCount = 0;
- std::string left(path + 1);
- while (!left.empty()) {
- // Extract the next path component.
- size_t nextSlash = left.find('/');
- std::string nextPathComponent = left.substr(0, nextSlash);
- if (nextSlash != std::string::npos) {
- left.erase(0, nextSlash + 1);
- } else {
- left.clear();
- }
- if (nextPathComponent.empty()) {
- continue;
- } else if (nextPathComponent == ".") {
- continue;
- } else if (nextPathComponent == "..") {
- // Strip the last path component except when we have single "/".
- if (resolved.size() > 1) {
- resolved.erase(resolved.rfind('/'));
- }
- continue;
- }
-
- // Append the next path component.
- if (resolved[resolved.size() - 1] != '/') {
- resolved += '/';
- }
- resolved += nextPathComponent;
-
- // See if we've got a symbolic link, and resolve it if so.
- struct stat sb;
- if (lstat(resolved.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode)) {
- if (symlinkCount++ > MAXSYMLINKS) {
- errno = ELOOP;
- return false;
- }
-
- std::string symlink;
- if (!readlink(resolved.c_str(), symlink)) {
- return false;
- }
- if (symlink[0] == '/') {
- // The symbolic link is absolute, so we need to start from scratch.
- resolved = "/";
- } else if (resolved.size() > 1) {
- // The symbolic link is relative, so we just lose the last path component (which
- // was the link).
- resolved.erase(resolved.rfind('/'));
- }
-
- if (!left.empty()) {
- const char* maybeSlash = (symlink[symlink.size() - 1] != '/') ? "/" : "";
- left = symlink + maybeSlash + left;
- } else {
- left = symlink;
- }
- }
- }
-
- // Remove trailing slash except when the resolved pathname is a single "/".
- if (resolved.size() > 1 && resolved[resolved.size() - 1] == '/') {
- resolved.erase(resolved.size() - 1, 1);
- }
- return true;
-}
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index e540942..45df4c5 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -51,11 +51,18 @@
return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
}
-static bool throwExceptionIfNecessary(JNIEnv* env) {
+static void throwException(JNIEnv* env) {
long error = ERR_get_error();
+ // OpenSSL's error queue may contain multiple errors. Clean up after them.
+ ERR_clear_error();
+
if (error == 0) {
- return false;
+ // An operation failed but did not push to the error queue. Throw a default
+ // exception.
+ jniThrowException(env, "java/lang/ArithmeticException", "Operation failed");
+ return;
}
+
char message[256];
ERR_error_string_n(error, message, sizeof(message));
int reason = ERR_GET_REASON(error);
@@ -68,9 +75,6 @@
} else {
jniThrowException(env, "java/lang/ArithmeticException", message);
}
- // OpenSSL's error queue may contain multiple errors. Clean up after them.
- ERR_clear_error();
- return true;
}
static int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
@@ -102,7 +106,9 @@
static jlong NativeBN_BN_new(JNIEnv* env, jclass) {
jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
- throwExceptionIfNecessary(env);
+ if (!result) {
+ throwException(env);
+ }
return result;
}
@@ -122,8 +128,9 @@
static void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
if (!twoValidHandles(env, to, from)) return;
- BN_copy(toBigNum(to), toBigNum(from));
- throwExceptionIfNecessary(env);
+ if (!BN_copy(toBigNum(to), toBigNum(from))) {
+ throwException(env);
+ }
}
static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
@@ -131,28 +138,27 @@
uint64_t dw = java_dw;
BIGNUM* a = toBigNum(a0);
- int ok;
static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
if (sizeof(dw) == sizeof(BN_ULONG)) {
- ok = BN_set_word(a, dw);
- } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
- ok = (bn_wexpand(a, 2) != NULL);
- if (ok) {
- a->d[0] = dw;
- a->d[1] = dw >> 32;
- a->top = 2;
- bn_correct_top(a);
+ if (!BN_set_word(a, dw)) {
+ throwException(env);
+ return;
}
+ } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
+ if (!bn_wexpand(a, 2)) {
+ throwException(env);
+ return;
+ }
+ a->d[0] = dw;
+ a->d[1] = dw >> 32;
+ a->top = 2;
+ bn_correct_top(a);
}
BN_set_negative(a, neg);
-
- if (!ok) {
- throwExceptionIfNecessary(env);
- }
}
static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
@@ -171,7 +177,9 @@
}
BIGNUM* a = toBigNum(a0);
int result = BN_dec2bn(&a, chars.c_str());
- throwExceptionIfNecessary(env);
+ if (result == 0) {
+ throwException(env);
+ }
return result;
}
@@ -183,7 +191,9 @@
}
BIGNUM* a = toBigNum(a0);
int result = BN_hex2bn(&a, chars.c_str());
- throwExceptionIfNecessary(env);
+ if (result == 0) {
+ throwException(env);
+ }
return result;
}
@@ -193,10 +203,12 @@
if (bytes.get() == NULL) {
return;
}
- BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
- if (!throwExceptionIfNecessary(env) && neg) {
- BN_set_negative(toBigNum(ret), true);
+ if (!BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret))) {
+ throwException(env);
+ return;
}
+
+ BN_set_negative(toBigNum(ret), neg);
}
/**
@@ -221,28 +233,29 @@
const int wlen = len;
#endif
const unsigned int* tmpInts = reinterpret_cast<const unsigned int*>(scopedArray.get());
- if ((tmpInts != NULL) && (bn_wexpand(ret, wlen) != NULL)) {
-#ifdef __LP64__
- if (len % 2) {
- ret->d[wlen - 1] = tmpInts[--len];
- }
- if (len > 0) {
- for (int i = len - 2; i >= 0; i -= 2) {
- ret->d[i/2] = ((unsigned long long)tmpInts[i+1] << 32) | tmpInts[i];
- }
- }
-#else
- int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
-#endif
- ret->top = wlen;
- ret->neg = neg;
- // need to call this due to clear byte at top if avoiding
- // having the top bit set (-ve number)
- // Basically get rid of top zero ints:
- bn_correct_top(ret);
- } else {
- throwExceptionIfNecessary(env);
+ if (!bn_wexpand(ret, wlen)) {
+ throwException(env);
+ return;
}
+
+#ifdef __LP64__
+ if (len % 2) {
+ ret->d[wlen - 1] = tmpInts[--len];
+ }
+ if (len > 0) {
+ for (int i = len - 2; i >= 0; i -= 2) {
+ ret->d[i/2] = ((unsigned long long)tmpInts[i+1] << 32) | tmpInts[i];
+ }
+ }
+#else
+ int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
+#endif
+ ret->top = wlen;
+ ret->neg = neg;
+ // need to call this due to clear byte at top if avoiding
+ // having the top bit set (-ve number)
+ // Basically get rid of top zero ints:
+ bn_correct_top(ret);
} else { // (len = 0) means value = 0 and sign will be 0, too.
ret->top = 0;
}
@@ -257,57 +270,63 @@
#define BYTES2ULONG(bytes, k) \
(((bytes)[(k) + 3] & 0xff) | ((bytes)[(k) + 2] & 0xff) << 8 | ((bytes)[(k) + 1] & 0xff) << 16 | ((bytes)[(k) + 0] & 0xff) << 24)
#endif
-static void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
+
+// negBigEndianBytes2bn interprets |bytes| as a little-endian two's complement negative integer and
+// sets |ret0| to the result. It returns true on success and false on allocation failure.
+static bool negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
BIGNUM* ret = toBigNum(ret0);
bn_check_top(ret);
// FIXME: assert bytesLen > 0
int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
int firstNonzeroDigit = -2;
- if (bn_wexpand(ret, wLen) != NULL) {
- BN_ULONG* d = ret->d;
- BN_ULONG di;
- ret->top = wLen;
- int highBytes = bytesLen % sizeof(BN_ULONG);
- int k = bytesLen;
- // Put bytes to the int array starting from the end of the byte array
- int i = 0;
- while (k > highBytes) {
- k -= sizeof(BN_ULONG);
- di = BYTES2ULONG(bytes, k);
- if (di != 0) {
- d[i] = -di;
- firstNonzeroDigit = i;
- i++;
- while (k > highBytes) {
- k -= sizeof(BN_ULONG);
- d[i] = ~BYTES2ULONG(bytes, k);
- i++;
- }
- break;
- } else {
- d[i] = 0;
- i++;
- }
- }
- if (highBytes != 0) {
- di = -1;
- // Put the first bytes in the highest element of the int array
- if (firstNonzeroDigit != -2) {
- for (k = 0; k < highBytes; k++) {
- di = (di << 8) | (bytes[k] & 0xFF);
- }
- d[i] = ~di;
- } else {
- for (k = 0; k < highBytes; k++) {
- di = (di << 8) | (bytes[k] & 0xFF);
- }
- d[i] = -di;
- }
- }
- // The top may have superfluous zeros, so fix it.
- bn_correct_top(ret);
+ if (!bn_wexpand(ret, wLen)) {
+ return false;
}
+
+ BN_ULONG* d = ret->d;
+ BN_ULONG di;
+ ret->top = wLen;
+ int highBytes = bytesLen % sizeof(BN_ULONG);
+ int k = bytesLen;
+ // Put bytes to the int array starting from the end of the byte array
+ int i = 0;
+ while (k > highBytes) {
+ k -= sizeof(BN_ULONG);
+ di = BYTES2ULONG(bytes, k);
+ if (di != 0) {
+ d[i] = -di;
+ firstNonzeroDigit = i;
+ i++;
+ while (k > highBytes) {
+ k -= sizeof(BN_ULONG);
+ d[i] = ~BYTES2ULONG(bytes, k);
+ i++;
+ }
+ break;
+ } else {
+ d[i] = 0;
+ i++;
+ }
+ }
+ if (highBytes != 0) {
+ di = -1;
+ // Put the first bytes in the highest element of the int array
+ if (firstNonzeroDigit != -2) {
+ for (k = 0; k < highBytes; k++) {
+ di = (di << 8) | (bytes[k] & 0xFF);
+ }
+ d[i] = ~di;
+ } else {
+ for (k = 0; k < highBytes; k++) {
+ di = (di << 8) | (bytes[k] & 0xFF);
+ }
+ d[i] = -di;
+ }
+ }
+ // The top may have superfluous zeros, so fix it.
+ bn_correct_top(ret);
+ return true;
}
static void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
@@ -323,16 +342,21 @@
//
// We can use the existing BN implementation for unsigned big endian bytes:
//
- BN_bin2bn(s, bytesLen, ret);
+ if (!BN_bin2bn(s, bytesLen, ret)) {
+ throwException(env);
+ return;
+ }
BN_set_negative(ret, false);
} else { // Negative value!
//
// We need to apply two's complement:
//
- negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
+ if (!negBigEndianBytes2bn(env, cls, s, bytesLen, ret0)) {
+ throwException(env);
+ return;
+ }
BN_set_negative(ret, true);
}
- throwExceptionIfNecessary(env);
}
static jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
@@ -373,6 +397,7 @@
if (!oneValidHandle(env, a)) return NULL;
char* tmpStr = BN_bn2dec(toBigNum(a));
if (tmpStr == NULL) {
+ throwException(env);
return NULL;
}
char* retStr = leadingZerosTrimmed(tmpStr);
@@ -385,6 +410,7 @@
if (!oneValidHandle(env, a)) return NULL;
char* tmpStr = BN_bn2hex(toBigNum(a));
if (tmpStr == NULL) {
+ throwException(env);
return NULL;
}
char* retStr = leadingZerosTrimmed(tmpStr);
@@ -472,111 +498,135 @@
static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_is_bit_set(toBigNum(a), n);
+ return BN_is_bit_set(toBigNum(a), n) ? JNI_TRUE : JNI_FALSE;
}
static void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
if (!twoValidHandles(env, r, a)) return;
+ int ok;
if (n >= 0) {
- BN_lshift(toBigNum(r), toBigNum(a), n);
+ ok = BN_lshift(toBigNum(r), toBigNum(a), n);
} else {
- BN_rshift(toBigNum(r), toBigNum(a), -n);
+ ok = BN_rshift(toBigNum(r), toBigNum(a), -n);
}
- throwExceptionIfNecessary(env);
+ if (!ok) {
+ throwException(env);
+ }
}
static void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
if (!oneValidHandle(env, a)) return;
- BN_add_word(toBigNum(a), w);
- throwExceptionIfNecessary(env);
+ if (!BN_add_word(toBigNum(a), w)) {
+ throwException(env);
+ }
}
static void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
if (!oneValidHandle(env, a)) return;
- BN_mul_word(toBigNum(a), w);
- throwExceptionIfNecessary(env);
+ if (!BN_mul_word(toBigNum(a), w)) {
+ throwException(env);
+ }
}
static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
if (!oneValidHandle(env, a)) return 0;
- int result = BN_mod_word(toBigNum(a), w);
- throwExceptionIfNecessary(env);
+ BN_ULONG result = BN_mod_word(toBigNum(a), w);
+ if (result == (BN_ULONG)-1) {
+ throwException(env);
+ }
return result;
}
static void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
if (!threeValidHandles(env, r, a, b)) return;
- BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
- throwExceptionIfNecessary(env);
+ if (!BN_add(toBigNum(r), toBigNum(a), toBigNum(b))) {
+ throwException(env);
+ }
}
static void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
if (!threeValidHandles(env, r, a, b)) return;
- BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
- throwExceptionIfNecessary(env);
+ if (!BN_sub(toBigNum(r), toBigNum(a), toBigNum(b))) {
+ throwException(env);
+ }
}
static void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
if (!threeValidHandles(env, r, a, b)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
if (!threeValidHandles(env, r, a, b)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
if (!threeValidHandles(env, r, a, p)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
if (!threeValidHandles(env, r, a, m)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
if (!fourValidHandles(env, r, a, p, m)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
if (!threeValidHandles(env, ret, a, n)) return;
Unique_BN_CTX ctx(BN_CTX_new());
- BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
- throwExceptionIfNecessary(env);
+ if (!BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get())) {
+ throwException(env);
+ }
}
static void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
- jboolean safe, jlong add, jlong rem, jlong cb) {
+ jboolean safe, jlong add, jlong rem) {
if (!oneValidHandle(env, ret)) return;
- BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
- reinterpret_cast<BN_GENCB*>(cb));
- throwExceptionIfNecessary(env);
+ if (!BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
+ NULL)) {
+ throwException(env);
+ }
}
-static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
- if (!oneValidHandle(env, p)) return JNI_FALSE;
+static jboolean NativeBN_BN_primality_test(JNIEnv* env, jclass, jlong candidate, int checks,
+ jboolean do_trial_decryption) {
+ if (!oneValidHandle(env, candidate)) return JNI_FALSE;
Unique_BN_CTX ctx(BN_CTX_new());
- return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
+ int is_probably_prime;
+ if (!BN_primality_test(&is_probably_prime, toBigNum(candidate), checks, ctx.get(),
+ do_trial_decryption, NULL)) {
+ throwException(env);
+ return JNI_FALSE;
+ }
+ return is_probably_prime ? JNI_TRUE : JNI_FALSE;
}
static JNINativeMethod gMethods[] = {
@@ -593,10 +643,10 @@
NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
- NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJ)V"),
NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
- NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
+ NATIVE_METHOD(NativeBN, BN_primality_test, "(JIZ)Z"),
NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 504a199..cacf62e 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -24,7 +24,6 @@
#include "JniException.h"
#include "NetworkUtilities.h"
#include "Portability.h"
-#include "readlink.h"
#include "ScopedBytes.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
@@ -61,6 +60,8 @@
#include <unistd.h>
#include <memory>
+#include <android-base/file.h>
+
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
@@ -1639,7 +1640,7 @@
}
std::string result;
- if (!readlink(path.c_str(), result)) {
+ if (!android::base::Readlink(path.c_str(), &result)) {
throwErrnoException(env, "readlink");
return NULL;
}
diff --git a/luni/src/main/native/readlink.cpp b/luni/src/main/native/readlink.cpp
deleted file mode 100644
index 555d515..0000000
--- a/luni/src/main/native/readlink.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "LocalArray.h"
-#include "readlink.h"
-
-#include <string>
-#include <unistd.h>
-
-bool readlink(const char* path, std::string& result) {
- // We can't know how big a buffer readlink(2) will need, so we need to
- // loop until it says "that fit".
- size_t bufSize = 512;
- while (true) {
- LocalArray<512> buf(bufSize);
- ssize_t len = readlink(path, &buf[0], buf.size());
- if (len == -1) {
- // An error occurred.
- return false;
- }
- if (static_cast<size_t>(len) < buf.size()) {
- // The buffer was big enough.
- result.assign(&buf[0], len);
- return true;
- }
- // Try again with a bigger buffer.
- bufSize *= 2;
- }
-}
diff --git a/luni/src/main/native/readlink.h b/luni/src/main/native/readlink.h
deleted file mode 100644
index 14031dc..0000000
--- a/luni/src/main/native/readlink.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-
-/**
- * Fills 'result' with the contents of the symbolic link 'path'. Sets errno and returns false on
- * failure, returns true on success. The contents of 'result' on failure are undefined. Possible
- * errors are those defined for readlink(2), except that this function takes care of sizing the
- * buffer appropriately.
- */
-bool readlink(const char* path, std::string& result);
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index fbba3b6..803d818 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -11,7 +11,6 @@
Register.cpp \
ZipUtilities.cpp \
android_system_OsConstants.cpp \
- canonicalize_path.cpp \
cbigint.cpp \
java_lang_StringToReal.cpp \
java_lang_invoke_MethodHandle.cpp \
@@ -26,7 +25,6 @@
libcore_io_Posix.cpp \
libcore_util_NativeAllocationRegistry.cpp \
org_apache_harmony_xml_ExpatParser.cpp \
- readlink.cpp \
sun_misc_Unsafe.cpp \
valueOf.cpp \
diff --git a/luni/src/test/java/dalvik/system/DexClassLoaderTest.java b/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
index 0e0ee8d..36fde22 100644
--- a/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
+++ b/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
@@ -76,6 +76,7 @@
assertTrue(file.delete());
}
}
+ assertTrue(dir.delete());
}
/**
diff --git a/luni/src/test/java/dalvik/system/InMemoryDexClassLoaderTest.java b/luni/src/test/java/dalvik/system/InMemoryDexClassLoaderTest.java
new file mode 100644
index 0000000..c164d3b
--- /dev/null
+++ b/luni/src/test/java/dalvik/system/InMemoryDexClassLoaderTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.system;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import libcore.io.Streams;
+import junit.framework.TestCase;
+
+/**
+ * Tests for the class {@link InMemoryDexClassLoader}.
+ */
+public class InMemoryDexClassLoaderTest extends TestCase {
+ private static final String PACKAGE_PATH = "dalvik/system/";
+
+ private File srcDir;
+ private File dex1;
+ private File dex2;
+
+ protected void setUp() throws Exception {
+ srcDir = File.createTempFile("src", "");
+ assertTrue(srcDir.delete());
+ assertTrue(srcDir.mkdirs());
+
+ dex1 = new File(srcDir, "loading-test.dex");
+ dex2 = new File(srcDir, "loading-test2.dex");
+
+ copyResource("loading-test.dex", dex1);
+ copyResource("loading-test2.dex", dex2);
+ }
+
+ protected void tearDown() {
+ cleanUpDir(srcDir);
+ }
+
+ private static void cleanUpDir(File dir) {
+ if (!dir.isDirectory()) {
+ return;
+ }
+ File[] files = dir.listFiles();
+ for (File file : files) {
+ if (file.isDirectory()) {
+ cleanUpDir(file);
+ } else {
+ assertTrue(file.delete());
+ }
+ }
+ assertTrue(dir.delete());
+ }
+
+ /**
+ * Copy a resource in the package directory to the indicated
+ * target file.
+ */
+ private static void copyResource(String resourceName,
+ File destination) throws IOException {
+ ClassLoader loader = InMemoryDexClassLoaderTest.class.getClassLoader();
+ InputStream in = loader.getResourceAsStream(PACKAGE_PATH + resourceName);
+ if (in == null) {
+ throw new IllegalStateException("Resource not found: " + PACKAGE_PATH + resourceName);
+ }
+ try (FileOutputStream out = new FileOutputStream(destination)) {
+ Streams.copy(in, out);
+ } finally {
+ in.close();
+ }
+ }
+
+ private static ByteBuffer ReadFileToByteBufferDirect(File file) throws IOException {
+ try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.length());
+ int done = 0;
+ while (done != file.length()) {
+ done += raf.getChannel().read(buffer);
+ }
+ buffer.rewind();
+ return buffer;
+ }
+ }
+
+ private static ByteBuffer ReadFileToByteBufferIndirect(File file) throws IOException {
+ ByteBuffer direct = ReadFileToByteBufferDirect(file);
+ byte[] array = new byte[direct.limit()];
+ direct.get(array);
+ return ByteBuffer.wrap(array);
+ }
+
+ /**
+ * Helper to construct a InMemoryDexClassLoader instance to test.
+ *
+ * Creates InMemoryDexClassLoader from ByteBuffer instances that are
+ * direct allocated.
+ *
+ * @param files The .dex files to use for the class path.
+ */
+ private static ClassLoader createLoaderDirect(File... files) throws IOException {
+ assertNotNull(files);
+ assertTrue(files.length > 0);
+ ClassLoader result = ClassLoader.getSystemClassLoader();
+ for (int i = 0; i < files.length; ++i) {
+ ByteBuffer buffer = ReadFileToByteBufferDirect(files[i]);
+ result = new InMemoryDexClassLoader(buffer, result);
+ }
+ return result;
+ }
+
+ /**
+ * Helper to construct a InMemoryDexClassLoader instance to test.
+ *
+ * Creates InMemoryDexClassLoader from ByteBuffer instances that are
+ * heap allocated.
+ *
+ * @param files The .dex files to use for the class path.
+ */
+ private static ClassLoader createLoaderIndirect(File... files) throws IOException {
+ assertNotNull(files);
+ assertTrue(files.length > 0);
+ ClassLoader result = ClassLoader.getSystemClassLoader();
+ for (int i = 0; i < files.length; ++i) {
+ ByteBuffer buffer = ReadFileToByteBufferIndirect(files[i]);
+ result = new InMemoryDexClassLoader(buffer, result);
+ }
+ return result;
+ }
+
+ /**
+ * Helper to construct a new InMemoryDexClassLoader via direct
+ * ByteBuffer instances.
+ *
+ * @param className The name of the class of the method to call.
+ * @param methodName The name of the method to call.
+ * @param files The .dex or .jar files to use for the class path.
+ */
+ private Object createLoaderDirectAndCallMethod(
+ String className, String methodName, File... files)
+ throws IOException, ReflectiveOperationException {
+ ClassLoader cl = createLoaderDirect(files);
+ Class c = cl.loadClass(className);
+ Method m = c.getMethod(methodName, (Class[]) null);
+ assertNotNull(m);
+ return m.invoke(null, (Object[]) null);
+ }
+
+ /**
+ * Helper to construct a new InMemoryDexClassLoader via indirect
+ * ByteBuffer instances.
+ *
+ * @param className The name of the class of the method to call.
+ * @param methodName The name of the method to call.
+ * @param files The .dex or .jar files to use for the class path.
+ */
+ private Object createLoaderIndirectAndCallMethod(
+ String className, String methodName, File... files)
+ throws IOException, ReflectiveOperationException {
+ ClassLoader cl = createLoaderIndirect(files);
+ Class c = cl.loadClass(className);
+ Method m = c.getMethod(methodName, (Class[]) null);
+ assertNotNull(m);
+ return m.invoke(null, (Object[]) null);
+ }
+
+ // ONE_DEX with direct ByteBuffer.
+
+ public void test_oneDexDirect_simpleUse() throws Exception {
+ String result = (String) createLoaderDirectAndCallMethod("test.Test1", "test", dex1);
+ assertSame("blort", result);
+ }
+
+ public void test_oneDexDirect_constructor() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_constructor", dex1);
+ }
+
+ public void test_oneDexDirect_callStaticMethod() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_callStaticMethod", dex1);
+ }
+
+ public void test_oneDexDirect_getStaticVariable() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_getStaticVariable", dex1);
+ }
+
+ public void test_oneDexDirect_callInstanceMethod() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_callInstanceMethod", dex1);
+ }
+
+ public void test_oneDexDirect_getInstanceVariable() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_getInstanceVariable", dex1);
+ }
+
+ // ONE_DEX with non-direct ByteBuffer.
+
+ public void test_oneDexIndirect_simpleUse() throws Exception {
+ String result = (String) createLoaderIndirectAndCallMethod("test.Test1", "test", dex1);
+ assertSame("blort", result);
+ }
+
+ public void test_oneDexIndirect_constructor() throws Exception {
+ createLoaderIndirectAndCallMethod("test.TestMethods", "test_constructor", dex1);
+ }
+
+ public void test_oneDexIndirect_callStaticMethod() throws Exception {
+ createLoaderIndirectAndCallMethod("test.TestMethods", "test_callStaticMethod", dex1);
+ }
+
+ public void test_oneDexIndirect_getStaticVariable() throws Exception {
+ createLoaderIndirectAndCallMethod("test.TestMethods", "test_getStaticVariable", dex1);
+ }
+
+ public void test_oneDexIndirect_callInstanceMethod() throws Exception {
+ createLoaderIndirectAndCallMethod("test.TestMethods", "test_callInstanceMethod", dex1);
+ }
+
+ public void test_oneDexIndirect_getInstanceVariable() throws Exception {
+ createLoaderIndirectAndCallMethod("test.TestMethods", "test_getInstanceVariable", dex1);
+ }
+
+ // TWO_DEX with direct ByteBuffer
+
+ public void test_twoDexDirect_simpleUse() throws Exception {
+ String result = (String) createLoaderDirectAndCallMethod("test.Test1", "test", dex1, dex2);
+ assertSame("blort", result);
+ }
+
+ public void test_twoDexDirect_constructor() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_constructor", dex1, dex2);
+ }
+
+ public void test_twoDexDirect_callStaticMethod() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_callStaticMethod", dex1, dex2);
+ }
+
+ public void test_twoDexDirect_getStaticVariable() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_getStaticVariable", dex1, dex2);
+ }
+
+ public void test_twoDexDirect_callInstanceMethod() throws Exception {
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_callInstanceMethod", dex1, dex2);
+ }
+
+ public void test_twoDexDirect_getInstanceVariable() throws Exception {
+ createLoaderDirectAndCallMethod(
+ "test.TestMethods", "test_getInstanceVariable", dex1, dex2);
+ }
+
+ public void test_twoDexDirect_target2_static_method() throws Exception {
+ String result =
+ (String) createLoaderDirectAndCallMethod("test2.Target2", "frotz", dex1, dex2);
+ assertSame("frotz", result);
+ }
+
+ public void test_twoDexDirect_diff_constructor() throws Exception {
+ // NB Ordering dex2 then dex1 as classloader's are nested and
+ // each only supports a single DEX image. The
+ // test.TestMethods.test_diff* methods depend on dex2 hence
+ // ordering.
+ createLoaderDirectAndCallMethod("test.TestMethods", "test_diff_constructor", dex2, dex1);
+ }
+
+ public void test_twoDexDirect_diff_callStaticMethod() throws Exception {
+ // NB See comment in test_twoDexDirect_diff_constructor.
+ createLoaderDirectAndCallMethod(
+ "test.TestMethods", "test_diff_callStaticMethod", dex2, dex1);
+ }
+
+ public void test_twoDexDirect_diff_getStaticVariable() throws Exception {
+ // NB See comment in test_twoDexDirect_diff_constructor.
+ createLoaderDirectAndCallMethod(
+ "test.TestMethods", "test_diff_getStaticVariable", dex2, dex1);
+ }
+
+ public void test_twoDexDirect_diff_callInstanceMethod() throws Exception {
+ // NB See comment in test_twoDexDirect_diff_constructor.
+ createLoaderDirectAndCallMethod(
+ "test.TestMethods", "test_diff_callInstanceMethod", dex2, dex1);
+ }
+
+ public void test_twoDexDirect_diff_getInstanceVariable() throws Exception {
+ // NB See comment in test_twoDexDirect_diff_constructor.
+ createLoaderDirectAndCallMethod(
+ "test.TestMethods", "test_diff_getInstanceVariable", dex2, dex1);
+ }
+}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index f98a55d..0beafae 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -635,4 +635,15 @@
}
}
}
+
+ public void test_readlink() throws Exception {
+ // ext2 and ext4 have PAGE_SIZE limits on symlink targets.
+ String xs = "";
+ for (int i = 0; i < (4096 - 1); ++i) xs += "x";
+
+ String path = System.getProperty("java.io.tmpdir") + "/symlink";
+ Libcore.os.symlink(xs, path);
+
+ assertEquals(xs, Libcore.os.readlink(path));
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/ClassTest.java b/luni/src/test/java/libcore/java/lang/ClassTest.java
index 69b7dc3..ba1351f 100644
--- a/luni/src/test/java/libcore/java/lang/ClassTest.java
+++ b/luni/src/test/java/libcore/java/lang/ClassTest.java
@@ -23,6 +23,10 @@
import junit.framework.TestCase;
import dalvik.system.PathClassLoader;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.TreeMap;
+import java.util.function.Function;
public class ClassTest extends TestCase {
@@ -120,4 +124,116 @@
fail("Got exception");
}
}
+
+ public void test_toString() throws Exception {
+ final String outerClassName = getClass().getName();
+ final String packageProtectedClassName = PackageProtectedClass.class.getName();
+
+ assertToString("int", int.class);
+ assertToString("class [I", int[].class);
+ assertToString("class java.lang.Object", Object.class);
+ assertToString("class [Ljava.lang.Object;", Object[].class);
+ assertToString("class java.lang.Integer", Integer.class);
+ assertToString("interface java.util.function.Function", Function.class);
+ assertToString(
+ "class " + outerClassName + "$PublicStaticInnerClass",
+ PublicStaticInnerClass.class);
+ assertToString(
+ "class " + outerClassName + "$DefaultStaticInnerClass",
+ DefaultStaticInnerClass.class);
+ assertToString(
+ "interface " + outerClassName + "$PublicInnerInterface",
+ PublicInnerInterface.class);
+ assertToString(
+ "class " + packageProtectedClassName,
+ PackageProtectedClass.class);
+ assertToString(
+ "class " + outerClassName + "$PrivateStaticInnerClass",
+ PrivateStaticInnerClass.class);
+ assertToString("interface java.lang.annotation.Retention", Retention.class);
+ assertToString("class java.lang.annotation.RetentionPolicy", RetentionPolicy.class);
+ assertToString("class java.util.TreeMap", TreeMap.class);
+ assertToString(
+ "interface " + outerClassName + "$WildcardInterface",
+ WildcardInterface.class);
+ }
+
+ private static void assertToString(String expected, Class<?> clazz) {
+ assertEquals(expected, clazz.toString());
+ }
+
+ public void test_getTypeName() throws Exception {
+ final String outerClassName = getClass().getName();
+ final String packageProtectedClassName = PackageProtectedClass.class.getName();
+
+ assertGetTypeName("int", int.class);
+ assertGetTypeName("int[]", int[].class);
+ assertGetTypeName("java.lang.Object", Object.class);
+ assertGetTypeName("java.lang.Object[]", Object[].class);
+ assertGetTypeName("java.lang.Integer", Integer.class);
+ assertGetTypeName("java.util.function.Function", Function.class);
+ assertGetTypeName(outerClassName + "$PublicStaticInnerClass", PublicStaticInnerClass.class);
+ assertGetTypeName(
+ outerClassName + "$DefaultStaticInnerClass",
+ DefaultStaticInnerClass.class);
+ assertGetTypeName(outerClassName + "$PublicInnerInterface", PublicInnerInterface.class);
+ assertGetTypeName(packageProtectedClassName, PackageProtectedClass.class);
+ assertGetTypeName(
+ outerClassName + "$PrivateStaticInnerClass",
+ PrivateStaticInnerClass.class);
+ assertGetTypeName("java.lang.annotation.Retention", Retention.class);
+ assertGetTypeName("java.lang.annotation.RetentionPolicy", RetentionPolicy.class);
+ assertGetTypeName("java.util.TreeMap", TreeMap.class);
+ assertGetTypeName(outerClassName + "$WildcardInterface", WildcardInterface.class);
+ }
+
+ private void assertGetTypeName(String expected, Class<?> clazz) {
+ assertEquals(expected, clazz.getTypeName());
+ }
+
+ public void test_toGenericString() throws Exception {
+ final String outerClassName = getClass().getName();
+ final String packageProtectedClassName = PackageProtectedClass.class.getName();
+
+ assertToGenericString("int", int.class);
+ assertToGenericString("public abstract final class [I", int[].class);
+ assertToGenericString("public class java.lang.Object", Object.class);
+ assertToGenericString("public abstract final class [Ljava.lang.Object;", Object[].class);
+ assertToGenericString("public final class java.lang.Integer", Integer.class);
+ assertToGenericString(
+ "public abstract interface java.util.function.Function<T,R>",
+ Function.class);
+ assertToGenericString("public static class " + outerClassName + "$PublicStaticInnerClass",
+ PublicStaticInnerClass.class);
+ assertToGenericString("static class " + outerClassName + "$DefaultStaticInnerClass",
+ DefaultStaticInnerClass.class);
+ assertToGenericString(
+ "public abstract static interface " + outerClassName + "$PublicInnerInterface",
+ PublicInnerInterface.class);
+ assertToGenericString("class " + packageProtectedClassName, PackageProtectedClass.class);
+ assertToGenericString(
+ "private static class " + outerClassName + "$PrivateStaticInnerClass",
+ PrivateStaticInnerClass.class);
+ assertToGenericString(
+ "public abstract @interface java.lang.annotation.Retention", Retention.class);
+ assertToGenericString("public final enum java.lang.annotation.RetentionPolicy",
+ RetentionPolicy.class);
+ assertToGenericString("public class java.util.TreeMap<K,V>", TreeMap.class);
+ assertToGenericString(
+ "abstract static interface " + outerClassName + "$WildcardInterface<T,U>",
+ WildcardInterface.class);
+ }
+
+ private static void assertToGenericString(String expected, Class<?> clazz) {
+ assertEquals(expected, clazz.toGenericString());
+ }
+
+ private static class PrivateStaticInnerClass {}
+ static class DefaultStaticInnerClass {}
+ public static class PublicStaticInnerClass {}
+ public interface PublicInnerInterface {}
+ interface WildcardInterface<
+ T extends Number,
+ U extends Function<? extends Number, ? super Number>>
+ extends Comparable<T> {}
}
diff --git a/luni/src/test/java/libcore/java/lang/OldThreadTest.java b/luni/src/test/java/libcore/java/lang/OldThreadTest.java
index 03031ac..9632680 100644
--- a/luni/src/test/java/libcore/java/lang/OldThreadTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldThreadTest.java
@@ -193,7 +193,7 @@
st = new Thread() {
public void run() {
try {
- sleep(10000);
+ sleep(1000);
} catch(InterruptedException ie) {
wasInterrupted = true;
}
@@ -203,7 +203,7 @@
st.start();
try {
- Thread.sleep(5000);
+ Thread.sleep(500);
} catch(InterruptedException e) {
fail("Unexpected InterruptedException was thrown");
}
@@ -211,7 +211,7 @@
st.interrupt();
try {
- Thread.sleep(5000);
+ Thread.sleep(500);
} catch(InterruptedException e) {
fail("Unexpected InterruptedException was thrown");
}
@@ -240,7 +240,7 @@
st = new Thread() {
public void run() {
try {
- sleep(10000, 99999);
+ sleep(1000, 9999);
} catch(InterruptedException ie) {
wasInterrupted = true;
}
@@ -250,7 +250,7 @@
st.start();
try {
- Thread.sleep(5000, 99999);
+ Thread.sleep(500, 9999);
} catch(InterruptedException e) {
fail("Unexpected InterruptedException was thrown");
}
@@ -258,7 +258,7 @@
st.interrupt();
try {
- Thread.sleep(5000);
+ Thread.sleep(500);
} catch(InterruptedException e) {
fail("Unexpected InterruptedException was thrown");
}
@@ -275,7 +275,7 @@
}
Counter countersYeld = new Counter(true);
try {
- Thread.sleep(11000);
+ Thread.sleep(1100);
} catch(InterruptedException ie) {}
for(Counter c:countersNotYeld) {
@@ -293,7 +293,7 @@
}
public void run() {
- for(int i = 0; i < 10000; i++) {
+ for(int i = 0; i < 1000; i++) {
if(isDoYield)
yield();
counter ++;
diff --git a/luni/src/test/java/libcore/java/lang/PackageProtectedClass.java b/luni/src/test/java/libcore/java/lang/PackageProtectedClass.java
new file mode 100644
index 0000000..95a253c
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/PackageProtectedClass.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.java.lang;
+
+/**
+ * Used by {@link ClassTest}.
+ */
+class PackageProtectedClass {
+}
diff --git a/luni/src/test/java/libcore/java/lang/SystemTest.java b/luni/src/test/java/libcore/java/lang/SystemTest.java
index f16c380..2dc9d49 100644
--- a/luni/src/test/java/libcore/java/lang/SystemTest.java
+++ b/luni/src/test/java/libcore/java/lang/SystemTest.java
@@ -126,8 +126,8 @@
public void testArrayCopyConcurrentModification() {
final AtomicBoolean done = new AtomicBoolean();
- final Object[] source = new Object[1024 * 1024];
- String[] target = new String[1024 * 1024];
+ final Object[] source = new Object[512 * 1024];
+ String[] target = new String[512 * 1024];
new Thread() {
@Override public void run() {
@@ -140,7 +140,7 @@
}
}.start();
- for (int i = 0; i < 8192; i++) {
+ for (int i = 0; i < 2048; i++) {
try {
System.arraycopy(source, 0, target, 0, source.length);
assertNull(target[source.length - 1]); // make sure the wrong type didn't sneak in
diff --git a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java
index d71b5b0..55e70033 100644
--- a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java
+++ b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java
@@ -102,11 +102,9 @@
* to finalize. Check that objects near that limit are okay.
*/
public void testWatchdogDoesNotFailForObjectsThatAreNearTheDeadline() throws Exception {
- CountDownLatch latch = new CountDownLatch(5);
+ CountDownLatch latch = new CountDownLatch(3);
createSlowFinalizer( 1, latch);
createSlowFinalizer(1000, latch);
- createSlowFinalizer(2000, latch);
- createSlowFinalizer(4000, latch);
createSlowFinalizer(8000, latch);
FinalizationTester.induceFinalization();
latch.await();
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ModifierTest.java b/luni/src/test/java/libcore/java/lang/reflect/ModifierTest.java
index 0505f2f..2d395c5 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/ModifierTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/ModifierTest.java
@@ -39,6 +39,10 @@
assertEquals(0xd3f, Modifier.methodModifiers());
}
+ public void test_parameterModifiers() {
+ assertEquals(0x10, Modifier.parameterModifiers());
+ }
+
public void test_isAbstractI() {
assertTrue(Modifier.isAbstract(Modifier.ABSTRACT));
assertTrue(!Modifier.isAbstract(-1 & ~Modifier.ABSTRACT));
diff --git a/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java b/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
index a251963..b21689e 100644
--- a/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
+++ b/luni/src/test/java/libcore/java/net/ServerSocketConcurrentCloseTest.java
@@ -73,7 +73,7 @@
* Test for b/27763633.
*/
public void testConcurrentServerSocketCloseReliablyThrows() {
- int numIterations = 200;
+ int numIterations = 100;
for (int i = 0; i < numIterations; i++) {
checkConnectIterationAndCloseSocket("Iteration " + (i+1) + " of " + numIterations,
/* msecPerIteration */ 50);
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
index a45002a..1e7cefe 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
@@ -69,10 +69,12 @@
private static final InetAddress UNICAST_IPv6_1 = lookup("2001:db8::1");
private static final InetAddress UNICAST_IPv6_2 = lookup("2001:db8::2");
- private NetworkInterface networkInterface1;
- private NetworkInterface IPV6networkInterface1;
+ private NetworkInterface ipv4NetworkInterface;
+ private NetworkInterface ipv6NetworkInterface;
private NetworkInterface loopbackInterface;
+ private boolean supportsMulticast;
+
@Override
protected void setUp() throws Exception {
// The loopback interface isn't actually useful for sending/receiving multicast messages
@@ -84,39 +86,39 @@
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
- // only consider interfaces that have addresses associated with them.
- // Otherwise tests don't work so well
- if (interfaces != null) {
- boolean atLeastOneInterface = false;
- while (interfaces.hasMoreElements() && (atLeastOneInterface == false)) {
- networkInterface1 = interfaces.nextElement();
- if (willWorkForMulticast(networkInterface1)) {
- atLeastOneInterface = true;
- }
- }
+ // Determine if the device is marked to support multicast or not. If this propery is not
+ // set we assume the device has an interface capable of supporting multicast.
+ supportsMulticast = Boolean.parseBoolean(
+ System.getProperty("android.cts.device.multicast", "true"));
+ if (!supportsMulticast) {
+ return;
+ }
- assertTrue("Test environment must have at least one environment capable of multicast",
- atLeastOneInterface);
-
- // Find the first multicast-compatible interface that supports IPV6 if one exists
- interfaces = NetworkInterface.getNetworkInterfaces();
-
- boolean found = false;
- while (interfaces.hasMoreElements() && !found) {
- NetworkInterface nextInterface = interfaces.nextElement();
- if (willWorkForMulticast(nextInterface)) {
- Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
- while (addresses.hasMoreElements()) {
- final InetAddress nextAddress = addresses.nextElement();
- if (nextAddress instanceof Inet6Address) {
- IPV6networkInterface1 = nextInterface;
- found = true;
- break;
- }
+ while (interfaces.hasMoreElements()
+ && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
+ NetworkInterface nextInterface = interfaces.nextElement();
+ if (willWorkForMulticast(nextInterface)) {
+ Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
+ final InetAddress nextAddress = addresses.nextElement();
+ if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
+ ipv6NetworkInterface = nextInterface;
+ } else if (nextAddress instanceof Inet4Address
+ && ipv4NetworkInterface == null) {
+ ipv4NetworkInterface = nextInterface;
}
}
}
}
+
+ if (ipv4NetworkInterface == null) {
+ fail("Test environment must have at least one network interface capable of IPv4"
+ + " multicast");
+ }
+ if (ipv6NetworkInterface == null) {
+ fail("Test environment must have at least one network interface capable of IPv6"
+ + " multicast");
+ }
}
public void test_open() throws IOException {
@@ -147,19 +149,25 @@
}
public void test_joinAnySource_afterClose() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
dc.close();
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
fail();
} catch (ClosedChannelException expected) {
}
}
public void test_joinAnySource_nullGroupAddress() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(null, networkInterface1);
+ dc.join(null, ipv4NetworkInterface);
fail();
} catch (NullPointerException expected) {
}
@@ -167,6 +175,9 @@
}
public void test_joinAnySource_nullNetworkInterface() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
dc.join(GOOD_MULTICAST_IPv4, null);
@@ -177,9 +188,12 @@
}
public void test_joinAnySource_nonMulticastGroupAddress_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(UNICAST_IPv4_1, networkInterface1);
+ dc.join(UNICAST_IPv4_1, ipv4NetworkInterface);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -187,9 +201,12 @@
}
public void test_joinAnySource_nonMulticastGroupAddress_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(UNICAST_IPv6_1, networkInterface1);
+ dc.join(UNICAST_IPv6_1, ipv6NetworkInterface);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -197,18 +214,22 @@
}
public void test_joinAnySource_IPv4() throws Exception {
- test_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4);
+ test_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4, ipv4NetworkInterface);
}
public void test_joinAnySource_IPv6() throws Exception {
- test_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6);
+ test_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6, ipv6NetworkInterface);
}
- private void test_joinAnySource(InetAddress group, InetAddress group2) throws Exception {
- // Set up a receiver join the group on networkInterface1
+ private void test_joinAnySource(InetAddress group, InetAddress group2,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
+ // Set up a receiver join the group on ipv4NetworkInterface
DatagramChannel receiverChannel = createReceiverChannel();
InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress();
- receiverChannel.join(group, networkInterface1);
+ receiverChannel.join(group, networkInterface);
String msg = "Hello World";
sendMulticastMessage(group, localAddress.getPort(), msg);
@@ -230,11 +251,14 @@
}
public void test_joinAnySource_processLimit() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
for (byte i = 1; i <= 25; i++) {
InetAddress groupAddress = Inet4Address.getByName("239.255.0." + i);
try {
- dc.join(groupAddress, networkInterface1);
+ dc.join(groupAddress, ipv4NetworkInterface);
} catch (SocketException e) {
// There is a limit, that's ok according to the RI docs. For this test a lower bound of 20
// is used, which appears to be the default linux limit.
@@ -248,8 +272,11 @@
}
public void test_joinAnySource_blockLimit() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
for (byte i = 1; i <= 15; i++) {
InetAddress sourceAddress = Inet4Address.getByName("10.0.0." + i);
try {
@@ -268,14 +295,20 @@
/** Confirms that calling join() does not cause an implicit bind() to take place. */
public void test_joinAnySource_doesNotCauseBind() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = DatagramChannel.open();
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
assertNull(dc.getLocalAddress());
dc.close();
}
public void test_joinAnySource_networkInterfaces() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
// Check that we can join on specific interfaces and that we only receive if data is
// received on that interface. This test is only really useful on devices with multiple
// non-loopback interfaces.
@@ -309,11 +342,11 @@
InetAddress firstAddress = addresses.nextElement();
if (firstAddress instanceof Inet4Address) {
group = GOOD_MULTICAST_IPv4;
- sendingInterface = networkInterface1;
+ sendingInterface = ipv4NetworkInterface;
} else {
// if this interface only seems to support IPV6 addresses
group = GOOD_MULTICAST_IPv6;
- sendingInterface = IPV6networkInterface1;
+ sendingInterface = ipv6NetworkInterface;
}
}
@@ -340,8 +373,11 @@
/** Confirms that the scope of each membership is network interface-level. */
public void test_join_canMixTypesOnDifferentInterfaces() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = DatagramChannel.open();
- MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
MembershipKey membershipKey2 = dc.join(GOOD_MULTICAST_IPv4, loopbackInterface, UNICAST_IPv4_1);
assertNotSame(membershipKey1, membershipKey2);
@@ -358,43 +394,51 @@
public void test_joinAnySource_multiple_joins_IPv4()
throws Exception {
- test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4);
+ test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
}
public void test_joinAnySource_multiple_joins_IPv6()
throws Exception {
- test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6);
+ test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
}
- private void test_joinAnySource_multiple_joins(InetAddress group) throws Exception {
+ private void test_joinAnySource_multiple_joins(InetAddress group,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey1 = dc.join(group, networkInterface1);
+ MembershipKey membershipKey1 = dc.join(group, networkInterface);
MembershipKey membershipKey2 = dc.join(group, loopbackInterface);
assertFalse(membershipKey1.equals(membershipKey2));
- MembershipKey membershipKey1_2 = dc.join(group, networkInterface1);
+ MembershipKey membershipKey1_2 = dc.join(group, networkInterface);
assertEquals(membershipKey1, membershipKey1_2);
dc.close();
}
public void test_joinAnySource_multicastLoopOption_IPv4() throws Exception {
- test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4);
+ test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
}
public void test_multicastLoopOption_IPv6() throws Exception {
- test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6);
+ test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
}
- private void test_joinAnySource_multicastLoopOption(InetAddress group) throws Exception {
+ private void test_joinAnySource_multicastLoopOption(InetAddress group,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
final String message = "Hello, world!";
DatagramChannel dc = createReceiverChannel();
dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */);
configureChannelForReceiving(dc);
- dc.join(group, networkInterface1);
+ dc.join(group, networkInterface);
InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
@@ -426,35 +470,43 @@
}
public void testMembershipKeyAccessors_IPv4() throws Exception {
- testMembershipKeyAccessors(GOOD_MULTICAST_IPv4);
+ testMembershipKeyAccessors(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
}
public void testMembershipKeyAccessors_IPv6() throws Exception {
- testMembershipKeyAccessors(GOOD_MULTICAST_IPv6);
+ testMembershipKeyAccessors(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
}
- private void testMembershipKeyAccessors(InetAddress group) throws Exception {
+ private void testMembershipKeyAccessors(InetAddress group,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey key = dc.join(group, networkInterface1);
+ MembershipKey key = dc.join(group, networkInterface);
assertSame(dc, key.channel());
assertSame(group, key.group());
assertTrue(key.isValid());
- assertSame(networkInterface1, key.networkInterface());
+ assertSame(networkInterface, key.networkInterface());
assertNull(key.sourceAddress());
}
public void test_dropAnySource_twice_IPv4() throws Exception {
- test_dropAnySource_twice(GOOD_MULTICAST_IPv4);
+ test_dropAnySource_twice(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
}
public void test_dropAnySource_twice_IPv6() throws Exception {
- test_dropAnySource_twice(GOOD_MULTICAST_IPv6);
+ test_dropAnySource_twice(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
}
- private void test_dropAnySource_twice(InetAddress group) throws Exception {
+ private void test_dropAnySource_twice(InetAddress group,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(group, networkInterface1);
+ MembershipKey membershipKey = dc.join(group, networkInterface);
assertTrue(membershipKey.isValid());
membershipKey.drop();
@@ -467,8 +519,11 @@
}
public void test_close_invalidatesMembershipKey() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
assertTrue(membershipKey.isValid());
@@ -478,8 +533,11 @@
}
public void test_block_null() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
try {
membershipKey.block(null);
fail();
@@ -490,8 +548,11 @@
}
public void test_block_mixedAddressTypes_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
try {
membershipKey.block(UNICAST_IPv6_1);
fail();
@@ -502,8 +563,11 @@
}
public void test_block_mixedAddressTypes_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
try {
membershipKey.block(UNICAST_IPv4_1);
fail();
@@ -514,8 +578,11 @@
}
public void test_block_cannotBlockWithSourceSpecificMembership() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
try {
membershipKey.block(UNICAST_IPv4_2);
fail();
@@ -526,8 +593,11 @@
}
public void test_block_multipleBlocksIgnored() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
membershipKey.block(UNICAST_IPv4_1);
MembershipKey membershipKey2 = membershipKey.block(UNICAST_IPv4_1);
@@ -537,8 +607,11 @@
}
public void test_block_wildcardAddress() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
try {
membershipKey.block(WILDCARD_IPv4);
fail();
@@ -549,8 +622,11 @@
}
public void test_unblock_multipleUnblocksFail() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
try {
membershipKey.unblock(UNICAST_IPv4_1);
@@ -573,8 +649,11 @@
}
public void test_unblock_null() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
membershipKey.block(UNICAST_IPv4_1);
try {
@@ -590,8 +669,11 @@
}
public void test_unblock_mixedAddressTypes_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface);
try {
membershipKey.unblock(UNICAST_IPv6_1);
fail();
@@ -605,8 +687,11 @@
}
public void test_unblock_mixedAddressTypes_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, networkInterface1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface);
try {
membershipKey.unblock(UNICAST_IPv4_1);
fail();
@@ -621,44 +706,51 @@
/** Checks that block() works when the receiver is bound to the multicast group address */
public void test_block_filtersAsExpected_groupBind_ipv4() throws Exception {
- InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
+ InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
test_block_filtersAsExpected(
ipv4LocalAddress /* senderBindAddress */,
GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
- GOOD_MULTICAST_IPv4 /* groupAddress */);
+ GOOD_MULTICAST_IPv4 /* groupAddress */,
+ ipv4NetworkInterface);
}
/** Checks that block() works when the receiver is bound to the multicast group address */
public void test_block_filtersAsExpected_groupBind_ipv6() throws Exception {
- InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
+ InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
test_block_filtersAsExpected(
ipv6LocalAddress /* senderBindAddress */,
GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
- GOOD_MULTICAST_IPv6 /* groupAddress */);
+ GOOD_MULTICAST_IPv6 /* groupAddress */,
+ ipv6NetworkInterface);
}
/** Checks that block() works when the receiver is bound to the "any" address */
public void test_block_filtersAsExpected_anyBind_ipv4() throws Exception {
- InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
+ InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
test_block_filtersAsExpected(
ipv4LocalAddress /* senderBindAddress */,
WILDCARD_IPv4 /* receiverBindAddress */,
- GOOD_MULTICAST_IPv4 /* groupAddress */);
+ GOOD_MULTICAST_IPv4 /* groupAddress */,
+ ipv4NetworkInterface);
}
/** Checks that block() works when the receiver is bound to the "any" address */
public void test_block_filtersAsExpected_anyBind_ipv6() throws Exception {
- InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
+ InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
test_block_filtersAsExpected(
ipv6LocalAddress /* senderBindAddress */,
WILDCARD_IPv6 /* receiverBindAddress */,
- GOOD_MULTICAST_IPv6 /* groupAddress */);
+ GOOD_MULTICAST_IPv6 /* groupAddress */,
+ ipv6NetworkInterface);
}
private void test_block_filtersAsExpected(
- InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress)
+ InetAddress senderBindAddress, InetAddress receiverBindAddress,
+ InetAddress groupAddress, NetworkInterface networkInterface)
throws Exception {
-
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel sendingChannel = DatagramChannel.open();
// In order to block a sender the sender's address must be known. The sendingChannel is
// explicitly bound to a known, non-loopback address.
@@ -674,7 +766,7 @@
InetSocketAddress groupSocketAddress =
new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
MembershipKey membershipKey =
- receivingChannel.join(groupSocketAddress.getAddress(), networkInterface1);
+ receivingChannel.join(groupSocketAddress.getAddress(), networkInterface);
ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
@@ -711,9 +803,12 @@
}
public void test_joinSourceSpecific_nullGroupAddress() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(null, networkInterface1, UNICAST_IPv4_1);
+ dc.join(null, ipv4NetworkInterface, UNICAST_IPv4_1);
fail();
} catch (NullPointerException expected) {
}
@@ -721,16 +816,22 @@
}
public void test_joinSourceSpecific_afterClose() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
dc.close();
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
fail();
} catch (ClosedChannelException expected) {
}
}
public void test_joinSourceSpecific_nullNetworkInterface() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
dc.join(GOOD_MULTICAST_IPv4, null, UNICAST_IPv4_1);
@@ -741,9 +842,12 @@
}
public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(UNICAST_IPv4_1, networkInterface1, UNICAST_IPv4_1);
+ dc.join(UNICAST_IPv4_1, ipv4NetworkInterface, UNICAST_IPv4_1);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -751,9 +855,12 @@
}
public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(UNICAST_IPv6_1, IPV6networkInterface1, UNICAST_IPv6_1);
+ dc.join(UNICAST_IPv6_1, ipv6NetworkInterface, UNICAST_IPv6_1);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -761,9 +868,12 @@
}
public void test_joinSourceSpecific_nullSourceAddress_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1, null);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, null);
fail();
} catch (NullPointerException expected) {
}
@@ -771,9 +881,12 @@
}
public void test_joinSourceSpecific_nullSourceAddress_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(GOOD_MULTICAST_IPv6, networkInterface1, null);
+ dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, null);
fail();
} catch (NullPointerException expected) {
}
@@ -781,14 +894,17 @@
}
public void test_joinSourceSpecific_mixedAddressTypes() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv6_1);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv6_1);
fail();
} catch (IllegalArgumentException expected) {
}
try {
- dc.join(GOOD_MULTICAST_IPv6, networkInterface1, UNICAST_IPv4_1);
+ dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, UNICAST_IPv4_1);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -796,9 +912,12 @@
}
public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv4() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1, BAD_MULTICAST_IPv4);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, BAD_MULTICAST_IPv4);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -806,9 +925,12 @@
}
public void test_joinSourceSpecific_nonUniicastSourceAddress_IPv6() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
try {
- dc.join(GOOD_MULTICAST_IPv6, networkInterface1, BAD_MULTICAST_IPv6);
+ dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, BAD_MULTICAST_IPv6);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -816,11 +938,14 @@
}
public void test_joinSourceSpecific_multipleSourceAddressLimit() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
for (byte i = 1; i <= 20; i++) {
InetAddress sourceAddress = Inet4Address.getByAddress(new byte[] { 10, 0, 0, i});
try {
- dc.join(GOOD_MULTICAST_IPv4, networkInterface1, sourceAddress);
+ dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, sourceAddress);
} catch (SocketException e) {
// There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
// is used, which appears to be the default linux limit. See /proc/sys/net/ipv4/igmp_max_msf
@@ -837,12 +962,13 @@
* address
*/
public void test_joinSourceSpecific_null() throws Exception {
- InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
+ InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
test_joinSourceSpecific(
ipv4LocalAddress /* senderBindAddress */,
GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
GOOD_MULTICAST_IPv4 /* groupAddress */,
- UNICAST_IPv4_1 /* badSenderAddress */);
+ UNICAST_IPv4_1 /* badSenderAddress */,
+ ipv4NetworkInterface);
}
/**
@@ -850,12 +976,13 @@
* address
*/
public void test_joinSourceSpecific_groupBind_ipv4() throws Exception {
- InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
+ InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
test_joinSourceSpecific(
ipv4LocalAddress /* senderBindAddress */,
GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
GOOD_MULTICAST_IPv4 /* groupAddress */,
- UNICAST_IPv4_1 /* badSenderAddress */);
+ UNICAST_IPv4_1 /* badSenderAddress */,
+ ipv6NetworkInterface);
}
/**
@@ -863,32 +990,35 @@
* address
*/
public void test_joinSourceSpecific_groupBind_ipv6() throws Exception {
- InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
+ InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
test_joinSourceSpecific(
ipv6LocalAddress /* senderBindAddress */,
GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
GOOD_MULTICAST_IPv6 /* groupAddress */,
- UNICAST_IPv6_1 /* badSenderAddress */);
+ UNICAST_IPv6_1 /* badSenderAddress */,
+ ipv6NetworkInterface);
}
/** Checks that a source-specific join() works when the receiver is bound to the "any" address */
public void test_joinSourceSpecific_anyBind_ipv4() throws Exception {
- InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
+ InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface);
test_joinSourceSpecific(
ipv4LocalAddress /* senderBindAddress */,
WILDCARD_IPv4 /* receiverBindAddress */,
GOOD_MULTICAST_IPv4 /* groupAddress */,
- UNICAST_IPv4_1 /* badSenderAddress */);
+ UNICAST_IPv4_1 /* badSenderAddress */,
+ ipv4NetworkInterface);
}
/** Checks that a source-specific join() works when the receiver is bound to the "any" address */
public void test_joinSourceSpecific_anyBind_ipv6() throws Exception {
- InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
+ InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface);
test_joinSourceSpecific(
ipv6LocalAddress /* senderBindAddress */,
WILDCARD_IPv6 /* receiverBindAddress */,
GOOD_MULTICAST_IPv6 /* groupAddress */,
- UNICAST_IPv6_1 /* badSenderAddress */);
+ UNICAST_IPv6_1 /* badSenderAddress */,
+ ipv6NetworkInterface);
}
/**
@@ -901,8 +1031,11 @@
*/
private void test_joinSourceSpecific(
InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress,
- InetAddress badSenderAddress)
+ InetAddress badSenderAddress, NetworkInterface networkInterface)
throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel sendingChannel = DatagramChannel.open();
// In order to be source-specific the sender's address must be known. The sendingChannel is
// explicitly bound to a known, non-loopback address.
@@ -919,7 +1052,7 @@
InetSocketAddress groupSocketAddress =
new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
MembershipKey membershipKey1 = receivingChannel
- .join(groupSocketAddress.getAddress(), networkInterface1, senderBindAddress);
+ .join(groupSocketAddress.getAddress(), networkInterface, senderBindAddress);
ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
@@ -932,7 +1065,7 @@
membershipKey1.drop();
- receivingChannel.join(groupSocketAddress.getAddress(), networkInterface1, badSenderAddress);
+ receivingChannel.join(groupSocketAddress.getAddress(), networkInterface, badSenderAddress);
// Send a message. It should not be received.
String msg2 = "Hello2";
@@ -946,18 +1079,24 @@
public void test_dropSourceSpecific_twice_IPv4() throws Exception {
test_dropSourceSpecific_twice(
- GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */);
+ GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */,
+ ipv4NetworkInterface);
}
public void test_dropSourceSpecific_twice_IPv6() throws Exception {
test_dropSourceSpecific_twice(
- GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */);
+ GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */,
+ ipv6NetworkInterface);
}
- private void test_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress)
+ private void test_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress,
+ NetworkInterface networkInterface)
throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(groupAddress, networkInterface1, sourceAddress);
+ MembershipKey membershipKey = dc.join(groupAddress, networkInterface, sourceAddress);
assertTrue(membershipKey.isValid());
membershipKey.drop();
@@ -973,22 +1112,27 @@
test_dropSourceSpecific_sourceKeysAreIndependent(
GOOD_MULTICAST_IPv4 /* groupAddress */,
UNICAST_IPv4_1 /* sourceAddress1 */,
- UNICAST_IPv4_2 /* sourceAddress2 */);
+ UNICAST_IPv4_2 /* sourceAddress2 */,
+ ipv4NetworkInterface);
}
public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv6() throws Exception {
test_dropSourceSpecific_sourceKeysAreIndependent(
GOOD_MULTICAST_IPv6 /* groupAddress */,
UNICAST_IPv6_1 /* sourceAddress1 */,
- UNICAST_IPv6_2 /* sourceAddress2 */);
+ UNICAST_IPv6_2 /* sourceAddress2 */,
+ ipv6NetworkInterface);
}
private void test_dropSourceSpecific_sourceKeysAreIndependent(
- InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2)
- throws Exception {
+ InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2,
+ NetworkInterface networkInterface) throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface1, sourceAddress1);
- MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface1, sourceAddress2);
+ MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface, sourceAddress1);
+ MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface, sourceAddress2);
assertFalse(membershipKey1.equals(membershipKey2));
assertTrue(membershipKey1.isValid());
assertTrue(membershipKey2.isValid());
@@ -1002,8 +1146,11 @@
}
public void test_drop_keyBehaviorAfterDrop() throws Exception {
+ if (!supportsMulticast) {
+ return;
+ }
DatagramChannel dc = createReceiverChannel();
- MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+ MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1);
membershipKey.drop();
assertFalse(membershipKey.isValid());
@@ -1020,7 +1167,7 @@
assertSame(dc, membershipKey.channel());
assertSame(GOOD_MULTICAST_IPv4, membershipKey.group());
assertSame(UNICAST_IPv4_1, membershipKey.sourceAddress());
- assertSame(networkInterface1, membershipKey.networkInterface());
+ assertSame(ipv4NetworkInterface, membershipKey.networkInterface());
}
private static void configureChannelForReceiving(DatagramChannel receivingChannel)
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileStoreTest.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileStoreTest.java
index c15aa31..763efbf 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultFileStoreTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileStoreTest.java
@@ -47,7 +47,7 @@
@Test
public void test_name() throws IOException, InterruptedException {
- Path path = Paths.get(filesSetup.getTestDir(), "dir");
+ Path path = filesSetup.getPathInTestDir("dir");
Files.createDirectory(path);
Process p = execCmdAndWaitForTermination("df", path.toAbsolutePath().toString());
String shellOutput = readFromInputStream(p.getInputStream()).split("\n")[1];
@@ -57,7 +57,7 @@
@Test
public void test_type() throws IOException, InterruptedException {
- Path path = Paths.get(filesSetup.getTestDir(), "dir");
+ Path path = filesSetup.getPathInTestDir("dir");
Files.createDirectory(path);
String fileStore = Files.getFileStore(path).name();
Process p = execCmdAndWaitForTermination("mount");
@@ -103,7 +103,7 @@
@Test
public void test_supportsFileAttributeView$Class() throws IOException {
- Path path = Paths.get(filesSetup.getTestDir(), "dir");
+ Path path = filesSetup.getPathInTestDir("dir");
Files.createDirectories(path);
assertTrue(Files.getFileStore(path).supportsFileAttributeView(
BasicFileAttributeView.class));
@@ -120,7 +120,7 @@
@Test
public void test_supportsFileAttributeView$String() throws IOException {
- Path path = Paths.get(filesSetup.getTestDir(), "dir");
+ Path path = filesSetup.getPathInTestDir("dir");
Files.createDirectories(path);
assertTrue(Files.getFileStore(path).supportsFileAttributeView("basic"));
assertTrue(Files.getFileStore(path).supportsFileAttributeView("unix"));
@@ -133,7 +133,7 @@
@Test
public void test_getFileStoreAttributeView() throws IOException {
- Path path = Paths.get(filesSetup.getTestDir(), "dir");
+ Path path = filesSetup.getPathInTestDir("dir");
Files.createDirectories(path);
assertNull(Files.getFileStore(path).getFileStoreAttributeView(
FileStoreAttributeView.class));
@@ -145,7 +145,7 @@
@Test
public void test_getAttribute() throws IOException {
- Path p = Paths.get(filesSetup.getTestDir(), "dir");
+ Path p = filesSetup.getPathInTestDir("dir");
Files.createDirectories(p);
FileStore store = Files.getFileStore(p);
assertEquals(store.getTotalSpace(), store.getAttribute("totalSpace"));
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
new file mode 100644
index 0000000..04be662
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.nio.file;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryNotEmptyException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.NotLinkException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static libcore.java.nio.file.FilesSetup.DATA_FILE;
+import static libcore.java.nio.file.FilesSetup.NonStandardOption;
+import static libcore.java.nio.file.FilesSetup.TEST_FILE_DATA;
+import static libcore.java.nio.file.FilesSetup.TEST_FILE_DATA_2;
+import static libcore.java.nio.file.FilesSetup.readFromFile;
+import static libcore.java.nio.file.FilesSetup.writeToFile;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+public class DefaultFileSystemProvider2Test {
+
+ @Rule
+ public FilesSetup filesSetup = new FilesSetup();
+
+ private FileSystemProvider provider;
+
+ @Before
+ public void setUp() throws Exception {
+ provider = filesSetup.getDataFilePath().getFileSystem().provider();
+ }
+
+ @Test
+ public void test_move() throws IOException {
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath());
+ assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getTestPath()));
+ assertFalse(Files.exists(filesSetup.getDataFilePath()));
+
+ filesSetup.reset();
+ Files.createFile(filesSetup.getTestPath());
+ // When target file exists.
+ try {
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath());
+ fail();
+ } catch (FileAlreadyExistsException expected) {}
+
+ // Move to existing target file with REPLACE_EXISTING copy option.
+ filesSetup.reset();
+ Files.createFile(filesSetup.getTestPath());
+ writeToFile(filesSetup.getDataFilePath(), TEST_FILE_DATA_2);
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath(), REPLACE_EXISTING);
+ assertEquals(TEST_FILE_DATA_2, readFromFile(filesSetup.getTestPath()));
+
+ // Copy from a non existent file.
+ filesSetup.reset();
+ try {
+ provider.move(filesSetup.getTestPath(), filesSetup.getDataFilePath(), REPLACE_EXISTING);
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_move_CopyOption() throws IOException {
+ FileTime fileTime = FileTime.fromMillis(System.currentTimeMillis() - 10000);
+ Files.setAttribute(filesSetup.getDataFilePath(), "basic:lastModifiedTime", fileTime);
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath());
+ assertEquals(fileTime.to(TimeUnit.SECONDS),
+ ((FileTime) Files.getAttribute(filesSetup.getTestPath(),
+ "basic:lastModifiedTime")).to(TimeUnit.SECONDS));
+ assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getTestPath()));
+
+ // ATOMIC_MOVE
+ filesSetup.reset();
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath(), ATOMIC_MOVE);
+ assertEquals(TEST_FILE_DATA, readFromFile(filesSetup.getTestPath()));
+
+ filesSetup.reset();
+ try {
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath(),
+ NonStandardOption.OPTION1);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ @Test
+ public void test_move_NPE() throws IOException {
+ try {
+ provider.move(null, filesSetup.getTestPath());
+ fail();
+ } catch(NullPointerException expected) {}
+
+ try {
+ provider.move(filesSetup.getDataFilePath(), null);
+ fail();
+ } catch(NullPointerException expected) {}
+
+ try {
+ provider.move(filesSetup.getDataFilePath(), filesSetup.getTestPath(),
+ (CopyOption[]) null);
+ fail();
+ } catch(NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_move_directory() throws IOException {
+ Path dirPath = filesSetup.getPathInTestDir("dir1");
+ final Path nestedDirPath = filesSetup.getPathInTestDir("dir1/dir");
+ final Path dirPath2 = filesSetup.getPathInTestDir("dir2");
+
+ Files.createDirectory(dirPath);
+ Files.createDirectory(nestedDirPath);
+ Files.copy(filesSetup.getDataFilePath(),
+ filesSetup.getPathInTestDir("dir1/" + DATA_FILE));
+ provider.move(dirPath, dirPath2);
+
+ Map<Path, Boolean> pathMap = new HashMap<>();
+ try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(dirPath2)) {
+ directoryStream.forEach(file -> pathMap.put(file, true));
+ }
+
+ // The files are not copied. The command is equivalent of creating a new directory.
+ assertEquals(2, pathMap.size());
+ assertEquals(TEST_FILE_DATA,
+ readFromFile(filesSetup.getPathInTestDir("dir2/" + DATA_FILE)));
+ assertFalse(Files.exists(dirPath));
+
+ filesSetup.reset();
+ }
+
+ @Test
+ public void test_move_directory_DirectoryNotEmptyException() throws IOException {
+ Path dirPath = filesSetup.getPathInTestDir("dir1");
+ Path dirPath4 = filesSetup.getPathInTestDir("dir4");
+ Files.createDirectory(dirPath);
+ Files.createDirectory(dirPath4);
+ Files.createFile(Paths.get(dirPath.toString(), DATA_FILE));
+ Files.createFile(Paths.get(dirPath4.toString(), DATA_FILE));
+ try {
+ Files.copy(dirPath, dirPath4, REPLACE_EXISTING);
+ fail();
+ } catch (DirectoryNotEmptyException expected) {}
+ }
+
+ @Test
+ public void test_readSymbolicLink() throws IOException {
+ provider.createSymbolicLink(/* Path of the symbolic link */ filesSetup.getTestPath(),
+ /* Path of the target of the symbolic link */
+ filesSetup.getDataFilePath().toAbsolutePath());
+ assertEquals(filesSetup.getDataFilePath().toAbsolutePath(),
+ Files.readSymbolicLink(filesSetup.getTestPath()));
+
+ // Sym link to itself
+ filesSetup.reset();
+ provider.createSymbolicLink(/* Path of the symbolic link */ filesSetup.getTestPath(),
+ /* Path of the target of the symbolic link */
+ filesSetup.getTestPath().toAbsolutePath());
+ assertEquals(filesSetup.getTestPath().toAbsolutePath(),
+ Files.readSymbolicLink(filesSetup.getTestPath()));
+
+ filesSetup.reset();
+ try {
+ provider.readSymbolicLink(filesSetup.getDataFilePath());
+ fail();
+ } catch (NotLinkException expected) {
+ }
+ }
+
+ @Test
+ public void test_readSymbolicLink_NPE() throws IOException {
+ try {
+ provider.readSymbolicLink(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isSameFile() throws IOException {
+ // When both the files exists.
+ assertTrue(provider.isSameFile(filesSetup.getDataFilePath(), filesSetup.getDataFilePath()));
+
+ // When the files doesn't exist.
+ assertTrue(provider.isSameFile(filesSetup.getTestPath(), filesSetup.getTestPath()));
+
+ // With two different files.
+ try {
+ assertFalse(
+ provider.isSameFile(filesSetup.getDataFilePath(), filesSetup.getTestPath()));
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_isSameFile_NPE() throws IOException {
+ try {
+ provider.isSameFile(null, filesSetup.getDataFilePath());
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ provider.isSameFile(filesSetup.getDataFilePath(), null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_getFileStore() throws IOException {
+ FileStore fileStore = provider.getFileStore(filesSetup.getDataFilePath());
+ assertNotNull(fileStore);
+ }
+
+ @Test
+ public void test_getFileStore_NPE() throws IOException {
+ try {
+ provider.getFileStore(null);
+ fail();
+ } catch(NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isHidden() throws IOException {
+ assertFalse(provider.isHidden(filesSetup.getDataFilePath()));
+ Files.setAttribute(filesSetup.getDataFilePath(), "dos:hidden", true);
+
+ // Files can't be hid.
+ assertFalse(provider.isHidden(filesSetup.getDataFilePath()));
+ }
+
+ @Test
+ public void test_isHidden_NPE() throws IOException {
+ try {
+ provider.isHidden(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_probeContentType_NPE() throws IOException {
+ try {
+ Files.probeContentType(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_getFileAttributeView() throws IOException {
+ BasicFileAttributeView fileAttributeView = provider
+ .getFileAttributeView(filesSetup.getDataFilePath(),
+ BasicFileAttributeView.class);
+
+ assertTrue(fileAttributeView.readAttributes().isRegularFile());
+ assertFalse(fileAttributeView.readAttributes().isDirectory());
+ }
+
+ @Test
+ public void test_getFileAttributeView_NPE() throws IOException {
+ try {
+ provider.getFileAttributeView(null, BasicFileAttributeView.class);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ provider.getFileAttributeView(filesSetup.getDataFilePath(), null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_readAttributes() throws IOException {
+ FileTime fileTime = FileTime.fromMillis(System.currentTimeMillis() - 10000);
+ Files.setAttribute(filesSetup.getDataFilePath(), "basic:lastModifiedTime", fileTime);
+ BasicFileAttributes basicFileAttributes = provider
+ .readAttributes(filesSetup.getDataFilePath(),
+ BasicFileAttributes.class);
+ FileTime lastModifiedTime = basicFileAttributes.lastModifiedTime();
+ assertEquals(fileTime.to(TimeUnit.SECONDS), lastModifiedTime.to(TimeUnit.SECONDS));
+
+ // When file is NON_EXISTENT.
+ try {
+ provider.readAttributes(filesSetup.getTestPath(), BasicFileAttributes.class);
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_readAttributes_NPE() throws IOException {
+ try {
+ provider.readAttributes(filesSetup.getDataFilePath(),
+ (Class<BasicFileAttributes>) null);
+ fail();
+ } catch(NullPointerException expected) {}
+
+ try {
+ provider.readAttributes(null, BasicFileAttributes.class);
+ fail();
+ } catch(NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_setAttribute() throws IOException {
+ // Other tests are covered in test_readAttributes.
+ // When file is NON_EXISTENT.
+ try {
+ FileTime fileTime = FileTime.fromMillis(System.currentTimeMillis());
+ provider.setAttribute(filesSetup.getTestPath(), "basic:lastModifiedTime", fileTime);
+ fail();
+ } catch (NoSuchFileException expected) {}
+
+ // ClassCastException
+ try {
+ provider.setAttribute(filesSetup.getDataFilePath(), "basic:lastModifiedTime", 10);
+ fail();
+ } catch (ClassCastException expected) {}
+
+ // IllegalArgumentException
+ try {
+ provider.setAttribute(filesSetup.getDataFilePath(), "xyz", 10);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ try {
+ provider.setAttribute(null, "xyz", 10);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ provider.setAttribute(filesSetup.getDataFilePath(), null, 10);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProviderTest.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProviderTest.java
index 3b1d65a..f14f68d 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProviderTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProviderTest.java
@@ -398,7 +398,7 @@
@Test
public void test_createDirectory() throws IOException {
// Check if createDirectory is actually creating a directory.
- Path newDirectory = Paths.get(filesSetup.getTestDir(), "newDir");
+ Path newDirectory = filesSetup.getPathInTestDir("newDir");
assertFalse(Files.exists(newDirectory));
assertFalse(Files.isDirectory(newDirectory));
@@ -415,7 +415,7 @@
}
// File with unicode name.
- Path unicodeFilePath = Paths.get(filesSetup.getTestDir(), "टेस्ट डायरेक्टरी");
+ Path unicodeFilePath = filesSetup.getPathInTestDir("टेस्ट डायरेक्टरी");
provider.createDirectory(unicodeFilePath);
assertTrue(Files.exists(unicodeFilePath));
}
@@ -430,7 +430,7 @@
// Creating a new file and passing multiple attribute of the same name.
perm = PosixFilePermissions.fromString("rw-------");
FileAttribute<Set<PosixFilePermission>> attr1 = PosixFilePermissions.asFileAttribute(perm);
- Path dirPath2 = Paths.get(filesSetup.getTestDir(), "new_file");
+ Path dirPath2 = filesSetup.getPathInTestDir("new_file");
provider.createDirectory(dirPath2, attr, attr1);
// Value should be equal to the last attribute passed.
assertEquals(attr1.value(), Files.getAttribute(dirPath2, attr.name()));
@@ -547,7 +547,7 @@
}
// Delete a directory.
- Path dirPath = Paths.get(filesSetup.getTestDir(), "dir");
+ Path dirPath = filesSetup.getPathInTestDir("dir");
Files.createDirectory(dirPath);
provider.delete(dirPath);
assertFalse(Files.exists(dirPath));
@@ -555,7 +555,7 @@
// Delete a non empty directory.
Files.createDirectory(dirPath);
- Files.createFile(Paths.get(filesSetup.getTestDir(), "dir/file"));
+ Files.createFile(filesSetup.getPathInTestDir("dir/file"));
try {
provider.delete(dirPath);
fail();
@@ -580,14 +580,14 @@
assertFalse(Files.deleteIfExists(filesSetup.getTestPath()));
// Delete a directory.
- Path dirPath = Paths.get(filesSetup.getTestDir(), "dir");
+ Path dirPath = filesSetup.getPathInTestDir("dir");
Files.createDirectory(dirPath);
assertTrue(Files.deleteIfExists(dirPath));
assertFalse(Files.exists(dirPath));
// Delete a non empty directory.
Files.createDirectory(dirPath);
- Files.createFile(Paths.get(filesSetup.getTestDir(), "dir/file"));
+ Files.createFile(filesSetup.getPathInTestDir("dir/file"));
try {
provider.deleteIfExists(dirPath);
fail();
@@ -629,8 +629,8 @@
// With target is a symbolic link file.
try {
filesSetup.reset();
- Path symlink = Paths.get(filesSetup.getTestDir(), "symlink");
- Path newFile = Paths.get(filesSetup.getTestDir(), "newDir");
+ Path symlink = filesSetup.getPathInTestDir("symlink");
+ Path newFile = filesSetup.getPathInTestDir("newDir");
Files.createFile(newFile);
assertTrue(Files.exists(newFile));
Files.createSymbolicLink(symlink, filesSetup.getDataFilePath());
@@ -694,17 +694,17 @@
@Test
public void test_copy_directory() throws IOException {
- final Path dirPath = Paths.get(filesSetup.getTestDir(), "dir1");
- final Path dirPath2 = Paths.get(filesSetup.getTestDir(), "dir2");
+ final Path dirPath = filesSetup.getPathInTestDir("dir1");
+ final Path dirPath2 = filesSetup.getPathInTestDir("dir2");
// Nested directory.
- final Path dirPath3 = Paths.get(filesSetup.getTestDir(), "dir1/dir");
+ final Path dirPath3 = filesSetup.getPathInTestDir("dir1/dir");
// Create dir1 and dir1/dir, and copying dir1/dir to dir2. Copy will create dir2, however,
// it will not copy the content of the source directory.
Files.createDirectory(dirPath);
Files.createDirectory(dirPath3);
provider.copy(filesSetup.getDataFilePath(),
- Paths.get(filesSetup.getTestDir(), "dir1/" + DATA_FILE));
+ filesSetup.getPathInTestDir("dir1/" + DATA_FILE));
provider.copy(dirPath, dirPath2);
assertTrue(Files.exists(dirPath2));
@@ -718,7 +718,7 @@
// When the target directory is not empty.
- Path dirPath4 = Paths.get(filesSetup.getTestDir(), "dir4");
+ Path dirPath4 = filesSetup.getPathInTestDir("dir4");
Files.createDirectories(dirPath4);
Path file = Paths.get("file");
Files.createFile(Paths.get(dirPath.toString(), file.toString()));
@@ -734,14 +734,14 @@
public void test_newDirectoryStream$Path$Filter() throws IOException {
// Initial setup of directory.
- Path path_root = Paths.get(filesSetup.getTestDir(), "dir");
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "dir/dir1");
- Path path_dir2 = Paths.get(filesSetup.getTestDir(), "dir/dir2");
- Path path_dir3 = Paths.get(filesSetup.getTestDir(), "dir/dir3");
+ Path path_root = filesSetup.getPathInTestDir("dir");
+ Path path_dir1 = filesSetup.getPathInTestDir("dir/dir1");
+ Path path_dir2 = filesSetup.getPathInTestDir("dir/dir2");
+ Path path_dir3 = filesSetup.getPathInTestDir("dir/dir3");
- Path path_f1 = Paths.get(filesSetup.getTestDir(), "dir/f1");
- Path path_f2 = Paths.get(filesSetup.getTestDir(), "dir/f2");
- Path path_f3 = Paths.get(filesSetup.getTestDir(), "dir/f3");
+ Path path_f1 = filesSetup.getPathInTestDir("dir/f1");
+ Path path_f2 = filesSetup.getPathInTestDir("dir/f2");
+ Path path_f3 = filesSetup.getPathInTestDir("dir/f3");
Files.createDirectory(path_root);
Files.createDirectory(path_dir1);
@@ -776,7 +776,7 @@
@Test
public void test_newDirectoryStream$Filter_Exception() throws IOException {
// Non existent directory.
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "newDir1");
+ Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
DirectoryStream.Filter<Path> fileFilter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
@@ -792,7 +792,7 @@
}
// File instead of directory.
- Path path_file1 = Paths.get(filesSetup.getTestDir(), "newFile1");
+ Path path_file1 = filesSetup.getPathInTestDir("newFile1");
Files.createFile(path_file1);
try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_file1,
fileFilter)) {
@@ -816,7 +816,7 @@
}
// Non existent directory.
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "newDir1");
+ Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
try (DirectoryStream<Path> directoryStream = provider.newDirectoryStream(path_dir1,
(DirectoryStream.Filter<? super Path>) null)) {
fail();
diff --git a/luni/src/test/java/libcore/java/nio/file/Files2Test.java b/luni/src/test/java/libcore/java/nio/file/Files2Test.java
new file mode 100644
index 0000000..61b8878
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/Files2Test.java
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.nio.file;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.io.IOException;
+import java.nio.file.CopyOption;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemLoopException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+import static java.nio.file.FileVisitResult.TERMINATE;
+import static junit.framework.TestCase.assertTrue;
+import static libcore.java.nio.file.FilesSetup.DATA_FILE;
+import static libcore.java.nio.file.FilesSetup.NON_EXISTENT_FILE;
+import static libcore.java.nio.file.FilesSetup.execCmdAndWaitForTermination;
+import static libcore.java.nio.file.FilesSetup.readFromInputStream;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class Files2Test {
+ @Rule
+ public FilesSetup filesSetup = new FilesSetup();
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule();
+ @Mock
+ private Path mockPath;
+ @Mock
+ private Path mockPath2;
+ @Mock
+ private FileSystem mockFileSystem;
+ @Mock
+ private FileSystemProvider mockFileSystemProvider;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mockPath.getFileSystem()).thenReturn(mockFileSystem);
+ when(mockPath2.getFileSystem()).thenReturn(mockFileSystem);
+ when(mockFileSystem.provider()).thenReturn(mockFileSystemProvider);
+ }
+
+ @Test
+ public void test_move() throws IOException {
+ CopyOption mockCopyOption = mock(CopyOption.class);
+ assertEquals(mockPath2, Files.move(mockPath, mockPath2, mockCopyOption));
+ verify(mockFileSystemProvider).move(mockPath, mockPath2, mockCopyOption);
+ }
+
+ @Test
+ public void test_readSymbolicLink() throws IOException {
+ when(mockFileSystemProvider.readSymbolicLink(mockPath)).thenReturn(mockPath2);
+ assertEquals(mockPath2, Files.readSymbolicLink(mockPath));
+ verify(mockFileSystemProvider).readSymbolicLink(mockPath);
+ }
+
+ @Test
+ public void test_isSameFile() throws IOException {
+ when(mockFileSystemProvider.isSameFile(mockPath, mockPath2)).thenReturn(true);
+ when(mockFileSystemProvider.isSameFile(mockPath2, mockPath)).thenReturn(false);
+ assertTrue(Files.isSameFile(mockPath, mockPath2));
+ assertFalse(Files.isSameFile(mockPath2, mockPath));
+ }
+
+ @Test
+ public void test_getFileStore() throws IOException {
+ FileStore mockFileStore = mock(FileStore.class);
+ when(mockFileSystemProvider.getFileStore(mockPath)).thenReturn(mockFileStore);
+ assertEquals(mockFileStore, Files.getFileStore(mockPath));
+ }
+
+ @Test
+ public void test_isHidden() throws IOException {
+ when(mockFileSystemProvider.isHidden(mockPath)).thenReturn(true);
+ when(mockFileSystemProvider.isHidden(mockPath2)).thenReturn(false);
+ assertTrue(Files.isHidden(mockPath));
+ assertFalse(Files.isHidden(mockPath2));
+ }
+
+ @Test
+ public void test_probeContentType() throws IOException {
+ assertEquals("text/plain",
+ Files.probeContentType(filesSetup.getPathInTestDir("file.txt")));
+ assertEquals("text/x-java",
+ Files.probeContentType(filesSetup.getPathInTestDir("file.java")));
+ }
+
+ @Test
+ public void test_getFileAttributeView() throws IOException {
+ FileAttributeView mockFileAttributeView = mock(FileAttributeView.class);
+ when(mockFileSystemProvider.getFileAttributeView(mockPath, FileAttributeView.class,
+ LinkOption.NOFOLLOW_LINKS)).thenReturn(mockFileAttributeView);
+ assertEquals(mockFileAttributeView, Files.getFileAttributeView(mockPath,
+ FileAttributeView.class, LinkOption.NOFOLLOW_LINKS));
+ }
+
+ @Test
+ public void test_readAttributes() throws IOException {
+ BasicFileAttributes mockBasicFileAttributes = mock(BasicFileAttributes.class);
+ when(mockFileSystemProvider.readAttributes(mockPath, BasicFileAttributes.class,
+ LinkOption.NOFOLLOW_LINKS)).thenReturn(mockBasicFileAttributes);
+ assertEquals(mockBasicFileAttributes, Files.readAttributes(mockPath,
+ BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS));
+
+ }
+
+ @Test
+ public void test_setAttribute() throws IOException {
+ assertEquals(mockPath, Files.setAttribute(mockPath, "string", 10,
+ LinkOption.NOFOLLOW_LINKS));
+ verify(mockFileSystemProvider).setAttribute(mockPath, "string", 10,
+ LinkOption.NOFOLLOW_LINKS);
+ }
+
+ @Test
+ public void test_getAttribute() throws IOException {
+ // Other tests are covered in test_readAttributes.
+ // When file is NON_EXISTENT.
+ try {
+ Files.getAttribute(filesSetup.getTestPath(), "basic:lastModifiedTime");
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_getAttribute_Exception() throws IOException {
+ // IllegalArgumentException
+ try {
+ Files.getAttribute(filesSetup.getDataFilePath(), "xyz");
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ try {
+ Files.getAttribute(null, "xyz");
+ fail();
+ } catch(NullPointerException expected) {}
+
+ try {
+ Files.getAttribute(filesSetup.getDataFilePath(), null);
+ fail();
+ } catch(NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_getPosixFilePermissions() throws IOException {
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
+ FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
+ Files.createFile(filesSetup.getTestPath(), attr);
+ assertEquals(attr.value(), Files.getPosixFilePermissions(filesSetup.getTestPath()));
+ }
+
+ @Test
+ public void test_getPosixFilePermissions_NPE() throws IOException {
+ try {
+ Files.getPosixFilePermissions(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_setPosixFilePermissions() throws IOException {
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
+ FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
+ Files.setPosixFilePermissions(filesSetup.getDataFilePath(), perm);
+ assertEquals(attr.value(), Files.getPosixFilePermissions(filesSetup.getDataFilePath()));
+ }
+
+ @Test
+ public void test_setPosixFilePermissions_NPE() throws IOException {
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
+ FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
+ try {
+ Files.setPosixFilePermissions(null, perm);
+ } catch(NullPointerException expected) {}
+
+ try {
+ Files.setPosixFilePermissions(filesSetup.getDataFilePath(), null);
+ } catch(NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_getOwner() throws IOException, InterruptedException {
+ String[] statCmd = { "stat", "-c", "%U", filesSetup.getTestDir() + "/" + DATA_FILE };
+ Process statProcess = execCmdAndWaitForTermination(statCmd);
+ String owner = readFromInputStream(statProcess.getInputStream()).trim();
+ assertEquals(owner, Files.getOwner(filesSetup.getDataFilePath()).getName());
+ }
+
+ @Test
+ public void test_getOwner_NPE() throws IOException, InterruptedException {
+ try {
+ Files.getOwner(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_setOwner() throws IOException {
+ // TODO: unable to set the owner due to insufficient permissions.
+ }
+
+ @Test
+ public void test_isSymbolicLink() throws IOException, InterruptedException {
+ assertFalse(Files.isSymbolicLink(filesSetup.getTestPath()));
+ assertFalse(Files.isSymbolicLink(filesSetup.getDataFilePath()));
+
+ // Creating a symbolic link.
+ String[] symLinkCmd = { "ln", "-s", DATA_FILE,
+ filesSetup.getTestDir() + "/" + NON_EXISTENT_FILE };
+ execCmdAndWaitForTermination(symLinkCmd);
+ assertTrue(Files.isSymbolicLink(filesSetup.getTestPath()));
+ }
+
+ @Test
+ public void test_isSymbolicLink_NPE() throws IOException, InterruptedException {
+ try {
+ Files.isSymbolicLink(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isDirectory() throws IOException, InterruptedException {
+ assertFalse(Files.isDirectory(filesSetup.getDataFilePath()));
+ // When file doesn't exist.
+ assertFalse(Files.isDirectory(filesSetup.getTestPath()));
+
+ // Creating a directory.
+ String dirName = "newDir";
+ Path dirPath = filesSetup.getPathInTestDir(dirName);
+ String mkdir[] = { "mkdir", filesSetup.getTestDir() + "/" + dirName };
+ execCmdAndWaitForTermination(mkdir);
+ assertTrue(Files.isDirectory(dirPath));
+ }
+
+ @Test
+ public void test_isDirectory_NPE() throws IOException {
+ try {
+ Files.isDirectory(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isRegularFile() throws IOException, InterruptedException {
+ assertTrue(Files.isRegularFile(filesSetup.getDataFilePath()));
+ // When file doesn't exist.
+ assertFalse(Files.isRegularFile(filesSetup.getTestPath()));
+
+ // Check directories.
+ Path dirPath = filesSetup.getPathInTestDir("dir");
+ Files.createDirectory(dirPath);
+ assertFalse(Files.isRegularFile(dirPath));
+
+ // Check symbolic link.
+ // When linked to itself.
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getTestPath().toAbsolutePath());
+ assertFalse(Files.isRegularFile(filesSetup.getTestPath()));
+
+ // When linked to some other file.
+ filesSetup.reset();
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getDataFilePath().toAbsolutePath());
+ assertTrue(Files.isRegularFile(filesSetup.getTestPath()));
+
+ // When asked to not follow the link.
+ assertFalse(Files.isRegularFile(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+
+ // Device file.
+ Path deviceFilePath = Paths.get("/dev/null");
+ assertTrue(Files.exists(deviceFilePath));
+ assertFalse(Files.isRegularFile(deviceFilePath));
+ }
+
+ @Test
+ public void test_isRegularFile_NPE() throws IOException {
+ try {
+ Files.isReadable(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_getLastModifiedTime() throws IOException, InterruptedException {
+ String touchCmd[] = { "touch", "-d", "2015-10-09T00:00:00",
+ filesSetup.getTestDir() + "/" + DATA_FILE };
+ execCmdAndWaitForTermination(touchCmd);
+ assertEquals("2015-10-09T00:00:00Z",
+ Files.getLastModifiedTime(filesSetup.getDataFilePath()).toString());
+
+ // Non existent file.
+ try {
+ Files.getLastModifiedTime(filesSetup.getTestPath()).toString();
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_getLastModifiedTime_NPE() throws IOException {
+ try {
+ Files.getLastModifiedTime(null, LinkOption.NOFOLLOW_LINKS);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ Files.getLastModifiedTime(filesSetup.getDataFilePath(), (LinkOption[]) null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_setLastModifiedTime() throws IOException, InterruptedException {
+ long timeInMillisToBeSet = System.currentTimeMillis() - 10000;
+ Files.setLastModifiedTime(filesSetup.getDataFilePath(),
+ FileTime.fromMillis(timeInMillisToBeSet));
+ assertEquals(timeInMillisToBeSet/1000,
+ Files.getLastModifiedTime(filesSetup.getDataFilePath()).to(TimeUnit.SECONDS));
+
+ // Non existent file.
+ try {
+ Files.setLastModifiedTime(filesSetup.getTestPath(),
+ FileTime.fromMillis(timeInMillisToBeSet));
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_setLastModifiedTime_NPE() throws IOException, InterruptedException {
+ try {
+ Files.setLastModifiedTime(null, FileTime.fromMillis(System.currentTimeMillis()));
+ fail();
+ } catch (NullPointerException expected) {}
+
+ // No NullPointerException.
+ Files.setLastModifiedTime(filesSetup.getDataFilePath(), null);
+ }
+
+ @Test
+ public void test_size() throws IOException, InterruptedException {
+ int testSizeInBytes = 5000;
+ String ddCmd[] = { "dd", "if=/dev/zero", "of=" + filesSetup.getTestDir() + "/" + DATA_FILE,
+ "bs="
+ + testSizeInBytes, "count=1"};
+ execCmdAndWaitForTermination(ddCmd);
+
+ assertEquals(testSizeInBytes, Files.size(filesSetup.getDataFilePath()));
+
+ try {
+ Files.size(filesSetup.getTestPath());
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @Test
+ public void test_size_NPE() throws IOException, InterruptedException {
+ try {
+ Files.size(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_exists() throws IOException {
+ // When file exists.
+ assertTrue(Files.exists(filesSetup.getDataFilePath()));
+
+ // When file doesn't exist.
+ assertFalse(Files.exists(filesSetup.getTestPath()));
+
+ // SymLink
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getDataFilePath().toAbsolutePath());
+ assertTrue(Files.exists(filesSetup.getTestPath()));
+
+ // When link shouldn't be followed
+ assertTrue(Files.exists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+
+ // When the target file doesn't exist.
+ Files.delete(filesSetup.getDataFilePath());
+ assertTrue(Files.exists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+ assertFalse(Files.exists(filesSetup.getTestPath()));
+
+ // Symlink to itself
+ filesSetup.reset();
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getTestPath().toAbsolutePath());
+ assertFalse(Files.exists(filesSetup.getTestPath()));
+ assertTrue(Files.exists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+ }
+
+ @Test
+ public void test_exists_NPE() throws IOException {
+ try {
+ Files.exists(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_notExists() throws IOException {
+ // When file exists.
+ assertFalse(Files.notExists(filesSetup.getDataFilePath()));
+
+ // When file doesn't exist.
+ assertTrue(Files.notExists(filesSetup.getTestPath()));
+
+ // SymLink
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getDataFilePath().toAbsolutePath());
+ assertFalse(Files.notExists(filesSetup.getTestPath()));
+
+ // When link shouldn't be followed
+ assertFalse(Files.notExists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+
+ // When the target file doesn't exist.
+ Files.delete(filesSetup.getDataFilePath());
+ assertFalse(Files.notExists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+ assertTrue(Files.notExists(filesSetup.getTestPath()));
+
+ // Symlink to itself
+ filesSetup.reset();
+ Files.createSymbolicLink(filesSetup.getTestPath(),
+ filesSetup.getTestPath().toAbsolutePath());
+ assertFalse(Files.notExists(filesSetup.getTestPath()));
+ assertFalse(Files.notExists(filesSetup.getTestPath(), LinkOption.NOFOLLOW_LINKS));
+ }
+
+ @Test
+ public void test_notExists_NPE() throws IOException {
+ try {
+ Files.notExists(null);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ Files.notExists(filesSetup.getDataFilePath(), (LinkOption[]) null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isReadable() throws IOException {
+ // When a readable file is available.
+ assertTrue(Files.isReadable(filesSetup.getDataFilePath()));
+
+ // When a file doesn't exist.
+ assertFalse(Files.isReadable(filesSetup.getTestPath()));
+
+ // Setting non readable permission for user
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("-wxrwxrwx");
+ Files.setPosixFilePermissions(filesSetup.getDataFilePath(), perm);
+ assertFalse(Files.isReadable(filesSetup.getDataFilePath()));
+ }
+
+ @Test
+ public void test_isReadable_NPE() throws IOException {
+ try {
+ Files.isReadable(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isWritable() throws IOException {
+ // When a readable file is available.
+ assertTrue(Files.isWritable(filesSetup.getDataFilePath()));
+
+ // When a file doesn't exist.
+ assertFalse(Files.isWritable(filesSetup.getTestPath()));
+
+ // Setting non writable permission for user
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("r-xrwxrwx");
+ Files.setPosixFilePermissions(filesSetup.getDataFilePath(), perm);
+ assertFalse(Files.isWritable(filesSetup.getDataFilePath()));
+ }
+
+ @Test
+ public void test_isWritable_NPE() {
+ try {
+ Files.isWritable(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_isExecutable() throws IOException {
+ // When a readable file is available.
+ assertFalse(Files.isExecutable(filesSetup.getDataFilePath()));
+
+ // When a file doesn't exist.
+ assertFalse(Files.isExecutable(filesSetup.getTestPath()));
+
+ // Setting non executable permission for user
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rw-rwxrwx");
+ Files.setPosixFilePermissions(filesSetup.getDataFilePath(), perm);
+ assertFalse(Files.isExecutable(filesSetup.getDataFilePath()));
+ }
+
+ @Test
+ public void test_isExecutable_NPE() {
+ try {
+ Files.isExecutable(null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_walkFileTree$Path$Set$int$FileVisitor_symbolicLinkFollow()
+ throws IOException, InterruptedException {
+ // Directory structure.
+ // root
+ // ├── dir1
+ // │ └── dir2 ─ dir3-file1 - file3
+ // │
+ // └── file2
+ //
+ // With follow link it should be able to traverse to dir3 and file1 when started from file2.
+
+ // Directory setup.
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+ Path dir2 = filesSetup.getPathInTestDir("root/dir1/dir2");
+ Path dir3 = filesSetup.getPathInTestDir("root/dir1/dir2/dir3");
+ Path file1 = filesSetup.getPathInTestDir("root/dir1/dir2/dir3/file1");
+ Path file2 = filesSetup.getPathInTestDir("root/file2");
+
+ Files.createDirectories(dir3);
+ Files.createFile(file1);
+ Files.createSymbolicLink(file2, dir2.toAbsolutePath());
+ assertTrue(Files.isSymbolicLink(file2));
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ Map<Object, VisitOption> expectedDirMap = new HashMap<>();
+ Set<FileVisitOption> option = new HashSet<>();
+ option.add(FileVisitOption.FOLLOW_LINKS);
+ Files.walkFileTree(file2, option, 50, new TestFileVisitor(dirMap, option));
+
+ expectedDirMap.put(file1.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(file2.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(dir3.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+
+ assertEquals(expectedDirMap, dirMap);
+ }
+
+ @Test
+ public void test_walkFileTree$Path$FileVisitor() throws IOException {
+ // Directory structure.
+ // .
+ // ├── DATA_FILE
+ // └── root
+ // ├── dir1
+ // │ ├── dir2
+ // │ │ ├── dir3
+ // │ │ └── file5
+ // │ ├── dir4
+ // │ └── file3
+ // ├── dir5
+ // └── file1
+ //
+
+ // Directory Setup.
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+ Path dir2 = filesSetup.getPathInTestDir("root/dir1/dir2");
+ Path dir3 = filesSetup.getPathInTestDir("root/dir1/dir2/dir3");
+ Path dir4 = filesSetup.getPathInTestDir("root/dir1/dir4");
+ Path dir5 = filesSetup.getPathInTestDir("root/dir5");
+ Path file1 = filesSetup.getPathInTestDir("root/file1");
+ Path file3 = filesSetup.getPathInTestDir("root/dir1/file3");
+ Path file5 = filesSetup.getPathInTestDir("root/dir1/dir2/file5");
+
+ Files.createDirectories(dir3);
+ Files.createDirectories(dir4);
+ Files.createDirectories(dir5);
+ Files.createFile(file3);
+ Files.createFile(file5);
+ Files.createSymbolicLink(file1, filesSetup.getDataFilePath().toAbsolutePath());
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ Map<Object, VisitOption> expectedDirMap = new HashMap<>();
+ Path returnedPath = Files.walkFileTree(rootDir, new Files2Test.TestFileVisitor(dirMap));
+
+ assertEquals(rootDir, returnedPath);
+
+ expectedDirMap.put(rootDir.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(dir1.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(dir2.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(dir3.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(file5.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(dir4.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(file3.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(dir5.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(file1.getFileName(), VisitOption.VISIT_FILE);
+ assertEquals(expectedDirMap, dirMap);
+ }
+
+ @Test
+ public void test_walkFileTree_depthFirst() throws IOException {
+ // Directory structure.
+ // .
+ // ├── DATA_FILE
+ // └── root
+ // ├── dir1 ── file1
+ // └── dir2 ── file2
+
+ // Directory Setup.
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+ Path dir2 = filesSetup.getPathInTestDir("root/dir2");
+ Path file1 = filesSetup.getPathInTestDir("root/dir1/file1");
+ Path file2 = filesSetup.getPathInTestDir("root/dir2/file2");
+
+ Files.createDirectories(dir1);
+ Files.createDirectories(dir2);
+ Files.createFile(file1);
+ Files.createFile(file2);
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ List<Object> keyList = new ArrayList<>();
+ Files.walkFileTree(rootDir,
+ new Files2Test.TestFileVisitor(dirMap, keyList));
+ assertEquals(rootDir.getFileName(), keyList.get(0));
+ if (keyList.get(1).equals(dir1.getFileName())) {
+ assertEquals(file1.getFileName(), keyList.get(2));
+ assertEquals(dir2.getFileName(), keyList.get(3));
+ assertEquals(file2.getFileName(), keyList.get(4));
+ } else if (keyList.get(1).equals(dir2.getFileName())){
+ assertEquals(file2.getFileName(), keyList.get(2));
+ assertEquals(dir1.getFileName(), keyList.get(3));
+ assertEquals(file1.getFileName(), keyList.get(4));
+ } else {
+ fail();
+ }
+ }
+
+ @Test
+ public void test_walkFileTree_negativeDepth() throws IOException {
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+
+ Files.createDirectories(dir1);
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ Set<FileVisitOption> option = new HashSet<>();
+ option.add(FileVisitOption.FOLLOW_LINKS);
+ try {
+ Files.walkFileTree(rootDir, option, -1,
+ new Files2Test.TestFileVisitor(dirMap));
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ }
+
+ @Test
+ public void test_walkFileTree_maximumDepth() throws IOException {
+ // Directory structure.
+ // root
+ // ├── dir1
+ // │ ├── dir2
+ // │ │ ├── dir3
+ // │ │ └── file5
+ // │ ├── dir4
+ // │ └── file3
+ // ├── dir5
+ // └── file1
+ //
+ // depth will be 2. file5, dir3 is not reachable.
+ // Directory Setup.
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+ Path dir2 = filesSetup.getPathInTestDir("root/dir1/dir2");
+ Path dir3 = filesSetup.getPathInTestDir("root/dir1/dir2/dir3");
+ Path dir4 = filesSetup.getPathInTestDir("root/dir1/dir4");
+ Path dir5 = filesSetup.getPathInTestDir("root/dir5");
+ Path file1 = filesSetup.getPathInTestDir("root/file1");
+ Path file3 = filesSetup.getPathInTestDir("root/dir1/file3");
+ Path file5 = filesSetup.getPathInTestDir("root/dir1/dir2/file5");
+
+ Files.createDirectories(dir3);
+ Files.createDirectories(dir4);
+ Files.createDirectories(dir5);
+ Files.createFile(file1);
+ Files.createFile(file3);
+ Files.createFile(file5);
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ Map<Object, VisitOption> expectedDirMap = new HashMap<>();
+ Set<FileVisitOption> option = new HashSet<>();
+ option.add(FileVisitOption.FOLLOW_LINKS);
+ Files.walkFileTree(rootDir, option, 2, new Files2Test.TestFileVisitor(dirMap));
+ assertTrue(Files.isDirectory(dir4));
+ expectedDirMap.put(rootDir.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(dir1.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ // Both of the directories are at maximum depth, therefore, will be treated as simple file.
+ expectedDirMap.put(dir2.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(dir4.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(dir5.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ expectedDirMap.put(file1.getFileName(), VisitOption.VISIT_FILE);
+ expectedDirMap.put(file3.getFileName(), VisitOption.VISIT_FILE);
+
+ assertEquals(expectedDirMap, dirMap);
+ }
+
+ @Test
+ public void test_walkFileTree$Path$FileVisitor_NPE() throws IOException {
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ try {
+ Files.walkFileTree(null,
+ new Files2Test.TestFileVisitor(new HashMap<>()));
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ Files.walkFileTree(rootDir, null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_walkFileTree$Path$FileVisitor_FileSystemLoopException() throws IOException {
+ // Directory structure.
+ // .
+ // ├── DATA_FILE
+ // └── root
+ // └── dir1
+ // └── file1
+ //
+ // file1 is symlink to dir1
+
+ // Directory Setup.
+ Path rootDir = filesSetup.getPathInTestDir("root");
+ Path dir1 = filesSetup.getPathInTestDir("root/dir1");
+ Path file1 = filesSetup.getPathInTestDir("root/dir1/file1");
+
+ Files.createDirectories(dir1);
+ Files.createSymbolicLink(file1, dir1.toAbsolutePath());
+ assertEquals(dir1.getFileName(), Files.readSymbolicLink(file1).getFileName());
+
+ Map<Object, VisitOption> dirMap = new HashMap<>();
+ Set<FileVisitOption> option = new HashSet<>();
+ option.add(FileVisitOption.FOLLOW_LINKS);
+ try {
+ Files.walkFileTree(rootDir, option, Integer.MAX_VALUE,
+ new Files2Test.TestFileVisitor(dirMap));
+ fail();
+ } catch (FileSystemLoopException expected) {}
+ }
+
+ // -- Mock Class --
+
+ private static class TestFileVisitor implements FileVisitor<Path> {
+
+ final Map<Object, VisitOption> dirMap;
+ LinkOption option[];
+ List<Object> keyList;
+
+ public TestFileVisitor(Map<Object, VisitOption> dirMap) {
+ this(dirMap, (List<Object>) null);
+ }
+
+ public TestFileVisitor(Map<Object, VisitOption> dirMap, Set<FileVisitOption> option) {
+ this.dirMap = dirMap;
+ for (FileVisitOption fileVisitOption : option) {
+ if (fileVisitOption.equals(FileVisitOption.FOLLOW_LINKS)) {
+ this.option = new LinkOption[0];
+ }
+ }
+
+ if (this.option == null) {
+ this.option = new LinkOption[] {LinkOption.NOFOLLOW_LINKS};
+ }
+ }
+
+ public TestFileVisitor(Map<Object, VisitOption> dirMap, List<Object> pathList) {
+ this.dirMap = dirMap;
+ this.option = new LinkOption[] {LinkOption.NOFOLLOW_LINKS};
+ keyList = pathList;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ if (keyList != null) {
+ keyList.add(dir.getFileName());
+ }
+ dirMap.put(dir.getFileName(), VisitOption.PRE_VISIT_DIRECTORY);
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (keyList != null) {
+ keyList.add(file.getFileName());
+ }
+ dirMap.put(file.getFileName(), VisitOption.VISIT_FILE);
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ if (exc != null) {
+ throw exc;
+ }
+ return TERMINATE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ if (exc != null) {
+ throw exc;
+ }
+ if (dirMap.getOrDefault(dir.getFileName(), VisitOption.UNVISITED)
+ != VisitOption.PRE_VISIT_DIRECTORY) {
+ return TERMINATE;
+ } else {
+ dirMap.put(dir.getFileName(), VisitOption.POST_VISIT_DIRECTORY);
+ return CONTINUE;
+ }
+ }
+ }
+
+ private enum VisitOption {
+ PRE_VISIT_DIRECTORY,
+ VISIT_FILE,
+ POST_VISIT_DIRECTORY,
+ UNVISITED,
+ }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/FilesSetup.java b/luni/src/test/java/libcore/java/nio/file/FilesSetup.java
index 6931978..66201d9 100644
--- a/luni/src/test/java/libcore/java/nio/file/FilesSetup.java
+++ b/luni/src/test/java/libcore/java/nio/file/FilesSetup.java
@@ -51,6 +51,8 @@
private Path testPath;
+ private Path testDirPath;
+
private boolean filesInitialized = false;
void setUp() throws Exception {
@@ -63,7 +65,8 @@
}
private void initializeFiles() throws IOException {
- testDir = Files.createTempDirectory("testDir").toString();
+ testDirPath = Files.createTempDirectory("testDir");
+ testDir = testDirPath.toString();
dataFilePath = Paths.get(testDir, DATA_FILE);
testPath = Paths.get(testDir, NON_EXISTENT_FILE);
File testInputFile = new File(testDir, DATA_FILE);
@@ -87,6 +90,11 @@
return dataFilePath;
}
+ Path getTestDirPath() {
+ checkState();
+ return testDirPath;
+ }
+
String getTestDir() {
checkState();
return testDir;
@@ -169,6 +177,10 @@
};
}
+ Path getPathInTestDir(String path) {
+ return Paths.get(getTestDir(), path);
+ }
+
/**
* Non Standard CopyOptions.
*/
@@ -176,9 +188,4 @@
OPTION1,
}
- static Object getFileKey(Path file) throws IOException {
- return Files.readAttributes(file, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS)
- .fileKey();
- }
-
}
diff --git a/luni/src/test/java/libcore/java/nio/file/FilesTest.java b/luni/src/test/java/libcore/java/nio/file/FilesTest.java
index 3f967c9..e1250a0 100644
--- a/luni/src/test/java/libcore/java/nio/file/FilesTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/FilesTest.java
@@ -38,7 +38,6 @@
import java.nio.file.NotDirectoryException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
@@ -127,7 +126,7 @@
assertTrue(Files.exists(filesSetup.getTestPath()));
// File with unicode name.
- Path unicodeFilePath = Paths.get(filesSetup.getTestDir(), "परीक्षण फ़ाइल");
+ Path unicodeFilePath = filesSetup.getPathInTestDir("परीक्षण फ़ाइल");
Files.createFile(unicodeFilePath);
Files.exists(unicodeFilePath);
@@ -156,7 +155,7 @@
// Creating a new file and passing multiple attribute of the same name.
perm = PosixFilePermissions.fromString("rw-------");
FileAttribute<Set<PosixFilePermission>> attr1 = PosixFilePermissions.asFileAttribute(perm);
- Path filePath2 = Paths.get(filesSetup.getTestDir(), "new_file");
+ Path filePath2 = filesSetup.getPathInTestDir("new_file");
Files.createFile(filePath2, attr, attr1);
// Value should be equal to the last attribute passed.
assertEquals(attr1.value(), Files.getAttribute(filePath2, attr.name()));
@@ -179,7 +178,7 @@
@Test
public void test_createDirectories() throws IOException {
// Should be able to create parent directories.
- Path dirPath = Paths.get(filesSetup.getTestDir(), "dir1/dir2/dir3");
+ Path dirPath = filesSetup.getPathInTestDir("dir1/dir2/dir3");
assertFalse(Files.exists(dirPath));
Files.createDirectories(dirPath);
assertTrue(Files.isDirectory(dirPath));
@@ -198,7 +197,7 @@
@Test
public void test_createDirectories$Path$Attr() throws IOException {
- Path dirPath = Paths.get(filesSetup.getTestDir(), "dir1/dir2/dir3");
+ Path dirPath = filesSetup.getPathInTestDir("dir1/dir2/dir3");
Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
assertFalse(Files.exists(dirPath));
@@ -214,7 +213,7 @@
assertEquals(attr.value(), Files.getAttribute(dirPath, attr.name()));
// Creating a new directory and passing multiple attribute of the same name.
- Path dirPath2 = Paths.get(filesSetup.getTestDir(), "dir1/dir2/dir4");
+ Path dirPath2 = filesSetup.getPathInTestDir("dir1/dir2/dir4");
Files.createDirectories(dirPath2, attr, attr1);
// Value should be equal to the last attribute passed.
assertEquals(attr1.value(), Files.getAttribute(dirPath2, attr.name()));
@@ -222,7 +221,7 @@
@Test
public void test_createDirectories$Path$Attr_NPE() throws IOException {
- Path dirPath = Paths.get(filesSetup.getTestDir(), "dir1/dir2/dir3");
+ Path dirPath = filesSetup.getPathInTestDir("dir1/dir2/dir3");
Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm);
try {
@@ -239,12 +238,12 @@
@Test
public void test_newDirectoryStream() throws IOException {
// Directory setup.
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "newDir1");
- Path path_dir2 = Paths.get(filesSetup.getTestDir(), "newDir1/newDir2");
- Path path_dir3 = Paths.get(filesSetup.getTestDir(), "newDir1/newDir3");
- Path path_file1 = Paths.get(filesSetup.getTestDir(), "newDir1/newFile1");
- Path path_file2 = Paths.get(filesSetup.getTestDir(), "newDir1/newFile2");
- Path path_file3 = Paths.get(filesSetup.getTestDir(), "newDir1/newDir2/newFile3");
+ Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
+ Path path_dir2 = filesSetup.getPathInTestDir("newDir1/newDir2");
+ Path path_dir3 = filesSetup.getPathInTestDir("newDir1/newDir3");
+ Path path_file1 = filesSetup.getPathInTestDir("newDir1/newFile1");
+ Path path_file2 = filesSetup.getPathInTestDir("newDir1/newFile2");
+ Path path_file3 = filesSetup.getPathInTestDir("newDir1/newDir2/newFile3");
Files.createDirectory(path_dir1);
Files.createDirectory(path_dir2);
@@ -270,14 +269,14 @@
public void test_newDirectoryStream_Exception() throws IOException {
// Non existent directory.
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "newDir1");
+ Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path_dir1)) {
fail();
} catch (NoSuchFileException expected) {
}
// File instead of directory.
- Path path_file1 = Paths.get(filesSetup.getTestDir(), "newFile1");
+ Path path_file1 = filesSetup.getPathInTestDir("newFile1");
Files.createFile(path_file1);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path_file1)) {
fail();
@@ -293,14 +292,14 @@
@Test
public void test_newDirectoryStream$Path$String() throws IOException {
// Directory setup.
- Path path_root = Paths.get(filesSetup.getTestDir(), "dir");
- Path path_java1 = Paths.get(filesSetup.getTestDir(), "dir/f1.java");
- Path path_java2 = Paths.get(filesSetup.getTestDir(), "dir/f2.java");
- Path path_java3 = Paths.get(filesSetup.getTestDir(), "dir/f3.java");
+ Path path_root = filesSetup.getPathInTestDir("dir");
+ Path path_java1 = filesSetup.getPathInTestDir("dir/f1.java");
+ Path path_java2 = filesSetup.getPathInTestDir("dir/f2.java");
+ Path path_java3 = filesSetup.getPathInTestDir("dir/f3.java");
- Path path_txt1 = Paths.get(filesSetup.getTestDir(), "dir/f1.txt");
- Path path_txt2 = Paths.get(filesSetup.getTestDir(), "dir/f2.txt");
- Path path_txt3 = Paths.get(filesSetup.getTestDir(), "dir/f3.txt");
+ Path path_txt1 = filesSetup.getPathInTestDir("dir/f1.txt");
+ Path path_txt2 = filesSetup.getPathInTestDir("dir/f2.txt");
+ Path path_txt3 = filesSetup.getPathInTestDir("dir/f3.txt");
Files.createDirectory(path_root);
// A directory with .java extension.
@@ -328,14 +327,14 @@
public void test_newDirectoryStream$Path$String_Exception() throws IOException {
// Non existent directory.
- Path path_dir1 = Paths.get(filesSetup.getTestDir(), "newDir1");
+ Path path_dir1 = filesSetup.getPathInTestDir("newDir1");
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path_dir1, "*.c")) {
fail();
} catch (NoSuchFileException expected) {
}
// File instead of directory.
- Path path_file1 = Paths.get(filesSetup.getTestDir(), "newFile1");
+ Path path_file1 = filesSetup.getPathInTestDir("newFile1");
Files.createFile(path_file1);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path_file1, "*.c")) {
fail();
diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java
new file mode 100644
index 0000000..e95f5bc
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/LinuxPathTest.java
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.nio.file;
+
+import com.sun.nio.file.ExtendedWatchEventModifier;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.ClosedWatchServiceException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class LinuxPathTest {
+
+ @Rule
+ public FilesSetup filesSetup = new FilesSetup();
+
+ /**
+ * CTS doesn't allow creating files in the test directory, however, Vogar allows creation of
+ * new files in the test directory. Therefore, for the tests which don't require write
+ * permission, dummyPath would serve the purpose, however, for the others, {@link
+ * FilesSetup#getTestDirPath()} should be used.
+ */
+ private static final Path dummyPath = Paths.get("dummyPath");
+
+ @Test
+ public void test_getFileSystem() {
+ assertTrue(dummyPath.getFileSystem().provider() instanceof
+ sun.nio.fs.LinuxFileSystemProvider);
+ }
+
+ @Test
+ public void test_isAbsolute() {
+ assertFalse(dummyPath.isAbsolute());
+ Path absolutePath = dummyPath.toAbsolutePath();
+ assertTrue(absolutePath.isAbsolute());
+ }
+
+ @Test
+ public void test_getRoot() {
+ assertEquals(Paths.get("/"), dummyPath.toAbsolutePath().getRoot());
+ assertNull(dummyPath.getRoot());
+ }
+
+ @Test
+ public void test_getFileName() {
+ assertEquals(dummyPath, dummyPath.getFileName());
+ assertEquals(dummyPath, dummyPath.toAbsolutePath().getFileName());
+ assertNull(dummyPath.getRoot());
+ assertEquals(Paths.get("data"), Paths.get("/data").getFileName());
+ assertEquals(Paths.get("data"), Paths.get("/data/").getFileName());
+ assertEquals(Paths.get(".."), Paths.get("/data/dir1/..").getFileName());
+ }
+
+ @Test
+ public void test_getParent() {
+ assertNull(dummyPath.getParent());
+ assertEquals(Paths.get("rootDir"), Paths.get("rootDir/dir").getParent());
+ }
+
+ @Test
+ public void test_getNameCount() {
+ assertEquals(0, Paths.get("/").getNameCount());
+ assertEquals(1, Paths.get("/dir").getNameCount());
+ assertEquals(2, Paths.get("/dir/dir").getNameCount());
+ assertEquals(2, Paths.get("/dir/..").getNameCount());
+ }
+
+ @Test
+ public void test_getName() {
+ assertEquals(Paths.get("t"), Paths.get("/t/t1/t2/t3").getName(0));
+ assertEquals(Paths.get("t2"), Paths.get("/t/t1/t2/t3").getName(2));
+ assertEquals(Paths.get("t3"), Paths.get("/t/t1/t2/t3").getName(3));
+
+ // Without root.
+ assertEquals(Paths.get("t3"), Paths.get("t/t1/t2/t3").getName(3));
+
+ // Invalid index.
+ try {
+ Paths.get("/t/t1/t2/t3").getName(4);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ // Negative index value.
+ try {
+ Paths.get("/t/t1/t2/t3").getName(-1);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ }
+
+ @Test
+ public void test_subPath() {
+ assertEquals(Paths.get("t1/t2"), Paths.get("t1/t2/t3").subpath(0, 2));
+ assertEquals(Paths.get("t2"), Paths.get("t1/t2/t3").subpath(1, 2));
+
+ try {
+ Paths.get("t1/t2/t3").subpath(1, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ try {
+ assertEquals(Paths.get("t1/t1"), Paths.get("t1/t2/t3").subpath(1, 0));
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ try {
+ assertEquals(Paths.get("t1/t1"), Paths.get("t1/t2/t3").subpath(1, 5));
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ }
+
+ @Test
+ public void test_startsWith$String() {
+ assertTrue(Paths.get("t1/t2").startsWith("t1"));
+ assertTrue(dummyPath.toAbsolutePath().startsWith("/"));
+ assertTrue(Paths.get("t1/t2/t3").startsWith("t1/t2"));
+ assertFalse(Paths.get("t1/t2").startsWith("t2"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_startsWith$String_NPE() {
+ filesSetup.getTestPath().startsWith((String) null);
+ }
+
+ @Test
+ public void test_startsWith$Path() {
+ assertTrue(Paths.get("t1/t2").startsWith(Paths.get("t1")));
+ assertTrue(dummyPath.toAbsolutePath().startsWith(Paths.get("/")));
+ assertTrue(Paths.get("t1/t2/t3").startsWith(Paths.get("t1/t2")));
+ assertFalse(Paths.get("t1/t2").startsWith(Paths.get("t2")));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_startsWith$Path_NPE() {
+ filesSetup.getTestPath().startsWith((Path) null);
+ }
+
+ @Test
+ public void test_endsWith$Path() {
+ assertTrue(Paths.get("t1/t2").endsWith(Paths.get("t2")));
+ assertTrue(Paths.get("t1/t2/t3").endsWith(Paths.get("t2/t3")));
+ assertFalse(Paths.get("t1/t2").endsWith(Paths.get("t1")));
+ assertTrue(Paths.get("/").endsWith(Paths.get("/")));
+ assertFalse(Paths.get("/data/").endsWith(Paths.get("/")));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_endsWith$Path_NPE() {
+ filesSetup.getTestPath().endsWith((Path)null);
+ }
+
+ @Test
+ public void test_endsWith$String() {
+ assertTrue(Paths.get("t1/t2").endsWith("t2"));
+ assertTrue(Paths.get("t1/t2/t3").endsWith("t2/t3"));
+ assertFalse(Paths.get("t1/t2").endsWith("t1"));
+ assertTrue(Paths.get("/").endsWith("/"));
+ assertFalse(Paths.get("/data/").endsWith("/"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_endsWith$String_NPE() {
+ filesSetup.getTestPath().endsWith((String)null);
+ }
+
+ @Test
+ public void test_normalize() {
+ assertEquals(Paths.get("t2/t3"), Paths.get("t1/../t2/t3").normalize());
+ assertEquals(Paths.get("../t2/t3"), Paths.get("t1/../../t2/t3").normalize());
+ assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/./t2/t3").normalize());
+ assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/././t2/t3").normalize());
+ assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/././t2/t3").normalize());
+ assertEquals(Paths.get("t1"), Paths.get("t1/"));
+ }
+
+ @Test
+ public void test_resolve$Path() {
+ Path p = Paths.get("p");
+ Path p1 = Paths.get("p1");
+ Path p1p = Paths.get("p1/p");
+ assertEquals(p1p, p1.resolve(p));
+ assertEquals(p.toAbsolutePath(), p1.resolve(p.toAbsolutePath()));
+ assertEquals(p1p.toAbsolutePath(), p1.toAbsolutePath().resolve(p));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_resolve$Path_NPE() {
+ dummyPath.resolve((Path)null);
+ }
+
+ @Test
+ public void test_resolve$String() {
+ Path p = Paths.get("p");
+ Path p1 = Paths.get("p1");
+ Path p1p = Paths.get("p1/p");
+ assertEquals(p1p, p1.resolve("p"));
+ assertEquals(p1p.toAbsolutePath(), p1.toAbsolutePath().resolve("p"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_resolve$String_NPE() {
+ dummyPath.resolve((String)null);
+ }
+
+ @Test
+ public void test_resolveSibling$Path() {
+ Path c2 = Paths.get("c2");
+ Path parent_c1 = Paths.get("parent/c1");
+ Path parent_c2 = Paths.get("parent/c2");
+ assertEquals(parent_c2, parent_c1.resolveSibling(c2));
+ assertEquals(c2.toAbsolutePath(), parent_c1.resolveSibling(c2.toAbsolutePath()));
+ assertEquals(parent_c2.toAbsolutePath(), parent_c1.toAbsolutePath().resolveSibling(c2));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_resolveSibling$String_Path() {
+ dummyPath.resolveSibling((Path) null);
+ }
+
+ @Test
+ public void test_resolveSibling$String() {
+ Path c2 = Paths.get("c2");
+ Path parent_c1 = Paths.get("parent/c1");
+ Path parent_c2 = Paths.get("parent/c2");
+ assertEquals(parent_c2, parent_c1.resolveSibling(c2.toString()));
+ assertEquals(c2.toAbsolutePath(), parent_c1.resolveSibling(c2.toAbsolutePath().toString()));
+ assertEquals(parent_c2.toAbsolutePath(), parent_c1.toAbsolutePath()
+ .resolveSibling(c2.toString()));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_resolveSibling$String_NPE() {
+ dummyPath.resolveSibling((String)null);
+ }
+
+ @Test
+ public void test_relativize() {
+ Path p1 = Paths.get("t1/t2/t3");
+ Path p2 = Paths.get("t1/t2");
+ assertEquals(Paths.get(".."), p1.relativize(p2));
+ assertEquals(Paths.get(".."), p1.toAbsolutePath().relativize(p2.toAbsolutePath()));
+ assertEquals(Paths.get("t3"), p2.relativize(p1));
+
+ // Can't be relativized as either of the paths are relative and the other is not.
+ try {
+ p1.relativize(p2.toAbsolutePath());
+ fail();
+ } catch (IllegalArgumentException expected) {}
+
+ try {
+ p1.toAbsolutePath().relativize(p2);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_relativize_NPE() {
+ dummyPath.relativize(null);
+ }
+
+ @Test
+ public void test_toURI() throws URISyntaxException {
+ assertEquals(new URI("file://" + dummyPath.toAbsolutePath().toString()), dummyPath.toUri());
+ assertEquals(new URI("file:///"), Paths.get("/").toUri());
+ assertEquals(new URI("file:///dir/.."), Paths.get(("/dir/..")).toUri());
+ assertEquals(new URI("file:///../"), Paths.get(("/..")).toUri());
+ assertEquals(new URI("file:///dir/.."), Paths.get(("/dir/..")).toUri());
+ assertEquals(new URI("file:///./"), Paths.get(("/.")).toUri());
+ assertEquals(new URI("file:///dir/."), Paths.get(("/dir/.")).toUri());
+ // For unicode characters.
+ assertEquals(new URI("file:///%E0%A4%B0%E0%A4%BE%E0%A4%B9."), Paths.get(("/राह.")).toUri());
+ }
+
+ @Test
+ public void test_toAbsolutePath() {
+ assertFalse(dummyPath.isAbsolute());
+ assertTrue(dummyPath.toAbsolutePath().isAbsolute());
+ }
+
+ @Test
+ public void test_toRealPath() throws IOException {
+ // When file doesn't exist.
+ try {
+ dummyPath.toRealPath();
+ fail();
+ } catch (NoSuchFileException expected) {}
+ Files.createFile(filesSetup.getTestPath());
+ Path realPath = filesSetup.getTestPath().toRealPath();
+ assertTrue(Files.isSameFile(filesSetup.getTestPath().toAbsolutePath(), realPath));
+ assertTrue(realPath.isAbsolute());
+ assertFalse(Files.isSymbolicLink(realPath));
+
+ Path dir = Paths.get(filesSetup.getTestDir(), "dir1/dir2");
+ Path file = Paths.get(filesSetup.getTestDir(), "dir1/dir2/../../file");
+ Files.createDirectories(dir);
+ Files.createFile(file);
+ realPath = file.toRealPath();
+ assertTrue(Files.isSameFile(file.toAbsolutePath(), realPath));
+ assertTrue(realPath.isAbsolute());
+ assertFalse(Files.isSymbolicLink(realPath));
+
+ // Sym links.
+ Path symLink = Paths.get(filesSetup.getTestDir(), "symlink");
+ Files.createSymbolicLink(symLink, filesSetup.getTestPath().toAbsolutePath());
+ realPath = symLink.toRealPath();
+ assertTrue(Files.isSameFile(symLink, realPath));
+ assertTrue(realPath.isAbsolute());
+ assertFalse(Files.isSymbolicLink(realPath));
+
+ realPath = symLink.toRealPath(LinkOption.NOFOLLOW_LINKS);
+ assertTrue(Files.isSameFile(symLink, realPath));
+ assertTrue(realPath.isAbsolute());
+ assertTrue(Files.isSymbolicLink(realPath));
+ }
+
+ @Test
+ public void test_toFile() {
+ File file = dummyPath.toFile();
+ assertEquals(dummyPath.toAbsolutePath().toString(), file.getAbsolutePath());
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind() throws IOException,
+ InterruptedException {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ WatchEvent.Kind<?>[] events = {ENTRY_CREATE, ENTRY_DELETE};
+ Path file = Paths.get(filesSetup.getTestDir(), "directory/file");
+ assertFalse(Files.exists(file));
+ Path directory = Paths.get(filesSetup.getTestDir(), "directory");
+ Files.createDirectories(directory);
+ WatchKey key = directory.register(watchService, events);
+
+ // Creating, modifying and deleting the file.
+ Files.createFile(file);
+ assertTrue(Files.exists(file));
+ // EVENT_MODIFY should not be logged.
+ Files.newOutputStream(file).write("hello".getBytes());
+ Files.delete(file);
+ assertFalse(Files.exists(file));
+
+ assertTrue(key.isValid());
+ assertEquals(directory, key.watchable());
+ List<WatchEvent<?>> eventList = new ArrayList<>();
+
+ // Wait for the events to be recorded by WatchService.
+ while(true) {
+ eventList.addAll(key.pollEvents());
+ if (eventList.size() == 2) break;
+ Thread.sleep(1000);
+ }
+ // Wait for the events to be recorded by watchService.
+ assertEquals(2, eventList.size());
+ assertEquals(ENTRY_CREATE, eventList.get(0).kind());
+ assertEquals(ENTRY_DELETE, eventList.get(1).kind());
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind_NPE() throws IOException,
+ InterruptedException {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ WatchEvent.Kind<?>[] events = {ENTRY_CREATE, ENTRY_DELETE};
+ Path directory = Paths.get(filesSetup.getTestDir(), "directory");
+ Files.createDirectories(directory);
+ try {
+ directory.register(null, events);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ directory.register(watchService, (WatchEvent.Kind<?>) null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind_Exception() throws IOException {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ Path directory = Paths.get(filesSetup.getTestDir(), "directory1");
+ Files.createFile(directory);
+
+ // When file is not a directory.
+ try {
+ directory.register(watchService, ENTRY_CREATE);
+ fail();
+ } catch (NotDirectoryException expected) {}
+
+ // When the events are not supported.
+ Files.deleteIfExists(directory);
+ Files.createDirectories(directory);
+ WatchEvent.Kind<?>[] events = {new NonStandardEvent<>()};
+ try {
+ directory.register(watchService, events);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ // When the watch service is closed.
+ watchService.close();
+ try {
+ directory.register(watchService, ENTRY_CREATE);
+ fail();
+ } catch (ClosedWatchServiceException expected) {}
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind_Exception_NPE() throws IOException {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ Path directory = Paths.get(filesSetup.getTestDir(), "directory1");
+ Files.createDirectories(directory);
+
+ // When file is not a directory.
+ try {
+ directory.register(null, ENTRY_CREATE);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ directory.register(watchService, null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind$WatchEvent_Modifier() throws IOException
+ {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ WatchEvent.Kind<?>[] events = {ENTRY_CREATE};
+ Path dirRoot = Paths.get(filesSetup.getTestDir(), "dir");
+ Files.createDirectories(dirRoot);
+ try {
+ WatchKey key = dirRoot.register(watchService, events,
+ ExtendedWatchEventModifier.FILE_TREE);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ assertTrue(expected.getMessage().contains("Modifier not supported"));
+ }
+ }
+
+ @Test
+ public void test_register$WatchService$WatchEvent_Kind$WatchEvent_Modifier_NPE()
+ throws IOException {
+ WatchService watchService = FileSystems.getDefault().newWatchService();
+ WatchEvent.Kind<?>[] events = {ENTRY_CREATE};
+ Path dirRoot = Paths.get(filesSetup.getTestDir(), "dir");
+ Files.createDirectories(dirRoot);
+ try {
+ WatchKey key = dirRoot.register(null, events,
+ ExtendedWatchEventModifier.FILE_TREE);
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ WatchKey key = dirRoot.register(watchService, null,
+ ExtendedWatchEventModifier.FILE_TREE);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void test_iterator() {
+ Path p = Paths.get("f1/f2/f3");
+ Iterator<Path> pathIterator = p.iterator();
+ assertEquals(Paths.get("f1"), pathIterator.next());
+ assertEquals(Paths.get("f2"), pathIterator.next());
+ assertEquals(Paths.get("f3"), pathIterator.next());
+ assertFalse(pathIterator.hasNext());
+ }
+
+ @Test
+ public void test_iterator_hasRoot() {
+ Path p = Paths.get("/f1/f2/f3");
+ Iterator<Path> pathIterator = p.iterator();
+ assertEquals(Paths.get("f1"), pathIterator.next());
+ assertEquals(Paths.get("f2"), pathIterator.next());
+ assertEquals(Paths.get("f3"), pathIterator.next());
+ assertFalse(pathIterator.hasNext());
+ }
+
+ @Test
+ public void test_compareTo() {
+ Path p1 = Paths.get("d/a");
+ Path p2 = Paths.get("d/b");
+ assertTrue(p1.compareTo(p2) < 0);
+ assertTrue(p2.compareTo(p1) > 0);
+ assertTrue(p1.compareTo(p1) == 0);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_compareTo_NPE() {
+ filesSetup.getTestPath().compareTo(null);
+ }
+
+ @Test
+ public void test_equals() {
+ Path p1 = Paths.get("a/b");
+ Path p2 = Paths.get("a/../a/b");
+ Path p3 = p1.toAbsolutePath();
+ assertFalse(p1.equals(p2));
+ assertTrue(p1.equals(p1));
+ assertFalse(p1.equals(p3));
+ }
+
+ @Test
+ public void test_equals_NPE() {
+ // Should not throw NPE.
+ filesSetup.getTestPath().equals(null);
+ }
+
+ @Test
+ public void test_hashCode() {
+ Path p1 = Paths.get("f1/f2/f3");
+ assertEquals(-642657684, p1.hashCode());
+
+ // With root component.
+ Path p2 = Paths.get("/f1/f2/f3");
+ assertEquals(306328475, p2.hashCode());
+ }
+
+ @Test
+ public void test_toString() {
+ Path p = Paths.get("f1/f2/f3");
+ assertEquals("f1/f2/f3", p.toString());
+
+ p = Paths.get("");
+ assertEquals("", p.toString());
+
+ p = Paths.get("..");
+ assertEquals("..", p.toString());
+
+ p = Paths.get(".");
+ assertEquals(".", p.toString());
+
+ p = Paths.get("dir/");
+ assertEquals("dir", p.toString());
+
+ p = Paths.get("/dir");
+ assertEquals("/dir", p.toString());
+ }
+
+ private static class NonStandardEvent<T> implements WatchEvent.Kind<T> {
+
+ @Override
+ public String name() {
+ return null;
+ }
+
+ @Override
+ public Class<T> type() {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/security/DomainLoadStoreParameterTest.java b/luni/src/test/java/libcore/java/security/DomainLoadStoreParameterTest.java
new file mode 100644
index 0000000..2c2e4b8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/DomainLoadStoreParameterTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import junit.framework.TestCase;
+
+import java.net.URI;
+import java.security.KeyStore;
+import java.security.DomainLoadStoreParameter;
+import java.util.HashMap;
+import java.util.Map;
+
+public class DomainLoadStoreParameterTest extends TestCase {
+ private static final String KEY_STORE_NAME = "keyStoreName";
+ private KeyStore.ProtectionParameter protectionParameter;
+ private URI validConfigurationURI;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ protectionParameter = new KeyStore.ProtectionParameter() {};
+ validConfigurationURI = new URI("http://UriForConfiguration.SergioRulesTheWorld.com/");
+ }
+
+ public void testConstructor_nullValues_throwException() throws Exception {
+ try {
+ new DomainLoadStoreParameter(null /* configuration */,
+ createNonEmptyParameters(KEY_STORE_NAME, protectionParameter));
+ fail("configuration can't be null when creating DomainLoadStoreParameter");
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ new DomainLoadStoreParameter(validConfigurationURI, null /* protectionParameters */);
+ fail("protection parameters can't be null when creating DomainLoadStoreParameter");
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /**
+ * Check that it returns the configuration specified in the constructor.
+ */
+ public void testGetConfiguration() {
+ DomainLoadStoreParameter domainLoadStoreParameter =
+ new DomainLoadStoreParameter(validConfigurationURI,
+ createNonEmptyParameters(KEY_STORE_NAME, protectionParameter));
+ assertSame(validConfigurationURI, domainLoadStoreParameter.getConfiguration());
+ }
+
+ public void testGetProtectionParams() {
+ Map<String, KeyStore.ProtectionParameter> protectionParameters =
+ createNonEmptyParameters(KEY_STORE_NAME, protectionParameter);
+ DomainLoadStoreParameter domainLoadStoreParameter =
+ new DomainLoadStoreParameter(validConfigurationURI, protectionParameters);
+ Map<String, KeyStore.ProtectionParameter> returnedParams =
+ domainLoadStoreParameter.getProtectionParams();
+ assertEquals(protectionParameters, returnedParams);
+
+ // Trying to add to the returned set throws an exception
+ try {
+ returnedParams.put("some_other_keystore", protectionParameter);
+ fail("The parameters returned by getProtectionParams should be unmodifiable");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ // Adding to the map passed as parameter doesn't change value in the
+ // {@code DomainLoadStoreParameter}, ie, it holds a copy.
+ Map<String, KeyStore.ProtectionParameter> originalProtectionParameters
+ = new HashMap<>(protectionParameters);
+ protectionParameters.put("some_other_keystore", protectionParameter);
+ assertEquals(originalProtectionParameters,
+ domainLoadStoreParameter.getProtectionParams());
+
+ }
+
+ /**
+ * Getter for the protection parameters in this domain.
+ *
+ * Check that always returns null. Keystore domains do not support a protection parameter.
+ */
+ public void testGetProtectionParameter() {
+ DomainLoadStoreParameter domainLoadStoreParameter =
+ new DomainLoadStoreParameter(validConfigurationURI,
+ createNonEmptyParameters("keyStoreName", protectionParameter));
+ // Check that always returns null. Keystore domains do not support a protection parameter.
+ assertNull(domainLoadStoreParameter.getProtectionParameter());
+ }
+
+ private Map<String, KeyStore.ProtectionParameter> createNonEmptyParameters(
+ String keyStoreName, KeyStore.ProtectionParameter protectionParameter) {
+ Map<String, KeyStore.ProtectionParameter> protectionParameters = new HashMap<>();
+ protectionParameters.put(keyStoreName, protectionParameter);
+ return protectionParameters;
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/PrincipalTest.java b/luni/src/test/java/libcore/java/security/PrincipalTest.java
new file mode 100644
index 0000000..de20325
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/PrincipalTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package java.security;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.HashSet;
+
+import javax.security.auth.Subject;
+
+
+public class PrincipalTest extends TestCase {
+ /**
+ * Default implementation of {@code implies} returns true iff the principal is one
+ * of the subject's principals, or if the subject is null.
+ */
+ public void test_Principal_implies() throws Exception {
+ HashSet<Principal> subjectPrincipals = new HashSet<>();
+ subjectPrincipals.add(new PrincipalWithEqualityByName("a"));
+ subjectPrincipals.add(new PrincipalWithEqualityByName("b"));
+ Subject subject = new Subject(
+ true /* readOnly */,
+ subjectPrincipals,
+ Collections.EMPTY_SET /* pubCredentials */,
+ Collections.EMPTY_SET /* privCredentials */);
+ Principal principalA = new PrincipalWithEqualityByName("a");
+ assertTrue(principalA.implies(subject));
+ Principal principalC = new PrincipalWithEqualityByName("c");
+ assertFalse(principalC.implies(subject));
+ assertFalse(principalC.implies(null));
+ }
+
+ private static class PrincipalWithEqualityByName implements Principal {
+
+ private final String name;
+
+ PrincipalWithEqualityByName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof PrincipalWithEqualityByName)) {
+ return false;
+ }
+ return this.name.equals(((PrincipalWithEqualityByName) other).getName());
+ }
+ }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java
index 7d9e633..d525cf0 100644
--- a/luni/src/test/java/libcore/java/security/ProviderTest.java
+++ b/luni/src/test/java/libcore/java/security/ProviderTest.java
@@ -43,6 +43,7 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Cipher;
@@ -661,6 +662,119 @@
}
}
+ // TODO(29631070): this is a general testing mechanism to test other operations that are
+ // going to be added.
+ public void testHashMapOperations() {
+ performHashMapOperationAndCheckResults(
+ PUT /* operation */,
+ mapOf("class1.algorithm1", "impl1") /* initialStatus */,
+ new Pair("class2.algorithm2", "impl2") /* operationParameters */,
+ mapOf("class1.algorithm1", "impl1",
+ "class2.algorithm2", "impl2"),
+ true /* mustChangeSecurityVersion */);
+ performHashMapOperationAndCheckResults(
+ PUT_ALL,
+ mapOf("class1.algorithm1", "impl1"),
+ mapOf("class2.algorithm2", "impl2", "class3.algorithm3", "impl3"),
+ mapOf("class1.algorithm1", "impl1",
+ "class2.algorithm2", "impl2",
+ "class3.algorithm3", "impl3"),
+ true /* mustChangeSecurityVersion */);
+ performHashMapOperationAndCheckResults(
+ REMOVE,
+ mapOf("class1.algorithm1", "impl1"),
+ "class1.algorithm1",
+ mapOf(),
+ true /* mustChangeSecurityVersion */);
+ performHashMapOperationAndCheckResults(
+ REMOVE,
+ mapOf("class1.algorithm1", "impl1"),
+ "class2.algorithm1",
+ mapOf("class1.algorithm1", "impl1"),
+ true /* mustChangeSecurityVersion */);
+ }
+
+ private static class Pair<A, B> {
+ private final A first;
+ private final B second;
+ Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
+
+ /* Holder class for the provider parameter and the parameter for the operation. */
+ private static class ProviderAndOperationParameter<T> {
+ private final Provider provider;
+ private final T operationParameters;
+ ProviderAndOperationParameter(Provider p, T o) {
+ provider = p;
+ operationParameters = o;
+ }
+ }
+
+ private static final Consumer<ProviderAndOperationParameter<Pair<String, String>>> PUT =
+ (ProviderAndOperationParameter<Pair<String, String>> provAndParam) ->
+ {
+ provAndParam.provider.put(provAndParam.operationParameters.first,
+ provAndParam.operationParameters.second);
+ };
+ private static final Consumer<ProviderAndOperationParameter<Map<String, String>>> PUT_ALL =
+ (ProviderAndOperationParameter<Map<String, String>> provAndParam) ->
+ provAndParam.provider.putAll(provAndParam.operationParameters);
+ private static final Consumer<ProviderAndOperationParameter<String>> REMOVE =
+ (ProviderAndOperationParameter<String> provAndParam) ->
+ provAndParam.provider.remove(provAndParam.operationParameters);
+
+
+ private static Map<String, String> mapOf(String... elements) {
+ Map<String, String> ret = new HashMap<String, String>();
+ for (int i = 0; i < elements.length; i += 2) {
+ ret.put(elements[i], elements[i + 1]);
+ }
+ return ret;
+ }
+
+
+ private <A> void performHashMapOperationAndCheckResults(
+ Consumer<ProviderAndOperationParameter<A>> operation,
+ Map<String, String> initialState,
+ A operationParameters,
+ Map<String, String> expectedResult,
+ boolean mustChangeVersion) {
+ Provider p = new MockProvider("MockProvider");
+ // Need to set as registered so that the security version will change on update.
+ p.setRegistered();
+ int securityVersionBeforeOperation = Security.getVersion();
+ p.putAll(initialState);
+
+ // Perform the operation.
+ operation.accept(new ProviderAndOperationParameter<A>(p, operationParameters));
+
+ // Check that elements are correctly mapped to services.
+ HashMap<String, String> services = new HashMap<String, String>();
+ for (Provider.Service s : p.getServices()) {
+ services.put(s.getType() + "." + s.getAlgorithm(), s.getClassName());
+ }
+ assertEquals(expectedResult.entrySet(), services.entrySet());
+
+ // Check that elements are in the provider hash map.
+ // The hash map in the provider has info other than services, include those in the
+ // expected results.
+ HashMap<String, String> hashExpectedResult = new HashMap<String, String>();
+ hashExpectedResult.putAll(expectedResult);
+ hashExpectedResult.put("Provider.id info", p.getInfo());
+ hashExpectedResult.put("Provider.id className", p.getClass().getName());
+ hashExpectedResult.put("Provider.id version", String.valueOf(p.getVersion()));
+ hashExpectedResult.put("Provider.id name", p.getName());
+
+ assertEquals(hashExpectedResult.entrySet(), p.entrySet());
+
+ if (mustChangeVersion) {
+ assertTrue(securityVersionBeforeOperation != Security.getVersion());
+ }
+ }
+
@SuppressWarnings("serial")
private static class MockProvider extends Provider {
public MockProvider(String name) {
diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
index 7eb3b45..2224c70 100644
--- a/luni/src/test/java/libcore/java/security/SecureRandomTest.java
+++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
@@ -174,4 +174,40 @@
SecureRandom.DEFAULT_SDK_TARGET_FOR_CRYPTO_PROVIDER_WORKAROUND);
}
}
+
+ /**
+ * Test that the strong instance is from OpenSSLProvider (as specified in security.properties)
+ * even if there are other providers installed.
+ */
+ public void testGetInstanceStrong() throws Exception {
+ Provider openSSLProvider = null;
+ for (Provider p : Security.getProviders()) {
+ if (p.getClass().getName().equals("com.android.org.conscrypt.OpenSSLProvider")) {
+ openSSLProvider = p;
+ }
+ }
+ if (openSSLProvider == null) {
+ throw new IllegalStateException("OpenSSLProvider not found");
+ }
+
+ // Default comes from the OpenSSLProvider
+ assertEquals(openSSLProvider, SecureRandom.getInstance("SHA1PRNG").getProvider());
+ assertEquals(openSSLProvider, new SecureRandom().getProvider());
+
+ Provider weakProvider = new Provider("MockWeakSecureRandomProvider", 1.0, "For testing") {
+ };
+ weakProvider.put("SecureRandom.SHA1PRNG", ProviderTest.SecureRandom1.class.getName());
+
+ // Insert a different provider with highest priority.
+ try {
+ Security.insertProviderAt(weakProvider, 1);
+ // Default comes from the weak provider.
+ assertEquals(weakProvider, SecureRandom.getInstance("SHA1PRNG").getProvider());
+ assertEquals(weakProvider, new SecureRandom().getProvider());
+ // Strong SecureRandom comes from the OpenSSLProvider.
+ assertEquals(openSSLProvider, SecureRandom.getInstanceStrong().getProvider());
+ } finally {
+ Security.removeProvider(weakProvider.getName());
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java b/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
index 2a9e5ef..4f6e170 100644
--- a/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
+++ b/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
@@ -18,6 +18,8 @@
import java.io.Serializable;
import java.util.AbstractCollection;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentHashMap;
import junit.framework.TestCase;
@@ -55,4 +57,31 @@
reader.join();
mutator.join();
}
+
+ // http://b/31052838
+ public void test_empty_removeAll_null() {
+ try {
+ new EmptyCollection().removeAll(null);
+ fail("Should have thrown");
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ // http://b/31052838
+ public void test_empty_retainAll_null() {
+ try {
+ new EmptyCollection().retainAll(null);
+ fail("Should have thrown");
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /**
+ * An AbstractCollection that does not override removeAll() / retainAll().
+ */
+ private static class EmptyCollection extends AbstractCollection<Object> {
+ @Override public Iterator iterator() { return Collections.emptySet().iterator(); }
+ @Override public int size() { return 0; }
+ }
+
}
diff --git a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
index deb0626..0116a31 100644
--- a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
+++ b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
@@ -576,10 +576,10 @@
final Matcher m = p.matcher("");
ArrayList<Thread> threads = new ArrayList<Thread>();
- for (int i = 0; i < 10; ++i) {
+ for (int i = 0; i < 5; ++i) {
Thread t = new Thread(new Runnable() {
public void run() {
- for (int i = 0; i < 4096; ++i) {
+ for (int i = 0; i < 1024; ++i) {
String s = "some example text";
m.reset(s);
try {
diff --git a/luni/src/test/java/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/net/MimeUtilsTest.java
index 156c9c4..ac0c017 100644
--- a/luni/src/test/java/libcore/net/MimeUtilsTest.java
+++ b/luni/src/test/java/libcore/net/MimeUtilsTest.java
@@ -18,8 +18,6 @@
import junit.framework.TestCase;
-import libcore.net.MimeUtils;
-
public class MimeUtilsTest extends TestCase {
public void test_15715370() {
assertEquals("audio/flac", MimeUtils.guessMimeTypeFromExtension("flac"));
@@ -71,4 +69,11 @@
assertNull(MimeUtils.guessMimeTypeFromExtension(""));
assertNull(MimeUtils.guessExtensionFromMimeType("doesnotexist"));
}
+
+ public void test_30793548() {
+ assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gpp"));
+ assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gp"));
+ assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3gpp2"));
+ assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3g2"));
+ }
}
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index 14fd77b..839067e 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -47,6 +47,7 @@
dalvik/src/main/java/dalvik/system/DalvikLogging.java \
dalvik/src/main/java/dalvik/system/DexClassLoader.java \
dalvik/src/main/java/dalvik/system/DexFile.java \
+ dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java \
dalvik/src/main/java/dalvik/system/DexPathList.java \
dalvik/src/main/java/dalvik/system/NativeStart.java \
dalvik/src/main/java/dalvik/system/PathClassLoader.java \
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index 43384f2..1e0a58b 100644
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -226,6 +226,12 @@
private transient int objectSize;
/**
+ * Aligned object size for allocation fast path. The value is max int if the object is
+ * uninitialized or finalizable, otherwise the aligned object size.
+ */
+ private transient int objectSizeAllocFastPath;
+
+ /**
* The lower 16 bits is the primitive type value, or 0 if not a primitive type; set for
* generated primitive classes.
*/
@@ -292,7 +298,6 @@
* information about modifiers and type parameters
*
* @since 1.8
- * @hide Hidden pending tests
*/
public String toGenericString() {
if (isPrimitive()) {
diff --git a/ojluni/src/main/java/java/lang/reflect/Constructor.java b/ojluni/src/main/java/java/lang/reflect/Constructor.java
index 4ac1ca8..3e26cbb 100644
--- a/ojluni/src/main/java/java/lang/reflect/Constructor.java
+++ b/ojluni/src/main/java/java/lang/reflect/Constructor.java
@@ -348,19 +348,6 @@
return super.isSynthetic();
}
- String getSignature() {
- StringBuilder result = new StringBuilder();
-
- result.append('(');
- Class<?>[] parameterTypes = getParameterTypes();
- for (Class<?> parameterType : parameterTypes) {
- result.append(Types.getSignature(parameterType));
- }
- result.append(")V");
-
- return result.toString();
- }
-
/**
* {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
diff --git a/ojluni/src/main/java/java/lang/reflect/Method.java b/ojluni/src/main/java/java/lang/reflect/Method.java
index ec0cdcf..a9f2eb7 100644
--- a/ojluni/src/main/java/java/lang/reflect/Method.java
+++ b/ojluni/src/main/java/java/lang/reflect/Method.java
@@ -487,27 +487,6 @@
}
/**
- * Returns the constructor's signature in non-printable form. This is called
- * (only) from IO native code and needed for deriving the serialVersionUID
- * of the class
- *
- * @return The constructor's signature.
- */
- @SuppressWarnings("unused")
- String getSignature() {
- StringBuilder result = new StringBuilder();
-
- result.append('(');
- Class<?>[] parameterTypes = getParameterTypes();
- for (Class<?> parameterType : parameterTypes) {
- result.append(Types.getSignature(parameterType));
- }
- result.append(')');
- result.append(Types.getSignature(getReturnType()));
-
- return result.toString();
- }
- /**
* Returns true if this and {@code method} have the same name and the same
* parameters in the same order. Such methods can share implementation if
* one method's return types is assignable to the other.
diff --git a/ojluni/src/main/java/java/lang/reflect/Modifier.java b/ojluni/src/main/java/java/lang/reflect/Modifier.java
index 760f1a3..e694505 100644
--- a/ojluni/src/main/java/java/lang/reflect/Modifier.java
+++ b/ojluni/src/main/java/java/lang/reflect/Modifier.java
@@ -502,7 +502,6 @@
*
* @jls 8.4.1 Formal Parameters
* @since 1.8
- * @hide Hidden pending tests
*/
public static int parameterModifiers() {
return PARAMETER_MODIFIERS;
diff --git a/ojluni/src/main/java/java/security/DomainLoadStoreParameter.java b/ojluni/src/main/java/java/security/DomainLoadStoreParameter.java
new file mode 100644
index 0000000..bc96975
--- /dev/null
+++ b/ojluni/src/main/java/java/security/DomainLoadStoreParameter.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package java.security;
+
+import java.net.URI;
+import java.util.*;
+import static java.security.KeyStore.*;
+
+/**
+ * Configuration data that specifies the keystores in a keystore domain.
+ * A keystore domain is a collection of keystores that are presented as a
+ * single logical keystore. The configuration data is used during
+ * {@code KeyStore}
+ * {@link KeyStore#load(KeyStore.LoadStoreParameter) load} and
+ * {@link KeyStore#store(KeyStore.LoadStoreParameter) store} operations.
+ * <p>
+ * The following syntax is supported for configuration data:
+ * <pre>{@code
+ * domain <domainName> [<property> ...] {
+ * keystore <keystoreName> [<property> ...] ;
+ * ...
+ * };
+ * ...
+ * }</pre>
+ * where {@code domainName} and {@code keystoreName} are identifiers
+ * and {@code property} is a key/value pairing. The key and value are
+ * separated by an 'equals' symbol and the value is enclosed in double
+ * quotes. A property value may be either a printable string or a binary
+ * string of colon-separated pairs of hexadecimal digits. Multi-valued
+ * properties are represented as a comma-separated list of values,
+ * enclosed in square brackets.
+ * See {@link Arrays#toString(java.lang.Object[])}.
+ * <p>
+ * To ensure that keystore entries are uniquely identified, each
+ * entry's alias is prefixed by its {@code keystoreName} followed
+ * by the entry name separator and each {@code keystoreName} must be
+ * unique within its domain. Entry name prefixes are omitted when
+ * storing a keystore.
+ * <p>
+ * Properties are context-sensitive: properties that apply to
+ * all the keystores in a domain are located in the domain clause,
+ * and properties that apply only to a specific keystore are located
+ * in that keystore's clause.
+ * Unless otherwise specified, a property in a keystore clause overrides
+ * a property of the same name in the domain clause. All property names
+ * are case-insensitive. The following properties are supported:
+ * <dl>
+ * <dt> {@code keystoreType="<type>"} </dt>
+ * <dd> The keystore type. </dd>
+ * <dt> {@code keystoreURI="<url>"} </dt>
+ * <dd> The keystore location. </dd>
+ * <dt> {@code keystoreProviderName="<name>"} </dt>
+ * <dd> The name of the keystore's JCE provider. </dd>
+ * <dt> {@code keystorePasswordEnv="<environment-variable>"} </dt>
+ * <dd> The environment variable that stores a keystore password.
+ * Alternatively, passwords may be supplied to the constructor
+ * method in a {@code Map<String, ProtectionParameter>}. </dd>
+ * <dt> {@code entryNameSeparator="<separator>"} </dt>
+ * <dd> The separator between a keystore name prefix and an entry name.
+ * When specified, it applies to all the entries in a domain.
+ * Its default value is a space. </dd>
+ * </dl>
+ * <p>
+ * For example, configuration data for a simple keystore domain
+ * comprising three keystores is shown below:
+ * <pre>
+ *
+ * domain app1 {
+ * keystore app1-truststore
+ * keystoreURI="file:///app1/etc/truststore.jks";
+ *
+ * keystore system-truststore
+ * keystoreURI="${java.home}/lib/security/cacerts";
+ *
+ * keystore app1-keystore
+ * keystoreType="PKCS12"
+ * keystoreURI="file:///app1/etc/keystore.p12";
+ * };
+ *
+ * </pre>
+ * @since 1.8
+ */
+public final class DomainLoadStoreParameter implements LoadStoreParameter {
+
+ private final URI configuration;
+ private final Map<String,ProtectionParameter> protectionParams;
+
+ /**
+ * Constructs a DomainLoadStoreParameter for a keystore domain with
+ * the parameters used to protect keystore data.
+ *
+ * @param configuration identifier for the domain configuration data.
+ * The name of the target domain should be specified in the
+ * {@code java.net.URI} fragment component when it is necessary
+ * to distinguish between several domain configurations at the
+ * same location.
+ *
+ * @param protectionParams the map from keystore name to the parameter
+ * used to protect keystore data.
+ * A {@code java.util.Collections.EMPTY_MAP} should be used
+ * when protection parameters are not required or when they have
+ * been specified by properties in the domain configuration data.
+ * It is cloned to prevent subsequent modification.
+ *
+ * @exception NullPointerException if {@code configuration} or
+ * {@code protectionParams} is {@code null}
+ */
+ public DomainLoadStoreParameter(URI configuration,
+ Map<String,ProtectionParameter> protectionParams) {
+ if (configuration == null || protectionParams == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.configuration = configuration;
+ this.protectionParams =
+ Collections.unmodifiableMap(new HashMap<>(protectionParams));
+ }
+
+ /**
+ * Gets the identifier for the domain configuration data.
+ *
+ * @return the identifier for the configuration data
+ */
+ public URI getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Gets the keystore protection parameters for keystores in this
+ * domain.
+ *
+ * @return an unmodifiable map of keystore names to protection
+ * parameters
+ */
+ public Map<String,ProtectionParameter> getProtectionParams() {
+ return protectionParams;
+ }
+
+ /**
+ * Gets the keystore protection parameters for this domain.
+ * Keystore domains do not support a protection parameter.
+ *
+ * @return always returns {@code null}
+ */
+ @Override
+ public KeyStore.ProtectionParameter getProtectionParameter() {
+ return null;
+ }
+}
diff --git a/ojluni/src/main/java/java/security/Principal.java b/ojluni/src/main/java/java/security/Principal.java
index fb29aca..a538e70 100644
--- a/ojluni/src/main/java/java/security/Principal.java
+++ b/ojluni/src/main/java/java/security/Principal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.security;
+import javax.security.auth.Subject;
+
/**
* This interface represents the abstract notion of a principal, which
* can be used to represent any entity, such as an individual, a
@@ -45,7 +47,6 @@
*
* @return true if the principal passed in is the same as that
* encapsulated by this principal, and false otherwise.
-
*/
public boolean equals(Object another);
@@ -69,4 +70,25 @@
* @return the name of this principal.
*/
public String getName();
+
+ /**
+ * Returns true if the specified subject is implied by this principal.
+ *
+ * <p>The default implementation of this method returns true if
+ * {@code subject} is non-null and contains at least one principal that
+ * is equal to this principal.
+ *
+ * <p>Subclasses may override this with a different implementation, if
+ * necessary.
+ *
+ * @param subject the {@code Subject}
+ * @return true if {@code subject} is non-null and is
+ * implied by this principal, or false otherwise.
+ * @since 1.8
+ */
+ public default boolean implies(Subject subject) {
+ if (subject == null)
+ return false;
+ return subject.getPrincipals().contains(this);
+ }
}
diff --git a/ojluni/src/main/java/java/security/PrivateKey.java b/ojluni/src/main/java/java/security/PrivateKey.java
index d836ea3..7d8a7ea 100644
--- a/ojluni/src/main/java/java/security/PrivateKey.java
+++ b/ojluni/src/main/java/java/security/PrivateKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,13 +26,23 @@
package java.security;
/**
- * <p>A private key. This interface contains no methods or constants.
- * It merely serves to group (and provide type safety for) all private key
- * interfaces.
- *
+ * A private key.
+ * The purpose of this interface is to group (and provide type safety
+ * for) all private key interfaces.
+ * <p>
* Note: The specialized private key interfaces extend this interface.
- * See, for example, the DSAPrivateKey interface in
- * <code>java.security.interfaces</code>.
+ * See, for example, the {@code DSAPrivateKey} interface in
+ * {@link java.security.interfaces}.
+ * <p>
+ * Implementations should override the default {@code destroy} and
+ * {@code isDestroyed} methods from the
+ * {@link javax.security.auth.Destroyable} interface to enable
+ * sensitive key information to be destroyed, cleared, or in the case
+ * where such information is immutable, unreferenced.
+ * Finally, since {@code PrivateKey} is {@code Serializable}, implementations
+ * should also override
+ * {@link java.io.ObjectOutputStream#writeObject(java.lang.Object)}
+ * to prevent keys that have been destroyed from being serialized.
*
* @see Key
* @see PublicKey
@@ -46,7 +56,8 @@
* @author Josh Bloch
*/
-public interface PrivateKey extends Key {
+public interface PrivateKey extends Key, javax.security.auth.Destroyable {
+
// Declare serialVersionUID to be compatible with JDK1.1
/**
* The class fingerprint that is set to indicate serialization
diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java
index 784cbf1..81ae9f3 100644
--- a/ojluni/src/main/java/java/security/Provider.java
+++ b/ojluni/src/main/java/java/security/Provider.java
@@ -464,6 +464,22 @@
putAll(copy);
}
+ private boolean checkLegacy(Object key) {
+ if (registered) {
+ Security.increaseVersion();
+ }
+ String keyString = (String)key;
+ if (keyString.startsWith("Provider.")) {
+ return false;
+ }
+
+ legacyChanged = true;
+ if (legacyStrings == null) {
+ legacyStrings = new LinkedHashMap<String,String>();
+ }
+ return true;
+ }
+
/**
* Copies all of the mappings from the specified Map to this provider.
* Internal method to be called AFTER the security check has been
@@ -479,37 +495,21 @@
}
private Object implRemove(Object key) {
- if (registered) {
- Security.increaseVersion();
- }
if (key instanceof String) {
- String keyString = (String)key;
- if (keyString.startsWith("Provider.")) {
+ if (!checkLegacy(key)) {
return null;
}
- legacyChanged = true;
- if (legacyStrings == null) {
- legacyStrings = new LinkedHashMap<String,String>();
- }
- legacyStrings.remove(keyString);
+ legacyStrings.remove((String)key);
}
return super.remove(key);
}
private Object implPut(Object key, Object value) {
if ((key instanceof String) && (value instanceof String)) {
- String keyString = (String)key;
- if (keyString.startsWith("Provider.")) {
+ if (!checkLegacy(key)) {
return null;
}
- if (registered) {
- Security.increaseVersion();
- }
- legacyChanged = true;
- if (legacyStrings == null) {
- legacyStrings = new LinkedHashMap<String,String>();
- }
- legacyStrings.put(keyString, (String)value);
+ legacyStrings.put((String)key, (String)value);
}
return super.put(key, value);
}
diff --git a/ojluni/src/main/java/java/security/SecureRandom.java b/ojluni/src/main/java/java/security/SecureRandom.java
index 6bf43f1..43bc3a3 100644
--- a/ojluni/src/main/java/java/security/SecureRandom.java
+++ b/ojluni/src/main/java/java/security/SecureRandom.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package java.security;
import java.util.*;
+import java.util.regex.*;
import java.security.Provider.Service;
import java.util.function.Function;
@@ -33,6 +34,9 @@
import dalvik.system.VMRuntime;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
+/** BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+import sun.security.util.Debug;
+*/
/**
* This class provides a cryptographically strong random number
@@ -51,7 +55,7 @@
* <i>RFC 1750: Randomness Recommendations for Security</i></a>.
*
* <p>A caller obtains a SecureRandom instance via the
- * no-argument constructor or one of the <code>getInstance</code> methods:
+ * no-argument constructor or one of the {@code getInstance} methods:
*
* <pre>
* SecureRandom random = new SecureRandom();
@@ -72,16 +76,16 @@
* random.nextBytes(bytes);
* </pre>
*
- * <p> Callers may also invoke the <code>generateSeed</code> method
+ * <p> Callers may also invoke the {@code generateSeed} method
* to generate a given number of seed bytes (to seed other random number
* generators, for example):
* <pre>
* byte seed[] = random.generateSeed(20);
* </pre>
*
- * Note: Depending on the implementation, the <code>generateSeed</code> and
- * <code>nextBytes</code> methods may block as entropy is being gathered,
- * for example, if they need to read from /dev/random on various unix-like
+ * Note: Depending on the implementation, the {@code generateSeed} and
+ * {@code nextBytes} methods may block as entropy is being gathered,
+ * for example, if they need to read from /dev/random on various Unix-like
* operating systems.
*
* The SHA1PRNG algorithm from the Crypto provider has been deprecated as it was insecure, and also
@@ -98,6 +102,13 @@
public class SecureRandom extends java.util.Random {
+ /** BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("securerandom");
+ END ANDROID-REMOVED */
+
/**
* The provider.
*
@@ -146,16 +157,16 @@
* for information about standard RNG algorithm names.
*
* <p> The returned SecureRandom object has not been seeded. To seed the
- * returned object, call the <code>setSeed</code> method.
- * If <code>setSeed</code> is not called, the first call to
- * <code>nextBytes</code> will force the SecureRandom object to seed itself.
- * This self-seeding will not occur if <code>setSeed</code> was
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
* previously called.
*/
public SecureRandom() {
/*
* This call to our superclass constructor will result in a call
- * to our own <code>setSeed</code> method, which will return
+ * to our own {@code setSeed} method, which will return
* immediately when it is passed zero.
*/
super(0);
@@ -235,6 +246,13 @@
this.secureRandomSpi = secureRandomSpi;
this.provider = provider;
this.algorithm = algorithm;
+
+ /** BEGIN ANDROID-REMOVED: this debugging mechanism is not supported in Android.
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("SecureRandom." + algorithm +
+ " algorithm from: " + this.provider.getName());
+ }
+ END ANDROID-REMOVED */
}
/**
@@ -251,10 +269,10 @@
* the {@link Security#getProviders() Security.getProviders()} method.
*
* <p> The returned SecureRandom object has not been seeded. To seed the
- * returned object, call the <code>setSeed</code> method.
- * If <code>setSeed</code> is not called, the first call to
- * <code>nextBytes</code> will force the SecureRandom object to seed itself.
- * This self-seeding will not occur if <code>setSeed</code> was
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
* previously called.
*
* @param algorithm the name of the RNG algorithm.
@@ -327,10 +345,10 @@
* the {@link Security#getProviders() Security.getProviders()} method.
*
* <p> The returned SecureRandom object has not been seeded. To seed the
- * returned object, call the <code>setSeed</code> method.
- * If <code>setSeed</code> is not called, the first call to
- * <code>nextBytes</code> will force the SecureRandom object to seed itself.
- * This self-seeding will not occur if <code>setSeed</code> was
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
* previously called.
*
* @param algorithm the name of the RNG algorithm.
@@ -416,10 +434,10 @@
* does not have to be registered in the provider list.
*
* <p> The returned SecureRandom object has not been seeded. To seed the
- * returned object, call the <code>setSeed</code> method.
- * If <code>setSeed</code> is not called, the first call to
- * <code>nextBytes</code> will force the SecureRandom object to seed itself.
- * This self-seeding will not occur if <code>setSeed</code> was
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
* previously called.
*
* @param algorithm the name of the RNG algorithm.
@@ -470,7 +488,7 @@
* Returns the name of the algorithm implemented by this SecureRandom
* object.
*
- * @return the name of the algorithm or <code>unknown</code>
+ * @return the name of the algorithm or {@code unknown}
* if the algorithm name cannot be determined.
* @since 1.5
*/
@@ -493,17 +511,18 @@
/**
* Reseeds this random object, using the eight bytes contained
- * in the given <code>long seed</code>. The given seed supplements,
+ * in the given {@code long seed}. The given seed supplements,
* rather than replaces, the existing seed. Thus, repeated calls
* are guaranteed never to reduce randomness.
*
* <p>This method is defined for compatibility with
- * <code>java.util.Random</code>.
+ * {@code java.util.Random}.
*
* @param seed the seed.
*
* @see #getSeed
*/
+ @Override
public void setSeed(long seed) {
/*
* Ignore call from super constructor (as well as any other calls
@@ -519,14 +538,14 @@
/**
* Generates a user-specified number of random bytes.
*
- * <p> If a call to <code>setSeed</code> had not occurred previously,
+ * <p> If a call to {@code setSeed} had not occurred previously,
* the first call to this method forces this SecureRandom object
* to seed itself. This self-seeding will not occur if
- * <code>setSeed</code> was previously called.
+ * {@code setSeed} was previously called.
*
* @param bytes the array to be filled in with random bytes.
*/
-
+ @Override
synchronized public void nextBytes(byte[] bytes) {
secureRandomSpi.engineNextBytes(bytes);
}
@@ -534,25 +553,27 @@
/**
* Generates an integer containing the user-specified number of
* pseudo-random bits (right justified, with leading zeros). This
- * method overrides a <code>java.util.Random</code> method, and serves
+ * method overrides a {@code java.util.Random} method, and serves
* to provide a source of random bits to all of the methods inherited
- * from that class (for example, <code>nextInt</code>,
- * <code>nextLong</code>, and <code>nextFloat</code>).
+ * from that class (for example, {@code nextInt},
+ * {@code nextLong}, and {@code nextFloat}).
*
* @param numBits number of pseudo-random bits to be generated, where
- * 0 <= <code>numBits</code> <= 32.
+ * {@code 0 <= numBits <= 32}.
*
- * @return an <code>int</code> containing the user-specified number
+ * @return an {@code int} containing the user-specified number
* of pseudo-random bits (right justified, with leading zeros).
*/
+ @Override
final protected int next(int numBits) {
int numBytes = (numBits+7)/8;
byte b[] = new byte[numBytes];
int next = 0;
nextBytes(b);
- for (int i = 0; i < numBytes; i++)
+ for (int i = 0; i < numBytes; i++) {
next = (next << 8) + (b[i] & 0xFF);
+ }
return next >>> (numBytes*8 - numBits);
}
@@ -564,8 +585,8 @@
*
* <p>This method is only included for backwards compatibility.
* The caller is encouraged to use one of the alternative
- * <code>getInstance</code> methods to obtain a SecureRandom object, and
- * then call the <code>generateSeed</code> method to obtain seed bytes
+ * {@code getInstance} methods to obtain a SecureRandom object, and
+ * then call the {@code generateSeed} method to obtain seed bytes
* from that object.
*
* @param numBytes the number of seed bytes to generate.
@@ -575,8 +596,9 @@
* @see #setSeed
*/
public static byte[] getSeed(int numBytes) {
- if (seedGenerator == null)
+ if (seedGenerator == null) {
seedGenerator = new SecureRandom();
+ }
return seedGenerator.generateSeed(numBytes);
}
@@ -625,6 +647,95 @@
return null;
}
+ /*
+ * Lazily initialize since Pattern.compile() is heavy.
+ * Effective Java (2nd Edition), Item 71.
+ */
+ private static final class StrongPatternHolder {
+ /*
+ * Entries are alg:prov separated by ,
+ * Allow for prepended/appended whitespace between entries.
+ *
+ * Capture groups:
+ * 1 - alg
+ * 2 - :prov (optional)
+ * 3 - prov (optional)
+ * 4 - ,nextEntry (optional)
+ * 5 - nextEntry (optional)
+ */
+ private static Pattern pattern =
+ Pattern.compile(
+ "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?");
+ }
+
+ /**
+ * Returns a {@code SecureRandom} object.
+ *
+ * In Android this is equivalent to get a SHA1PRNG from OpenSSLProvider.
+ *
+ * Some situations require strong random values, such as when
+ * creating high-value/long-lived secrets like RSA public/private
+ * keys. To help guide applications in selecting a suitable strong
+ * {@code SecureRandom} implementation, Java distributions
+ * include a list of known strong {@code SecureRandom}
+ * implementations in the {@code securerandom.strongAlgorithms}
+ * Security property.
+ * <p>
+ * Every implementation of the Java platform is required to
+ * support at least one strong {@code SecureRandom} implementation.
+ *
+ * @return a strong {@code SecureRandom} implementation
+ *
+ * @throws NoSuchAlgorithmException if no algorithm is available
+ *
+ * @see Security#getProperty(String)
+ *
+ * @since 1.8
+ */
+ public static SecureRandom getInstanceStrong()
+ throws NoSuchAlgorithmException {
+ String property = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return Security.getProperty(
+ "securerandom.strongAlgorithms");
+ }
+ });
+
+ if ((property == null) || (property.length() == 0)) {
+ throw new NoSuchAlgorithmException(
+ "Null/empty securerandom.strongAlgorithms Security Property");
+ }
+
+ String remainder = property;
+ while (remainder != null) {
+ Matcher m;
+ if ((m = StrongPatternHolder.pattern.matcher(
+ remainder)).matches()) {
+
+ String alg = m.group(1);
+ String prov = m.group(3);
+
+ try {
+ if (prov == null) {
+ return SecureRandom.getInstance(alg);
+ } else {
+ return SecureRandom.getInstance(alg, prov);
+ }
+ } catch (NoSuchAlgorithmException |
+ NoSuchProviderException e) {
+ }
+ remainder = m.group(5);
+ } else {
+ remainder = null;
+ }
+ }
+
+ throw new NoSuchAlgorithmException(
+ "No strong SecureRandom impls available: " + property);
+ }
+
// Declare serialVersionUID to be compatible with JDK1.1
static final long serialVersionUID = 4940670005562187L;
diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java
index 3e82610..e40a1dc 100644
--- a/ojluni/src/main/java/java/util/WeakHashMap.java
+++ b/ojluni/src/main/java/java/util/WeakHashMap.java
@@ -25,6 +25,7 @@
*/
package java.util;
+
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
import java.util.function.BiConsumer;
@@ -191,7 +192,7 @@
@SuppressWarnings("unchecked")
private Entry<K,V>[] newTable(int n) {
- return (Entry<K,V>[]) new Entry[n];
+ return (Entry<K,V>[]) new Entry<?,?>[n];
}
/**
@@ -287,6 +288,23 @@
}
/**
+ * Retrieve object hash code and applies a supplemental hash function to the
+ * result hash, which defends against poor quality hash functions. This is
+ * critical because HashMap uses power-of-two length hash tables, that
+ * otherwise encounter collisions for hashCodes that do not differ
+ * in lower bits.
+ */
+ final int hash(Object k) {
+ int h = k.hashCode();
+
+ // This function ensures that hashCodes that differ only by
+ // constant multiples at each bit position have a bounded
+ // number of collisions (approximately 8 at default load factor).
+ h ^= (h >>> 20) ^ (h >>> 12);
+ return h ^ (h >>> 7) ^ (h >>> 4);
+ }
+
+ /**
* Returns index for hash code h.
*/
private static int indexFor(int h, int length) {
@@ -375,7 +393,7 @@
*/
public V get(Object key) {
Object k = maskNull(key);
- int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
+ int h = hash(k);
Entry<K,V>[] tab = getTable();
int index = indexFor(h, tab.length);
Entry<K,V> e = tab[index];
@@ -405,7 +423,7 @@
*/
Entry<K,V> getEntry(Object key) {
Object k = maskNull(key);
- int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
+ int h = hash(k);
Entry<K,V>[] tab = getTable();
int index = indexFor(h, tab.length);
Entry<K,V> e = tab[index];
@@ -428,7 +446,7 @@
*/
public V put(K key, V value) {
Object k = maskNull(key);
- int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
+ int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
@@ -570,7 +588,7 @@
*/
public V remove(Object key) {
Object k = maskNull(key);
- int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
+ int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
Entry<K,V> prev = tab[i];
@@ -601,7 +619,7 @@
Entry<K,V>[] tab = getTable();
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
Object k = maskNull(entry.getKey());
- int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
+ int h = hash(k);
int i = indexFor(h, tab.length);
Entry<K,V> prev = tab[i];
Entry<K,V> e = prev;
@@ -683,7 +701,7 @@
*/
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
- int hash;
+ final int hash;
Entry<K,V> next;
/**
@@ -731,8 +749,7 @@
public int hashCode() {
K k = getKey();
V v = getValue();
- return ((k==null ? 0 : k.hashCode()) ^
- (v==null ? 0 : v.hashCode()));
+ return Objects.hashCode(k) ^ Objects.hashCode(v);
}
public String toString() {
@@ -742,21 +759,21 @@
private abstract class HashIterator<T> implements Iterator<T> {
private int index;
- private Entry<K,V> entry = null;
- private Entry<K,V> lastReturned = null;
+ private Entry<K,V> entry;
+ private Entry<K,V> lastReturned;
private int expectedModCount = modCount;
/**
* Strong reference needed to avoid disappearance of key
* between hasNext and next
*/
- private Object nextKey = null;
+ private Object nextKey;
/**
* Strong reference needed to avoid disappearance of key
* between nextEntry() and any use of the entry
*/
- private Object currentKey = null;
+ private Object currentKey;
HashIterator() {
index = isEmpty() ? 0 : table.length;
@@ -831,7 +848,7 @@
// Views
- private transient Set<Map.Entry<K,V>> entrySet = null;
+ private transient Set<Map.Entry<K,V>> entrySet;
/**
* Returns a {@link Set} view of the keys contained in this map.
@@ -1014,7 +1031,7 @@
Objects.requireNonNull(function);
int expectedModCount = modCount;
- Entry<K, V>[] tab = getTable();
+ Entry<K, V>[] tab = getTable();;
for (Entry<K, V> entry : tab) {
while (entry != null) {
Object key = entry.get();
@@ -1030,7 +1047,6 @@
}
}
-
/**
* Similar form as other hash Spliterators, but skips dead
* elements.
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 89ae10f..b0d574e 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -572,6 +572,7 @@
ojluni/src/main/java/java/security/DigestInputStream.java \
ojluni/src/main/java/java/security/DigestOutputStream.java \
ojluni/src/main/java/java/security/DomainCombiner.java \
+ ojluni/src/main/java/java/security/DomainLoadStoreParameter.java \
ojluni/src/main/java/java/security/GeneralSecurityException.java \
ojluni/src/main/java/java/security/GuardedObject.java \
ojluni/src/main/java/java/security/Guard.java \