yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame] | 1 | #include "ares-test.h" |
| 2 | |
| 3 | // library initialization is only needed for windows builds |
| 4 | #ifdef WIN32 |
| 5 | #define EXPECTED_NONINIT ARES_ENOTINITIALIZED |
| 6 | #else |
| 7 | #define EXPECTED_NONINIT ARES_SUCCESS |
| 8 | #endif |
| 9 | |
| 10 | namespace ares { |
| 11 | namespace test { |
| 12 | |
| 13 | TEST(LibraryInit, Basic) { |
| 14 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 15 | EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); |
| 16 | EXPECT_EQ(ARES_SUCCESS, ares_library_initialized()); |
| 17 | ares_library_cleanup(); |
| 18 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 19 | } |
| 20 | |
| 21 | TEST(LibraryInit, UnexpectedCleanup) { |
| 22 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 23 | ares_library_cleanup(); |
| 24 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 25 | } |
| 26 | |
| 27 | TEST(LibraryInit, DISABLED_InvalidParam) { |
| 28 | // TODO: police flags argument to ares_library_init() |
| 29 | EXPECT_EQ(ARES_EBADQUERY, ares_library_init(ARES_LIB_INIT_ALL << 2)); |
| 30 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 31 | ares_library_cleanup(); |
| 32 | } |
| 33 | |
| 34 | TEST(LibraryInit, Nested) { |
| 35 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 36 | EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); |
| 37 | EXPECT_EQ(ARES_SUCCESS, ares_library_initialized()); |
| 38 | EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); |
| 39 | EXPECT_EQ(ARES_SUCCESS, ares_library_initialized()); |
| 40 | ares_library_cleanup(); |
| 41 | EXPECT_EQ(ARES_SUCCESS, ares_library_initialized()); |
| 42 | ares_library_cleanup(); |
| 43 | EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized()); |
| 44 | } |
| 45 | |
| 46 | TEST(LibraryInit, BasicChannelInit) { |
| 47 | EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL)); |
| 48 | ares_channel channel = nullptr; |
| 49 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 50 | EXPECT_NE(nullptr, channel); |
| 51 | ares_destroy(channel); |
| 52 | ares_library_cleanup(); |
| 53 | } |
| 54 | |
| 55 | TEST_F(LibraryTest, OptionsChannelInit) { |
| 56 | struct ares_options opts = {0}; |
| 57 | int optmask = 0; |
| 58 | opts.flags = ARES_FLAG_USEVC | ARES_FLAG_PRIMARY; |
| 59 | optmask |= ARES_OPT_FLAGS; |
| 60 | opts.timeout = 2000; |
| 61 | optmask |= ARES_OPT_TIMEOUTMS; |
| 62 | opts.tries = 2; |
| 63 | optmask |= ARES_OPT_TRIES; |
| 64 | opts.ndots = 4; |
| 65 | optmask |= ARES_OPT_NDOTS; |
| 66 | opts.udp_port = 54; |
| 67 | optmask |= ARES_OPT_UDP_PORT; |
| 68 | opts.tcp_port = 54; |
| 69 | optmask |= ARES_OPT_TCP_PORT; |
| 70 | opts.socket_send_buffer_size = 514; |
| 71 | optmask |= ARES_OPT_SOCK_SNDBUF; |
| 72 | opts.socket_receive_buffer_size = 514; |
| 73 | optmask |= ARES_OPT_SOCK_RCVBUF; |
| 74 | opts.ednspsz = 1280; |
| 75 | optmask |= ARES_OPT_EDNSPSZ; |
| 76 | opts.nservers = 2; |
| 77 | opts.servers = (struct in_addr *)malloc(opts.nservers * sizeof(struct in_addr)); |
| 78 | opts.servers[0].s_addr = htonl(0x01020304); |
| 79 | opts.servers[1].s_addr = htonl(0x02030405); |
| 80 | optmask |= ARES_OPT_SERVERS; |
| 81 | opts.ndomains = 2; |
| 82 | opts.domains = (char **)malloc(opts.ndomains * sizeof(char *)); |
| 83 | opts.domains[0] = strdup("example.com"); |
| 84 | opts.domains[1] = strdup("example2.com"); |
| 85 | optmask |= ARES_OPT_DOMAINS; |
| 86 | opts.lookups = strdup("b"); |
| 87 | optmask |= ARES_OPT_LOOKUPS; |
| 88 | optmask |= ARES_OPT_ROTATE; |
| 89 | |
| 90 | ares_channel channel = nullptr; |
| 91 | EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); |
| 92 | EXPECT_NE(nullptr, channel); |
| 93 | |
| 94 | ares_channel channel2 = nullptr; |
| 95 | EXPECT_EQ(ARES_SUCCESS, ares_dup(&channel2, channel)); |
| 96 | |
| 97 | struct ares_options opts2 = {0}; |
| 98 | int optmask2 = 0; |
| 99 | EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel2, &opts2, &optmask2)); |
| 100 | |
| 101 | // Note that not all opts-settable fields are saved (e.g. |
| 102 | // ednspsz, socket_{send,receive}_buffer_size). |
| 103 | EXPECT_EQ(opts.flags, opts2.flags); |
| 104 | EXPECT_EQ(opts.timeout, opts2.timeout); |
| 105 | EXPECT_EQ(opts.tries, opts2.tries); |
| 106 | EXPECT_EQ(opts.ndots, opts2.ndots); |
| 107 | EXPECT_EQ(opts.udp_port, opts2.udp_port); |
| 108 | EXPECT_EQ(opts.tcp_port, opts2.tcp_port); |
| 109 | EXPECT_EQ(1, opts2.nservers); // Truncated by ARES_FLAG_PRIMARY |
| 110 | EXPECT_EQ(opts.servers[0].s_addr, opts2.servers[0].s_addr); |
| 111 | EXPECT_EQ(opts.ndomains, opts2.ndomains); |
| 112 | EXPECT_EQ(std::string(opts.domains[0]), std::string(opts2.domains[0])); |
| 113 | EXPECT_EQ(std::string(opts.domains[1]), std::string(opts2.domains[1])); |
| 114 | EXPECT_EQ(std::string(opts.lookups), std::string(opts2.lookups)); |
| 115 | |
| 116 | ares_destroy_options(&opts); |
| 117 | ares_destroy_options(&opts2); |
| 118 | ares_destroy(channel); |
| 119 | ares_destroy(channel2); |
| 120 | } |
| 121 | |
| 122 | TEST_F(LibraryTest, ChannelAllocFail) { |
| 123 | ares_channel channel; |
| 124 | for (int ii = 1; ii <= 25; ii++) { |
| 125 | ClearFails(); |
| 126 | SetAllocFail(ii); |
| 127 | channel = nullptr; |
| 128 | int rc = ares_init(&channel); |
| 129 | // The number of allocations depends on local environment, so don't expect ENOMEM. |
| 130 | if (rc == ARES_ENOMEM) { |
| 131 | EXPECT_EQ(nullptr, channel); |
| 132 | } else { |
| 133 | ares_destroy(channel); |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | TEST_F(LibraryTest, OptionsChannelAllocFail) { |
| 139 | struct ares_options opts = {0}; |
| 140 | int optmask = 0; |
| 141 | opts.flags = ARES_FLAG_USEVC; |
| 142 | optmask |= ARES_OPT_FLAGS; |
| 143 | opts.timeout = 2; |
| 144 | optmask |= ARES_OPT_TIMEOUT; |
| 145 | opts.tries = 2; |
| 146 | optmask |= ARES_OPT_TRIES; |
| 147 | opts.ndots = 4; |
| 148 | optmask |= ARES_OPT_NDOTS; |
| 149 | opts.udp_port = 54; |
| 150 | optmask |= ARES_OPT_UDP_PORT; |
| 151 | opts.tcp_port = 54; |
| 152 | optmask |= ARES_OPT_TCP_PORT; |
| 153 | opts.socket_send_buffer_size = 514; |
| 154 | optmask |= ARES_OPT_SOCK_SNDBUF; |
| 155 | opts.socket_receive_buffer_size = 514; |
| 156 | optmask |= ARES_OPT_SOCK_RCVBUF; |
| 157 | opts.ednspsz = 1280; |
| 158 | optmask |= ARES_OPT_EDNSPSZ; |
| 159 | opts.nservers = 2; |
| 160 | opts.servers = (struct in_addr *)malloc(opts.nservers * sizeof(struct in_addr)); |
| 161 | opts.servers[0].s_addr = htonl(0x01020304); |
| 162 | opts.servers[1].s_addr = htonl(0x02030405); |
| 163 | optmask |= ARES_OPT_SERVERS; |
| 164 | opts.ndomains = 2; |
| 165 | opts.domains = (char **)malloc(opts.ndomains * sizeof(char *)); |
| 166 | opts.domains[0] = strdup("example.com"); |
| 167 | opts.domains[1] = strdup("example2.com"); |
| 168 | optmask |= ARES_OPT_DOMAINS; |
| 169 | opts.lookups = strdup("b"); |
| 170 | optmask |= ARES_OPT_LOOKUPS; |
| 171 | optmask |= ARES_OPT_ROTATE; |
| 172 | |
| 173 | ares_channel channel = nullptr; |
| 174 | for (int ii = 1; ii <= 8; ii++) { |
| 175 | ClearFails(); |
| 176 | SetAllocFail(ii); |
| 177 | int rc = ares_init_options(&channel, &opts, optmask); |
| 178 | if (rc == ARES_ENOMEM) { |
| 179 | EXPECT_EQ(nullptr, channel); |
| 180 | } else { |
| 181 | EXPECT_EQ(ARES_SUCCESS, rc); |
| 182 | ares_destroy(channel); |
| 183 | channel = nullptr; |
| 184 | } |
| 185 | } |
| 186 | ClearFails(); |
| 187 | |
| 188 | EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); |
| 189 | EXPECT_NE(nullptr, channel); |
| 190 | |
| 191 | // Add some servers and a sortlist for flavour. |
| 192 | EXPECT_EQ(ARES_SUCCESS, |
| 193 | ares_set_servers_csv(channel, "1.2.3.4,0102:0304:0506:0708:0910:1112:1314:1516,2.3.4.5")); |
| 194 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel, "1.2.3.4 2.3.4.5")); |
| 195 | |
| 196 | ares_channel channel2 = nullptr; |
| 197 | for (int ii = 1; ii <= 18; ii++) { |
| 198 | ClearFails(); |
| 199 | SetAllocFail(ii); |
| 200 | EXPECT_EQ(ARES_ENOMEM, ares_dup(&channel2, channel)) << ii; |
| 201 | EXPECT_EQ(nullptr, channel2) << ii; |
| 202 | } |
| 203 | |
| 204 | struct ares_options opts2; |
| 205 | int optmask2 = 0; |
| 206 | for (int ii = 1; ii <= 6; ii++) { |
| 207 | memset(&opts2, 0, sizeof(opts2)); |
| 208 | ClearFails(); |
| 209 | SetAllocFail(ii); |
| 210 | EXPECT_EQ(ARES_ENOMEM, ares_save_options(channel, &opts2, &optmask2)) << ii; |
| 211 | // May still have allocations even after ARES_ENOMEM return code. |
| 212 | ares_destroy_options(&opts2); |
| 213 | } |
| 214 | ares_destroy_options(&opts); |
| 215 | ares_destroy(channel); |
| 216 | } |
| 217 | |
| 218 | TEST_F(LibraryTest, FailChannelInit) { |
| 219 | EXPECT_EQ(ARES_SUCCESS, |
| 220 | ares_library_init_mem(ARES_LIB_INIT_ALL, |
| 221 | &LibraryTest::amalloc, |
| 222 | &LibraryTest::afree, |
| 223 | &LibraryTest::arealloc)); |
| 224 | SetAllocFail(1); |
| 225 | ares_channel channel = nullptr; |
| 226 | EXPECT_EQ(ARES_ENOMEM, ares_init(&channel)); |
| 227 | EXPECT_EQ(nullptr, channel); |
| 228 | ares_library_cleanup(); |
| 229 | } |
| 230 | |
| 231 | #ifndef WIN32 |
| 232 | TEST_F(LibraryTest, EnvInit) { |
| 233 | ares_channel channel = nullptr; |
| 234 | EnvValue v1("LOCALDOMAIN", "this.is.local"); |
| 235 | EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2"); |
| 236 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 237 | ares_destroy(channel); |
| 238 | } |
| 239 | |
| 240 | TEST_F(LibraryTest, EnvInitAllocFail) { |
| 241 | ares_channel channel; |
| 242 | EnvValue v1("LOCALDOMAIN", "this.is.local"); |
| 243 | EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2"); |
| 244 | for (int ii = 1; ii <= 10; ii++) { |
| 245 | ClearFails(); |
| 246 | SetAllocFail(ii); |
| 247 | channel = nullptr; |
| 248 | int rc = ares_init(&channel); |
| 249 | if (rc == ARES_SUCCESS) { |
| 250 | ares_destroy(channel); |
| 251 | } else { |
| 252 | EXPECT_EQ(ARES_ENOMEM, rc); |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | #endif |
| 257 | |
| 258 | TEST_F(DefaultChannelTest, SetAddresses) { |
| 259 | ares_set_local_ip4(channel_, 0x01020304); |
| 260 | byte addr6[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 261 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; |
| 262 | ares_set_local_ip6(channel_, addr6); |
| 263 | ares_set_local_dev(channel_, "dummy"); |
| 264 | } |
| 265 | |
| 266 | TEST_F(DefaultChannelTest, SetSortlistFailures) { |
| 267 | EXPECT_EQ(ARES_ENODATA, ares_set_sortlist(nullptr, "1.2.3.4")); |
| 268 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "xyzzy ; lwk")); |
| 269 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "xyzzy ; 0x123")); |
| 270 | } |
| 271 | |
| 272 | TEST_F(DefaultChannelTest, SetSortlistVariants) { |
| 273 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4")); |
| 274 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4 ; 2.3.4.5")); |
| 275 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "129.1.1.1")); |
| 276 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "192.1.1.1")); |
| 277 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "224.1.1.1")); |
| 278 | EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "225.1.1.1")); |
| 279 | } |
| 280 | |
| 281 | TEST_F(DefaultChannelTest, SetSortlistAllocFail) { |
| 282 | for (int ii = 1; ii <= 3; ii++) { |
| 283 | ClearFails(); |
| 284 | SetAllocFail(ii); |
| 285 | EXPECT_EQ(ARES_ENOMEM, ares_set_sortlist(channel_, "12.13.0.0/16 1234::5678/40 1.2.3.4")) << ii; |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | #ifdef USE_WINSOCK |
| 290 | TEST(Init, NoLibraryInit) { |
| 291 | ares_channel channel = nullptr; |
| 292 | EXPECT_EQ(ARES_ENOTINITIALIZED, ares_init(&channel)); |
| 293 | } |
| 294 | #endif |
| 295 | |
| 296 | #ifdef HAVE_CONTAINER |
| 297 | // These tests rely on the ability of non-root users to create a chroot |
| 298 | // using Linux namespaces. |
| 299 | |
| 300 | |
| 301 | // The library uses a variety of information sources to initialize a channel, |
| 302 | // in particular to determine: |
| 303 | // - search: the search domains to use |
| 304 | // - servers: the name servers to use |
| 305 | // - lookup: whether to check files or DNS or both (e.g. "fb") |
| 306 | // - options: various resolver options |
| 307 | // - sortlist: the order of preference for IP addresses |
| 308 | // |
| 309 | // The first source from the following list is used: |
| 310 | // - init_by_options(): explicitly specified values in struct ares_options |
| 311 | // - init_by_environment(): values from the environment: |
| 312 | // - LOCALDOMAIN -> search (single value) |
| 313 | // - RES_OPTIONS -> options |
| 314 | // - init_by_resolv_conf(): values from various config files: |
| 315 | // - /etc/resolv.conf -> search, lookup, servers, sortlist, options |
| 316 | // - /etc/nsswitch.conf -> lookup |
| 317 | // - /etc/host.conf -> lookup |
| 318 | // - /etc/svc.conf -> lookup |
| 319 | // - init_by_defaults(): fallback values: |
| 320 | // - gethostname(3) -> domain |
| 321 | // - "fb" -> lookup |
| 322 | |
| 323 | NameContentList filelist = { |
| 324 | {"/etc/resolv.conf", "nameserver 1.2.3.4\n" |
| 325 | "sortlist 1.2.3.4/16 2.3.4.5\n" |
| 326 | "search first.com second.com\n"}, |
| 327 | {"/etc/hosts", "3.4.5.6 ahostname.com\n"}, |
| 328 | {"/etc/nsswitch.conf", "hosts: files\n"}}; |
| 329 | CONTAINED_TEST_F(LibraryTest, ContainerChannelInit, |
| 330 | "myhostname", "mydomainname.org", filelist) { |
| 331 | ares_channel channel = nullptr; |
| 332 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 333 | std::vector<std::string> actual = GetNameServers(channel); |
| 334 | std::vector<std::string> expected = {"1.2.3.4"}; |
| 335 | EXPECT_EQ(expected, actual); |
| 336 | |
| 337 | struct ares_options opts; |
| 338 | int optmask = 0; |
| 339 | ares_save_options(channel, &opts, &optmask); |
| 340 | EXPECT_EQ(2, opts.ndomains); |
| 341 | EXPECT_EQ(std::string("first.com"), std::string(opts.domains[0])); |
| 342 | EXPECT_EQ(std::string("second.com"), std::string(opts.domains[1])); |
| 343 | ares_destroy_options(&opts); |
| 344 | |
| 345 | HostResult result; |
| 346 | ares_gethostbyname(channel, "ahostname.com", AF_INET, HostCallback, &result); |
| 347 | ProcessWork(channel, NoExtraFDs, nullptr); |
| 348 | EXPECT_TRUE(result.done_); |
| 349 | std::stringstream ss; |
| 350 | ss << result.host_; |
| 351 | EXPECT_EQ("{'ahostname.com' aliases=[] addrs=[3.4.5.6]}", ss.str()); |
| 352 | |
| 353 | ares_destroy(channel); |
| 354 | return HasFailure(); |
| 355 | } |
| 356 | |
| 357 | CONTAINED_TEST_F(LibraryTest, ContainerSortlistOptionInit, |
| 358 | "myhostname", "mydomainname.org", filelist) { |
| 359 | ares_channel channel = nullptr; |
| 360 | struct ares_options opts = {0}; |
| 361 | int optmask = 0; |
| 362 | optmask |= ARES_OPT_SORTLIST; |
| 363 | opts.nsort = 0; |
| 364 | // Explicitly specifying an empty sortlist in the options should override the |
| 365 | // environment. |
| 366 | EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); |
| 367 | ares_save_options(channel, &opts, &optmask); |
| 368 | EXPECT_EQ(0, opts.nsort); |
| 369 | EXPECT_EQ(nullptr, opts.sortlist); |
| 370 | EXPECT_EQ(ARES_OPT_SORTLIST, (optmask & ARES_OPT_SORTLIST)); |
| 371 | ares_destroy_options(&opts); |
| 372 | |
| 373 | ares_destroy(channel); |
| 374 | return HasFailure(); |
| 375 | } |
| 376 | |
| 377 | NameContentList fullresolv = { |
| 378 | {"/etc/resolv.conf", " nameserver 1.2.3.4 \n" |
| 379 | "search first.com second.com\n" |
| 380 | "lookup bind\n" |
| 381 | "options debug ndots:5\n" |
| 382 | "sortlist 1.2.3.4/16 2.3.4.5\n"}}; |
| 383 | CONTAINED_TEST_F(LibraryTest, ContainerFullResolvInit, |
| 384 | "myhostname", "mydomainname.org", fullresolv) { |
| 385 | ares_channel channel = nullptr; |
| 386 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 387 | |
| 388 | struct ares_options opts; |
| 389 | int optmask = 0; |
| 390 | ares_save_options(channel, &opts, &optmask); |
| 391 | EXPECT_EQ(std::string("b"), std::string(opts.lookups)); |
| 392 | EXPECT_EQ(5, opts.ndots); |
| 393 | ares_destroy_options(&opts); |
| 394 | |
| 395 | ares_destroy(channel); |
| 396 | return HasFailure(); |
| 397 | } |
| 398 | |
| 399 | NameContentList hostconf = { |
| 400 | {"/etc/resolv.conf", "nameserver 1.2.3.4\n" |
| 401 | "sortlist1.2.3.4\n" // malformed line |
| 402 | "search first.com second.com\n"}, |
| 403 | {"/etc/host.conf", "order bind hosts\n"}}; |
| 404 | CONTAINED_TEST_F(LibraryTest, ContainerHostConfInit, |
| 405 | "myhostname", "mydomainname.org", hostconf) { |
| 406 | ares_channel channel = nullptr; |
| 407 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 408 | |
| 409 | struct ares_options opts; |
| 410 | int optmask = 0; |
| 411 | ares_save_options(channel, &opts, &optmask); |
| 412 | EXPECT_EQ(std::string("bf"), std::string(opts.lookups)); |
| 413 | ares_destroy_options(&opts); |
| 414 | |
| 415 | ares_destroy(channel); |
| 416 | return HasFailure(); |
| 417 | } |
| 418 | |
| 419 | NameContentList svcconf = { |
| 420 | {"/etc/resolv.conf", "nameserver 1.2.3.4\n" |
| 421 | "search first.com second.com\n"}, |
| 422 | {"/etc/svc.conf", "hosts= bind\n"}}; |
| 423 | CONTAINED_TEST_F(LibraryTest, ContainerSvcConfInit, |
| 424 | "myhostname", "mydomainname.org", svcconf) { |
| 425 | ares_channel channel = nullptr; |
| 426 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 427 | |
| 428 | struct ares_options opts; |
| 429 | int optmask = 0; |
| 430 | ares_save_options(channel, &opts, &optmask); |
| 431 | EXPECT_EQ(std::string("b"), std::string(opts.lookups)); |
| 432 | ares_destroy_options(&opts); |
| 433 | |
| 434 | ares_destroy(channel); |
| 435 | return HasFailure(); |
| 436 | } |
| 437 | |
| 438 | // Failures when expected config filenames are inaccessible. |
| 439 | class MakeUnreadable { |
| 440 | public: |
| 441 | explicit MakeUnreadable(const std::string& filename) |
| 442 | : filename_(filename) { |
| 443 | chmod(filename_.c_str(), 0000); |
| 444 | } |
| 445 | ~MakeUnreadable() { chmod(filename_.c_str(), 0644); } |
| 446 | private: |
| 447 | std::string filename_; |
| 448 | }; |
| 449 | |
| 450 | CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable, |
| 451 | "myhostname", "mydomainname.org", filelist) { |
| 452 | ares_channel channel = nullptr; |
| 453 | MakeUnreadable hide("/etc/resolv.conf"); |
| 454 | // Unavailable /etc/resolv.conf falls back to defaults |
| 455 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 456 | return HasFailure(); |
| 457 | } |
| 458 | CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable, |
| 459 | "myhostname", "mydomainname.org", filelist) { |
| 460 | ares_channel channel = nullptr; |
| 461 | // Unavailable /etc/nsswitch.conf falls back to defaults. |
| 462 | MakeUnreadable hide("/etc/nsswitch.conf"); |
| 463 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 464 | |
| 465 | struct ares_options opts; |
| 466 | int optmask = 0; |
| 467 | ares_save_options(channel, &opts, &optmask); |
| 468 | EXPECT_EQ(std::string("fb"), std::string(opts.lookups)); |
| 469 | ares_destroy_options(&opts); |
| 470 | |
| 471 | ares_destroy(channel); |
| 472 | return HasFailure(); |
| 473 | } |
| 474 | CONTAINED_TEST_F(LibraryTest, ContainerHostConfNotReadable, |
| 475 | "myhostname", "mydomainname.org", hostconf) { |
| 476 | ares_channel channel = nullptr; |
| 477 | // Unavailable /etc/host.conf falls back to defaults. |
| 478 | MakeUnreadable hide("/etc/host.conf"); |
| 479 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 480 | ares_destroy(channel); |
| 481 | return HasFailure(); |
| 482 | } |
| 483 | CONTAINED_TEST_F(LibraryTest, ContainerSvcConfNotReadable, |
| 484 | "myhostname", "mydomainname.org", svcconf) { |
| 485 | ares_channel channel = nullptr; |
| 486 | // Unavailable /etc/svc.conf falls back to defaults. |
| 487 | MakeUnreadable hide("/etc/svc.conf"); |
| 488 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 489 | ares_destroy(channel); |
| 490 | return HasFailure(); |
| 491 | } |
| 492 | |
| 493 | NameContentList rotateenv = { |
| 494 | {"/etc/resolv.conf", "nameserver 1.2.3.4\n" |
| 495 | "search first.com second.com\n" |
| 496 | "options rotate\n"}}; |
| 497 | CONTAINED_TEST_F(LibraryTest, ContainerRotateInit, |
| 498 | "myhostname", "mydomainname.org", rotateenv) { |
| 499 | ares_channel channel = nullptr; |
| 500 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 501 | |
| 502 | struct ares_options opts; |
| 503 | int optmask = 0; |
| 504 | ares_save_options(channel, &opts, &optmask); |
| 505 | EXPECT_EQ(ARES_OPT_ROTATE, (optmask & ARES_OPT_ROTATE)); |
| 506 | ares_destroy_options(&opts); |
| 507 | |
| 508 | ares_destroy(channel); |
| 509 | return HasFailure(); |
| 510 | } |
| 511 | |
| 512 | CONTAINED_TEST_F(LibraryTest, ContainerRotateOverride, |
| 513 | "myhostname", "mydomainname.org", rotateenv) { |
| 514 | ares_channel channel = nullptr; |
| 515 | struct ares_options opts = {0}; |
| 516 | int optmask = ARES_OPT_NOROTATE; |
| 517 | EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask)); |
| 518 | |
| 519 | optmask = 0; |
| 520 | ares_save_options(channel, &opts, &optmask); |
| 521 | EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE)); |
| 522 | ares_destroy_options(&opts); |
| 523 | |
| 524 | ares_destroy(channel); |
| 525 | return HasFailure(); |
| 526 | } |
| 527 | |
| 528 | NameContentList multiresolv = { |
| 529 | {"/etc/resolv.conf", " nameserver 1::2 ; ;;\n" |
| 530 | " domain first.com\n"}, |
| 531 | {"/etc/nsswitch.conf", "hosts: files\n"}}; |
| 532 | CONTAINED_TEST_F(LibraryTest, ContainerMultiResolvInit, |
| 533 | "myhostname", "mydomainname.org", multiresolv) { |
| 534 | ares_channel channel = nullptr; |
| 535 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 536 | std::vector<std::string> actual = GetNameServers(channel); |
| 537 | std::vector<std::string> expected = {"0001:0000:0000:0000:0000:0000:0000:0002"}; |
| 538 | EXPECT_EQ(expected, actual); |
| 539 | |
| 540 | struct ares_options opts; |
| 541 | int optmask = 0; |
| 542 | ares_save_options(channel, &opts, &optmask); |
| 543 | EXPECT_EQ(1, opts.ndomains); |
| 544 | EXPECT_EQ(std::string("first.com"), std::string(opts.domains[0])); |
| 545 | ares_destroy_options(&opts); |
| 546 | |
| 547 | ares_destroy(channel); |
| 548 | return HasFailure(); |
| 549 | } |
| 550 | |
| 551 | NameContentList systemdresolv = { |
| 552 | {"/etc/resolv.conf", "nameserver 1.2.3.4\n" |
| 553 | "domain first.com\n"}, |
| 554 | {"/etc/nsswitch.conf", "hosts: junk resolve files\n"}}; |
| 555 | CONTAINED_TEST_F(LibraryTest, ContainerSystemdResolvInit, |
| 556 | "myhostname", "mydomainname.org", systemdresolv) { |
| 557 | ares_channel channel = nullptr; |
| 558 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 559 | |
| 560 | struct ares_options opts; |
| 561 | int optmask = 0; |
| 562 | ares_save_options(channel, &opts, &optmask); |
| 563 | EXPECT_EQ(std::string("bf"), std::string(opts.lookups)); |
| 564 | ares_destroy_options(&opts); |
| 565 | |
| 566 | ares_destroy(channel); |
| 567 | return HasFailure(); |
| 568 | } |
| 569 | |
| 570 | NameContentList empty = {}; // no files |
| 571 | CONTAINED_TEST_F(LibraryTest, ContainerEmptyInit, |
| 572 | "host.domain.org", "domain.org", empty) { |
| 573 | ares_channel channel = nullptr; |
| 574 | EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); |
| 575 | std::vector<std::string> actual = GetNameServers(channel); |
| 576 | std::vector<std::string> expected = {"127.0.0.1"}; |
| 577 | EXPECT_EQ(expected, actual); |
| 578 | |
| 579 | struct ares_options opts; |
| 580 | int optmask = 0; |
| 581 | ares_save_options(channel, &opts, &optmask); |
| 582 | EXPECT_EQ(1, opts.ndomains); |
| 583 | EXPECT_EQ(std::string("domain.org"), std::string(opts.domains[0])); |
| 584 | EXPECT_EQ(std::string("fb"), std::string(opts.lookups)); |
| 585 | ares_destroy_options(&opts); |
| 586 | |
| 587 | |
| 588 | ares_destroy(channel); |
| 589 | return HasFailure(); |
| 590 | } |
| 591 | |
| 592 | #endif |
| 593 | |
| 594 | } // namespace test |
| 595 | } // namespace ares |