summaryrefslogtreecommitdiffstats
path: root/src/tests/safe-format-tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/safe-format-tests.c')
-rw-r--r--src/tests/safe-format-tests.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/tests/safe-format-tests.c b/src/tests/safe-format-tests.c
new file mode 100644
index 0000000..0fe813e
--- /dev/null
+++ b/src/tests/safe-format-tests.c
@@ -0,0 +1,252 @@
+/*
+ * This file originated in realmd
+ *
+ * Copyright 2012 Red Hat Inc
+ *
+ * This program 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 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#include "src/util/safe-format-string.h"
+
+#include <check.h>
+#include <popt.h>
+#include <string.h>
+#include <talloc.h>
+
+#ifndef ck_assert_int_ge
+#define ck_assert_int_ge(X, Y) _ck_assert_int(X, >=, Y)
+#endif
+
+#ifndef ck_assert_int_lt
+#define ck_assert_int_lt(X, Y) _ck_assert_int(X, <, Y)
+#endif
+
+typedef struct {
+ const char *format;
+ const char *args[8];
+ const char *result;
+} Fixture;
+
+static const Fixture fixtures[] = {
+ {
+ /* Just a bog standard string */
+ "%s", { "blah", NULL, },
+ "blah"
+ },
+ {
+ /* Empty to print */
+ "%s", { "", NULL, },
+ ""
+ },
+ {
+ /* Nothing to print */
+ "", { "blah", NULL, },
+ ""
+ },
+ {
+ /* Width right aligned */
+ "%8s", { "blah", NULL, },
+ " blah"
+ },
+ {
+ /* Width left aligned */
+ "whoop %-8s doo", { "dee", NULL, },
+ "whoop dee doo"
+ },
+ {
+ /* Width space aligned (ignored) */
+ "whoop % 8s doo", { "dee", NULL, },
+ "whoop dee doo"
+ },
+ {
+ /* Width left space aligned (ignored) */
+ "whoop % -8s doo", { "dee", NULL, },
+ "whoop dee doo"
+ },
+ {
+ /* Precision 1 digit */
+ "whoop %.3s doo", { "deedle-dee", NULL, },
+ "whoop dee doo"
+ },
+ {
+ /* Precision, N digits */
+ "whoop %.10s doo", { "deedle-dee-deedle-do-deedle-dum", NULL, },
+ "whoop deedle-dee doo"
+ },
+ {
+ /* Precision, zero digits */
+ "whoop %.s doo", { "deedle", NULL, },
+ "whoop doo"
+ },
+ {
+ /* Multiple simple arguments */
+ "space %s %s", { "man", "dances", NULL, },
+ "space man dances"
+ },
+ {
+ /* Literal percent */
+ "100%% of space folk dance", { NULL, },
+ "100% of space folk dance"
+ },
+ {
+ /* Multiple simple arguments */
+ "space %2$s %1$s", { "dances", "man", NULL, },
+ "space man dances"
+ },
+ {
+ /* Skipping an argument (not supported by standard printf) */
+ "space %2$s dances", { "dances", "man", NULL, },
+ "space man dances"
+ },
+
+ /* Failures start here */
+
+ {
+ /* Unsupported conversion */
+ "%x", { "blah", NULL, },
+ NULL
+ },
+ {
+ /* Bad positional argument */
+ "space %55$s dances", { "dances", "man", NULL, },
+ NULL
+ },
+ {
+ /* Zero positional argument */
+ "space %0$s dances", { "dances", "man", NULL, },
+ NULL
+ },
+ {
+ /* Too many args used */
+ "%s %s dances", { "space", NULL, },
+ NULL
+ },
+ {
+ /* Too many digits used */
+ "%1234567890s dances", { "space", NULL, },
+ NULL
+ },
+};
+
+
+static void
+callback(void *data, const char *piece, size_t len)
+{
+ char **str = data;
+ *str = talloc_strndup_append(*str, piece, len);
+}
+
+START_TEST(test_safe_format_string_cb)
+{
+ const Fixture *fixture;
+ char *out;
+ int num_args;
+ int ret;
+ void *mem_ctx;
+
+ fixture = &fixtures[_i];
+ mem_ctx = talloc_init("safe-printf");
+
+ for (num_args = 0; fixture->args[num_args] != NULL; )
+ num_args++;
+
+ out = talloc_strdup(mem_ctx, "");
+ ret = safe_format_string_cb(callback, &out, fixture->format,
+ (const char * const*)fixture->args, num_args);
+ if (fixture->result) {
+ ck_assert_int_ge(ret, 0);
+ ck_assert_str_eq(out, fixture->result);
+ ck_assert_int_eq(ret, strlen(out));
+ } else {
+ ck_assert_int_lt(ret, 0);
+ }
+
+ talloc_free(mem_ctx);
+}
+END_TEST
+
+START_TEST(test_safe_format_string)
+{
+ char buffer[8];
+ int ret;
+
+ ret = safe_format_string(buffer, 8, "%s", "space", "man", NULL);
+ ck_assert_int_eq(ret, 5);
+ ck_assert_str_eq(buffer, "space");
+
+ ret = safe_format_string(buffer, 8, "", "space", "man", NULL);
+ ck_assert_int_eq(ret, 0);
+ ck_assert_str_eq(buffer, "");
+
+ ret = safe_format_string(buffer, 8, "the %s %s dances away", "space", "man", NULL);
+ ck_assert_int_eq(ret, 25);
+ ck_assert_str_eq(buffer, "the spa");
+
+ ret = safe_format_string(NULL, 0, "the %s %s dances away", "space", "man", NULL);
+ ck_assert_int_eq(ret, 25);
+
+ ret = safe_format_string(buffer, 8, "%5$s", NULL);
+ ck_assert_int_lt(ret, 0);
+}
+END_TEST
+
+static Suite *
+create_safe_format_suite(void)
+{
+ Suite *s = suite_create("safe-format");
+ TCase *tc_format = tcase_create("safe-format-string");
+
+ /* One for each fixture */
+ tcase_add_loop_test(tc_format, test_safe_format_string_cb, 0,
+ (sizeof (fixtures) / sizeof (fixtures[0])));
+
+ tcase_add_test(tc_format, test_safe_format_string);
+
+ suite_add_tcase(s, tc_format);
+
+ return s;
+}
+
+int
+main(int argc, const char *argv[])
+{
+ int opt;
+ poptContext pc;
+ int failure_count;
+ Suite *suite;
+ SRunner *sr;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_TABLEEND
+ };
+
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch(opt) {
+ default:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+ }
+ poptFreeContext(pc);
+
+ suite = create_safe_format_suite();
+ sr = srunner_create(suite);
+ /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
+ srunner_run_all(sr, CK_ENV);
+ failure_count = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}