xref: /freebsd/bin/cp/tests/cp_test.sh (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1#
2# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3#
4# Copyright (c) 2020 Kyle Evans <kevans@FreeBSD.org>
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28
29check_size()
30{
31	file=$1
32	sz=$2
33
34	atf_check -o inline:"$sz\n" stat -f '%z' $file
35}
36
37atf_test_case basic
38basic_body()
39{
40	echo "foo" > bar
41
42	atf_check cp bar baz
43	check_size baz 4
44}
45
46atf_test_case basic_symlink
47basic_symlink_body()
48{
49	echo "foo" > bar
50	ln -s bar baz
51
52	atf_check cp baz foo
53	atf_check test '!' -L foo
54
55	atf_check -e inline:"cp: baz and baz are identical (not copied).\n" \
56	    -s exit:1 cp baz baz
57	atf_check -e inline:"cp: bar and baz are identical (not copied).\n" \
58	    -s exit:1 cp baz bar
59}
60
61atf_test_case chrdev
62chrdev_body()
63{
64	echo "foo" > bar
65
66	check_size bar 4
67	atf_check cp /dev/null trunc
68	check_size trunc 0
69	atf_check cp bar trunc
70	check_size trunc 4
71	atf_check cp /dev/null trunc
72	check_size trunc 0
73}
74
75atf_test_case matching_srctgt
76matching_srctgt_body()
77{
78
79	# PR235438: `cp -R foo foo` would previously infinitely recurse and
80	# eventually error out.
81	mkdir foo
82	echo "qux" > foo/bar
83	cp foo/bar foo/zoo
84
85	atf_check cp -R foo foo
86	atf_check -o inline:"qux\n" cat foo/foo/bar
87	atf_check -o inline:"qux\n" cat foo/foo/zoo
88	atf_check -e not-empty -s not-exit:0 stat foo/foo/foo
89}
90
91atf_test_case matching_srctgt_contained
92matching_srctgt_contained_body()
93{
94
95	# Let's do the same thing, except we'll try to recursively copy foo into
96	# one of its subdirectories.
97	mkdir foo
98	ln -s foo coo
99	echo "qux" > foo/bar
100	mkdir foo/moo
101	touch foo/moo/roo
102	cp foo/bar foo/zoo
103
104	atf_check cp -R foo foo/moo
105	atf_check cp -RH coo foo/moo
106	atf_check -o inline:"qux\n" cat foo/moo/foo/bar
107	atf_check -o inline:"qux\n" cat foo/moo/coo/bar
108	atf_check -o inline:"qux\n" cat foo/moo/foo/zoo
109	atf_check -o inline:"qux\n" cat foo/moo/coo/zoo
110
111	# We should have copied the contents of foo/moo before foo, coo started
112	# getting copied in.
113	atf_check -o not-empty stat foo/moo/foo/moo/roo
114	atf_check -o not-empty stat foo/moo/coo/moo/roo
115	atf_check -e not-empty -s not-exit:0 stat foo/moo/foo/moo/foo
116	atf_check -e not-empty -s not-exit:0 stat foo/moo/coo/moo/coo
117}
118
119atf_test_case matching_srctgt_link
120matching_srctgt_link_body()
121{
122
123	mkdir foo
124	echo "qux" > foo/bar
125	cp foo/bar foo/zoo
126
127	atf_check ln -s foo roo
128	atf_check cp -RH roo foo
129	atf_check -o inline:"qux\n" cat foo/roo/bar
130	atf_check -o inline:"qux\n" cat foo/roo/zoo
131}
132
133atf_test_case matching_srctgt_nonexistent
134matching_srctgt_nonexistent_body()
135{
136
137	# We'll copy foo to a nonexistent subdirectory; ideally, we would
138	# skip just the directory and end up with a layout like;
139	#
140	# foo/
141	#     bar
142	#     dne/
143	#         bar
144	#         zoo
145	#     zoo
146	#
147	mkdir foo
148	echo "qux" > foo/bar
149	cp foo/bar foo/zoo
150
151	atf_check cp -R foo foo/dne
152	atf_check -o inline:"qux\n" cat foo/dne/bar
153	atf_check -o inline:"qux\n" cat foo/dne/zoo
154	atf_check -e not-empty -s not-exit:0 stat foo/dne/foo
155}
156
157recursive_link_setup()
158{
159	extra_cpflag=$1
160
161	mkdir -p foo/bar
162	ln -s bar foo/baz
163
164	mkdir foo-mirror
165	eval "cp -R $extra_cpflag foo foo-mirror"
166}
167
168atf_test_case recursive_link_dflt
169recursive_link_dflt_body()
170{
171	recursive_link_setup
172
173	# -P is the default, so this should work and preserve the link.
174	atf_check cp -R foo foo-mirror
175	atf_check test -L foo-mirror/foo/baz
176}
177
178atf_test_case recursive_link_Hflag
179recursive_link_Hflag_body()
180{
181	recursive_link_setup
182
183	# -H will not follow either, so this should also work and preserve the
184	# link.
185	atf_check cp -RH foo foo-mirror
186	atf_check test -L foo-mirror/foo/baz
187}
188
189atf_test_case recursive_link_Lflag
190recursive_link_Lflag_body()
191{
192	recursive_link_setup -L
193
194	# -L will work, but foo/baz ends up expanded to a directory.
195	atf_check test -d foo-mirror/foo/baz -a \
196	    '(' ! -L foo-mirror/foo/baz ')'
197	atf_check cp -RL foo foo-mirror
198	atf_check test -d foo-mirror/foo/baz -a \
199	    '(' ! -L foo-mirror/foo/baz ')'
200}
201
202atf_test_case standalone_Pflag
203standalone_Pflag_body()
204{
205	echo "foo" > bar
206	ln -s bar foo
207
208	atf_check cp -P foo baz
209	atf_check -o inline:'Symbolic Link\n' stat -f %SHT baz
210}
211
212atf_init_test_cases()
213{
214	atf_add_test_case basic
215	atf_add_test_case basic_symlink
216	atf_add_test_case chrdev
217	atf_add_test_case matching_srctgt
218	atf_add_test_case matching_srctgt_contained
219	atf_add_test_case matching_srctgt_link
220	atf_add_test_case matching_srctgt_nonexistent
221	atf_add_test_case recursive_link_dflt
222	atf_add_test_case recursive_link_Hflag
223	atf_add_test_case recursive_link_Lflag
224	atf_add_test_case standalone_Pflag
225}
226