1 /*-
2 * Copyright (c) 2025 Klara, Inc.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #ifndef FTS_TEST_H_INCLUDED
8 #define FTS_TEST_H_INCLUDED
9
10 struct fts_expect {
11 int fts_info;
12 const char *fts_name;
13 const char *fts_accpath;
14 };
15
16 struct fts_testcase {
17 char **paths;
18 int fts_options;
19 struct fts_expect *fts_expect;
20 };
21
22 /* shorter name for dead links */
23 #define FTS_DL FTS_SLNONE
24
25 /* are we being debugged? */
26 static bool fts_test_debug;
27
28 /*
29 * Set debug flag if appropriate.
30 */
31 static void
fts_check_debug(void)32 fts_check_debug(void)
33 {
34 fts_test_debug = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
35 isatty(STDERR_FILENO);
36 }
37
38 /*
39 * Lexical order for reproducability.
40 */
41 static int
fts_lexical_compar(const FTSENT * const * a,const FTSENT * const * b)42 fts_lexical_compar(const FTSENT * const *a, const FTSENT * const *b)
43 {
44 return (strcmp((*a)->fts_name, (*b)->fts_name));
45 }
46
47 /*
48 * Run FTS with the specified paths and options and verify that it
49 * produces the expected result in the correct order.
50 */
51 static void
fts_test(const struct atf_tc * tc,const struct fts_testcase * fts_tc)52 fts_test(const struct atf_tc *tc, const struct fts_testcase *fts_tc)
53 {
54 FTS *fts;
55 FTSENT *ftse;
56 const struct fts_expect *expect = fts_tc->fts_expect;
57 long level = 0;
58
59 fts = fts_open(fts_tc->paths, fts_tc->fts_options, fts_lexical_compar);
60 ATF_REQUIRE_MSG(fts != NULL, "fts_open(): %m");
61 while ((ftse = fts_read(fts)) != NULL && expect->fts_name != NULL) {
62 if (expect->fts_info == FTS_DP || expect->fts_info == FTS_DNR)
63 level--;
64 if (fts_test_debug) {
65 fprintf(stderr, "%2ld %2d %s\n", level,
66 ftse->fts_info, ftse->fts_name);
67 }
68 ATF_CHECK_STREQ(expect->fts_name, ftse->fts_name);
69 ATF_CHECK_STREQ(expect->fts_accpath, ftse->fts_accpath);
70 ATF_CHECK_INTEQ(expect->fts_info, ftse->fts_info);
71 ATF_CHECK_INTEQ(level, ftse->fts_level);
72 if (expect->fts_info == FTS_D)
73 level++;
74 expect++;
75 }
76 ATF_CHECK_EQ(NULL, ftse);
77 ATF_CHECK_EQ(NULL, expect->fts_name);
78 ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m");
79 }
80
81 #endif /* FTS_TEST_H_INCLUDED */
82