Merge "Test fix: Handle missing dummy0 network interface" into nyc-mr2-dev
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 51c2a94..9082209 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -1537,8 +1537,13 @@
sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
- if (recvCount > 0) {
- fillInetSocketAddress(env, javaInetSocketAddress, ss);
+ if (recvCount >= 0) {
+ // The socket may have performed orderly shutdown and recvCount would return 0 (see man 2
+ // recvfrom), in which case ss.ss_family == AF_UNIX and fillInetSocketAddress would fail.
+ // Don't fill in the address if recvfrom didn't succeed. http://b/33483694
+ if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
+ fillInetSocketAddress(env, javaInetSocketAddress, ss);
+ }
}
return recvCount;
}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index b2c3775..9729cf2 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -150,7 +150,20 @@
// allow (but strip) trailing \n, \r and \r\n
// assertForbiddenRequestHeaderValue("\r");
// End of workaround
- assertEquals("a valid\tvalue", setAndReturnRequestHeaderValue("a valid\tvalue"));
+
+ // '\t' in header values can either be (a) forbidden or (b) allowed.
+ // The original version of Android N (API 23) implemented behavior
+ // (a), but OEMs can backport a fix that changes the behavior to (b).
+ // Therefore, this test has been relaxed for Android N CTS to allow
+ // either behavior. It is planned that future versions of Android only
+ // allow behavior (b).
+ try {
+ // throws IAE in case (a), passes in case (b)
+ assertEquals("a valid\tvalue", setAndReturnRequestHeaderValue("a valid\tvalue"));
+ } catch (IllegalArgumentException tolerated) {
+ // verify case (a)
+ assertForbiddenRequestHeaderValue("\t");
+ }
assertForbiddenRequestHeaderValue("\u001f");
assertForbiddenRequestHeaderValue("\u007f");
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index 789e3e9..629015f 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -757,4 +757,26 @@
assertEquals("/some/path", new URL("http://foobar.com/some/path#").getFile());
assertEquals("/some/path", new URL("http://foobar.com/some/path?#").getFile());
}
+
+ // http://b/31858037
+ public void testFragmentWithSlash() throws Exception {
+ final String host = "example.com";
+ final String fragment = "@not-a-host-name/a";
+ URL url = new URL(String.format("http://%s#%s", host, fragment));
+ assertNull(url.getUserInfo());
+ assertEquals(host, url.getAuthority());
+ assertEquals(host, url.getHost());
+ assertEquals(fragment, url.getRef());
+ }
+
+ // http://b/31858037
+ public void testFragmentWithQuery() throws Exception {
+ final String host = "example.com";
+ final String fragment = "@not-a-host-name?a";
+ URL url = new URL(String.format("http://%s#%s", host, fragment));
+ assertNull(url.getUserInfo());
+ assertEquals(host, url.getAuthority());
+ assertEquals(host, url.getHost());
+ assertEquals(fragment, url.getRef());
+ }
}
diff --git a/luni/src/test/java/libcore/java/nio/BufferTest.java b/luni/src/test/java/libcore/java/nio/BufferTest.java
index 9a2cb12..9063e27 100644
--- a/luni/src/test/java/libcore/java/nio/BufferTest.java
+++ b/luni/src/test/java/libcore/java/nio/BufferTest.java
@@ -1429,4 +1429,41 @@
assertFalse(bigEndian.asFloatBuffer().slice().get() ==
littleEndian.asFloatBuffer().slice().get());
}
+
+ // http://b/32655865
+ public void test_ByteBufferAsXBuffer_ByteOrder_2() {
+ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10);
+ byteBuffer.order(ByteOrder.BIG_ENDIAN);
+ // Fill a ByteBuffer with different bytes that make it easy to tell byte ordering issues.
+ for (int i = 0; i < 10; i++) {
+ byteBuffer.put((byte)i);
+ }
+ byteBuffer.rewind();
+
+ // Create BIG_ENDIAN views of the buffer.
+ ShortBuffer sb_be = byteBuffer.asShortBuffer();
+ LongBuffer lb_be = byteBuffer.asLongBuffer();
+ IntBuffer ib_be = byteBuffer.asIntBuffer();
+ DoubleBuffer db_be = byteBuffer.asDoubleBuffer();
+ CharBuffer cb_be = byteBuffer.asCharBuffer();
+ FloatBuffer fb_be = byteBuffer.asFloatBuffer();
+
+ // Change the order of the underlying buffer.
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ // Create LITTLE_ENDIAN views of the buffer.
+ ShortBuffer sb_le = byteBuffer.asShortBuffer();
+ LongBuffer lb_le = byteBuffer.asLongBuffer();
+ IntBuffer ib_le = byteBuffer.asIntBuffer();
+ DoubleBuffer db_le = byteBuffer.asDoubleBuffer();
+ CharBuffer cb_le = byteBuffer.asCharBuffer();
+ FloatBuffer fb_le = byteBuffer.asFloatBuffer();
+
+ assertFalse(sb_be.get() == sb_le.get());
+ assertFalse(lb_be.get() == lb_le.get());
+ assertFalse(ib_be.get() == ib_le.get());
+ assertFalse(db_be.get() == db_le.get());
+ assertFalse(cb_be.get() == cb_le.get());
+ assertFalse(fb_be.get() == fb_le.get());
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/FormatterTest.java b/luni/src/test/java/libcore/java/util/FormatterTest.java
index e87fee5..aed9ca0 100644
--- a/luni/src/test/java/libcore/java/util/FormatterTest.java
+++ b/luni/src/test/java/libcore/java/util/FormatterTest.java
@@ -17,7 +17,11 @@
package libcore.java.util;
import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
import java.util.Calendar;
+import java.util.Formatter;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
@@ -183,4 +187,24 @@
assertEquals(expected, String.format(Locale.US, "%t" + pattern, c));
assertEquals(expected, String.format(Locale.US, "%T" + pattern, c));
}
+
+ // http://b/33245708: Some locales have a group separator != '\0' but a default decimal format
+ // pattern without grouping (e.g. a group size of zero). This would throw divide by zero when
+ // working out where to place the separator.
+ public void testGroupingSizeZero() {
+ Locale localeWithoutGrouping = new Locale("hy");
+ DecimalFormat decimalFormat =
+ (DecimalFormat) NumberFormat.getInstance(localeWithoutGrouping);
+
+ // Confirm the locale is still a good example: it has a group separator, but no grouping in
+ // the default decimal format.
+ assertEquals(0, decimalFormat.getGroupingSize());
+ assertFalse(decimalFormat.isGroupingUsed());
+ DecimalFormatSymbols symbols = decimalFormat.getDecimalFormatSymbols();
+ assertTrue(symbols.getGroupingSeparator() != '\0');
+
+ Formatter formatter = new Formatter(localeWithoutGrouping);
+ formatter.format("%,d", 123456789);
+ // No exception expected
+ }
}
diff --git a/ojluni/src/main/java/java/net/URLStreamHandler.java b/ojluni/src/main/java/java/net/URLStreamHandler.java
index e177363..ddea036 100755
--- a/ojluni/src/main/java/java/net/URLStreamHandler.java
+++ b/ojluni/src/main/java/java/net/URLStreamHandler.java
@@ -175,6 +175,14 @@
i = limit;
}
+ // ----- BEGIN android -----
+ // i may become greater than limit
+ // b/31858037
+ if (i > limit) {
+ i = limit;
+ }
+ // ----- END android -----
+
host = authority = spec.substring(start, i);
int ind = authority.indexOf('@');
diff --git a/ojluni/src/main/java/java/nio/ByteBuffer.java b/ojluni/src/main/java/java/nio/ByteBuffer.java
index 523bbda..1e50922 100644
--- a/ojluni/src/main/java/java/nio/ByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBuffer.java
@@ -555,14 +555,14 @@
// isDirect() doesn't imply !hasArray(), ByteBuffer.allocateDirect allocated buffer will
// have a backing, non-gc-movable byte array. JNI allocated direct byte buffers WILL NOT
// have a backing array.
- final Object srcObject = src.isDirect() ? src : src.array();
+ final Object srcObject = src.isDirect() ? src : src.hb;
int srcOffset = src.position();
if (!src.isDirect()) {
srcOffset += src.offset;
}
final ByteBuffer dst = this;
- final Object dstObject = dst.isDirect() ? dst : dst.array();
+ final Object dstObject = dst.isDirect() ? dst : dst.hb;
int dstOffset = dst.position();
if (!dst.isDirect()) {
dstOffset += dst.offset;
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
index c94bc37..9dbb8a6 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
@@ -37,7 +37,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsDoubleBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsDoubleBuffer.java
index f9c13fa..ff4a6bf 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsDoubleBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsDoubleBuffer.java
@@ -38,7 +38,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsFloatBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsFloatBuffer.java
index 667c8bd..8e4e2e8 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsFloatBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsFloatBuffer.java
@@ -37,7 +37,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsIntBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsIntBuffer.java
index 275f37e..e340426 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsIntBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsIntBuffer.java
@@ -37,7 +37,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsLongBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsLongBuffer.java
index 1ea65e3..70f59c9 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsLongBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsLongBuffer.java
@@ -37,7 +37,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAsShortBuffer.java b/ojluni/src/main/java/java/nio/ByteBufferAsShortBuffer.java
index 90aec35..5178a7e 100644
--- a/ojluni/src/main/java/java/nio/ByteBufferAsShortBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBufferAsShortBuffer.java
@@ -37,7 +37,7 @@
int mark, int pos, int lim, int cap,
int off, ByteOrder order) {
super(mark, pos, lim, cap);
- this.bb = bb;
+ this.bb = bb.duplicate();
this.isReadOnly = bb.isReadOnly;
// There are only two possibilities for the type of ByteBuffer "bb", viz, DirectByteBuffer and
// HeapByteBuffer. We only have to initialize the field when bb is an instance of
diff --git a/ojluni/src/main/java/java/util/Formatter.java b/ojluni/src/main/java/java/util/Formatter.java
index 9a4e234..c656e9c 100755
--- a/ojluni/src/main/java/java/util/Formatter.java
+++ b/ojluni/src/main/java/java/util/Formatter.java
@@ -4193,6 +4193,14 @@
grpSep = dfs.getGroupingSeparator();
DecimalFormat df = (DecimalFormat) NumberFormat.getIntegerInstance(l);
grpSize = df.getGroupingSize();
+ // Android-changed: http://b/33245708 : Some locales have a group separator but
+ // also patterns without groups. If we do not clear the group separator in these
+ // cases a divide by zero is thrown when determining where to place the
+ // separators.
+ if (!df.isGroupingUsed() || df.getGroupingSize() == 0) {
+ grpSep = '\0';
+ }
+ // Android-changed: end http://b/33245708.
}
}
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index 0396e8c..2a24a2e 100755
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -33,6 +33,7 @@
import java.util.function.Consumer;
import java.util.function.BiConsumer;
+// Android-added: Note about spliterator order b/33945212 in Android N
/**
* <p>Hash table and linked list implementation of the <tt>Map</tt> interface,
* with predictable iteration order. This implementation differs from
@@ -140,6 +141,23 @@
* returned by all of this class's collection view methods are
* <em><a href="Spliterator.html#binding">late-binding</a></em>,
* <em>fail-fast</em>, and additionally report {@link Spliterator#ORDERED}.
+ * <em>Note</em>: The implementation of these spliterators in Android Nougat
+ * (API levels 24 and 25) uses the wrong order (inconsistent with the
+ * iterators, which use the correct order), despite reporting
+ * {@link Spliterator#ORDERED}. You may use the following code fragments
+ * to obtain a correctly ordered Spliterator on API level 24 and 25:
+ * <ul>
+ * <li>For a Collection view {@code c = lhm.keySet()},
+ * {@code c = lhm.keySet()} or {@code c = lhm.values()}, use
+ * {@code java.util.Spliterators.spliterator(c, c.spliterator().characteristics())}
+ * instead of {@code c.spliterator()}.
+ * <li>Instead of {@code lhm.stream()} or {@code lhm.parallelStream()}, use
+ * {@code java.util.stream.StreamSupport.stream(spliterator, false)}
+ * to construct a (nonparallel) {@link java.util.stream.Stream} from
+ * such a {@code Spliterator}.
+ * </ul>
+ * Note that these workarounds are only suggested where {@code lhm} is a
+ * {@code LinkedHashMap}.
*
* <p>This class is a member of the
* <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/collections/index.html">