xref: /freebsd/lib/libc/tests/gen/fts_blocks_test.c (revision 92f340d137ba5d6db7610ba1dae35842e2c9c8ea)
1 /*-
2  * Copyright (c) 2025 Klara, Inc.
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <sys/stat.h>
8 
9 #include <fcntl.h>
10 #include <fts.h>
11 
12 #include <atf-c.h>
13 
14 /*
15  * Create two directories with three files each in lexicographical order,
16  * then call FTS with a sort block that sorts in reverse lexicographical
17  * order.  This has the least chance of getting a false positive due to
18  * differing file system semantics.  UFS will return the files in the
19  * order they were created while ZFS will sort them lexicographically; in
20  * both cases, the order we expect is the reverse.
21  */
22 ATF_TC_WITHOUT_HEAD(fts_blocks_test);
23 ATF_TC_BODY(fts_blocks_test, tc)
24 {
25 	char *args[] = {
26 		"bar", "foo", NULL
27 	};
28 	char *paths[] = {
29 		"foo", "z", "y", "x", "foo",
30 		"bar", "c", "b", "a", "bar",
31 		NULL
32 	};
33 	char **expect = paths;
34 	FTS *fts;
35 	FTSENT *ftse;
36 
37 	ATF_REQUIRE_EQ(0, mkdir("bar", 0755));
38 	ATF_REQUIRE_EQ(0, close(creat("bar/a", 0644)));
39 	ATF_REQUIRE_EQ(0, close(creat("bar/b", 0644)));
40 	ATF_REQUIRE_EQ(0, close(creat("bar/c", 0644)));
41 	ATF_REQUIRE_EQ(0, mkdir("foo", 0755));
42 	ATF_REQUIRE_EQ(0, close(creat("foo/x", 0644)));
43 	ATF_REQUIRE_EQ(0, close(creat("foo/y", 0644)));
44 	ATF_REQUIRE_EQ(0, close(creat("foo/z", 0644)));
45 	fts = fts_open_b(args, 0,
46 	    ^(const FTSENT * const *a, const FTSENT * const *b) {
47 		    return (strcmp((*b)->fts_name, (*a)->fts_name));
48 	    });
49 	ATF_REQUIRE_MSG(fts != NULL, "fts_open_b(): %m");
50 	while ((ftse = fts_read(fts)) != NULL && *expect != NULL) {
51 		ATF_CHECK_STREQ(*expect, ftse->fts_name);
52 		expect++;
53 	}
54 	ATF_CHECK_EQ(NULL, ftse);
55 	ATF_CHECK_EQ(NULL, *expect);
56 	ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m");
57 }
58 
59 ATF_TP_ADD_TCS(tp)
60 {
61 	ATF_TP_ADD_TC(tp, fts_blocks_test);
62 	return (atf_no_error());
63 }
64