Test for thread creation failed

Netd should not crash when thread creation is failed on Asynchronous
API call.

Bug: 169105756
Test: run test w/ and w/o I9241a094653651e1bdda79eb753e7a53e5e51d8f
Change-Id: Iadd94eb661ea15adfffc8d8e31e7990901bedb28
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index 5d41a8a..67f59a6 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -2705,6 +2705,54 @@
     EXPECT_EQ(1U, GetNumQueries(dns, host_name));
 }
 
+// Run a large number of DNS queries through asynchronous API to create
+// thousands of threads in resolver to simulate the failure of thread creation
+// when memory per process is exhausted. (The current critical value is about
+// 84xx threads.)
+TEST_F(ResolverTest, Async_OutOfMemory) {
+    constexpr char host_name[] = "howdy.example.com.";
+    constexpr size_t AMOUNT_OF_UIDS = 40;
+    constexpr size_t MAX_QUERIES_PER_UID = 256;
+    constexpr size_t NUM_OF_QUERIES = AMOUNT_OF_UIDS * MAX_QUERIES_PER_UID;
+
+    test::DNSResponder dns;
+    StartDns(dns, {{host_name, ns_type::ns_t_a, "1.2.3.4"}});
+    ASSERT_TRUE(mDnsClient.SetResolversForNetwork());
+    dns.setDeferredResp(true);
+
+    std::vector<int> fds;
+    fds.reserve(NUM_OF_QUERIES);
+    bool send_query = true;
+    for (size_t i = 0; i < AMOUNT_OF_UIDS && send_query; i++) {
+        ScopedChangeUID scopedChangeUID(TEST_UID - i);
+        for (size_t j = 0; j < MAX_QUERIES_PER_UID; j++) {
+            int fd = resNetworkQuery(TEST_NETID, "howdy.example.com", ns_c_in, ns_t_a, 0);
+            if (fd >= 0) {
+                fds.emplace_back(fd);
+            } else {
+                send_query = false;
+                break;
+            }
+        }
+    }
+
+    dns.setDeferredResp(false);
+    EXPECT_EQ(NUM_OF_QUERIES, fds.size());
+    // TODO: AIBinder_DeathRecipient_new does not work (b/172178636), which
+    // should be fixed. Fortunately, netd crash is still detectable at the point
+    // of DumpResolverService() in TearDown(), where accesses mDnsClient. Also,
+    // the fds size will be less than NUM_OF_QUERIES in that case.
+
+    uint8_t buf[MAXPACKET];
+    int rcode;
+    for (auto fd : fds) {
+        memset(buf, 0, MAXPACKET);
+        getAsyncResponse(fd, &rcode, buf, MAXPACKET);
+        // The results of each DNS query are not examined, since they won't all
+        // succeed or all fail. Here we only focus on netd is crashed or not.
+    }
+}
+
 // This test checks that the resolver should not generate the request containing OPT RR when using
 // cleartext DNS. If we query the DNS server not supporting EDNS0 and it reponds with
 // FORMERR_ON_EDNS, we will fallback to no EDNS0 and try again. If the server does no response, we