xref: /freebsd/bin/cp/tests/cp_test.sh (revision 45c23c2608ec3e34b5c7ce18eca91a46419e363c)
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	echo "qux" > foo/bar
99	mkdir foo/loo
100	mkdir foo/moo
101	mkdir foo/roo
102	cp foo/bar foo/zoo
103
104	atf_check cp -R foo foo/moo
105	atf_check -o inline:"qux\n" cat foo/moo/foo/bar
106	atf_check -o inline:"qux\n" cat foo/moo/foo/zoo
107	atf_check -e not-empty -s not-exit:0 stat foo/moo/foo/moo
108}
109
110atf_test_case matching_srctgt_link
111matching_srctgt_link_body()
112{
113
114	mkdir foo
115	echo "qux" > foo/bar
116	cp foo/bar foo/zoo
117
118	atf_check ln -s foo roo
119	atf_check cp -RH roo foo
120	atf_check -o inline:"qux\n" cat foo/roo/bar
121	atf_check -o inline:"qux\n" cat foo/roo/zoo
122}
123
124atf_test_case matching_srctgt_nonexistent
125matching_srctgt_nonexistent_body()
126{
127
128	# We'll copy foo to a nonexistent subdirectory; ideally, we would
129	# skip just the directory and end up with a layout like;
130	#
131	# foo/
132	#     bar
133	#     dne/
134	#         bar
135	#         zoo
136	#     zoo
137	#
138	mkdir foo
139	echo "qux" > foo/bar
140	cp foo/bar foo/zoo
141
142	atf_check cp -R foo foo/dne
143	atf_check -o inline:"qux\n" cat foo/dne/bar
144	atf_check -o inline:"qux\n" cat foo/dne/zoo
145	atf_check -e not-empty -s not-exit:0 stat foo/dne/foo
146}
147
148recursive_link_setup()
149{
150	extra_cpflag=$1
151
152	mkdir -p foo/bar
153	ln -s bar foo/baz
154
155	mkdir foo-mirror
156	eval "cp -R $extra_cpflag foo foo-mirror"
157}
158
159atf_test_case recursive_link_dflt
160recursive_link_dflt_body()
161{
162	recursive_link_setup
163
164	# -P is the default, so this should work and preserve the link.
165	atf_check cp -R foo foo-mirror
166	atf_check test -L foo-mirror/foo/baz
167}
168
169atf_test_case recursive_link_Hflag
170recursive_link_Hflag_body()
171{
172	recursive_link_setup
173
174	# -H will not follow either, so this should also work and preserve the
175	# link.
176	atf_check cp -RH foo foo-mirror
177	atf_check test -L foo-mirror/foo/baz
178}
179
180atf_test_case recursive_link_Lflag
181recursive_link_Lflag_body()
182{
183	recursive_link_setup -L
184
185	# -L will work, but foo/baz ends up expanded to a directory.
186	atf_check test -d foo-mirror/foo/baz -a \
187	    '(' ! -L foo-mirror/foo/baz ')'
188	atf_check cp -RL foo foo-mirror
189	atf_check test -d foo-mirror/foo/baz -a \
190	    '(' ! -L foo-mirror/foo/baz ')'
191}
192
193atf_test_case standalone_Pflag
194standalone_Pflag_body()
195{
196	echo "foo" > bar
197	ln -s bar foo
198
199	atf_check cp -P foo baz
200	atf_check -o inline:'Symbolic Link\n' stat -f %SHT baz
201}
202
203atf_init_test_cases()
204{
205	atf_add_test_case basic
206	atf_add_test_case basic_symlink
207	atf_add_test_case chrdev
208	atf_add_test_case matching_srctgt
209	atf_add_test_case matching_srctgt_contained
210	atf_add_test_case matching_srctgt_link
211	atf_add_test_case matching_srctgt_nonexistent
212	atf_add_test_case recursive_link_dflt
213	atf_add_test_case recursive_link_Hflag
214	atf_add_test_case recursive_link_Lflag
215	atf_add_test_case standalone_Pflag
216}
217