diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-04-04 14:09:56 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-04-04 20:56:17 +0200 |
commit | 07d6f1a3ca990e0e4f93b010605d4d87a3abdf24 (patch) | |
tree | 770f01ae611f7835f61b9809ffc4a68c3ef90b13 /resolv/tst-ns_name.c | |
parent | fce3da82e56a66bdafcef437abef0fa7b82b8d2b (diff) | |
download | glibc-07d6f1a3ca990e0e4f93b010605d4d87a3abdf24.tar.gz glibc-07d6f1a3ca990e0e4f93b010605d4d87a3abdf24.tar.xz glibc-07d6f1a3ca990e0e4f93b010605d4d87a3abdf24.zip |
resolv: Add test coverage for ns_name_unpack, ns_name_ntop
Diffstat (limited to 'resolv/tst-ns_name.c')
-rw-r--r-- | resolv/tst-ns_name.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/resolv/tst-ns_name.c b/resolv/tst-ns_name.c new file mode 100644 index 0000000000..66d9a6666b --- /dev/null +++ b/resolv/tst-ns_name.c @@ -0,0 +1,303 @@ +/* Test ns_name-related functions. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This test program processes the tst-ns_name.data file. */ + +#include <ctype.h> +#include <resolv.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/support.h> +#include <support/xstdio.h> + +/* A byte buffer and its length. */ +struct buffer +{ + unsigned char *data; + size_t length; +}; + +/* Convert a base64-encoded string to its binary representation. */ +static bool +base64_to_buffer (const char *base64, struct buffer *result) +{ + /* "-" denotes an empty input. */ + if (strcmp (base64, "-") == 0) + { + result->data = xmalloc (1); + result->length = 0; + return true; + } + + size_t size = strlen (base64); + unsigned char *data = xmalloc (size); + int ret = b64_pton (base64, data, size); + if (ret < 0 || ret > size) + return false; + result->data = xrealloc (data, ret); + result->length = ret; + return true; +} + +/* A test case for ns_name_unpack and ns_name_ntop. */ +struct test_case +{ + char *path; + size_t lineno; + struct buffer input; + size_t input_offset; + int unpack_result; + struct buffer unpack_output; + int ntop_result; + char *ntop_text; +}; + +/* Deallocate the buffers associated with the test case. */ +static void +free_test_case (struct test_case *t) +{ + free (t->path); + free (t->input.data); + free (t->unpack_output.data); + free (t->ntop_text); +} + +/* Extract the test case information from a test file line. */ +static bool +parse_test_case (const char *path, size_t lineno, const char *line, + struct test_case *result) +{ + memset (result, 0, sizeof (*result)); + result->path = xstrdup (path); + result->lineno = lineno; + result->ntop_result = -1; + char *input = NULL; + char *unpack_output = NULL; + int ret = sscanf (line, "%ms %zu %d %ms %d %ms", + &input, &result->input_offset, + &result->unpack_result, &unpack_output, + &result->ntop_result, &result->ntop_text); + if (ret < 3) + { + printf ("%s:%zu: error: missing input fields\n", path, lineno); + free (input); + return false; + } + if (!base64_to_buffer (input, &result->input)) + { + printf ("%s:%zu: error: malformed base64 input data\n", path, lineno); + free (input); + free (unpack_output); + free (result->ntop_text); + return false; + } + free (input); + + if (unpack_output == NULL) + result->unpack_output = (struct buffer) { NULL, 0 }; + else if (!base64_to_buffer (unpack_output, &result->unpack_output)) + { + printf ("%s:%zu: error: malformed base64 unpack data\n", path, lineno); + free (result->input.data); + free (unpack_output); + free (result->ntop_text); + return false; + } + free (unpack_output); + + /* At this point, all allocated buffers have been transferred to + *result. */ + + if (result->input_offset > result->input.length) + { + printf ("%s:%zu: error: input offset %zu exceeds buffer size %zu\n", + path, lineno, result->input_offset, result->input.length); + free_test_case (result); + return false; + } + if (result->unpack_result < -1) + { + printf ("%s:%zu: error: invalid unpack result %d\n", + path, lineno, result->unpack_result); + free_test_case (result); + return false; + } + if (result->ntop_result < -1) + { + printf ("%s:%zu: error: invalid ntop result %d\n", + path, lineno, result->ntop_result); + free_test_case (result); + return false; + } + + bool fields_consistent; + switch (ret) + { + case 3: + fields_consistent = result->unpack_result == -1; + break; + case 5: + fields_consistent = result->unpack_result != -1 + && result->ntop_result == -1; + break; + case 6: + fields_consistent = result->unpack_result != -1 + && result->ntop_result != -1; + break; + default: + fields_consistent = false; + } + if (!fields_consistent) + { + printf ("%s:%zu: error: wrong number of fields: %d\n", + path, lineno, ret); + free_test_case (result); + return false; + } + return true; +} + +/* Format the buffer as a hexadecimal string and write it to standard + output. */ +static void +print_hex (const char *label, struct buffer buffer) +{ + printf (" %s ", label); + unsigned char *p = buffer.data; + unsigned char *end = p + buffer.length; + while (p < end) + { + printf ("%02X", *p & 0xFF); + ++p; + } + putchar ('\n'); +} + +/* Run the test case specified in *T. */ +static void +run_test_case (struct test_case *t) +{ + unsigned char *unpacked = xmalloc (NS_MAXCDNAME); + int consumed = ns_name_unpack + (t->input.data, t->input.data + t->input.length, + t->input.data + t->input_offset, + unpacked, NS_MAXCDNAME); + if (consumed != t->unpack_result) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_unpack\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, t->unpack_result, consumed); + return; + } + if (consumed != -1) + { + if (memcmp (unpacked, t->unpack_output.data, consumed) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_unpack\n", + t->path, t->lineno); + print_hex ("expected:", t->unpack_output); + print_hex ("actual: ", (struct buffer) { unpacked, consumed }); + return; + } + + char *text = xmalloc (NS_MAXDNAME); + int ret = ns_name_ntop (unpacked, text, NS_MAXDNAME); + if (ret != t->ntop_result) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_top\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, t->ntop_result, ret); + return; + } + if (ret != -1) + { + if (strcmp (text, t->ntop_text) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_ntop\n", + t->path, t->lineno); + printf (" expected: \"%s\"\n", t->ntop_text); + printf (" actual: \"%s\"\n", text); + return; + } + } + free (text); + } + free (unpacked); +} + +/* Open the file at PATH, parse the test cases contained in it, and + run them. */ +static void +run_test_file (const char *path) +{ + FILE *fp = xfopen (path, "re"); + char *line = NULL; + size_t line_allocated = 0; + size_t lineno = 0; + + while (true) + { + ssize_t ret = getline (&line, &line_allocated, fp); + if (ret < 0) + { + if (ferror (fp)) + { + printf ("%s: error reading file: %m\n", path); + exit (1); + } + TEST_VERIFY (feof (fp)); + break; + } + + ++lineno; + char *p = line; + while (isspace (*p)) + ++p; + if (*p == '\0' || *p == '#') + continue; + + struct test_case test_case; + if (!parse_test_case (path, lineno, line, &test_case)) + { + support_record_failure (); + continue; + } + run_test_case (&test_case); + free_test_case (&test_case); + } + free (line); + xfclose (fp); +} + +static int +do_test (void) +{ + run_test_file ("tst-ns_name.data"); + return 0; +} + +#include <support/test-driver.c> |