xref: /freebsd/bin/mv/tests/mv_test.sh (revision d4fb5984ab0b96cc784c907e622deda910d020f2)
1 #
2 # Copyright (c) 2007 Diomidis Spinellis
3 # Copyright (c) 2023 Klara, Inc.
4 #
5 # SPDX-License-Identifier: BSD-2-Clause
6 #
7 
8 mv_setup() {
9 	atf_check mkdir fs
10 	atf_check mount -t tmpfs -o size=1m tmp fs
11 }
12 
13 mv_cleanup() {
14 	umount fs || true
15 }
16 
17 # Make a file that can later be verified
18 mv_makefile() {
19 	local cn="${1##*/}"
20 	echo "$cn-$cn" >"$1"
21 }
22 
23 # Verify that the file specified is correct
24 mv_checkfile() {
25 	atf_check -o inline:"$1-$1\n" cat "$2"
26 }
27 
28 # Make a fifo that can later be verified
29 mv_makepipe() {
30 	atf_check mkfifo $1
31 }
32 
33 # Verify that the file specified is correct
34 mv_checkpipe() {
35 	atf_check test -p "$2"
36 }
37 
38 # Make a directory that can later be verified
39 mv_makedir() {
40 	local cn="${1##*/}"
41 	atf_check mkdir -p "$1/$cn-$cn"
42 }
43 
44 # Verify that the directory specified is correct
45 mv_checkdir() {
46 	atf_check test -d "$2/$1-$1"
47 }
48 
49 # Verify that the specified file does not exist
50 # (is not there)
51 mv_checkabsent() {
52 	atf_check -s exit:1 test -r "$1"
53 }
54 
55 atf_test_case rename_file cleanup
56 rename_file_head() {
57 	atf_set "descr" "Rename file"
58 	atf_set "require.user" "root"
59 }
60 rename_file_body() {
61 	mv_setup
62 	for FS in "" "fs/" ; do
63 		mv_makefile fa
64 		atf_check mv fa ${FS}fb
65 		mv_checkfile fa ${FS}fb
66 		mv_checkabsent fa
67 	done
68 }
69 rename_file_cleanup() {
70 	mv_cleanup
71 }
72 
73 atf_test_case file_into_dir cleanup
74 file_into_dir_head() {
75 	atf_set "descr" "Move files into directory"
76 	atf_set "require.user" "root"
77 }
78 file_into_dir_body() {
79 	mv_setup
80 	for FS in "" "fs/" ; do
81 		mv_makefile fa
82 		mv_makefile fb
83 		atf_check mkdir -p ${FS}1/2/3
84 		atf_check mv fa fb ${FS}1/2/3
85 		mv_checkfile fa ${FS}1/2/3/fa
86 		mv_checkfile fb ${FS}1/2/3/fb
87 		mv_checkabsent fa
88 		mv_checkabsent fb
89 	done
90 }
91 file_into_dir_cleanup() {
92 	mv_cleanup
93 }
94 
95 atf_test_case file_from_dir cleanup
96 file_from_dir_head() {
97 	atf_set "descr" "Move file from directory to file"
98 	atf_set "require.user" "root"
99 }
100 file_from_dir_body() {
101 	mv_setup
102 	atf_check mkdir -p 1/2/3
103 	for FS in "" "fs/" ; do
104 		mv_makefile 1/2/3/fa
105 		atf_check mv 1/2/3/fa ${FS}fb
106 		mv_checkfile fa ${FS}fb
107 		mv_checkabsent 1/2/3/fa
108 	done
109 }
110 file_from_dir_cleanup() {
111 	mv_cleanup
112 }
113 
114 atf_test_case file_from_dir_replace cleanup
115 file_from_dir_replace_head() {
116 	atf_set "descr" "Move file from directory to existing file"
117 	atf_set "require.user" "root"
118 }
119 file_from_dir_replace_body() {
120 	mv_setup
121 	atf_check mkdir -p 1/2/3
122 	for FS in "" "fs/" ; do
123 		mv_makefile 1/2/3/fa
124 		:> ${FS}fb
125 		atf_check mv 1/2/3/fa ${FS}fb
126 		mv_checkfile fa ${FS}fb
127 		mv_checkabsent 1/2/3/fa
128 	done
129 }
130 file_from_dir_replace_cleanup() {
131 	mv_cleanup
132 }
133 
134 atf_test_case file_to_dir cleanup
135 file_to_dir_head() {
136 	atf_set "descr" "Move file from directory to existing directory"
137 	atf_set "require.user" "root"
138 }
139 file_to_dir_body() {
140 	mv_setup
141 	atf_check mkdir -p 1/2/3
142 	for FS in "" "fs/" ; do
143 		mv_makefile 1/2/3/fa
144 		atf_check mkdir -p ${FS}db/fa
145 		# Should fail per POSIX step 3a:
146 		# Destination path is a file of type directory and
147 		# source_file is not a file of type directory
148 		atf_check -s not-exit:0 -e match:"Is a directory" \
149 		      mv 1/2/3/fa ${FS}db
150 		mv_checkfile fa 1/2/3/fa
151 	done
152 }
153 file_to_dir_cleanup() {
154 	mv_cleanup
155 }
156 
157 atf_test_case file_from_rename_dir cleanup
158 file_from_rename_dir_head() {
159 	atf_set "descr" "Move file from directory to directory"
160 	atf_set "require.user" "root"
161 }
162 file_from_rename_dir_body() {
163 	mv_setup
164 	atf_check mkdir -p da1/da2/da3
165 	for FS in "" "fs/" ; do
166 		atf_check mkdir -p ${FS}db1/db2/db3
167 		mv_makefile da1/da2/da3/fa
168 		atf_check mv da1/da2/da3/fa ${FS}db1/db2/db3/fb
169 		mv_checkfile fa ${FS}db1/db2/db3/fb
170 		mv_checkabsent da1/da2/da3/fa
171 	done
172 }
173 file_from_rename_dir_cleanup() {
174 	mv_cleanup
175 }
176 
177 atf_test_case rename_dir cleanup
178 rename_dir_head() {
179 	atf_set "descr" "Rename directory"
180 	atf_set "require.user" "root"
181 }
182 rename_dir_body() {
183 	mv_setup
184 	for FS in "" "fs/" ; do
185 		mv_makedir da
186 		atf_check mv da ${FS}db
187 		mv_checkdir da ${FS}db
188 		mv_checkabsent da
189 	done
190 }
191 rename_dir_cleanup() {
192 	mv_cleanup
193 }
194 
195 atf_test_case dir_to_dir cleanup
196 dir_to_dir_head() {
197 	atf_set "descr" "Move directory to directory name"
198 	atf_set "require.user" "root"
199 }
200 dir_to_dir_body() {
201 	mv_setup
202 	for FS in "" "fs/" ; do
203 		mv_makedir da1/da2/da3/da
204 		atf_check mkdir -p ${FS}db1/db2/db3
205 		atf_check mv da1/da2/da3/da ${FS}db1/db2/db3/db
206 		mv_checkdir da ${FS}db1/db2/db3/db
207 		mv_checkabsent da1/da2/da3/da
208 	done
209 }
210 dir_to_dir_cleanup() {
211 	mv_cleanup
212 }
213 
214 atf_test_case dir_into_dir cleanup
215 dir_into_dir_head() {
216 	atf_set "descr" "Move directory to directory"
217 	atf_set "require.user" "root"
218 }
219 dir_into_dir_body() {
220 	mv_setup
221 	for FS in "" "fs/" ; do
222 		mv_makedir da1/da2/da3/da
223 		atf_check mkdir -p ${FS}db1/db2/db3
224 		atf_check mv da1/da2/da3/da ${FS}db1/db2/db3
225 		mv_checkdir da ${FS}db1/db2/db3/da
226 		mv_checkabsent da1/da2/da3/da
227 	done
228 }
229 dir_into_dir_cleanup() {
230 	mv_cleanup
231 }
232 
233 atf_test_case dir_to_empty_dir cleanup
234 dir_to_empty_dir_head() {
235 	atf_set "descr" "Move directory to existing empty directory"
236 	atf_set "require.user" "root"
237 }
238 dir_to_empty_dir_body() {
239 	mv_setup
240 	for FS in "" "fs/" ; do
241 		mv_makedir da1/da2/da3/da
242 		atf_check mkdir -p ${FS}db1/db2/db3/da
243 		atf_check mv da1/da2/da3/da ${FS}db1/db2/db3
244 		mv_checkdir da ${FS}db1/db2/db3/da
245 		mv_checkabsent da1/da2/da3/da
246 	done
247 }
248 dir_to_empty_dir_cleanup() {
249 	mv_cleanup
250 }
251 
252 atf_test_case dir_to_nonempty_dir cleanup
253 dir_to_nonempty_dir_head() {
254 	atf_set "descr" "Move directory to existing non-empty directory"
255 	atf_set "require.user" "root"
256 }
257 dir_to_nonempty_dir_body() {
258 	mv_setup
259 	for FS in "" "fs/" ; do
260 		mv_makedir da1/da2/da3/da
261 		atf_check mkdir -p ${FS}db1/db2/db3/da/full
262 		# Should fail (per the semantics of rename(2))
263 		atf_check -s not-exit:0 -e match:"Directory not empty" \
264 		      mv da1/da2/da3/da ${FS}db1/db2/db3
265 		mv_checkdir da da1/da2/da3/da
266 	done
267 }
268 dir_to_nonempty_dir_cleanup() {
269 	mv_cleanup
270 }
271 
272 atf_test_case dir_to_file cleanup
273 dir_to_file_head() {
274 	atf_set "descr" "Move directory to existing file"
275 	atf_set "require.user" "root"
276 }
277 dir_to_file_body() {
278 	mv_setup
279 	for FS in "" "fs/" ; do
280 		mv_makedir da1/da2/da3/da
281 		atf_check mkdir -p ${FS}db1/db2/db3
282 		:> ${FS}db1/db2/db3/da
283 		# Should fail per POSIX step 3b:
284 		# Destination path is a file not of type directory
285 		# and source_file is a file of type directory
286 		atf_check -s not-exit:0 -e match:"Not a directory" \
287 		      mv da1/da2/da3/da ${FS}db1/db2/db3/da
288 		mv_checkdir da da1/da2/da3/da
289 	done
290 }
291 dir_to_file_cleanup() {
292 	mv_cleanup
293 }
294 
295 atf_test_case rename_fifo cleanup
296 rename_fifo_head() {
297 	atf_set "descr" "Rename fifo"
298 	atf_set "require.user" "root"
299 }
300 rename_fifo_body() {
301 	mv_setup
302 	for FS in "" "fs/" ; do
303 		mv_makepipe fa
304 		atf_check mv fa ${FS}fb
305 		mv_checkpipe fa ${FS}fb
306 		mv_checkabsent fa
307 	done
308 }
309 rename_fifo_cleanup() {
310 	mv_cleanup
311 }
312 
313 atf_test_case fifo_into_dir cleanup
314 fifo_into_dir_head() {
315 	atf_set "descr" "Move fifos into directory"
316 	atf_set "require.user" "root"
317 }
318 fifo_into_dir_body() {
319 	mv_setup
320 	for FS in "" "fs/" ; do
321 		mv_makepipe fa
322 		mv_makepipe fb
323 		atf_check mkdir -p ${FS}1/2/3
324 		atf_check mv fa fb ${FS}1/2/3
325 		mv_checkpipe fa ${FS}1/2/3/fa
326 		mv_checkpipe fb ${FS}1/2/3/fb
327 		mv_checkabsent fa
328 		mv_checkabsent fb
329 	done
330 }
331 fifo_into_dir_cleanup() {
332 	mv_cleanup
333 }
334 
335 atf_test_case fifo_from_dir cleanup
336 fifo_from_dir_head() {
337 	atf_set "descr" "Move fifo from directory to fifo"
338 	atf_set "require.user" "root"
339 }
340 fifo_from_dir_body() {
341 	mv_setup
342 	atf_check mkdir -p 1/2/3
343 	for FS in "" "fs/" ; do
344 		mv_makepipe 1/2/3/fa
345 		atf_check mv 1/2/3/fa ${FS}fb
346 		mv_checkpipe fa ${FS}fb
347 		mv_checkabsent 1/2/3/fa
348 	done
349 }
350 fifo_from_dir_cleanup() {
351 	mv_cleanup
352 }
353 
354 atf_test_case fifo_from_dir_into_dir cleanup
355 fifo_from_dir_into_dir_head() {
356 	atf_set "descr" "Move fifo from directory to directory"
357 	atf_set "require.user" "root"
358 }
359 fifo_from_dir_into_dir_body() {
360 	mv_setup
361 	atf_check mkdir -p da1/da2/da3
362 	for FS in "" "fs/" ; do
363 		atf_check mkdir -p ${FS}db1/db2/db3
364 		mv_makepipe da1/da2/da3/fa
365 		atf_check mv da1/da2/da3/fa ${FS}db1/db2/db3/fb
366 		mv_checkpipe fa ${FS}db1/db2/db3/fb
367 		mv_checkabsent da1/da2/da3/fa
368 	done
369 }
370 fifo_from_dir_into_dir_cleanup() {
371 	mv_cleanup
372 }
373 
374 atf_test_case mv_f cleanup
375 mv_f_head() {
376 	atf_set "descr" "Force replacement"
377 	atf_set "require.user" "root"
378 }
379 mv_f_body() {
380 	mv_setup
381 	for FS in "" "fs/" ; do
382 		mv_makefile fa
383 		atf_check mv fa ${FS}fb
384 		mv_checkfile fa ${FS}fb
385 		mv_checkabsent fa
386 		mv_makefile fa
387 		:> ${FS}fb
388 		atf_check mv -i -n -f fa ${FS}fb
389 		mv_checkfile fa ${FS}fb
390 		mv_checkabsent fa
391 	done
392 }
393 mv_f_cleanup() {
394 	mv_cleanup
395 }
396 
397 atf_test_case mv_h cleanup
398 mv_h_head() {
399 	atf_set "descr" "Replace symbolic link"
400 	atf_set "require.user" "root"
401 }
402 mv_h_body() {
403 	mv_setup
404 	for FS in "" "fs/" ; do
405 		atf_check mkdir ${FS}da
406 		atf_check ln -s da ${FS}db
407 		# First test without -h, file goes into symlink target
408 		mv_makefile fa
409 		atf_check mv fa ${FS}db
410 		mv_checkfile fa ${FS}da/fa
411 		# Second test with -h, file replaces symlink
412 		mv_makefile fa
413 		atf_check mv -h fa ${FS}db
414 		mv_checkfile fa ${FS}db
415 	done
416 }
417 mv_h_cleanup() {
418 	mv_cleanup
419 }
420 
421 atf_test_case mv_i cleanup
422 mv_i_head() {
423 	atf_set "descr" "Confirm replacement"
424 	atf_set "require.user" "root"
425 }
426 mv_i_body() {
427 	mv_setup
428 	echo n >n
429 	echo y >y
430 	for FS in "" "fs/" ; do
431 		mv_makefile fa
432 		mv_makefile ${FS}fb
433 		# First test, answer no, file is not replaced
434 		atf_check -e match:"^overwrite ${FS}fb\\?" \
435 		      mv -i fa ${FS}fb <n
436 		mv_checkfile fa fa
437 		mv_checkfile fb ${FS}fb
438 		# Second test, answer yes, file is replaced
439 		atf_check -e match:"^overwrite ${FS}fb\\?" \
440 		      mv -i fa ${FS}fb <y
441 		mv_checkabsent fa
442 		mv_checkfile fa ${FS}fb
443 	done
444 }
445 mv_i_cleanup() {
446 	mv_cleanup
447 }
448 
449 atf_test_case mv_n cleanup
450 mv_n_head() {
451 	atf_set "descr" "Decline replacement"
452 	atf_set "require.user" "root"
453 }
454 mv_n_body() {
455 	mv_setup
456 	for FS in "" "fs/" ; do
457 		mv_makefile fa
458 		mv_makefile ${FS}fb
459 		atf_check mv -n fa ${FS}fb
460 		mv_checkfile fa fa
461 		mv_checkfile fb ${FS}fb
462 	done
463 }
464 mv_n_cleanup() {
465 	mv_cleanup
466 }
467 
468 atf_test_case mv_v cleanup
469 mv_v_head() {
470 	atf_set "descr" "Verbose mode"
471 	atf_set "require.user" "root"
472 }
473 mv_v_body() {
474 	mv_setup
475 	for FS in "" "fs/" ; do
476 		mv_makefile fa
477 		atf_check mkdir ${FS}da
478 		atf_check -o inline:"fa -> ${FS}da/fa\n" \
479 		      mv -v fa ${FS}da
480 	done
481 }
482 mv_v_cleanup() {
483 	mv_cleanup
484 }
485 
486 atf_init_test_cases() {
487 	atf_add_test_case rename_file
488 	atf_add_test_case file_into_dir
489 	atf_add_test_case file_from_dir
490 	atf_add_test_case file_from_dir_replace
491 	atf_add_test_case file_to_dir
492 	atf_add_test_case file_from_rename_dir
493 	atf_add_test_case rename_dir
494 	atf_add_test_case dir_to_dir
495 	atf_add_test_case dir_into_dir
496 	atf_add_test_case dir_to_empty_dir
497 	atf_add_test_case dir_to_nonempty_dir
498 	atf_add_test_case dir_to_file
499 	atf_add_test_case rename_fifo
500 	atf_add_test_case fifo_into_dir
501 	atf_add_test_case fifo_from_dir
502 	atf_add_test_case fifo_from_dir_into_dir
503 	atf_add_test_case mv_f
504 	atf_add_test_case mv_h
505 	atf_add_test_case mv_i
506 	atf_add_test_case mv_n
507 	atf_add_test_case mv_v
508 }
509