Merge "[automerger skipped] Merge "DO NOT MERGE: CDD Annotations for Section: 7.4.7" into oreo-mr1-cts-dev am: 6cc6a0c703  -s ours" into pie-cts-dev
am: 601d7ae0d7  -s ours

Change-Id: I9ea2fccf656a78ebe195a48420215b69dae8923d
diff --git a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp b/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
index 1892a44..7dc6240 100644
--- a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
+++ b/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
@@ -18,36 +18,29 @@
 #include <error.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <fcntl.h>
 #include <string.h>
 #include <sys/socket.h>
-#include <sys/utsname.h>
 
 #include <gtest/gtest.h>
 #include <qtaguid/qtaguid.h>
 
-int hasQtaguidKernelSupport() {
-    struct utsname buf;
-    int kernel_version_major;
-    int kernel_version_minor;
-
-    int ret = uname(&buf);
-    if (ret) {
-        ret = -errno;
-        return ret;
-    }
-    char dummy;
-    ret = sscanf(buf.release, "%d.%d%c", &kernel_version_major, &kernel_version_minor, &dummy);
-    if (ret < 3)
-        return -EINVAL;
-
-    if ((kernel_version_major == 4 && kernel_version_minor < 9) ||
-        (kernel_version_major < 4)) {
-        return 1;
-    } else {
-        return access("/proc/net/xt_qtaguid/ctrl", F_OK) != -1;
-    }
+int canAccessQtaguidFile() {
+    int fd = open("/proc/net/xt_qtaguid/ctrl", O_RDONLY | O_CLOEXEC);
+    close(fd);
+    return fd != -1;
 }
 
+#define SKIP_IF_QTAGUID_NOT_SUPPORTED()                                                       \
+  do {                                                                                        \
+    int res = canAccessQtaguidFile();                                                      \
+    ASSERT_LE(0, res);                                                                        \
+    if (!res) {                                                                               \
+          GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";  \
+          return;                                                                             \
+    }                                                                                         \
+  } while (0)
+
 int getCtrlSkInfo(int tag, uid_t uid, uint64_t* sk_addr, int* ref_cnt) {
     FILE *fp;
     fp = fopen("/proc/net/xt_qtaguid/ctrl", "r");
@@ -95,12 +88,8 @@
 }
 
 TEST (NativeQtaguidTest, close_socket_without_untag) {
-    int res = hasQtaguidKernelSupport();
-    ASSERT_LE(0, res);
-    if (!res) {
-          GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
-          return;
-    }
+    SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
     uid_t uid = getuid();
     int tag = arc4random();
@@ -114,12 +103,8 @@
 }
 
 TEST (NativeQtaguidTest, close_socket_without_untag_ipv6) {
-    int res = hasQtaguidKernelSupport();
-    ASSERT_LE(0, res);
-    if (!res) {
-          GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
-          return;
-    }
+    SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
     int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
     uid_t uid = getuid();
     int tag = arc4random();
@@ -133,12 +118,8 @@
 }
 
 TEST (NativeQtaguidTest, no_socket_addr_leak) {
-    int res = hasQtaguidKernelSupport();
-    ASSERT_LE(0, res);
-    if (!res) {
-          GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
-          return;
-    }
+  SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
   checkNoSocketPointerLeaks(AF_INET);
   checkNoSocketPointerLeaks(AF_INET6);
 }
diff --git a/tests/cts/net/src/android/net/cts/UriTest.java b/tests/cts/net/src/android/net/cts/UriTest.java
index 5c54cda..080f00b 100644
--- a/tests/cts/net/src/android/net/cts/UriTest.java
+++ b/tests/cts/net/src/android/net/cts/UriTest.java
@@ -164,22 +164,61 @@
         String encoded = Uri.encode("Bob:/", "/");
         assertEquals(-1, encoded.indexOf(':'));
         assertTrue(encoded.indexOf('/') > -1);
-        assertDecode(null);
-        assertDecode("");
-        assertDecode("Bob");
-        assertDecode(":Bob");
-        assertDecode("::Bob");
-        assertDecode("Bob::Lee");
-        assertDecode("Bob:Lee");
-        assertDecode("Bob::");
-        assertDecode("Bob:");
-        assertDecode("::Bob::");
+        assertEncodeDecodeRoundtripExact(null);
+        assertEncodeDecodeRoundtripExact("");
+        assertEncodeDecodeRoundtripExact("Bob");
+        assertEncodeDecodeRoundtripExact(":Bob");
+        assertEncodeDecodeRoundtripExact("::Bob");
+        assertEncodeDecodeRoundtripExact("Bob::Lee");
+        assertEncodeDecodeRoundtripExact("Bob:Lee");
+        assertEncodeDecodeRoundtripExact("Bob::");
+        assertEncodeDecodeRoundtripExact("Bob:");
+        assertEncodeDecodeRoundtripExact("::Bob::");
     }
 
-    private void assertDecode(String s) {
+    private static void assertEncodeDecodeRoundtripExact(String s) {
         assertEquals(s, Uri.decode(Uri.encode(s, null)));
     }
 
+    public void testDecode_emptyString_returnsEmptyString() {
+        assertEquals("", Uri.decode(""));
+    }
+
+    public void testDecode_null_returnsNull() {
+        assertNull(Uri.decode(null));
+    }
+
+    public void testDecode_wrongHexDigit() {
+        // %p in the end.
+        assertEquals("ab/$\u0102%\u0840\uFFFD\u0000", Uri.decode("ab%2f$%C4%82%25%e0%a1%80%p"));
+    }
+
+    public void testDecode_secondHexDigitWrong() {
+        // %1p in the end.
+        assertEquals("ab/$\u0102%\u0840\uFFFD\u0001", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%1p"));
+    }
+
+    public void testDecode_endsWithPercent_appendsUnknownCharacter() {
+        // % in the end.
+        assertEquals("ab/$\u0102%\u0840\uFFFD", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%"));
+    }
+
+    public void testDecode_plusNotConverted() {
+        assertEquals("ab/$\u0102%+\u0840", Uri.decode("ab%2f$%c4%82%25+%e0%a1%80"));
+    }
+
+    // Last character needs decoding (make sure we are flushing the buffer with chars to decode).
+    public void testDecode_lastCharacter() {
+        assertEquals("ab/$\u0102%\u0840", Uri.decode("ab%2f$%c4%82%25%e0%a1%80"));
+    }
+
+    // Check that a second row of encoded characters is decoded properly (internal buffers are
+    // reset properly).
+    public void testDecode_secondRowOfEncoded() {
+        assertEquals("ab/$\u0102%\u0840aa\u0840",
+                Uri.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80"));
+    }
+
     public void testFromFile() {
         File f = new File("/tmp/bob");
         Uri uri = Uri.fromFile(f);
diff --git a/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java b/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
index 70ae496..95f415c 100644
--- a/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
+++ b/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
@@ -230,6 +230,19 @@
         final String EXPECTED = "Issued to: c=ccc,o=testOName,ou=testUName,cn=testCName;\n"
             + "Issued by: e=aeei,c=adb,o=testOName,ou=testUName,cn=testCName;\n";
         assertEquals(EXPECTED, ssl.toString());
+        assertNull(ssl.getX509Certificate());
     }
 
+    public void testGetX509Certificate() {
+        final String TO = "c=ccc,o=testOName,ou=testUName,cn=testCName";
+        final String BY = "e=aeei,c=adb,o=testOName,ou=testUName,cn=testCName";
+        Date validNotBefore = new Date(System.currentTimeMillis() - 1000);
+        Date validNotAfter = new Date(System.currentTimeMillis());
+        SslCertificate ssl = new SslCertificate(TO, BY, validNotBefore, validNotAfter);
+        assertNull(ssl.getX509Certificate());
+
+        X509Certificate cert = new MockX509Certificate();
+        ssl = new SslCertificate(cert);
+        assertSame(cert, ssl.getX509Certificate());
+    }
 }