quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares-test-init.cc (25569B)


      1 /* MIT License
      2  *
      3  * Copyright (c) The c-ares project and its contributors
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #include "ares-test.h"
     27 
     28 extern "C" {
     29   #include "ares_private.h"
     30 }
     31 
     32 // library initialization is only needed for windows builds
     33 #ifdef WIN32
     34 #define EXPECTED_NONINIT ARES_ENOTINITIALIZED
     35 #else
     36 #define EXPECTED_NONINIT ARES_SUCCESS
     37 #endif
     38 
     39 namespace ares {
     40 namespace test {
     41 
     42 TEST(LibraryInit, Basic) {
     43   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     44   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
     45   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
     46   ares_library_cleanup();
     47   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     48 }
     49 
     50 TEST(LibraryInit, UnexpectedCleanup) {
     51   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     52   ares_library_cleanup();
     53   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     54 }
     55 
     56 TEST(LibraryInit, Nested) {
     57   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     58   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
     59   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
     60   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
     61   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
     62   ares_library_cleanup();
     63   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
     64   ares_library_cleanup();
     65   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
     66 }
     67 
     68 TEST(LibraryInit, BasicChannelInit) {
     69   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
     70   ares_channel_t *channel = nullptr;
     71   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
     72   EXPECT_NE(nullptr, channel);
     73   ares_destroy(channel);
     74   ares_library_cleanup();
     75 }
     76 
     77 TEST_F(LibraryTest, OptionsChannelInit) {
     78   struct ares_options opts;
     79   int optmask = 0;
     80   memset(&opts, 0, sizeof(opts));
     81   opts.flags = ARES_FLAG_USEVC | ARES_FLAG_PRIMARY;
     82   optmask |= ARES_OPT_FLAGS;
     83   opts.timeout = 2000;
     84   optmask |= ARES_OPT_TIMEOUTMS;
     85   opts.tries = 2;
     86   optmask |= ARES_OPT_TRIES;
     87   opts.ndots = 4;
     88   optmask |= ARES_OPT_NDOTS;
     89   opts.udp_port = 54;
     90   optmask |= ARES_OPT_MAXTIMEOUTMS;
     91   opts.maxtimeout = 10000;
     92   optmask |= ARES_OPT_UDP_PORT;
     93   opts.tcp_port = 54;
     94   optmask |= ARES_OPT_TCP_PORT;
     95   opts.socket_send_buffer_size = 514;
     96   optmask |= ARES_OPT_SOCK_SNDBUF;
     97   opts.socket_receive_buffer_size = 514;
     98   optmask |= ARES_OPT_SOCK_RCVBUF;
     99   opts.ednspsz = 1280;
    100   optmask |= ARES_OPT_EDNSPSZ;
    101   opts.nservers = 2;
    102   opts.servers = (struct in_addr *)malloc((size_t)opts.nservers * sizeof(struct in_addr));
    103   opts.servers[0].s_addr = htonl(0x01020304);
    104   opts.servers[1].s_addr = htonl(0x02030405);
    105   optmask |= ARES_OPT_SERVERS;
    106   opts.ndomains = 2;
    107   opts.domains = (char **)malloc((size_t)opts.ndomains * sizeof(char *));
    108   opts.domains[0] = strdup("example.com");
    109   opts.domains[1] = strdup("example2.com");
    110   optmask |= ARES_OPT_DOMAINS;
    111   opts.lookups = strdup("b");
    112   optmask |= ARES_OPT_LOOKUPS;
    113   optmask |= ARES_OPT_ROTATE;
    114   opts.resolvconf_path = strdup("/etc/resolv.conf");
    115   optmask |= ARES_OPT_RESOLVCONF;
    116   opts.hosts_path = strdup("/etc/hosts");
    117   optmask |= ARES_OPT_HOSTS_FILE;
    118 
    119   ares_channel_t *channel = nullptr;
    120   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
    121   EXPECT_NE(nullptr, channel);
    122 
    123   ares_channel_t *channel2 = nullptr;
    124   EXPECT_EQ(ARES_SUCCESS, ares_dup(&channel2, channel));
    125   EXPECT_NE(nullptr, channel2);
    126 
    127   struct ares_options opts2;
    128   int optmask2 = 0;
    129   memset(&opts2, 0, sizeof(opts2));
    130   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel2, &opts2, &optmask2));
    131 
    132   // Note that not all opts-settable fields are saved (e.g.
    133   // ednspsz, socket_{send,receive}_buffer_size).
    134   EXPECT_EQ(opts.flags, opts2.flags);
    135   EXPECT_EQ(opts.timeout, opts2.timeout);
    136   EXPECT_EQ(opts.tries, opts2.tries);
    137   EXPECT_EQ(opts.ndots, opts2.ndots);
    138   EXPECT_EQ(opts.maxtimeout, opts2.maxtimeout);
    139   EXPECT_EQ(opts.udp_port, opts2.udp_port);
    140   EXPECT_EQ(opts.tcp_port, opts2.tcp_port);
    141   EXPECT_EQ(1, opts2.nservers);  // Truncated by ARES_FLAG_PRIMARY
    142   EXPECT_EQ(opts.servers[0].s_addr, opts2.servers[0].s_addr);
    143   EXPECT_EQ(opts.ndomains, opts2.ndomains);
    144   EXPECT_EQ(std::string(opts.domains[0]), std::string(opts2.domains[0]));
    145   EXPECT_EQ(std::string(opts.domains[1]), std::string(opts2.domains[1]));
    146   EXPECT_EQ(std::string(opts.lookups), std::string(opts2.lookups));
    147   EXPECT_EQ(std::string(opts.resolvconf_path), std::string(opts2.resolvconf_path));
    148   EXPECT_EQ(std::string(opts.hosts_path), std::string(opts2.hosts_path));
    149 
    150   ares_destroy_options(&opts);
    151   ares_destroy_options(&opts2);
    152   ares_destroy(channel);
    153   ares_destroy(channel2);
    154 }
    155 
    156 TEST_F(LibraryTest, ChannelAllocFail) {
    157   ares_channel_t *channel;
    158   for (int ii = 1; ii <= 25; ii++) {
    159     ClearFails();
    160     SetAllocFail(ii);
    161     channel = nullptr;
    162     int rc = ares_init(&channel);
    163     // The number of allocations depends on local environment, so don't expect ENOMEM.
    164     if (rc == ARES_ENOMEM) {
    165       EXPECT_EQ(nullptr, channel);
    166     } else {
    167       ares_destroy(channel);
    168     }
    169   }
    170 }
    171 
    172 TEST_F(LibraryTest, OptionsChannelAllocFail) {
    173   struct ares_options opts;
    174   int optmask = 0;
    175   memset(&opts, 0, sizeof(opts));
    176   opts.flags = ARES_FLAG_USEVC;
    177   optmask |= ARES_OPT_FLAGS;
    178   opts.timeout = 2;
    179   optmask |= ARES_OPT_TIMEOUT;
    180   opts.tries = 2;
    181   optmask |= ARES_OPT_TRIES;
    182   opts.ndots = 4;
    183   optmask |= ARES_OPT_NDOTS;
    184   opts.udp_port = 54;
    185   optmask |= ARES_OPT_UDP_PORT;
    186   opts.tcp_port = 54;
    187   optmask |= ARES_OPT_TCP_PORT;
    188   opts.socket_send_buffer_size = 514;
    189   optmask |= ARES_OPT_SOCK_SNDBUF;
    190   opts.socket_receive_buffer_size = 514;
    191   optmask |= ARES_OPT_SOCK_RCVBUF;
    192   opts.ednspsz = 1280;
    193   optmask |= ARES_OPT_EDNSPSZ;
    194   opts.nservers = 2;
    195   opts.servers = (struct in_addr *)malloc((size_t)opts.nservers * sizeof(struct in_addr));
    196   opts.servers[0].s_addr = htonl(0x01020304);
    197   opts.servers[1].s_addr = htonl(0x02030405);
    198   optmask |= ARES_OPT_SERVERS;
    199   opts.ndomains = 2;
    200   opts.domains = (char **)malloc((size_t)opts.ndomains * sizeof(char *));
    201   opts.domains[0] = strdup("example.com");
    202   opts.domains[1] = strdup("example2.com");
    203   optmask |= ARES_OPT_DOMAINS;
    204   opts.lookups = strdup("b");
    205   optmask |= ARES_OPT_LOOKUPS;
    206   optmask |= ARES_OPT_ROTATE;
    207   opts.resolvconf_path = strdup("/etc/resolv.conf");
    208   optmask |= ARES_OPT_RESOLVCONF;
    209   opts.hosts_path = strdup("/etc/hosts");
    210   optmask |= ARES_OPT_HOSTS_FILE;
    211 
    212   ares_channel_t *channel = nullptr;
    213   for (int ii = 1; ii <= 8; ii++) {
    214     ClearFails();
    215     SetAllocFail(ii);
    216     int rc = ares_init_options(&channel, &opts, optmask);
    217     if (rc == ARES_ENOMEM) {
    218       EXPECT_EQ(nullptr, channel);
    219     } else {
    220       EXPECT_EQ(ARES_SUCCESS, rc);
    221       ares_destroy(channel);
    222       channel = nullptr;
    223     }
    224   }
    225   ClearFails();
    226 
    227   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
    228   EXPECT_NE(nullptr, channel);
    229 
    230   // Add some servers and a sortlist for flavour.
    231   EXPECT_EQ(ARES_SUCCESS,
    232             ares_set_servers_csv(channel, "1.2.3.4,0102:0304:0506:0708:0910:1112:1314:1516,2.3.4.5"));
    233   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel, "1.2.3.4 2.3.4.5"));
    234 
    235   ares_channel_t *channel2 = nullptr;
    236   for (int ii = 1; ii <= 18; ii++) {
    237     ClearFails();
    238     SetAllocFail(ii);
    239     EXPECT_EQ(ARES_ENOMEM, ares_dup(&channel2, channel)) << ii;
    240     EXPECT_EQ(nullptr, channel2) << ii;
    241   }
    242 
    243   struct ares_options opts2;
    244   int optmask2 = 0;
    245   for (int ii = 1; ii <= 6; ii++) {
    246     memset(&opts2, 0, sizeof(opts2));
    247     ClearFails();
    248     SetAllocFail(ii);
    249     EXPECT_EQ(ARES_ENOMEM, ares_save_options(channel, &opts2, &optmask2)) << ii;
    250     // May still have allocations even after ARES_ENOMEM return code.
    251     ares_destroy_options(&opts2);
    252   }
    253   ares_destroy_options(&opts);
    254   ares_destroy(channel);
    255 }
    256 
    257 TEST_F(LibraryTest, FailChannelInit) {
    258   EXPECT_EQ(ARES_SUCCESS,
    259             ares_library_init_mem(ARES_LIB_INIT_ALL,
    260                                   &LibraryTest::amalloc,
    261                                   &LibraryTest::afree,
    262                                   &LibraryTest::arealloc));
    263   SetAllocFail(1);
    264   ares_channel_t *channel = nullptr;
    265   EXPECT_EQ(ARES_ENOMEM, ares_init(&channel));
    266   EXPECT_EQ(nullptr, channel);
    267   ares_library_cleanup();
    268 }
    269 
    270 #ifndef WIN32
    271 TEST_F(LibraryTest, EnvInit) {
    272   ares_channel_t *channel = nullptr;
    273   EnvValue v1("LOCALDOMAIN", "this.is.local");
    274   EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2");
    275   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    276   ares_destroy(channel);
    277 }
    278 
    279 TEST_F(LibraryTest, EnvInitModernOptions) {
    280   ares_channel_t *channel = nullptr;
    281   EnvValue v1("LOCALDOMAIN", "this.is.local");
    282   EnvValue v2("RES_OPTIONS", "options debug retrans:2 ndots:3 attempts:4 timeout:5 rotate");
    283   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    284 
    285   channel->optmask |= ARES_OPT_TRIES;
    286   channel->optmask |= ARES_OPT_TIMEOUTMS;
    287 
    288   struct ares_options opts;
    289   memset(&opts, 0, sizeof(opts));
    290   int optmask = 0;
    291   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &opts, &optmask));
    292   EXPECT_EQ(5000, opts.timeout);
    293   EXPECT_EQ(4, opts.tries);
    294 
    295   ares_destroy(channel);
    296 }
    297 
    298 TEST_F(LibraryTest, EnvInitAllocFail) {
    299   ares_channel_t *channel;
    300   EnvValue v1("LOCALDOMAIN", "this.is.local");
    301   EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2");
    302   for (int ii = 1; ii <= 10; ii++) {
    303     ClearFails();
    304     SetAllocFail(ii);
    305     channel = nullptr;
    306     int rc = ares_init(&channel);
    307     if (rc == ARES_SUCCESS) {
    308       ares_destroy(channel);
    309     } else {
    310       EXPECT_EQ(ARES_ENOMEM, rc);
    311     }
    312   }
    313 }
    314 #endif
    315 
    316 TEST_F(DefaultChannelTest, SetAddresses) {
    317   ares_set_local_ip4(channel_, 0x01020304);
    318   byte addr6[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    319                     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
    320   ares_set_local_ip6(channel_, addr6);
    321   ares_set_local_dev(channel_, "dummy");
    322 }
    323 
    324 TEST_F(DefaultChannelTest, SetSortlistFailures) {
    325   EXPECT_EQ(ARES_ENODATA, ares_set_sortlist(nullptr, "1.2.3.4"));
    326   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "111.111.111.111*/16"));
    327   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "111.111.111.111/255.255.255.240*"));
    328   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "1 0123456789012345"));
    329   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "1 /01234567890123456789012345678901"));
    330   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "xyzzy ; lwk"));
    331   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "xyzzy ; 0x123"));
    332 }
    333 
    334 TEST_F(DefaultChannelTest, SetSortlistVariants) {
    335   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4"));
    336   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4 ; 2.3.4.5"));
    337   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4/26;1234::5678/126;4.5.6.7;5678::1234"));
    338   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, " 1.2.3.4/26 1234::5678/126   4.5.6.7 5678::1234  "));
    339   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "129.1.1.1"));
    340   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "192.1.1.1"));
    341   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "224.1.1.1"));
    342   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "225.1.1.1"));
    343 }
    344 
    345 TEST_F(DefaultChannelTest, SetSortlistAllocFail) {
    346   for (int ii = 1; ii <= 3; ii++) {
    347     ClearFails();
    348     SetAllocFail(ii);
    349     EXPECT_EQ(ARES_ENOMEM, ares_set_sortlist(channel_, "12.13.0.0/16 1234::5678/40 1.2.3.4")) << ii;
    350   }
    351 }
    352 
    353 #ifdef USE_WINSOCK
    354 TEST(Init, NoLibraryInit) {
    355   ares_channel_t *channel = nullptr;
    356   EXPECT_EQ(ARES_ENOTINITIALIZED, ares_init(&channel));
    357 }
    358 #endif
    359 
    360 #ifdef HAVE_CONTAINER
    361 // These tests rely on the ability of non-root users to create a chroot
    362 // using Linux namespaces.
    363 
    364 
    365 // The library uses a variety of information sources to initialize a channel,
    366 // in particular to determine:
    367 //  - search: the search domains to use
    368 //  - servers: the name servers to use
    369 //  - lookup: whether to check files or DNS or both (e.g. "fb")
    370 //  - options: various resolver options
    371 //  - sortlist: the order of preference for IP addresses
    372 //
    373 // The first source from the following list is used:
    374 //  - init_by_options(): explicitly specified values in struct ares_options
    375 //  - init_by_environment(): values from the environment:
    376 //     - LOCALDOMAIN -> search (single value)
    377 //     - RES_OPTIONS -> options
    378 //  - init_by_resolv_conf(): values from various config files:
    379 //     - /etc/resolv.conf -> search, lookup, servers, sortlist, options
    380 //     - /etc/nsswitch.conf -> lookup
    381 //     - /etc/host.conf -> lookup
    382 //     - /etc/svc.conf -> lookup
    383 //  - init_by_defaults(): fallback values:
    384 //     - gethostname(3) -> domain
    385 //     - "fb" -> lookup
    386 
    387 NameContentList filelist = {
    388   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
    389                        "sortlist 1.2.3.4/16 2.3.4.5\n"
    390                        "search first.com second.com\n"},
    391   {"/etc/hosts", "3.4.5.6 ahostname.com\n"},
    392   {"/etc/nsswitch.conf", "hosts: files\n"}};
    393 CONTAINED_TEST_F(LibraryTest, ContainerChannelInit,
    394                  "myhostname", "mydomainname.org", filelist) {
    395   ares_channel_t *channel = nullptr;
    396   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    397   std::string actual = GetNameServers(channel);
    398   std::string expected = "1.2.3.4:53";
    399   EXPECT_EQ(expected, actual);
    400   EXPECT_EQ(2, channel->ndomains);
    401   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
    402   EXPECT_EQ(std::string("second.com"), std::string(channel->domains[1]));
    403 
    404   HostResult result;
    405   ares_gethostbyname(channel, "ahostname.com", AF_INET, HostCallback, &result);
    406   ProcessWork(channel, NoExtraFDs, nullptr);
    407   EXPECT_TRUE(result.done_);
    408   std::stringstream ss;
    409   ss << result.host_;
    410 
    411   EXPECT_EQ("{'ahostname.com' aliases=[] addrs=[3.4.5.6]}", ss.str());
    412 
    413   ares_destroy(channel);
    414   return HasFailure();
    415 }
    416 
    417 CONTAINED_TEST_F(LibraryTest, ContainerSortlistOptionInit,
    418                  "myhostname", "mydomainname.org", filelist) {
    419   ares_channel_t *channel = nullptr;
    420   struct ares_options opts;
    421   memset(&opts, 0, sizeof(opts));
    422   int optmask = 0;
    423   optmask |= ARES_OPT_SORTLIST;
    424   opts.nsort = 0;
    425   // Explicitly specifying an empty sortlist in the options should override the
    426   // environment.
    427   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
    428   EXPECT_EQ(0, channel->nsort);
    429   EXPECT_EQ(nullptr, channel->sortlist);
    430   EXPECT_EQ(ARES_OPT_SORTLIST, (channel->optmask & ARES_OPT_SORTLIST));
    431 
    432   ares_destroy(channel);
    433   return HasFailure();
    434 }
    435 
    436 NameContentList fullresolv = {
    437   {"/etc/resolv.conf", " nameserver   1.2.3.4 \n"
    438                        "search   first.com second.com\n"
    439                        "lookup bind\n"
    440                        "options debug ndots:5\n"
    441                        "sortlist 1.2.3.4/16 2.3.4.5\n"}};
    442 CONTAINED_TEST_F(LibraryTest, ContainerFullResolvInit,
    443                  "myhostname", "mydomainname.org", fullresolv) {
    444   ares_channel_t *channel = nullptr;
    445   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    446 
    447   EXPECT_EQ(std::string("b"), std::string(channel->lookups));
    448   EXPECT_EQ(5, channel->ndots);
    449 
    450   ares_destroy(channel);
    451   return HasFailure();
    452 }
    453 
    454 // Allow path for resolv.conf to be configurable
    455 NameContentList myresolvconf = {
    456   {"/tmp/myresolv.cnf", " nameserver   1.2.3.4 \n"
    457                        "search   first.com second.com\n"
    458                        "lookup bind\n"
    459                        "options debug ndots:5\n"
    460                        "sortlist 1.2.3.4/16 2.3.4.5\n"}};
    461 CONTAINED_TEST_F(LibraryTest, ContainerMyResolvConfInit,
    462                  "myhostname", "mydomain.org", myresolvconf) {
    463   char filename[] = "/tmp/myresolv.cnf";
    464   ares_channel_t *channel = nullptr;
    465   struct ares_options options;
    466   memset(&options, 0, sizeof(options));
    467   options.resolvconf_path = strdup(filename);
    468   int optmask = ARES_OPT_RESOLVCONF;
    469   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask));
    470 
    471   optmask = 0;
    472   free(options.resolvconf_path);
    473   options.resolvconf_path = NULL;
    474 
    475   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &options, &optmask));
    476   EXPECT_EQ(ARES_OPT_RESOLVCONF, (optmask & ARES_OPT_RESOLVCONF));
    477   EXPECT_EQ(std::string(filename), std::string(options.resolvconf_path));
    478 
    479   ares_destroy_options(&options);
    480   ares_destroy(channel);
    481   return HasFailure();
    482 }
    483 
    484 // Allow hosts path to be configurable
    485 NameContentList myhosts = {
    486   {"/tmp/hosts", "10.0.12.26     foobar\n"
    487                  "2001:A0:C::1A  foobar\n"}};
    488 CONTAINED_TEST_F(LibraryTest, ContainerMyHostsInit,
    489                  "myhostname", "mydomain.org", myhosts) {
    490   char filename[] = "/tmp/hosts";
    491   ares_channel_t *channel = nullptr;
    492   struct ares_options options;
    493 
    494   options.hosts_path = strdup(filename);
    495   int optmask = ARES_OPT_HOSTS_FILE;
    496   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask));
    497   memset(&options, 0, sizeof(options));
    498   optmask = 0;
    499   free(options.hosts_path);
    500   options.hosts_path = NULL;
    501 
    502   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &options, &optmask));
    503   EXPECT_EQ(ARES_OPT_HOSTS_FILE, (optmask & ARES_OPT_HOSTS_FILE));
    504   EXPECT_EQ(std::string(filename), std::string(options.hosts_path));
    505 
    506   ares_destroy_options(&options);
    507   ares_destroy(channel);
    508   return HasFailure();
    509 }
    510 
    511 NameContentList svcconf = {
    512   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
    513                        "search first.com second.com\n"},
    514   {"/etc/svc.conf", "hosts= bind\n"}};
    515 CONTAINED_TEST_F(LibraryTest, ContainerSvcConfInit,
    516                  "myhostname", "mydomainname.org", svcconf) {
    517   ares_channel_t *channel = nullptr;
    518   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    519 
    520   EXPECT_EQ(std::string("b"), std::string(channel->lookups));
    521 
    522   ares_destroy(channel);
    523   return HasFailure();
    524 }
    525 
    526 NameContentList malformedresolvconflookup = {
    527   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
    528                        "lookup garbage\n"}};  // malformed line
    529 CONTAINED_TEST_F(LibraryTest, ContainerMalformedResolvConfLookup,
    530                  "myhostname", "mydomainname.org", malformedresolvconflookup) {
    531   ares_channel_t *channel = nullptr;
    532   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    533 
    534   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
    535 
    536   ares_destroy(channel);
    537   return HasFailure();
    538 }
    539 
    540 // Failures when expected config filenames are inaccessible.
    541 class MakeUnreadable {
    542  public:
    543   explicit MakeUnreadable(const std::string& filename)
    544     : filename_(filename) {
    545     chmod(filename_.c_str(), 0000);
    546   }
    547   ~MakeUnreadable() { chmod(filename_.c_str(), 0644); }
    548  private:
    549   std::string filename_;
    550 };
    551 
    552 CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable,
    553                  "myhostname", "mydomainname.org", filelist) {
    554   ares_channel_t *channel = nullptr;
    555   MakeUnreadable hide("/etc/resolv.conf");
    556   // Unavailable /etc/resolv.conf falls back to defaults
    557   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    558   return HasFailure();
    559 }
    560 CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable,
    561                  "myhostname", "mydomainname.org", filelist) {
    562   ares_channel_t *channel = nullptr;
    563   // Unavailable /etc/nsswitch.conf falls back to defaults.
    564   MakeUnreadable hide("/etc/nsswitch.conf");
    565   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    566 
    567   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
    568 
    569   ares_destroy(channel);
    570   return HasFailure();
    571 }
    572 
    573 CONTAINED_TEST_F(LibraryTest, ContainerSvcConfNotReadable,
    574                  "myhostname", "mydomainname.org", svcconf) {
    575   ares_channel_t *channel = nullptr;
    576   // Unavailable /etc/svc.conf falls back to defaults.
    577   MakeUnreadable hide("/etc/svc.conf");
    578   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    579   ares_destroy(channel);
    580   return HasFailure();
    581 }
    582 
    583 NameContentList rotateenv = {
    584   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
    585                        "search first.com second.com\n"
    586                        "options rotate\n"}};
    587 CONTAINED_TEST_F(LibraryTest, ContainerRotateInit,
    588                  "myhostname", "mydomainname.org", rotateenv) {
    589   ares_channel_t *channel = nullptr;
    590   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    591 
    592   EXPECT_EQ(ARES_TRUE, channel->rotate);
    593 
    594   ares_destroy(channel);
    595   return HasFailure();
    596 }
    597 
    598 CONTAINED_TEST_F(LibraryTest, ContainerRotateOverride,
    599                  "myhostname", "mydomainname.org", rotateenv) {
    600   ares_channel_t *channel = nullptr;
    601   struct ares_options opts;
    602   memset(&opts, 0, sizeof(opts));
    603   int optmask = ARES_OPT_NOROTATE;
    604   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
    605   optmask = 0;
    606   ares_save_options(channel, &opts, &optmask);
    607   EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE));
    608   ares_destroy_options(&opts);
    609 
    610   ares_destroy(channel);
    611   return HasFailure();
    612 }
    613 
    614 // Test that blacklisted IPv6 resolves are ignored.  They're filtered from any
    615 // source, so resolv.conf is as good as any.
    616 NameContentList blacklistedIpv6 = {
    617   {"/etc/resolv.conf", " nameserver 254.192.1.1\n" // 0xfe.0xc0.0x01.0x01
    618                        " nameserver fec0::dead\n"  // Blacklisted
    619                        " nameserver ffc0::c001\n"  // Not blacklisted
    620                        " domain first.com\n"},
    621   {"/etc/nsswitch.conf", "hosts: files\n"}};
    622 CONTAINED_TEST_F(LibraryTest, ContainerBlacklistedIpv6,
    623                  "myhostname", "mydomainname.org", blacklistedIpv6) {
    624   ares_channel_t *channel = nullptr;
    625   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    626   std::string actual = GetNameServers(channel);
    627   std::string expected = "254.192.1.1:53,"
    628                          "[ffc0::c001]:53";
    629   EXPECT_EQ(expected, actual);
    630 
    631   EXPECT_EQ(1, channel->ndomains);
    632   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
    633 
    634   ares_destroy(channel);
    635   return HasFailure();
    636 }
    637 
    638 NameContentList multiresolv = {
    639   {"/etc/resolv.conf", " nameserver 1::2 ;  ;;\n"
    640                        " domain first.com\n"},
    641   {"/etc/nsswitch.conf", "hosts: files\n"}};
    642 CONTAINED_TEST_F(LibraryTest, ContainerMultiResolvInit,
    643                  "myhostname", "mydomainname.org", multiresolv) {
    644   ares_channel_t *channel = nullptr;
    645   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    646   std::string actual = GetNameServers(channel);
    647   std::string expected = "[1::2]:53";
    648   EXPECT_EQ(expected, actual);
    649 
    650   EXPECT_EQ(1, channel->ndomains);
    651   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
    652 
    653   ares_destroy(channel);
    654   return HasFailure();
    655 }
    656 
    657 NameContentList systemdresolv = {
    658   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
    659                        "domain first.com\n"},
    660   {"/etc/nsswitch.conf", "hosts: junk resolve files\n"}};
    661 CONTAINED_TEST_F(LibraryTest, ContainerSystemdResolvInit,
    662                  "myhostname", "mydomainname.org", systemdresolv) {
    663   ares_channel_t *channel = nullptr;
    664   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    665 
    666   EXPECT_EQ(std::string("bf"), std::string(channel->lookups));
    667 
    668   ares_destroy(channel);
    669   return HasFailure();
    670 }
    671 
    672 NameContentList empty = {};  // no files
    673 CONTAINED_TEST_F(LibraryTest, ContainerEmptyInit,
    674                  "host.domain.org", "domain.org", empty) {
    675   ares_channel_t *channel = nullptr;
    676   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
    677   std::string actual = GetNameServers(channel);
    678   std::string expected = "127.0.0.1:53";
    679   EXPECT_EQ(expected, actual);
    680 
    681   EXPECT_EQ(1, channel->ndomains);
    682   EXPECT_EQ(std::string("domain.org"), std::string(channel->domains[0]));
    683   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
    684 
    685   ares_destroy(channel);
    686   return HasFailure();
    687 }
    688 
    689 // Test that init fails if the flag to not use a default local named server is
    690 // enabled and no other nameservers are available.
    691 CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrEmptyInit,
    692                  "myhostname", "mydomainname.org", empty) {
    693   ares_channel_t *channel = nullptr;
    694   struct ares_options opts;
    695   memset(&opts, 0, sizeof(opts));
    696   int optmask = ARES_OPT_FLAGS;
    697   opts.flags = ARES_FLAG_NO_DFLT_SVR;
    698   EXPECT_EQ(ARES_ENOSERVER, ares_init_options(&channel, &opts, optmask));
    699 
    700   EXPECT_EQ(nullptr, channel);
    701   return HasFailure();
    702 }
    703 // Test that init succeeds if the flag to not use a default local named server
    704 // is enabled but other nameservers are available.
    705 CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrFullInit,
    706                  "myhostname", "mydomainname.org", filelist) {
    707   ares_channel_t *channel = nullptr;
    708   struct ares_options opts;
    709   memset(&opts, 0, sizeof(opts));
    710   int optmask = ARES_OPT_FLAGS;
    711   opts.flags = ARES_FLAG_NO_DFLT_SVR;
    712   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
    713 
    714   std::string actual = GetNameServers(channel);
    715   std::string expected = "1.2.3.4:53";
    716   EXPECT_EQ(expected, actual);
    717 
    718   ares_destroy(channel);
    719   return HasFailure();
    720 }
    721 
    722 #endif
    723 
    724 }  // namespace test
    725 }  // namespace ares