Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / tests / nacl_io_test / host_resolver_test.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <arpa/inet.h>
6 #include <netinet/in.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9
10 #include "fake_ppapi/fake_pepper_interface.h"
11 #include "gtest/gtest.h"
12 #include "nacl_io/kernel_intercept.h"
13
14 using namespace nacl_io;
15 using namespace sdk_util;
16
17 namespace {
18
19 class HostResolverTest : public ::testing::Test {
20  public:
21   HostResolverTest() {}
22
23   void SetUp() {
24     ki_init(NULL);
25   }
26
27   void TearDown() {
28     ki_uninit();
29   }
30 };
31
32 #define FAKE_HOSTNAME "example.com"
33 #define FAKE_IP 0x01020304
34
35 class FakeHostResolverTest : public ::testing::Test {
36  public:
37   FakeHostResolverTest() : pepper_(NULL), fake_resolver_(NULL) {}
38
39   void SetUp() {
40     pepper_ = new FakePepperInterface();
41     fake_resolver_ = static_cast<FakeHostResolverInterface*>(
42         pepper_->GetHostResolverInterface());
43
44     // Seed the fake resolver with some data
45     fake_resolver_->fake_hostname = FAKE_HOSTNAME;
46     AddFakeAddress(AF_INET);
47
48     ki_init_interface(NULL, pepper_);
49   }
50
51   void AddFakeAddress(int family) {
52     if (family == AF_INET) {
53       int address_count = fake_resolver_->fake_addresses_v4.size();
54       // Each new address we add is FAKE_IP incremented by 1
55       // each time to be unique.
56       sockaddr_in fake_addr;
57       fake_addr.sin_family = family;
58       fake_addr.sin_addr.s_addr = htonl(FAKE_IP + address_count);
59       fake_resolver_->fake_addresses_v4.push_back(fake_addr);
60     } else if (family == AF_INET6) {
61       sockaddr_in6 fake_addr;
62       fake_addr.sin6_family = family;
63       int address_count = fake_resolver_->fake_addresses_v6.size();
64       for (uint8_t i = 0; i < 16; i++) {
65         fake_addr.sin6_addr.s6_addr[i] = i + address_count;
66       }
67       fake_resolver_->fake_addresses_v6.push_back(fake_addr);
68     }
69   }
70
71   void TearDown() {
72     ki_uninit();
73     pepper_ = NULL;
74   }
75
76  protected:
77   FakePepperInterface* pepper_;
78   FakeHostResolverInterface* fake_resolver_;
79 };
80
81 }  // namespace
82
83 #define NULL_INFO ((struct addrinfo*)NULL)
84 #define NULL_ADDR ((struct sockaddr*)NULL)
85 #define NULL_HOST (static_cast<hostent*>(NULL))
86
87 TEST_F(HostResolverTest, Getaddrinfo_Numeric) {
88   struct addrinfo* ai = NULL;
89   struct sockaddr_in* in;
90   struct addrinfo hints;
91
92   // Numberic only
93   memset(&hints, 0, sizeof(hints));
94   hints.ai_family = AF_INET;
95   hints.ai_socktype = SOCK_STREAM;
96
97   uint32_t expected_addr = htonl(0x01020304);
98   ASSERT_EQ(0, ki_getaddrinfo("1.2.3.4", NULL, &hints, &ai));
99   ASSERT_NE(NULL_INFO, ai);
100   ASSERT_NE(NULL_ADDR, ai->ai_addr);
101   ASSERT_EQ(AF_INET, ai->ai_family);
102   ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
103   in = (struct sockaddr_in*)ai->ai_addr;
104   ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
105   ASSERT_EQ(NULL_INFO, ai->ai_next);
106
107   ki_freeaddrinfo(ai);
108 }
109
110 TEST_F(HostResolverTest, Getaddrinfo_MissingPPAPI) {
111   // Verify that full lookups fail due to lack of PPAPI interfaces
112   struct addrinfo* ai = NULL;
113   ASSERT_EQ(EAI_SYSTEM, ki_getaddrinfo("google.com", NULL, NULL, &ai));
114 }
115
116 TEST_F(HostResolverTest, Getaddrinfo_Passive) {
117   struct addrinfo* ai = NULL;
118   struct sockaddr_in* in;
119   struct sockaddr_in6* in6;
120   struct addrinfo hints;
121   memset(&hints, 0, sizeof(hints));
122
123   uint32_t expected_port = htons(22);
124   in_addr_t expected_addr = htonl(INADDR_ANY);
125   in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
126
127   // AI_PASSIVE means that the returned address will be a wildcard
128   // address suitable for binding and listening.  This should not
129   // hit PPAPI at all, so we don't need fakes.
130   hints.ai_family = AF_INET;
131   hints.ai_flags = AI_PASSIVE;
132   hints.ai_socktype = SOCK_DGRAM;
133   ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
134   ASSERT_NE(NULL_INFO, ai);
135   ASSERT_NE(NULL_ADDR, ai->ai_addr);
136   ASSERT_EQ(NULL_INFO, ai->ai_next);
137   in = (struct sockaddr_in*)ai->ai_addr;
138   ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
139   ASSERT_EQ(expected_port, in->sin_port);
140   ASSERT_EQ(AF_INET, in->sin_family);
141   ki_freeaddrinfo(ai);
142
143   // Same test with AF_INET6
144   hints.ai_family = AF_INET6;
145   ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
146   ASSERT_NE(NULL_INFO, ai);
147   ASSERT_NE(NULL_ADDR, ai->ai_addr);
148   ASSERT_EQ(NULL_INFO, ai->ai_next);
149   in6 = (struct sockaddr_in6*)ai->ai_addr;
150   ASSERT_EQ(expected_port, in6->sin6_port);
151   ASSERT_EQ(AF_INET6, in6->sin6_family);
152   ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr,
153                &expected_addr6,
154                sizeof(expected_addr6)));
155   ki_freeaddrinfo(ai);
156 }
157
158 TEST_F(HostResolverTest, Getaddrinfo_Passive_Any) {
159   // Similar to Getaddrinfo_Passive but don't set
160   // ai_family in the hints, so we should get muplitple
161   // results back for the different families.
162   struct addrinfo* ai = NULL;
163   struct sockaddr_in* in;
164   struct sockaddr_in6* in6;
165   struct addrinfo hints;
166   memset(&hints, 0, sizeof(hints));
167
168   uint32_t expected_port = htons(22);
169   in_addr_t expected_addr = htonl(INADDR_ANY);
170   in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
171
172   hints.ai_flags = AI_PASSIVE;
173   hints.ai_socktype = SOCK_DGRAM;
174   ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
175   ASSERT_NE(NULL_INFO, ai);
176   int count = 0;
177   bool got_v4 = false;
178   bool got_v6 = false;
179   while (ai) {
180     ASSERT_NE(NULL_ADDR, ai->ai_addr);
181     switch (ai->ai_addr->sa_family) {
182       case AF_INET:
183         in = (struct sockaddr_in*)ai->ai_addr;
184         ASSERT_EQ(expected_port, in->sin_port);
185         ASSERT_EQ(AF_INET, in->sin_family);
186         ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
187         got_v4 = true;
188         break;
189       case AF_INET6:
190         in6 = (struct sockaddr_in6*)ai->ai_addr;
191         ASSERT_EQ(expected_port, in6->sin6_port);
192         ASSERT_EQ(AF_INET6, in6->sin6_family);
193         ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr,
194                             &expected_addr6,
195                             sizeof(expected_addr6)));
196         got_v6 = true;
197         break;
198       default:
199         ASSERT_TRUE(false) << "Unknown address type: " << ai->ai_addr;
200         break;
201     }
202     ai = ai->ai_next;
203     count++;
204   }
205
206   ASSERT_EQ(2, count);
207   ASSERT_TRUE(got_v4);
208   ASSERT_TRUE(got_v6);
209 }
210
211 TEST_F(FakeHostResolverTest, Getaddrinfo_Lookup) {
212   struct addrinfo* ai = NULL;
213   struct sockaddr_in* in;
214   struct addrinfo hints;
215   memset(&hints, 0, sizeof(hints));
216
217   in_addr_t expected_addr = htonl(FAKE_IP);
218
219   // Lookup the fake hostname using getaddrinfo
220   hints.ai_family = AF_INET;
221   hints.ai_socktype = SOCK_STREAM;
222   ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
223   ASSERT_NE(NULL_INFO, ai);
224   ASSERT_NE(NULL_ADDR, ai->ai_addr);
225   ASSERT_EQ(AF_INET, ai->ai_family);
226   ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
227   in = (struct sockaddr_in*)ai->ai_addr;
228   ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
229   ASSERT_EQ(NULL_INFO, ai->ai_next);
230
231   ki_freeaddrinfo(ai);
232 }
233
234 TEST_F(FakeHostResolverTest, Getaddrinfo_Multi) {
235   struct addrinfo* ai = NULL;
236   struct addrinfo hints;
237   memset(&hints, 0, sizeof(hints));
238
239   // Add four fake address on top of the initial one
240   // that the fixture creates.
241   AddFakeAddress(AF_INET);
242   AddFakeAddress(AF_INET);
243   AddFakeAddress(AF_INET6);
244   AddFakeAddress(AF_INET6);
245
246   hints.ai_socktype = SOCK_STREAM;
247
248   // First we test with AF_INET
249   hints.ai_family = AF_INET;
250   ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
251   ASSERT_NE(NULL_INFO, ai);
252
253   // We expect to be returned 3 AF_INET address with
254   // address FAKE_IP, FAKE_IP+1 and FAKE_IP+2, since that
255   // is that the fake was seeded with.
256   uint32_t expected_addr = htonl(FAKE_IP);
257   int count = 0;
258   struct addrinfo* current = ai;
259   while (current != NULL) {
260     ASSERT_NE(NULL_ADDR, current->ai_addr);
261     ASSERT_EQ(AF_INET, current->ai_family);
262     ASSERT_EQ(SOCK_STREAM, current->ai_socktype);
263     sockaddr_in* in = (sockaddr_in*)current->ai_addr;
264     ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
265     expected_addr += htonl(1);
266     current = current->ai_next;
267     count++;
268   }
269   ASSERT_EQ(3, count);
270   ki_freeaddrinfo(ai);
271
272   // Same test but with AF_INET6
273   hints.ai_family = AF_INET6;
274   ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
275   ASSERT_NE(NULL_INFO, ai);
276
277   count = 0;
278   current = ai;
279   while (current != NULL) {
280     ASSERT_NE(NULL_ADDR, current->ai_addr);
281     ASSERT_EQ(AF_INET6, current->ai_family);
282     ASSERT_EQ(SOCK_STREAM, current->ai_socktype);
283     sockaddr_in6* in = (sockaddr_in6*)current->ai_addr;
284     for (int i = 0; i < 16; i++) {
285       ASSERT_EQ(i + count, in->sin6_addr.s6_addr[i]);
286     }
287     current = current->ai_next;
288     count++;
289   }
290   ASSERT_EQ(2, count);
291   ki_freeaddrinfo(ai);
292
293   // Same test but with AF_UNSPEC.  Here we expect to get
294   // 5 address back: 3 * v4 and 2 * v6.
295   hints.ai_family = AF_UNSPEC;
296   ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
297   ASSERT_NE(NULL_INFO, ai);
298
299   count = 0;
300   current = ai;
301   while (current != NULL) {
302     ASSERT_NE(NULL_ADDR, ai->ai_addr);
303     ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
304     current = current->ai_next;
305     count++;
306   }
307   ASSERT_EQ(5, count);
308
309   ki_freeaddrinfo(ai);
310 }
311
312 TEST_F(FakeHostResolverTest, Gethostbyname) {
313   hostent* host = ki_gethostbyname(FAKE_HOSTNAME);
314
315   // Verify the returned hostent structure
316   ASSERT_NE(NULL_HOST, host);
317   ASSERT_EQ(AF_INET, host->h_addrtype);
318   ASSERT_EQ(sizeof(in_addr_t), host->h_length);
319   ASSERT_STREQ(FAKE_HOSTNAME, host->h_name);
320
321   in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list);
322   ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list);
323   ASSERT_EQ(NULL, addr_list[1]);
324   in_addr_t exptected_addr = htonl(FAKE_IP);
325   ASSERT_EQ(exptected_addr, *addr_list[0]);
326 }
327
328 TEST_F(FakeHostResolverTest, Gethostbyname_Failure) {
329   hostent* host = ki_gethostbyname("nosuchhost.com");
330   ASSERT_EQ(NULL_HOST, host);
331   ASSERT_EQ(HOST_NOT_FOUND, h_errno);
332 }
333
334 // Looking up purely numeric hostnames should work without PPAPI
335 // so we don't need the fakes for this test
336 TEST_F(HostResolverTest, Gethostbyname_Numeric) {
337   struct hostent* host = ki_gethostbyname("8.8.8.8");
338
339   // Verify the returned hostent structure
340   ASSERT_NE(NULL_HOST, host);
341   ASSERT_EQ(AF_INET, host->h_addrtype);
342   ASSERT_EQ(sizeof(in_addr_t), host->h_length);
343   ASSERT_STREQ("8.8.8.8", host->h_name);
344
345   in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list);
346   ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list);
347   ASSERT_EQ(NULL, addr_list[1]);
348   ASSERT_EQ(inet_addr("8.8.8.8"), *addr_list[0]);
349 }
350
351 // These utility functions are only used for newlib (glibc provides its own
352 // implementations of these functions).
353 #if !defined(__GLIBC__)
354
355 TEST(SocketUtilityFunctions, Hstrerror) {
356   EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
357 }
358
359 TEST(SocketUtilityFunctions, Gai_Strerror) {
360   EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
361 }
362
363 #endif  // !defined(__GLIBC__)