From patchwork Mon Jul 3 15:57:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 21392 Received: (qmail 36725 invoked by alias); 3 Jul 2017 15:57:55 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 36714 invoked by uid 89); 3 Jul 2017 15:57:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=debate, 2607 X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 84A843B74D Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 84A843B74D Date: Mon, 03 Jul 2017 17:57:50 +0200 To: libc-alpha@sourceware.org Subject: [PATCH COMMITTED] resolv: Add preinit tests to resolv/tst-resolv-res_init-skeleton.c User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170703155750.3DED4424FDF42@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) 2017-07-03 Florian Weimer * resolv/tst-resolv-res_init-skeleton.c (special_tests_count, special_test_call_res_init) (special_test_callback, special_test_thread_func) (run_special_test_on_thread, special_test): Define. (do_test): call special_test. (test_init_names): Fix typo. diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c index b5fe2cf..ce206f5 100644 --- a/resolv/tst-resolv-res_init-skeleton.c +++ b/resolv/tst-resolv-res_init-skeleton.c @@ -260,7 +260,7 @@ enum test_init static const char *const test_init_names[] = { [test_init] = "res_init", - [test_ninit] = "res_init", + [test_ninit] = "res_ninit", [test_mkquery] = "res_mkquery", [test_gethostbyname] = "gethostbyname", [test_getaddrinfo] = "getaddrinfo", @@ -540,6 +540,192 @@ test_file_contents (const struct test_case *t) } } +/* Special tests which do not follow the general pattern. */ +enum { special_tests_count = 7 }; + +#if TEST_THREAD +/* Called from test number 3-6 to trigger reloading of the + configuration. */ +static void * +special_test_call_res_init (void *closure) +{ + TEST_VERIFY (res_init () == 0); + return NULL; +} +#endif + +/* Implementation of special tests. */ +static void +special_test_callback (void *closure) +{ + unsigned int *test_indexp = closure; + unsigned test_index = *test_indexp; + TEST_VERIFY (test_index < special_tests_count); + if (test_verbose > 0) + printf ("info: special test %u\n", test_index); + xchroot (path_chroot); + + switch (test_index) + { + case 0: + case 1: + /* Second res_init with missing or empty file preserves + flags. */ + if (test_index == 1) + TEST_VERIFY (unlink (_PATH_RESCONF) == 0); + _res.options = RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* First res_init clears flag. */ + TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); + _res.options |= RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* Second res_init preserves flag. */ + TEST_VERIFY (_res.options & RES_USE_EDNS0); + if (test_index == 1) + /* Restore empty file. */ + support_write_file_string (_PATH_RESCONF, ""); + break; + + case 2: + /* Second res_init is cumulative. */ + support_write_file_string (_PATH_RESCONF, + "options rotate\n" + "nameserver 192.0.2.1\n"); + _res.options = RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* First res_init clears flag. */ + TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); + /* And sets RES_ROTATE. */ + TEST_VERIFY (_res.options & RES_ROTATE); + _res.options |= RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* Second res_init preserves flag. */ + TEST_VERIFY (_res.options & RES_USE_EDNS0); + TEST_VERIFY (_res.options & RES_ROTATE); + /* Reloading the configuration does not clear the explicitly set + flag. */ + support_write_file_string (_PATH_RESCONF, + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n"); + TEST_VERIFY (res_init () == 0); + TEST_VERIFY (_res.nscount == 2); + TEST_VERIFY (_res.options & RES_USE_EDNS0); + /* Whether RES_ROTATE (originally in resolv.conf, now removed) + should be preserved is subject to debate. See bug 21701. */ + /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */ + break; + + case 3: + case 4: + case 5: + case 6: + /* Test res_init change broadcast. This requires a second + thread to trigger the reload. */ +#if TEST_THREAD + support_write_file_string (_PATH_RESCONF, + "options edns0\n" + "nameserver 192.0.2.1\n"); + for (int iteration = 0; iteration < 2; ++iteration) + { + switch (test_index) + { + case 3: + TEST_VERIFY (res_init () == 0); + break; + case 4: + { + unsigned char buf[512]; + TEST_VERIFY + (res_mkquery (QUERY, test_hostname, C_IN, T_A, + NULL, 0, NULL, buf, sizeof (buf)) > 0); + } + break; + case 5: + gethostbyname (test_hostname); + break; + case 6: + { + struct addrinfo *ai; + (void) getaddrinfo (test_hostname, NULL, NULL, &ai); + } + break; + } + if (iteration == 0) + { + TEST_VERIFY (_res.options & RES_USE_EDNS0); + TEST_VERIFY (!(_res.options & RES_ROTATE)); + TEST_VERIFY (_res.nscount == 1); + support_write_file_string (_PATH_RESCONF, + "options rotate\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n"); + xpthread_join (xpthread_create + (NULL, special_test_call_res_init, NULL)); + } + else + { + /* edns0 was dropped, but the flag is not cleared. See + bug 21701. */ + /* TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); */ + TEST_VERIFY (_res.options & RES_ROTATE); + TEST_VERIFY (_res.nscount == 2); + } + } +#endif + break; + } +} + +#if TEST_THREAD +/* Helper function which calls special_test_callback from a + thread. */ +static void * +special_test_thread_func (void *closure) +{ + special_test_callback (closure); + return NULL; +} + +/* Variant of special_test_callback which runs the function on a + non-main thread. */ +static void +run_special_test_on_thread (void *closure) +{ + xpthread_join (xpthread_create (NULL, special_test_thread_func, closure)); +} +#endif /* TEST_THREAD */ + +/* Perform the requested special test in a subprocess using + special_test_callback. */ +static void +special_test (unsigned int test_index) +{ +#if TEST_THREAD + for (int do_thread = 0; do_thread < 2; ++do_thread) +#endif + { + void (*func) (void *) = special_test_callback; +#if TEST_THREAD + if (do_thread) + func = run_special_test_on_thread; +#endif + struct support_capture_subprocess proc + = support_capture_subprocess (func, &test_index); + char *test_name = xasprintf ("special test %u", test_index); + if (strcmp (proc.out.buffer, "") != 0) + { + support_record_failure (); + printf ("error: output mismatch for %s\n", test_name); + support_run_diff ("expected", "", + "actual", proc.out.buffer); + } + support_capture_subprocess_check (&proc, test_name, 0, sc_allow_stdout); + free (test_name); + support_capture_subprocess_free (&proc); + } +} + + /* Dummy DNS server. It ensures that the probe queries sent by gethostbyname and getaddrinfo receive a reply even if the system applies a very strict rate limit to localhost. */ @@ -672,6 +858,11 @@ do_test (void) } } + /* The tests which do not follow a regular pattern. */ + for (unsigned int test_index = 0; + test_index < special_tests_count; ++test_index) + special_test (test_index); + if (server > 0) { if (kill (server, SIGTERM) < 0)