blob: 683dd216889c9ecbf305346d752fb967c13e0d79 [file] [log] [blame]
nuccachen5c2d32f2018-11-28 18:19:39 +08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "libnetd_resolv_test"
18
19#include <gtest/gtest.h>
20
21#include <android-base/stringprintf.h>
22#include <netdb.h>
23
24#include "dns_responder.h"
25#include "netd_resolv/resolv.h"
26
27// TODO: make this dynamic and stop depending on implementation details.
28constexpr unsigned int TEST_NETID = 30;
29
30// Specifying 0 in ai_socktype or ai_protocol of struct addrinfo indicates that any type or
31// protocol can be returned by getaddrinfo().
32constexpr unsigned int ANY = 0;
33
34using android::base::StringPrintf;
35
36namespace android {
37namespace net {
38
39// Minimize class ResolverTest to be class TestBase because class TestBase doesn't need all member
40// functions of class ResolverTest and class DnsResponderClient.
41class TestBase : public ::testing::Test {
42 protected:
43 void TearDown() {
44 resolv_delete_cache_for_net(TEST_NETID);
45 resolv_set_nameservers_for_net(TEST_NETID, nullptr, 0, "", nullptr);
46 }
47
48 static std::string ToString(const addrinfo* ai) {
49 if (!ai) return "<null>";
50 for (const auto* aip = ai; aip != nullptr; aip = aip->ai_next) {
51 char host[NI_MAXHOST];
52 int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
53 NI_NUMERICHOST);
54 if (rv != 0) return gai_strerror(rv);
55 return host;
56 }
57 return "<invalid>";
58 }
59
60 size_t GetNumQueries(const test::DNSResponder& dns, const char* name) const {
61 auto queries = dns.queries();
62 size_t found = 0;
63 for (const auto& p : queries) {
64 if (p.first == name) {
65 ++found;
66 }
67 }
68 return found;
69 }
70
71 const char* mDefaultSearchDomains = "example.com";
72 const __res_params mDefaultParams_Binder = {
73 .sample_validity = 300,
74 .success_threshold = 25,
75 .min_samples = 8,
76 .max_samples = 8,
77 .base_timeout_msec = 100,
78 };
79};
80
81class GetAddrInfoForNetContextTest : public TestBase {};
82
83TEST_F(GetAddrInfoForNetContextTest, InvalidParameters) {
84 struct addrinfo* result = nullptr;
85 const android_net_context netcontext = {
86 .app_netid = NETID_UNSET,
87 .app_mark = MARK_UNSET,
88 .dns_netid = NETID_UNSET,
89 .dns_mark = MARK_UNSET,
90 .uid = NET_CONTEXT_INVALID_UID,
91 };
92
93 // Both null "netcontext" and null "res" of android_getaddrinfofornetcontext() are not tested
94 // here because they are checked by assert() without returning any error number.
95
96 // Invalid hostname and servname.
97 // Both hostname and servname are null pointers. Expect error number EAI_NONAME.
98 int rv = android_getaddrinfofornetcontext(nullptr /*hostname*/, nullptr /*servname*/,
99 nullptr /*hints*/, &netcontext, &result);
100 EXPECT_EQ(EAI_NONAME, rv);
101 if (result) {
102 freeaddrinfo(result);
103 result = nullptr;
104 }
105
106 // Invalid hints.
107 // These place holders are used to test function call with unrequired parameters.
108 // The content is not important because function call returns error directly if
109 // there have any unrequired parameter.
110 char placeholder_cname[] = "invalid_cname";
111 sockaddr placeholder_addr = {};
112 addrinfo placeholder_next = {};
113 static const struct TestConfig {
114 int ai_flags;
115 socklen_t ai_addrlen;
116 char* ai_canonname;
117 struct sockaddr* ai_addr;
118 struct addrinfo* ai_next;
119 int expected_errorno; // expected result
120
121 std::string asParameters() const {
122 return StringPrintf("0x%x/%u/%s/%p/%p", ai_flags, ai_addrlen,
123 ai_canonname ? ai_canonname : "(null)", (void*) ai_addr,
124 (void*) ai_next);
125 }
126 } testConfigs[]{
127 {0, sizeof(struct in_addr) /*bad*/, nullptr, nullptr, nullptr, EAI_BADHINTS},
128 {0, 0, placeholder_cname /*bad*/, nullptr, nullptr, EAI_BADHINTS},
129 {0, 0, nullptr, &placeholder_addr /*bad*/, nullptr, EAI_BADHINTS},
130 {0, 0, nullptr, nullptr, &placeholder_next /*bad*/, EAI_BADHINTS},
131 {AI_ALL /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
132 {AI_V4MAPPED_CFG /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
133 {AI_V4MAPPED /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
134 {AI_DEFAULT /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
135 };
136
137 for (const auto& config : testConfigs) {
138 SCOPED_TRACE(config.asParameters());
139
140 // In current test configuration set, ai_family, ai_protocol and ai_socktype are not
141 // checked because other fields cause hints error check failed first.
142 const struct addrinfo hints = {
143 .ai_flags = config.ai_flags,
144 .ai_family = AF_UNSPEC,
145 .ai_socktype = ANY,
146 .ai_protocol = ANY,
147 .ai_addrlen = config.ai_addrlen,
148 .ai_canonname = config.ai_canonname,
149 .ai_addr = config.ai_addr,
150 .ai_next = config.ai_next,
151 };
152
153 rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
154 &netcontext, &result);
155 EXPECT_EQ(config.expected_errorno, rv);
156
157 if (result) {
158 freeaddrinfo(result);
159 result = nullptr;
160 }
161 }
162}
163
164TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_Family) {
165 const android_net_context netcontext = {
166 .app_netid = NETID_UNSET,
167 .app_mark = MARK_UNSET,
168 .dns_netid = NETID_UNSET,
169 .dns_mark = MARK_UNSET,
170 .uid = NET_CONTEXT_INVALID_UID,
171 };
172
173 for (int family = 0; family < AF_MAX; ++family) {
174 if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6) {
175 continue; // skip supported family
176 }
177 SCOPED_TRACE(StringPrintf("family: %d", family));
178
179 struct addrinfo* result = nullptr;
180 const struct addrinfo hints = {
181 .ai_family = family, // unsupported family
182 };
183
184 int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
185 &netcontext, &result);
186 EXPECT_EQ(EAI_FAMILY, rv);
187
188 if (result) freeaddrinfo(result);
189 }
190}
191
192TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_MeaningfulSocktypeAndProtocolCombination) {
193 const android_net_context netcontext = {
194 .app_netid = NETID_UNSET,
195 .app_mark = MARK_UNSET,
196 .dns_netid = NETID_UNSET,
197 .dns_mark = MARK_UNSET,
198 .uid = NET_CONTEXT_INVALID_UID,
199 };
200
201 static const int families[] = {PF_INET, PF_INET6, PF_UNSPEC};
202 // Skip to test socket type SOCK_RAW in meaningful combination (explore_options[]) of
203 // system\netd\resolv\getaddrinfo.cpp. In explore_options[], the socket type SOCK_RAW always
204 // comes with protocol ANY which causes skipping meaningful socktype/protocol combination
205 // check. So it nerver returns error number EAI_BADHINTS which we want to test in this test
206 // case.
207 static const int socktypes[] = {SOCK_STREAM, SOCK_DGRAM};
208
209 // If both socktype/protocol are specified, check non-meaningful combination returns
210 // expected error number EAI_BADHINTS. See meaningful combination in explore_options[] of
211 // system\netd\resolv\getaddrinfo.cpp.
212 for (const auto& family : families) {
213 for (const auto& socktype : socktypes) {
214 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
215 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d", family,
216 socktype, protocol));
217
218 // Both socktype/protocol need to be specified.
219 if (!socktype || !protocol) continue;
220
221 // Skip meaningful combination in explore_options[] of
222 // system\netd\resolv\getaddrinfo.cpp.
223 if ((family == AF_INET6 && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
224 (family == AF_INET6 && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
225 (family == AF_INET && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
226 (family == AF_INET && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
227 (family == AF_UNSPEC && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
228 (family == AF_UNSPEC && socktype == SOCK_STREAM && protocol == IPPROTO_TCP)) {
229 continue;
230 }
231
232 struct addrinfo* result = nullptr;
233 const struct addrinfo hints = {
234 .ai_family = family,
235 .ai_protocol = protocol,
236 .ai_socktype = socktype,
237 };
238
239 int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
240 &netcontext, &result);
241 EXPECT_EQ(EAI_BADHINTS, rv);
242
243 if (result) freeaddrinfo(result);
244 }
245 }
246 }
247}
248
249TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_PortNameAndNumber) {
250 const android_net_context netcontext = {
251 .app_netid = NETID_UNSET,
252 .app_mark = MARK_UNSET,
253 .dns_netid = NETID_UNSET,
254 .dns_mark = MARK_UNSET,
255 .uid = NET_CONTEXT_INVALID_UID,
256 };
257 constexpr char http_portno[] = "80";
258 constexpr char invalid_portno[] = "65536"; // out of valid port range from 0 to 65535
259 constexpr char http_portname[] = "http";
260 constexpr char invalid_portname[] = "invalid_portname";
261
262 static const struct TestConfig {
263 int ai_flags;
264 int ai_family;
265 int ai_socktype;
266 const char* servname;
267 int expected_errorno; // expected result
268
269 std::string asParameters() const {
270 return StringPrintf("0x%x/%d/%d/%s", ai_flags, ai_family, ai_socktype,
271 servname ? servname : "(null)");
272 }
273 } testConfigs[]{
274 {0, AF_INET, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
275 {0, AF_INET6, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
276 {0, AF_UNSPEC, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
277 {0, AF_INET, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
278 {0, AF_INET6, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
279 {0, AF_UNSPEC, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
280 {0, AF_INET, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
281 {0, AF_INET6, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
282 {0, AF_UNSPEC, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
283 {0, AF_INET, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
284 {0, AF_INET6, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
285 {0, AF_UNSPEC, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
286 {0, AF_INET, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
287 {0, AF_INET6, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
288 {0, AF_UNSPEC, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
289 {0, AF_INET, ANY, invalid_portno /*bad*/, EAI_SERVICE},
290 {0, AF_INET, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
291 {0, AF_INET, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
292 {0, AF_INET6, ANY, invalid_portno /*bad*/, EAI_SERVICE},
293 {0, AF_INET6, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
294 {0, AF_INET6, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
295 {0, AF_UNSPEC, ANY, invalid_portno /*bad*/, EAI_SERVICE},
296 {0, AF_UNSPEC, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
297 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
298 {AI_NUMERICSERV, AF_INET, ANY, http_portname /*bad*/, EAI_NONAME},
299 {AI_NUMERICSERV, AF_INET, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
300 {AI_NUMERICSERV, AF_INET, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
301 {AI_NUMERICSERV, AF_INET6, ANY, http_portname /*bad*/, EAI_NONAME},
302 {AI_NUMERICSERV, AF_INET6, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
303 {AI_NUMERICSERV, AF_INET6, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
304 {AI_NUMERICSERV, AF_UNSPEC, ANY, http_portname /*bad*/, EAI_NONAME},
305 {AI_NUMERICSERV, AF_UNSPEC, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
306 {AI_NUMERICSERV, AF_UNSPEC, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
307 {0, AF_INET, ANY, invalid_portname /*bad*/, EAI_SERVICE},
308 {0, AF_INET, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
309 {0, AF_INET, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
310 {0, AF_INET6, ANY, invalid_portname /*bad*/, EAI_SERVICE},
311 {0, AF_INET6, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
312 {0, AF_INET6, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
313 {0, AF_UNSPEC, ANY, invalid_portname /*bad*/, EAI_SERVICE},
314 {0, AF_UNSPEC, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
315 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
316 };
317
318 for (const auto& config : testConfigs) {
319 const std::string testParameters = config.asParameters();
320 SCOPED_TRACE(testParameters);
321
322 const struct addrinfo hints = {
323 .ai_flags = config.ai_flags,
324 .ai_family = config.ai_family,
325 .ai_socktype = config.ai_socktype,
326 };
327
328 struct addrinfo* result = nullptr;
329 int rv = android_getaddrinfofornetcontext("localhost", config.servname, &hints, &netcontext,
330 &result);
331 EXPECT_EQ(config.expected_errorno, rv);
332
333 if (result) freeaddrinfo(result);
334 }
335}
336
337// Blocked by aosp/816674 which causes wrong error code EAI_FAIL (4) but EAI_NODATA (7).
338// TODO: fix aosp/816674 and add testcases AlphabeticalHostname_NoData back.
339/*
340TEST_F(GetAddrInfoForNetContextTest, AlphabeticalHostname_NoData) {
341 constexpr char listen_addr[] = "127.0.0.3";
342 constexpr char listen_srv[] = "53";
343 constexpr char v4_host_name[] = "v4only.example.com.";
344 constexpr char nonexistent_host_name[] = "nonexistent.example.com.";
345 test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
346 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
347 ASSERT_TRUE(dns.startServer());
348 const char* servers[] = {listen_addr};
349 ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
350 sizeof(servers) / sizeof(servers[0]),
351 mDefaultSearchDomains, &mDefaultParams_Binder));
352 dns.clearQueries();
353
354 struct addrinfo* result = nullptr;
355 const android_net_context netcontext = {
356 .app_netid = TEST_NETID,
357 .app_mark = MARK_UNSET,
358 .dns_netid = TEST_NETID,
359 .dns_mark = MARK_UNSET,
360 .uid = NET_CONTEXT_INVALID_UID,
361 };
362
363 // Query nonexistent hostname.
364 int rv =
365 android_getaddrinfofornetcontext("nonexistent", nullptr, nullptr, &netcontext, &result);
366 EXPECT_LE(1U, GetNumQueries(dns, nonexistent_host_name));
367 EXPECT_TRUE(result == nullptr);
368 EXPECT_EQ(EAI_NODATA, rv);
369
370 if (result) {
371 freeaddrinfo(result);
372 result = nullptr;
373 }
374
375 // Want AAAA answer but DNS server has A answer only.
376 const addrinfo hints = {.ai_family = AF_INET6};
377 rv = android_getaddrinfofornetcontext("v4only", nullptr, &hints, &netcontext, &result);
378 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
379 EXPECT_TRUE(result == nullptr);
380 EXPECT_EQ(EAI_NODATA, rv);
381
382 if (result) freeaddrinfo(result);
383}
384*/
385
386TEST_F(GetAddrInfoForNetContextTest, AlphabeticalHostname) {
387 constexpr char listen_addr[] = "127.0.0.3";
388 constexpr char listen_srv[] = "53";
389 constexpr char host_name[] = "sawadee.example.com.";
390 constexpr char v4addr[] = "1.2.3.4";
391 constexpr char v6addr[] = "::1.2.3.4";
392
393 test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
394 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
395 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
396 ASSERT_TRUE(dns.startServer());
397 const char* servers[] = {listen_addr};
398 ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
399 sizeof(servers) / sizeof(servers[0]),
400 mDefaultSearchDomains, &mDefaultParams_Binder));
401
402 const android_net_context netcontext = {
403 .app_netid = TEST_NETID,
404 .app_mark = MARK_UNSET,
405 .dns_netid = TEST_NETID,
406 .dns_mark = MARK_UNSET,
407 .uid = NET_CONTEXT_INVALID_UID,
408 };
409
410 static const struct TestConfig {
411 int ai_family;
412 const std::string expected_addr;
413 } testConfigs[]{
414 {AF_INET, v4addr},
415 {AF_INET6, v6addr},
416 };
417
418 for (const auto& config : testConfigs) {
419 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
420 dns.clearQueries();
421
422 struct addrinfo* result = nullptr;
423 const struct addrinfo hints = {.ai_family = config.ai_family};
424 int rv = android_getaddrinfofornetcontext("sawadee", nullptr, &hints, &netcontext, &result);
425 EXPECT_EQ(0, rv);
426 EXPECT_TRUE(result != nullptr);
427 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
428 EXPECT_EQ(config.expected_addr, ToString(result));
429
430 if (result) freeaddrinfo(result);
431 }
432}
433
434TEST_F(GetAddrInfoForNetContextTest, ServerResponseError) {
435 constexpr char listen_addr[] = "127.0.0.3";
436 constexpr char listen_srv[] = "53";
437 constexpr char host_name[] = "hello.example.com.";
438
439 const android_net_context netcontext = {
440 .app_netid = TEST_NETID,
441 .app_mark = MARK_UNSET,
442 .dns_netid = TEST_NETID,
443 .dns_mark = MARK_UNSET,
444 .uid = NET_CONTEXT_INVALID_UID,
445 };
446
447 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0 which
448 // means no error.
449 // clang-format off
450 static const ns_rcode rcodes[] = {ns_rcode::ns_r_formerr,
451 ns_rcode::ns_r_servfail,
452 ns_rcode::ns_r_nxdomain,
453 ns_rcode::ns_r_notimpl,
454 ns_rcode::ns_r_refused};
455 // clang-format on
456
457 for (const auto& rcode : rcodes) {
458 SCOPED_TRACE(StringPrintf("rcode: %d", rcode));
459
460 test::DNSResponder dns(listen_addr, listen_srv, 250, rcode /*response specific rcode*/);
461 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
462 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
463 ASSERT_TRUE(dns.startServer());
464 const char* servers[] = {listen_addr};
465 ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
466 sizeof(servers) / sizeof(servers[0]),
467 mDefaultSearchDomains, &mDefaultParams_Binder));
468
469 struct addrinfo* result = nullptr;
470 const struct addrinfo hints = {.ai_family = AF_UNSPEC};
471 int rv = android_getaddrinfofornetcontext(host_name, nullptr, &hints, &netcontext, &result);
472 EXPECT_EQ(EAI_NODATA, rv);
473
474 if (result) freeaddrinfo(result);
475 }
476}
477
478// TODO: Add private DNS server timeout test.
479TEST_F(GetAddrInfoForNetContextTest, ServerTimeout) {
480 constexpr char listen_addr[] = "127.0.0.3";
481 constexpr char listen_srv[] = "53";
482 constexpr char host_name[] = "hello.example.com.";
483 test::DNSResponder dns(listen_addr, listen_srv, 250, static_cast<ns_rcode>(-1) /*no response*/);
484 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
485 dns.setResponseProbability(0.0); // always ignore requests and don't response
486 ASSERT_TRUE(dns.startServer());
487 const char* servers[] = {listen_addr};
488 ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
489 sizeof(servers) / sizeof(servers[0]),
490 mDefaultSearchDomains, &mDefaultParams_Binder));
491
492 struct addrinfo* result = nullptr;
493 const android_net_context netcontext = {
494 .app_netid = TEST_NETID,
495 .app_mark = MARK_UNSET,
496 .dns_netid = TEST_NETID,
497 .dns_mark = MARK_UNSET,
498 .uid = NET_CONTEXT_INVALID_UID,
499 };
500
501 const struct addrinfo hints = {.ai_family = AF_UNSPEC};
502 int rv = android_getaddrinfofornetcontext("hello", nullptr, &hints, &netcontext, &result);
503 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
504
505 if (result) freeaddrinfo(result);
506}
507
508// Local host file function (files_getaddrinfo) is not tested because it only returns a boolean
509// (success or failure) without any error number.
510
511// TODO: Add test NULL hostname, or numeric hostname for android_getaddrinfofornetcontext
512// TODO: Add test for android_gethostbyaddrfornetcontext and android_gethostbynamefornetcontext.
513
514} // end of namespace net
515} // end of namespace android