From 4b05fbd1e7201b15aba4b9ac490a3cc065004147 Mon Sep 17 00:00:00 2001 From: Edward Savage-Jones Date: Thu, 25 Feb 2016 00:36:09 +0100 Subject: [PATCH 1/4] Swapped memset params memset bug Change-Id: Icf173de400ae1cfcffd590b3fb789c54f6a55bae --- tests/cts/net/jni/NativeDnsJni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cts/net/jni/NativeDnsJni.c b/tests/cts/net/jni/NativeDnsJni.c index 4eb3c7aebc..352c0c52cc 100644 --- a/tests/cts/net/jni/NativeDnsJni.c +++ b/tests/cts/net/jni/NativeDnsJni.c @@ -126,7 +126,7 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas return JNI_FALSE; } - memset(buf, sizeof(buf), 0); + memset(buf, 0, sizeof(buf)); res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags); if (res != 0) { ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2, From 60bd0b56fb447fa1021f9f48008297479dcc3d4f Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Thu, 9 Jun 2016 13:32:31 -0700 Subject: [PATCH 2/4] Fix misc-macro-parentheses warnings in cts. Add parentheses around macro arguments used beside operators. Use 'aoto' type to avoid clang-tidy warnings of missing parentheses of 'TYPE *'. Bug: 28705665 Change-Id: I5d2c3b2bdfb7775200f31a011758b9a35b14794d --- tests/cts/net/jni/NativeMultinetworkJni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cts/net/jni/NativeMultinetworkJni.c b/tests/cts/net/jni/NativeMultinetworkJni.c index ad56b510c3..6990efa452 100644 --- a/tests/cts/net/jni/NativeMultinetworkJni.c +++ b/tests/cts/net/jni/NativeMultinetworkJni.c @@ -30,7 +30,7 @@ #include #include -#define UNUSED(X) ((void) X) +#define UNUSED(X) ((void) (X)) static const char kHostname[] = "connectivitycheck.android.com"; From a87e5240cc29979270520dca070b43f54e82c5a6 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Tue, 28 Jun 2016 18:24:20 +0100 Subject: [PATCH 3/4] Initialize MockWebServer in setUp() not construction time Should be a no-op but makes test suite creation cheaper. Bug: 29820565 Change-Id: Ieee5568a6f477d591436275be4d4e7e3d5dbd322 --- .../net/src/android/net/http/cts/HttpResponseCacheTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java b/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java index 545541d68b..7987a50eb9 100644 --- a/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java +++ b/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java @@ -38,10 +38,11 @@ import java.util.UUID; public final class HttpResponseCacheTest extends TestCase { private File cacheDir; - private MockWebServer server = new MockWebServer(); + private MockWebServer server; @Override public void setUp() throws Exception { super.setUp(); + server = new MockWebServer(); String tmp = System.getProperty("java.io.tmpdir"); cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID()); cacheDir.mkdirs(); From 52376fc1c8ce135fdc6dccf44a6b2770834b0682 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Wed, 31 Aug 2016 11:30:13 +0100 Subject: [PATCH 4/4] Add CTS tests for LocalSocket read/write timeouts The behavior was not previous covered and broke in N due to commit c80af6d8. There is an associated fix in frameworks/base. Some refactoring of existing tests to reduce duplication and tidy up sockets after tests. Test: Ran the new CTS test (before and after related fix) Bug: 31205169 Change-Id: Ie94335bc535beefcc5301d5469de6b8211af0bab --- .../src/android/net/cts/LocalSocketTest.java | 196 ++++++++++++++---- 1 file changed, 159 insertions(+), 37 deletions(-) diff --git a/tests/cts/net/src/android/net/cts/LocalSocketTest.java b/tests/cts/net/src/android/net/cts/LocalSocketTest.java index 77f0a44705..0ff4a3080b 100644 --- a/tests/cts/net/src/android/net/cts/LocalSocketTest.java +++ b/tests/cts/net/src/android/net/cts/LocalSocketTest.java @@ -22,12 +22,18 @@ import android.net.Credentials; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; +import android.system.Os; +import android.system.OsConstants; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public class LocalSocketTest extends TestCase { @@ -177,58 +183,114 @@ public class LocalSocketTest extends TestCase { socket.close(); } + // http://b/31205169 + public void testSetSoTimeout_readTimeout() throws Exception { + String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout"; + + try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { + final LocalSocket clientSocket = socketPair.clientSocket; + + // Set the timeout in millis. + int timeoutMillis = 1000; + clientSocket.setSoTimeout(timeoutMillis); + + // Avoid blocking the test run if timeout doesn't happen by using a separate thread. + Callable reader = () -> { + try { + clientSocket.getInputStream().read(); + return Result.noException("Did not block"); + } catch (IOException e) { + return Result.exception(e); + } + }; + // Allow the configured timeout, plus some slop. + int allowedTime = timeoutMillis + 2000; + Result result = runInSeparateThread(allowedTime, reader); + + // Check the message was a timeout, it's all we have to go on. + String expectedMessage = Os.strerror(OsConstants.EAGAIN); + result.assertThrewIOException(expectedMessage); + } + } + + // http://b/31205169 + public void testSetSoTimeout_writeTimeout() throws Exception { + String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout"; + + try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { + final LocalSocket clientSocket = socketPair.clientSocket; + + // Set the timeout in millis. + int timeoutMillis = 1000; + clientSocket.setSoTimeout(timeoutMillis); + + // Set a small buffer size so we know we can flood it. + clientSocket.setSendBufferSize(100); + final int bufferSize = clientSocket.getSendBufferSize(); + + // Avoid blocking the test run if timeout doesn't happen by using a separate thread. + Callable writer = () -> { + try { + byte[] toWrite = new byte[bufferSize * 2]; + clientSocket.getOutputStream().write(toWrite); + return Result.noException("Did not block"); + } catch (IOException e) { + return Result.exception(e); + } + }; + // Allow the configured timeout, plus some slop. + int allowedTime = timeoutMillis + 2000; + + Result result = runInSeparateThread(allowedTime, writer); + + // Check the message was a timeout, it's all we have to go on. + String expectedMessage = Os.strerror(OsConstants.EAGAIN); + result.assertThrewIOException(expectedMessage); + } + } + public void testAvailable() throws Exception { String address = ADDRESS_PREFIX + "_testAvailable"; - LocalServerSocket localServerSocket = new LocalServerSocket(address); - LocalSocket clientSocket = new LocalSocket(); - // establish connection between client and server - LocalSocketAddress locSockAddr = new LocalSocketAddress(address); - clientSocket.connect(locSockAddr); - assertTrue(clientSocket.isConnected()); - LocalSocket serverSocket = localServerSocket.accept(); + try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { + LocalSocket clientSocket = socketPair.clientSocket; + LocalSocket serverSocket = socketPair.serverSocket.accept(); - OutputStream clientOutputStream = clientSocket.getOutputStream(); - InputStream serverInputStream = serverSocket.getInputStream(); - assertEquals(0, serverInputStream.available()); + OutputStream clientOutputStream = clientSocket.getOutputStream(); + InputStream serverInputStream = serverSocket.getInputStream(); + assertEquals(0, serverInputStream.available()); - byte[] buffer = new byte[50]; - clientOutputStream.write(buffer); - assertEquals(50, serverInputStream.available()); + byte[] buffer = new byte[50]; + clientOutputStream.write(buffer); + assertEquals(50, serverInputStream.available()); - InputStream clientInputStream = clientSocket.getInputStream(); - OutputStream serverOutputStream = serverSocket.getOutputStream(); - assertEquals(0, clientInputStream.available()); - serverOutputStream.write(buffer); - assertEquals(50, serverInputStream.available()); + InputStream clientInputStream = clientSocket.getInputStream(); + OutputStream serverOutputStream = serverSocket.getOutputStream(); + assertEquals(0, clientInputStream.available()); + serverOutputStream.write(buffer); + assertEquals(50, serverInputStream.available()); - clientSocket.close(); - serverSocket.close(); - localServerSocket.close(); + serverSocket.close(); + } } public void testFlush() throws Exception { String address = ADDRESS_PREFIX + "_testFlush"; - LocalServerSocket localServerSocket = new LocalServerSocket(address); - LocalSocket clientSocket = new LocalSocket(); - // establish connection between client and server - LocalSocketAddress locSockAddr = new LocalSocketAddress(address); - clientSocket.connect(locSockAddr); - assertTrue(clientSocket.isConnected()); - LocalSocket serverSocket = localServerSocket.accept(); + try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { + LocalSocket clientSocket = socketPair.clientSocket; + LocalSocket serverSocket = socketPair.serverSocket.accept(); - OutputStream clientOutputStream = clientSocket.getOutputStream(); - InputStream serverInputStream = serverSocket.getInputStream(); - testFlushWorks(clientOutputStream, serverInputStream); + OutputStream clientOutputStream = clientSocket.getOutputStream(); + InputStream serverInputStream = serverSocket.getInputStream(); + testFlushWorks(clientOutputStream, serverInputStream); - OutputStream serverOutputStream = serverSocket.getOutputStream(); - InputStream clientInputStream = clientSocket.getInputStream(); - testFlushWorks(serverOutputStream, clientInputStream); + OutputStream serverOutputStream = serverSocket.getOutputStream(); + InputStream clientInputStream = clientSocket.getInputStream(); + testFlushWorks(serverOutputStream, clientInputStream); - clientSocket.close(); - serverSocket.close(); - localServerSocket.close(); + serverSocket.close(); + } } private void testFlushWorks(OutputStream outputStream, InputStream inputStream) @@ -296,4 +358,64 @@ public class LocalSocketTest extends TestCase { assertEquals(expected, bytesRead); } } + + private static class Result { + private final String type; + private final Exception e; + + private Result(String type, Exception e) { + this.type = type; + this.e = e; + } + + static Result noException(String description) { + return new Result(description, null); + } + + static Result exception(Exception e) { + return new Result(e.getClass().getName(), e); + } + + void assertThrewIOException(String expectedMessage) { + assertEquals("Unexpected result type", IOException.class.getName(), type); + assertEquals("Unexpected exception message", expectedMessage, e.getMessage()); + } + } + + private static Result runInSeparateThread(int allowedTime, final Callable callable) + throws Exception { + ExecutorService service = Executors.newSingleThreadScheduledExecutor(); + Future future = service.submit(callable); + Result result = future.get(allowedTime, TimeUnit.MILLISECONDS); + if (!future.isDone()) { + fail("Worker thread appears blocked"); + } + return result; + } + + private static class LocalSocketPair implements AutoCloseable { + static LocalSocketPair createConnectedSocketPair(String address) throws Exception { + LocalServerSocket localServerSocket = new LocalServerSocket(address); + final LocalSocket clientSocket = new LocalSocket(); + + // Establish connection between client and server + LocalSocketAddress locSockAddr = new LocalSocketAddress(address); + clientSocket.connect(locSockAddr); + assertTrue(clientSocket.isConnected()); + return new LocalSocketPair(localServerSocket, clientSocket); + } + + final LocalServerSocket serverSocket; + final LocalSocket clientSocket; + + LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) { + this.serverSocket = serverSocket; + this.clientSocket = clientSocket; + } + + public void close() throws Exception { + serverSocket.close(); + clientSocket.close(); + } + } }