aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/tests/gen/fts_test.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/tests/gen/fts_test.h')
-rw-r--r--lib/libc/tests/gen/fts_test.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/libc/tests/gen/fts_test.h b/lib/libc/tests/gen/fts_test.h
new file mode 100644
index 000000000000..b3f15050f265
--- /dev/null
+++ b/lib/libc/tests/gen/fts_test.h
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 2025 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef FTS_TEST_H_INCLUDED
+#define FTS_TEST_H_INCLUDED
+
+struct fts_expect {
+ int fts_info;
+ const char *fts_name;
+ const char *fts_accpath;
+};
+
+struct fts_testcase {
+ char **paths;
+ int fts_options;
+ struct fts_expect *fts_expect;
+};
+
+/* shorter name for dead links */
+#define FTS_DL FTS_SLNONE
+
+/* are we being debugged? */
+static bool fts_test_debug;
+
+/*
+ * Set debug flag if appropriate.
+ */
+static void
+fts_check_debug(void)
+{
+ fts_test_debug = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
+ isatty(STDERR_FILENO);
+}
+
+/*
+ * Lexical order for reproducability.
+ */
+static int
+fts_lexical_compar(const FTSENT * const *a, const FTSENT * const *b)
+{
+ return (strcmp((*a)->fts_name, (*b)->fts_name));
+}
+
+/*
+ * Run FTS with the specified paths and options and verify that it
+ * produces the expected result in the correct order.
+ */
+static void
+fts_test(const struct atf_tc *tc, const struct fts_testcase *fts_tc)
+{
+ FTS *fts;
+ FTSENT *ftse;
+ const struct fts_expect *expect = fts_tc->fts_expect;
+ long level = 0;
+
+ fts = fts_open(fts_tc->paths, fts_tc->fts_options, fts_lexical_compar);
+ ATF_REQUIRE_MSG(fts != NULL, "fts_open(): %m");
+ while ((ftse = fts_read(fts)) != NULL && expect->fts_name != NULL) {
+ if (expect->fts_info == FTS_DP || expect->fts_info == FTS_DNR)
+ level--;
+ if (fts_test_debug) {
+ fprintf(stderr, "%2ld %2d %s\n", level,
+ ftse->fts_info, ftse->fts_name);
+ }
+ ATF_CHECK_STREQ(expect->fts_name, ftse->fts_name);
+ ATF_CHECK_STREQ(expect->fts_accpath, ftse->fts_accpath);
+ ATF_CHECK_INTEQ(expect->fts_info, ftse->fts_info);
+ ATF_CHECK_INTEQ(level, ftse->fts_level);
+ if (expect->fts_info == FTS_D)
+ level++;
+ expect++;
+ }
+ ATF_CHECK_EQ(NULL, ftse);
+ ATF_CHECK_EQ(NULL, expect->fts_name);
+ ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m");
+}
+
+#endif /* FTS_TEST_H_INCLUDED */