aboutsummaryrefslogtreecommitdiff
path: root/resolv/tst-ns_name.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/tst-ns_name.c')
-rw-r--r--resolv/tst-ns_name.c303
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>