1 #include <stic.h>
2
3 #include <sys/stat.h> /* chmod() */
4
5 #include <stdint.h> /* uint64_t */
6 #include <stdio.h> /* remove() rename() */
7 #include <string.h> /* strcmp() */
8
9 #include "../../src/io/iop.h"
10 #include "../../src/io/ior.h"
11 #include "../../src/utils/env.h"
12 #include "../../src/utils/fs.h"
13
14 #include "utils.h"
15
16 static IoErrCbResult ignore_errors(struct io_args_t *args,
17 const ioe_err_t *err);
18 static int can_rename_changing_case(void);
19
TEST(file_is_moved)20 TEST(file_is_moved)
21 {
22 create_empty_file(SANDBOX_PATH "/binary-data");
23
24 {
25 io_args_t args = {
26 .arg1.src = SANDBOX_PATH "/binary-data",
27 .arg2.dst = SANDBOX_PATH "/moved-binary-data",
28 };
29 assert_success(ior_mv(&args));
30 }
31
32 assert_false(file_exists(SANDBOX_PATH "/binary-data"));
33 assert_true(file_exists(SANDBOX_PATH "/moved-binary-data"));
34
35 remove(SANDBOX_PATH "/moved-binary-data");
36 }
37
TEST(empty_directory_is_moved)38 TEST(empty_directory_is_moved)
39 {
40 create_empty_dir(SANDBOX_PATH "/empty-dir");
41
42 {
43 io_args_t args = {
44 .arg1.src = SANDBOX_PATH "/empty-dir",
45 .arg2.dst = SANDBOX_PATH "/moved-empty-dir",
46 };
47 assert_success(ior_mv(&args));
48 }
49
50 assert_false(is_dir(SANDBOX_PATH "/empty-dir"));
51 assert_true(is_dir(SANDBOX_PATH "/moved-empty-dir"));
52
53 delete_dir(SANDBOX_PATH "/moved-empty-dir");
54 }
55
TEST(non_empty_directory_is_moved)56 TEST(non_empty_directory_is_moved)
57 {
58 create_non_empty_dir(SANDBOX_PATH "/non-empty-dir", "a-file");
59
60 {
61 io_args_t args = {
62 .arg1.src = SANDBOX_PATH "/non-empty-dir",
63 .arg2.dst = SANDBOX_PATH "/moved-non-empty-dir",
64 };
65 assert_success(ior_mv(&args));
66 }
67
68 assert_true(file_exists(SANDBOX_PATH "/moved-non-empty-dir/a-file"));
69
70 delete_tree(SANDBOX_PATH "/moved-non-empty-dir");
71 }
72
TEST(empty_nested_directory_is_moved)73 TEST(empty_nested_directory_is_moved)
74 {
75 create_empty_nested_dir(SANDBOX_PATH "/non-empty-dir", "empty-nested-dir");
76
77 {
78 io_args_t args = {
79 .arg1.src = SANDBOX_PATH "/non-empty-dir",
80 .arg2.dst = SANDBOX_PATH "/moved-non-empty-dir",
81 };
82 assert_success(ior_mv(&args));
83 }
84
85 assert_true(is_dir(SANDBOX_PATH "/moved-non-empty-dir/empty-nested-dir"));
86
87 delete_tree(SANDBOX_PATH "/moved-non-empty-dir");
88 }
89
TEST(non_empty_nested_directory_is_moved)90 TEST(non_empty_nested_directory_is_moved)
91 {
92 create_non_empty_nested_dir(SANDBOX_PATH "/non-empty-dir", "nested-dir",
93 "a-file");
94
95 {
96 io_args_t args = {
97 .arg1.src = SANDBOX_PATH "/non-empty-dir",
98 .arg2.dst = SANDBOX_PATH "/moved-non-empty-dir",
99 };
100 assert_success(ior_mv(&args));
101 }
102
103 assert_false(file_exists(SANDBOX_PATH "/non-empty-dir/nested-dir/a-file"));
104 assert_true(file_exists(SANDBOX_PATH
105 "/moved-non-empty-dir/nested-dir/a-file"));
106
107 delete_tree(SANDBOX_PATH "/moved-non-empty-dir");
108 }
109
TEST(fails_to_overwrite_file_by_default)110 TEST(fails_to_overwrite_file_by_default)
111 {
112 create_empty_file(SANDBOX_PATH "/a-file");
113
114 {
115 io_args_t args = {
116 .arg1.src = TEST_DATA_PATH "/read/two-lines",
117 .arg2.dst = SANDBOX_PATH "/a-file",
118 };
119 assert_failure(ior_mv(&args));
120 }
121
122 delete_file(SANDBOX_PATH "/a-file");
123 }
124
TEST(fails_to_overwrite_dir_by_default)125 TEST(fails_to_overwrite_dir_by_default)
126 {
127 create_empty_dir(SANDBOX_PATH "/empty-dir");
128
129 {
130 io_args_t args = {
131 .arg1.src = TEST_DATA_PATH "/read",
132 .arg2.dst = SANDBOX_PATH "/empty-dir",
133 };
134 assert_failure(ior_mv(&args));
135 }
136
137 delete_dir(SANDBOX_PATH "/empty-dir");
138 }
139
TEST(overwrites_file_when_asked)140 TEST(overwrites_file_when_asked)
141 {
142 create_empty_file(SANDBOX_PATH "/a-file");
143 clone_file(TEST_DATA_PATH "/read/two-lines", SANDBOX_PATH "/two-lines");
144
145 {
146 io_args_t args = {
147 .arg1.src = SANDBOX_PATH "/two-lines",
148 .arg2.dst = SANDBOX_PATH "/a-file",
149 .arg3.crs = IO_CRS_REPLACE_FILES,
150 };
151 assert_success(ior_mv(&args));
152 }
153
154 delete_file(SANDBOX_PATH "/a-file");
155 }
156
TEST(overwrites_dir_when_asked)157 TEST(overwrites_dir_when_asked)
158 {
159 create_empty_dir(SANDBOX_PATH "/dir");
160
161 {
162 io_args_t args = {
163 .arg1.src = TEST_DATA_PATH "/read",
164 .arg2.dst = SANDBOX_PATH "/read",
165 };
166 assert_success(ior_cp(&args));
167 }
168
169 assert_success(chmod(SANDBOX_PATH "/read", 0700));
170
171 {
172 io_args_t args = {
173 .arg1.src = SANDBOX_PATH "/read",
174 .arg2.dst = SANDBOX_PATH "/dir",
175 .arg3.crs = IO_CRS_REPLACE_ALL,
176 };
177 assert_success(ior_mv(&args));
178 }
179
180 {
181 io_args_t args = {
182 .arg1.path = SANDBOX_PATH "/dir",
183 };
184 assert_failure(iop_rmdir(&args));
185 }
186
187 delete_tree(SANDBOX_PATH "/dir");
188 }
189
TEST(appending_fails_for_directories)190 TEST(appending_fails_for_directories)
191 {
192 create_empty_dir(SANDBOX_PATH "/dir");
193
194 {
195 io_args_t args = {
196 .arg1.src = TEST_DATA_PATH "/read",
197 .arg2.dst = SANDBOX_PATH "/read",
198 };
199 assert_success(ior_cp(&args));
200 }
201
202 assert_success(chmod(SANDBOX_PATH "/read", 0700));
203
204 {
205 io_args_t args = {
206 .arg1.src = SANDBOX_PATH "/read",
207 .arg2.dst = SANDBOX_PATH "/dir",
208 .arg3.crs = IO_CRS_APPEND_TO_FILES,
209 };
210 assert_failure(ior_mv(&args));
211 }
212
213 delete_dir(SANDBOX_PATH "/dir");
214
215 delete_tree(SANDBOX_PATH "/read");
216 }
217
TEST(appending_works_for_files)218 TEST(appending_works_for_files)
219 {
220 uint64_t size;
221
222 clone_file(TEST_DATA_PATH "/read/two-lines", SANDBOX_PATH "/two-lines");
223
224 size = get_file_size(SANDBOX_PATH "/two-lines");
225
226 clone_file(TEST_DATA_PATH "/read/two-lines", SANDBOX_PATH "/two-lines2");
227
228 {
229 io_args_t args = {
230 .arg1.src = SANDBOX_PATH "/two-lines2",
231 .arg2.dst = SANDBOX_PATH "/two-lines",
232 .arg3.crs = IO_CRS_APPEND_TO_FILES,
233 };
234 assert_success(ior_mv(&args));
235 }
236
237 assert_int_equal(size, get_file_size(SANDBOX_PATH "/two-lines"));
238
239 delete_file(SANDBOX_PATH "/two-lines");
240 }
241
TEST(directories_can_be_merged)242 TEST(directories_can_be_merged)
243 {
244 create_empty_dir(SANDBOX_PATH "/first");
245 create_empty_file(SANDBOX_PATH "/first/first-file");
246
247 create_empty_dir(SANDBOX_PATH "/second");
248 create_empty_file(SANDBOX_PATH "/second/second-file");
249
250 {
251 io_args_t args = {
252 .arg1.src = SANDBOX_PATH "/first",
253 .arg2.dst = SANDBOX_PATH "/second",
254 .arg3.crs = IO_CRS_REPLACE_FILES,
255 };
256 assert_success(ior_mv(&args));
257 }
258
259 /* Original directory must be deleted. */
260 assert_false(file_exists(SANDBOX_PATH "/first"));
261
262 assert_true(file_exists(SANDBOX_PATH "/second/second-file"));
263 assert_true(file_exists(SANDBOX_PATH "/second/first-file"));
264
265 delete_tree(SANDBOX_PATH "/second");
266 }
267
TEST(nested_directories_can_be_merged)268 TEST(nested_directories_can_be_merged)
269 {
270 create_empty_dir(SANDBOX_PATH "/first");
271 create_empty_dir(SANDBOX_PATH "/first/nested");
272 create_empty_file(SANDBOX_PATH "/first/nested/first-file");
273
274 create_empty_dir(SANDBOX_PATH "/second");
275 create_empty_dir(SANDBOX_PATH "/second/nested");
276 create_empty_file(SANDBOX_PATH "/second/nested/second-file");
277
278 {
279 io_args_t args = {
280 .arg1.src = SANDBOX_PATH "/first",
281 .arg2.dst = SANDBOX_PATH "/second",
282 .arg3.crs = IO_CRS_REPLACE_FILES,
283 };
284 assert_success(ior_mv(&args));
285 }
286
287 /* Original directory must be deleted. */
288 assert_false(file_exists(SANDBOX_PATH "/first/nested"));
289 assert_false(file_exists(SANDBOX_PATH "/first"));
290
291 assert_true(file_exists(SANDBOX_PATH "/second/nested/second-file"));
292 assert_true(file_exists(SANDBOX_PATH "/second/nested/first-file"));
293
294 delete_tree(SANDBOX_PATH "/second");
295 }
296
TEST(fails_to_move_directory_inside_itself)297 TEST(fails_to_move_directory_inside_itself)
298 {
299 create_empty_dir(SANDBOX_PATH "/empty-dir");
300
301 {
302 io_args_t args = {
303 .arg1.src = SANDBOX_PATH "/empty-dir",
304 .arg2.dst = SANDBOX_PATH "/empty-dir/empty-dir-copy",
305 };
306 assert_failure(ior_mv(&args));
307 }
308
309 delete_dir(SANDBOX_PATH "/empty-dir");
310 }
311
312 /* Creating symbolic links on Windows requires administrator rights. */
TEST(symlink_is_symlink_after_move,IF (not_windows))313 TEST(symlink_is_symlink_after_move, IF(not_windows))
314 {
315 {
316 io_args_t args = {
317 .arg1.path = TEST_DATA_PATH "/read/two-lines",
318 .arg2.target = SANDBOX_PATH "/sym-link",
319 };
320 assert_success(iop_ln(&args));
321 }
322
323 assert_true(is_symlink(SANDBOX_PATH "/sym-link"));
324
325 {
326 io_args_t args = {
327 .arg1.src = SANDBOX_PATH "/sym-link",
328 .arg2.dst = SANDBOX_PATH "/moved-sym-link",
329 };
330 assert_success(ior_mv(&args));
331 }
332
333 assert_false(is_symlink(SANDBOX_PATH "/sym-link"));
334 assert_true(is_symlink(SANDBOX_PATH "/moved-sym-link"));
335
336 delete_file(SANDBOX_PATH "/moved-sym-link");
337 }
338
TEST(case_change_on_rename,IF (can_rename_changing_case))339 TEST(case_change_on_rename, IF(can_rename_changing_case))
340 {
341 create_empty_file(SANDBOX_PATH "/a-file");
342
343 {
344 io_args_t args = {
345 .arg1.src = SANDBOX_PATH "/a-file",
346 .arg2.dst = SANDBOX_PATH "/A-file",
347 };
348 assert_success(ior_mv(&args));
349 }
350
351 delete_file(SANDBOX_PATH "/A-file");
352 }
353
TEST(error_on_move_preserves_source_file,IF (not_windows))354 TEST(error_on_move_preserves_source_file, IF(not_windows))
355 {
356 io_args_t args = {
357 .arg1.src = SANDBOX_PATH "/file",
358 .arg2.dst = SANDBOX_PATH "/ro/file",
359
360 .result.errors = IOE_ERRLST_INIT,
361 .result.errors_cb = &ignore_errors,
362 };
363
364 create_empty_file(SANDBOX_PATH "/file");
365 create_empty_dir(SANDBOX_PATH "/ro");
366 assert_success(chmod(SANDBOX_PATH "/ro", 0500));
367
368 assert_success(ior_mv(&args));
369 assert_int_equal(1, args.result.errors.error_count);
370 ioe_errlst_free(&args.result.errors);
371
372 delete_file(SANDBOX_PATH "/file");
373 delete_dir(SANDBOX_PATH "/ro");
374 }
375
376 static IoErrCbResult
ignore_errors(struct io_args_t * args,const ioe_err_t * err)377 ignore_errors(struct io_args_t *args, const ioe_err_t *err)
378 {
379 return IO_ECR_IGNORE;
380 }
381
382 static int
can_rename_changing_case(void)383 can_rename_changing_case(void)
384 {
385 int ok;
386 create_empty_file(SANDBOX_PATH "/file");
387 ok = rename(SANDBOX_PATH "/file", SANDBOX_PATH "/FiLe") == 0;
388 if(ok)
389 {
390 delete_file(SANDBOX_PATH "/FiLe");
391 }
392 else
393 {
394 delete_file(SANDBOX_PATH "/file");
395 }
396 return ok;
397 }
398
399 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
400 /* vim: set cinoptions+=t0 filetype=c : */
401