1 /* Test for <file_change_detection.c>.
2 Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <file_change_detection.h>
21 #include <array_length.h>
23 #include <support/check.h>
24 #include <support/support.h>
25 #include <support/temp_file.h>
26 #include <support/test-driver.h>
27 #include <support/xstdio.h>
28 #include <support/xunistd.h>
32 all_same (struct file_change_detection
*array
, size_t length
)
34 for (size_t i
= 0; i
< length
; ++i
)
35 for (size_t j
= 0; j
< length
; ++j
)
38 printf ("info: comparing %zu and %zu\n", i
, j
);
39 TEST_VERIFY (__file_is_unchanged (array
+ i
, array
+ j
));
44 all_different (struct file_change_detection
*array
, size_t length
)
46 for (size_t i
= 0; i
< length
; ++i
)
47 for (size_t j
= 0; j
< length
; ++j
)
52 printf ("info: comparing %zu and %zu\n", i
, j
);
53 TEST_VERIFY (!__file_is_unchanged (array
+ i
, array
+ j
));
60 /* Use a temporary directory with various paths. */
61 char *tempdir
= support_create_temp_directory ("tst-file_change_detection-");
63 char *path_dangling
= xasprintf ("%s/dangling", tempdir
);
64 char *path_does_not_exist
= xasprintf ("%s/does-not-exist", tempdir
);
65 char *path_empty1
= xasprintf ("%s/empty1", tempdir
);
66 char *path_empty2
= xasprintf ("%s/empty2", tempdir
);
67 char *path_fifo
= xasprintf ("%s/fifo", tempdir
);
68 char *path_file1
= xasprintf ("%s/file1", tempdir
);
69 char *path_file2
= xasprintf ("%s/file2", tempdir
);
70 char *path_loop
= xasprintf ("%s/loop", tempdir
);
71 char *path_to_empty1
= xasprintf ("%s/to-empty1", tempdir
);
72 char *path_to_file1
= xasprintf ("%s/to-file1", tempdir
);
74 add_temp_file (path_dangling
);
75 add_temp_file (path_empty1
);
76 add_temp_file (path_empty2
);
77 add_temp_file (path_fifo
);
78 add_temp_file (path_file1
);
79 add_temp_file (path_file2
);
80 add_temp_file (path_loop
);
81 add_temp_file (path_to_empty1
);
82 add_temp_file (path_to_file1
);
84 xsymlink ("target-does-not-exist", path_dangling
);
85 support_write_file_string (path_empty1
, "");
86 support_write_file_string (path_empty2
, "");
87 TEST_COMPARE (mknod (path_fifo
, 0777 | S_IFIFO
, 0), 0);
88 support_write_file_string (path_file1
, "line\n");
89 support_write_file_string (path_file2
, "line\n");
90 xsymlink ("loop", path_loop
);
91 xsymlink ("empty1", path_to_empty1
);
92 xsymlink ("file1", path_to_file1
);
94 FILE *fp_file1
= xfopen (path_file1
, "r");
95 FILE *fp_file2
= xfopen (path_file2
, "r");
96 FILE *fp_empty1
= xfopen (path_empty1
, "r");
97 FILE *fp_empty2
= xfopen (path_empty2
, "r");
99 /* Test for the same (empty) files. */
101 struct file_change_detection fcd
[10];
103 /* Two empty files always have the same contents. */
104 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_empty1
));
105 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_empty2
));
106 /* So does a missing file (which is treated as empty). */
107 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++],
108 path_does_not_exist
));
109 /* And a symbolic link loop. */
110 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_loop
));
111 /* And a dangling symbolic link. */
112 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_dangling
));
113 /* And a directory. */
114 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], tempdir
));
115 /* And a symbolic link to an empty file. */
116 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_to_empty1
));
117 /* Likewise for access the file via a FILE *. */
118 TEST_VERIFY (__file_change_detection_for_fp (&fcd
[i
++], fp_empty1
));
119 TEST_VERIFY (__file_change_detection_for_fp (&fcd
[i
++], fp_empty2
));
120 /* And a NULL FILE * (missing file). */
121 TEST_VERIFY (__file_change_detection_for_fp (&fcd
[i
++], NULL
));
122 TEST_COMPARE (i
, array_length (fcd
));
124 all_same (fcd
, array_length (fcd
));
127 /* Symbolic links are resolved. */
129 struct file_change_detection fcd
[3];
131 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_file1
));
132 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_to_file1
));
133 TEST_VERIFY (__file_change_detection_for_fp (&fcd
[i
++], fp_file1
));
134 TEST_COMPARE (i
, array_length (fcd
));
135 all_same (fcd
, array_length (fcd
));
138 /* Test for different files. */
140 struct file_change_detection fcd
[5];
142 /* The other files are not empty. */
143 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_empty1
));
144 /* These two files have the same contents, but have different file
146 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_file1
));
147 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_file2
));
148 /* FIFOs are always different, even with themselves. */
149 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_fifo
));
150 TEST_VERIFY (__file_change_detection_for_path (&fcd
[i
++], path_fifo
));
151 TEST_COMPARE (i
, array_length (fcd
));
152 all_different (fcd
, array_length (fcd
));
154 /* Replacing the file with its symbolic link does not make a
156 TEST_VERIFY (__file_change_detection_for_path (&fcd
[1], path_to_file1
));
157 all_different (fcd
, array_length (fcd
));
160 /* Wait for a file change. Depending on file system time stamp
161 resolution, this subtest blocks for a while. */
162 for (int use_stdio
= 0; use_stdio
< 2; ++use_stdio
)
164 struct file_change_detection initial
;
165 TEST_VERIFY (__file_change_detection_for_path (&initial
, path_file1
));
168 support_write_file_string (path_file1
, "line\n");
169 struct file_change_detection current
;
171 TEST_VERIFY (__file_change_detection_for_fp (¤t
, fp_file1
));
173 TEST_VERIFY (__file_change_detection_for_path
174 (¤t
, path_file1
));
175 if (!__file_is_unchanged (&initial
, ¤t
))
177 /* Wait for a bit to reduce system load. */
187 free (path_dangling
);
188 free (path_does_not_exist
);
195 free (path_to_empty1
);
196 free (path_to_file1
);
203 #include <support/test-driver.c>