xref: /freebsd/sbin/bectl/tests/bectl_test.sh (revision f0483545503a78e16e256d46d458a2faae2f07ea)
1#
2# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3#
4# Copyright (c) 2018 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
29# Establishes a bectl_create zpool that can be used for some light testing; contains
30# a 'default' BE and not much else.
31bectl_create_setup()
32{
33	zpool=$1
34	disk=$2
35	mnt=$3
36
37	kldload -n -q zfs || atf_skip "ZFS module not loaded on the current system"
38	atf_check mkdir -p ${mnt}
39	atf_check truncate -s 1G ${disk}
40	atf_check zpool create -o altroot=${mnt} ${zpool} ${disk}
41	atf_check zfs create -o mountpoint=none ${zpool}/ROOT
42	atf_check zfs create -o mountpoint=/ -o canmount=noauto \
43	    ${zpool}/ROOT/default
44}
45bectl_create_deep_setup()
46{
47	zpool=$1
48	disk=$2
49	mnt=$3
50
51	bectl_create_setup ${zpool} ${disk} ${mnt}
52	atf_check mkdir -p ${root}
53	atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
54	atf_check mkdir -p ${root}/usr
55	atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
56	    ${zpool}/ROOT/default/usr
57	atf_check -o ignore bectl -r ${zpool}/ROOT umount default
58}
59
60bectl_cleanup()
61{
62	zpool=$1
63
64	if zpool get health ${zpool} >/dev/null 2>&1; then
65		zpool destroy -f ${zpool}
66	fi
67}
68
69atf_test_case bectl_create cleanup
70bectl_create_head()
71{
72
73	atf_set "descr" "Check the various forms of bectl create"
74	atf_set "require.user" root
75}
76bectl_create_body()
77{
78	cwd=$(realpath .)
79	zpool=bectl_test
80	disk=${cwd}/disk.img
81	mount=${cwd}/mnt
82
83	bectl_create_setup ${zpool} ${disk} ${mount}
84	# Test standard creation, creation of a snapshot, and creation from a
85	# snapshot.
86	atf_check bectl -r ${zpool}/ROOT create -e default default2
87	atf_check bectl -r ${zpool}/ROOT create default2@test_snap
88	atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
89}
90bectl_create_cleanup()
91{
92
93	bectl_cleanup bectl_test
94}
95
96atf_test_case bectl_destroy cleanup
97bectl_destroy_head()
98{
99
100	atf_set "descr" "Check bectl destroy"
101	atf_set "require.user" root
102}
103bectl_destroy_body()
104{
105	cwd=$(realpath .)
106	zpool=bectl_test
107	disk=${cwd}/disk.img
108	mount=${cwd}/mnt
109
110	bectl_create_setup ${zpool} ${disk} ${mount}
111	atf_check bectl -r ${zpool}/ROOT create -e default default2
112	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
113	atf_check bectl -r ${zpool}/ROOT destroy default2
114	atf_check -e not-empty -s not-exit:0 zfs get mountpoint ${zpool}/ROOT/default2
115}
116bectl_destroy_cleanup()
117{
118
119	bectl_cleanup bectl_test
120}
121
122atf_test_case bectl_export_import cleanup
123bectl_export_import_head()
124{
125
126	atf_set "descr" "Check bectl export and import"
127	atf_set "require.user" root
128}
129bectl_export_import_body()
130{
131	cwd=$(realpath .)
132	zpool=bectl_test
133	disk=${cwd}/disk.img
134	mount=${cwd}/mnt
135
136	bectl_create_setup ${zpool} ${disk} ${mount}
137	atf_check -o save:exported bectl -r ${zpool}/ROOT export default
138	atf_check -x "bectl -r ${zpool}/ROOT import default2 < exported"
139	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
140	atf_check bectl -r ${zpool}/ROOT destroy default2
141	atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
142	    ${zpool}/ROOT/default2
143}
144bectl_export_import_cleanup()
145{
146
147	bectl_cleanup bectl_test
148}
149
150atf_test_case bectl_list cleanup
151bectl_list_head()
152{
153
154	atf_set "descr" "Check bectl list"
155	atf_set "require.user" root
156}
157bectl_list_body()
158{
159	cwd=$(realpath .)
160	zpool=bectl_test
161	disk=${cwd}/disk.img
162	mount=${cwd}/mnt
163
164	bectl_create_setup ${zpool} ${disk} ${mount}
165	# Test the list functionality, including that BEs come and go away
166	# as they're created and destroyed.  Creation and destruction tests
167	# use the 'zfs' utility to verify that they're actually created, so
168	# these are just light tests that 'list' is picking them up.
169	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
170	atf_check -o not-empty grep 'default' list.out
171	atf_check bectl -r ${zpool}/ROOT create -e default default2
172	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
173	atf_check -o not-empty grep 'default2' list.out
174	atf_check bectl -r ${zpool}/ROOT destroy default2
175	atf_check -o save:list.out bectl -r ${zpool}/ROOT list
176	atf_check -s not-exit:0 grep 'default2' list.out
177	# XXX TODO: Formatting checks
178}
179bectl_list_cleanup()
180{
181
182	bectl_cleanup bectl_test
183}
184
185atf_test_case bectl_mount cleanup
186bectl_mount_head()
187{
188
189	atf_set "descr" "Check bectl mount/unmount"
190	atf_set "require.user" root
191}
192bectl_mount_body()
193{
194	cwd=$(realpath .)
195	zpool=bectl_test
196	disk=${cwd}/disk.img
197	mount=${cwd}/mnt
198	root=${mount}/root
199
200	bectl_create_deep_setup ${zpool} ${disk} ${mount}
201	atf_check mkdir -p ${root}
202	# Test unmount first...
203	atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
204	atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
205	atf_check bectl -r ${zpool}/ROOT unmount default
206	atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
207	# Then umount!
208	atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
209	atf_check -o not-empty -x "mount | grep '^${zpool}/ROOT/default'"
210	atf_check bectl -r ${zpool}/ROOT umount default
211	atf_check -s not-exit:0 -x "mount | grep '^${zpool}/ROOT/default'"
212}
213bectl_mount_cleanup()
214{
215
216	bectl_cleanup bectl_test
217}
218
219atf_test_case bectl_rename cleanup
220bectl_rename_head()
221{
222
223	atf_set "descr" "Check bectl rename"
224	atf_set "require.user" root
225}
226bectl_rename_body()
227{
228	cwd=$(realpath .)
229	zpool=bectl_test
230	disk=${cwd}/disk.img
231	mount=${cwd}/mnt
232
233	bectl_create_setup ${zpool} ${disk} ${mount}
234	atf_check bectl -r ${zpool}/ROOT rename default default2
235	atf_check -o not-empty zfs get mountpoint ${zpool}/ROOT/default2
236	atf_check -e not-empty -s not-exit:0 zfs get mountpoint \
237	    ${zpool}/ROOT/default
238}
239bectl_rename_cleanup()
240{
241
242	bectl_cleanup bectl_test
243}
244
245atf_test_case bectl_jail cleanup
246bectl_jail_head()
247{
248
249	atf_set "descr" "Check bectl rename"
250	atf_set "require.user" root
251}
252bectl_jail_body()
253{
254	cwd=$(realpath .)
255	zpool=bectl_test
256	disk=${cwd}/disk.img
257	mount=${cwd}/mnt
258	root=${mount}/root
259
260	if [ ! -f /rescue/rescue ]; then
261		atf_skip "This test requires a rescue binary"
262	fi
263	bectl_create_deep_setup ${zpool} ${disk} ${mount}
264	# Prepare our minimal BE... plop a rescue binary into it
265	atf_check mkdir -p ${root}
266	atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
267	atf_check mkdir -p ${root}/rescue
268	atf_check cp /rescue/rescue ${root}/rescue/rescue
269	atf_check bectl -r ${zpool}/ROOT umount default
270
271	# Prepare a second boot environment
272	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT create -e default target
273
274	# When a jail name is not explicit, it should match the jail id.
275	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o jid=233637 default
276	atf_check -o inline:"233637\n" -s exit:0 -x "jls -j 233637 name"
277	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
278
279	# Basic command-mode tests, with and without jail cleanup
280	atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
281	    jail default /rescue/rescue ls -1
282	atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
283	    jail -Uo path=${root} default /rescue/rescue ls -1
284	atf_check [ -f ${root}/rescue/rescue ]
285	atf_check bectl -r ${zpool}/ROOT ujail default
286
287	# Batch mode tests
288	atf_check bectl -r ${zpool}/ROOT jail -bo path=${root} default
289	atf_check -o not-empty -x "jls | grep -F \"${root}\""
290	atf_check bectl -r ${zpool}/ROOT ujail default
291	atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
292	# 'unjail' naming
293	atf_check bectl -r ${zpool}/ROOT jail -b default
294	atf_check bectl -r ${zpool}/ROOT unjail default
295	atf_check -s not-exit:0 -x "jls | grep -F \"${root}\""
296	# 'unjail' by BE name. Force bectl to lookup jail id by the BE name.
297	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b default
298	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT jail -b -o name=bectl_test target
299	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail target
300	atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
301	# cannot unjail an unjailed BE (by either command name)
302	atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT ujail default
303	atf_check -e ignore -s not-exit:0 bectl -r ${zpool}/ROOT unjail default
304
305	# set+unset
306	atf_check bectl -r ${zpool}/ROOT jail -b -o path=${root} -u path default
307	# Ensure that it didn't mount at ${root}
308	atf_check -s not-exit:0 -x "mount | grep -F '${root}'"
309	atf_check bectl -r ${zpool}/ROOT ujail default
310}
311
312# If a test has failed, it's possible that the boot environment hasn't
313# been 'unjail'ed. We want to remove the jail before 'bectl_cleanup'
314# attempts to destroy the zpool.
315bectl_jail_cleanup()
316{
317	for bootenv in "default" "target"; do
318		# mountpoint of the boot environment
319		mountpoint="$(bectl -r bectl_test/ROOT list -H | grep ${bootenv} | awk '{print $3}')"
320
321		# see if any jail paths match the boot environment mountpoint
322		jailid="$(jls | grep ${mountpoint} | awk '{print $1}')"
323
324		if [ -z "$jailid" ]; then
325		       continue;
326		fi
327		jail -r ${jailid}
328	done;
329
330	bectl_cleanup bectl_test
331}
332
333atf_init_test_cases()
334{
335	atf_add_test_case bectl_create
336	atf_add_test_case bectl_destroy
337	atf_add_test_case bectl_export_import
338	atf_add_test_case bectl_list
339	atf_add_test_case bectl_mount
340	atf_add_test_case bectl_rename
341	atf_add_test_case bectl_jail
342}
343