1267265Sjilles#
2267265Sjilles# Copyright 2014, Google Inc. All rights reserved.
3267265Sjilles#
4267265Sjilles# Redistribution and use in source and binary forms, with or without
5267265Sjilles# modification, are permitted provided that the following conditions are
6267265Sjilles# met:
7267265Sjilles#
8267265Sjilles# * Redistributions of source code must retain the above copyright
9267265Sjilles#   notice, this list of conditions and the following disclaimer.
10267265Sjilles# * Redistributions in binary form must reproduce the above copyright
11267265Sjilles#   notice, this list of conditions and the following disclaimer in the
12267265Sjilles#   documentation and/or other materials provided with the distribution.
13267265Sjilles# * Neither the name of Google Inc. nor the names of its
14267265Sjilles#   contributors may be used to endorse or promote products derived from
15267265Sjilles#   this software without specific written permission.
16267265Sjilles#
17267265Sjilles# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18267265Sjilles# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19267265Sjilles# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20267265Sjilles# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21267265Sjilles# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22267265Sjilles# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23267265Sjilles# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24267265Sjilles# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25267265Sjilles# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26267265Sjilles# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27267265Sjilles# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28267265Sjilles#
29267265Sjilles# $FreeBSD: releng/10.2/usr.bin/truncate/tests/truncate_test.sh 267265 2014-06-09 10:39:55Z jilles $
30267265Sjilles#
31267265Sjilles
32267265Sjilles# Helper function that is always used to create and fill stderr.txt for these
33267265Sjilles# tests.
34267265Sjilles_custom_create_file()
35267265Sjilles{
36267265Sjilles	# The first argument is a command.
37267265Sjilles	# The second is just a string.
38267265Sjilles	case "${1}" in
39267265Sjilles		creat) > stderr.txt ;;
40267265Sjilles		print) [ "${2}" ] && \
41267265Sjilles		    printf "%s\n" "${2}" >> stderr.txt ;;
42267265Sjilles	esac
43267265Sjilles}
44267265Sjilles
45267265Sjilles# Helper function that create the file stderr.txt that contains the string
46267265Sjilles# passed in as the first argument.
47267265Sjillescreate_stderr_file()
48267265Sjilles{
49267265Sjilles	_custom_create_file creat
50267265Sjilles	_custom_create_file print "${1}"
51267265Sjilles}
52267265Sjilles
53267265Sjilles# Helper function that create the file stderr.txt that contains the expected
54267265Sjilles# truncate utility usage message.
55267265Sjillescreate_stderr_usage_file()
56267265Sjilles{
57267265Sjilles	_custom_create_file creat
58267265Sjilles	_custom_create_file print "${1}"
59267265Sjilles	_custom_create_file print \
60267265Sjilles	    "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ..."
61267265Sjilles	_custom_create_file print "       truncate [-c] -r rfile file ..."
62267265Sjilles}
63267265Sjilles
64267265Sjillesatf_test_case illegal_option
65267265Sjillesillegal_option_head()
66267265Sjilles{
67267265Sjilles	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
68267265Sjilles	    "invalid command line option"
69267265Sjilles}
70267265Sjillesillegal_option_body()
71267265Sjilles{
72267265Sjilles	create_stderr_usage_file 'truncate: illegal option -- 7'
73267265Sjilles
74267265Sjilles	# We expect the error message, with no new files.
75267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt
76267265Sjilles	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
77267265Sjilles}
78267265Sjilles
79267265Sjillesatf_test_case illegal_size
80267265Sjillesillegal_size_head()
81267265Sjilles{
82267265Sjilles	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
83267265Sjilles	    "invalid power of two convention"
84267265Sjilles}
85267265Sjillesillegal_size_body()
86267265Sjilles{
87267265Sjilles	create_stderr_file "truncate: invalid size argument \`+1L'"
88267265Sjilles
89267265Sjilles	# We expect the error message, with no new files.
90267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt
91267265Sjilles	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
92267265Sjilles}
93267265Sjilles
94267265Sjillesatf_test_case too_large_size
95267265Sjillestoo_large_size_head()
96267265Sjilles{
97267265Sjilles	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
98267265Sjilles	    "a size that is INT64_MAX < size <= UINT64_MAX"
99267265Sjilles}
100267265Sjillestoo_large_size_body()
101267265Sjilles{
102267265Sjilles	create_stderr_file "truncate: invalid size argument \`8388608t'"
103267265Sjilles
104267265Sjilles	# We expect the error message, with no new files.
105267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt \
106267265Sjilles	    truncate -s8388608t output.txt
107267265Sjilles	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
108267265Sjilles}
109267265Sjilles
110267265Sjillesatf_test_case opt_c
111267265Sjillesopt_c_head()
112267265Sjilles{
113267265Sjilles	atf_set "descr" "Verifies that -c prevents creation of new files"
114267265Sjilles}
115267265Sjillesopt_c_body()
116267265Sjilles{
117267265Sjilles	# No new files and truncate returns 0 as if this is a success.
118267265Sjilles	atf_check truncate -c -s 0 doesnotexist.txt
119267265Sjilles	[ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
120267265Sjilles	> reference
121267265Sjilles	atf_check truncate -c -r reference doesnotexist.txt
122267265Sjilles	[ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
123267265Sjilles
124267265Sjilles	create_stderr_file
125267265Sjilles
126267265Sjilles	# The existing file will be altered by truncate.
127267265Sjilles	> exists.txt
128267265Sjilles	atf_check -e file:stderr.txt truncate -c -s1 exists.txt
129267265Sjilles	[ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes"
130267265Sjilles}
131267265Sjilles
132267265Sjillesatf_test_case opt_rs
133267265Sjillesopt_rs_head()
134267265Sjilles{
135267265Sjilles	atf_set "descr" "Verifies that truncate command line flags" \
136267265Sjilles	    "-s and -r cannot be specifed together"
137267265Sjilles}
138267265Sjillesopt_rs_body()
139267265Sjilles{
140267265Sjilles	create_stderr_usage_file
141267265Sjilles
142267265Sjilles	# Force an error due to the use of both -s and -r.
143267265Sjilles	> afile
144267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile
145267265Sjilles}
146267265Sjilles
147267265Sjillesatf_test_case no_files
148267265Sjillesno_files_head()
149267265Sjilles{
150267265Sjilles	atf_set "descr" "Verifies that truncate needs a list of files on" \
151267265Sjilles	    "the command line"
152267265Sjilles}
153267265Sjillesno_files_body()
154267265Sjilles{
155267265Sjilles	create_stderr_usage_file
156267265Sjilles
157267265Sjilles	# A list of files must be present on the command line.
158267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -s1
159267265Sjilles}
160267265Sjilles
161267265Sjillesatf_test_case bad_refer
162267265Sjillesbad_refer_head()
163267265Sjilles{
164267265Sjilles	atf_set "descr" "Verifies that truncate detects a non-existent" \
165267265Sjilles	    "reference file"
166267265Sjilles}
167267265Sjillesbad_refer_body()
168267265Sjilles{
169267265Sjilles	create_stderr_file "truncate: afile: No such file or directory"
170267265Sjilles
171267265Sjilles	# The reference file must exist before you try to use it.
172267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile
173267265Sjilles	[ ! -e afile ] || atf_fail "afile should not exist"
174267265Sjilles}
175267265Sjilles
176267265Sjillesatf_test_case bad_truncate cleanup
177267265Sjillesbad_truncate_head()
178267265Sjilles{
179267265Sjilles	atf_set "descr" "Verifies that truncate reports an error during" \
180267265Sjilles	    "truncation"
181267265Sjilles}
182267265Sjillesbad_truncate_body()
183267265Sjilles{
184267265Sjilles	create_stderr_file "truncate: exists.txt: Operation not permitted"
185267265Sjilles
186267265Sjilles	# Trying to get the ftruncate() call to return -1.
187267265Sjilles	> exists.txt
188267265Sjilles	atf_check chflags uimmutable exists.txt
189267265Sjilles
190267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt
191267265Sjilles}
192267265Sjillesbad_truncate_cleanup()
193267265Sjilles{
194267265Sjilles	chflags 0 exists.txt
195267265Sjilles}
196267265Sjilles
197267265Sjillesatf_test_case new_absolute_grow
198267265Sjillesnew_absolute_grow_head()
199267265Sjilles{
200267265Sjilles	atf_set "descr" "Verifies truncate can make and grow a new 1m file"
201267265Sjilles}
202267265Sjillesnew_absolute_grow_body()
203267265Sjilles{
204267265Sjilles	create_stderr_file
205267265Sjilles
206267265Sjilles	# Create a new file and grow it to 1024 bytes.
207267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
208267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
209267265Sjilles	eval $(stat -s output.txt)
210267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
211267265Sjilles
212267265Sjilles	create_stderr_file
213267265Sjilles
214267265Sjilles	# Grow the existing file to 1M.  We are using absolute sizes.
215267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt
216267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
217267265Sjilles	eval $(stat -s output.txt)
218267265Sjilles	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
219267265Sjilles}
220267265Sjilles
221267265Sjillesatf_test_case new_absolute_shrink
222267265Sjillesnew_absolute_shrink_head()
223267265Sjilles{
224267265Sjilles	atf_set "descr" "Verifies that truncate can make and" \
225267265Sjilles	    "shrink a new 1m file"
226267265Sjilles}
227267265Sjillesnew_absolute_shrink_body()
228267265Sjilles{
229267265Sjilles	create_stderr_file
230267265Sjilles
231267265Sjilles	# Create a new file and grow it to 1048576 bytes.
232267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt
233267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
234267265Sjilles	eval $(stat -s output.txt)
235267265Sjilles	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
236267265Sjilles
237267265Sjilles	create_stderr_file
238267265Sjilles
239267265Sjilles	# Shrink the existing file to 1k.  We are using absolute sizes.
240267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
241267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
242267265Sjilles	eval $(stat -s output.txt)
243267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
244267265Sjilles}
245267265Sjilles
246267265Sjillesatf_test_case new_relative_grow
247267265Sjillesnew_relative_grow_head()
248267265Sjilles{
249267265Sjilles	atf_set "descr" "Verifies truncate can make and grow a new 1m file" \
250267265Sjilles	    "using relative sizes"
251267265Sjilles}
252267265Sjillesnew_relative_grow_body()
253267265Sjilles{
254267265Sjilles	create_stderr_file
255267265Sjilles
256267265Sjilles	# Create a new file and grow it to 1024 bytes.
257267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt
258267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
259267265Sjilles	eval $(stat -s output.txt)
260267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
261267265Sjilles
262267265Sjilles	create_stderr_file
263267265Sjilles
264267265Sjilles	# Grow the existing file to 1M.  We are using relative sizes.
265267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt
266267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
267267265Sjilles	eval $(stat -s output.txt)
268267265Sjilles	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
269267265Sjilles}
270267265Sjilles
271267265Sjillesatf_test_case new_relative_shrink
272267265Sjillesnew_relative_shrink_head()
273267265Sjilles{
274267265Sjilles	atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \
275267265Sjilles	    "using relative sizes"
276267265Sjilles}
277267265Sjillesnew_relative_shrink_body()
278267265Sjilles{
279267265Sjilles	create_stderr_file
280267265Sjilles
281267265Sjilles	# Create a new file and grow it to 1049600 bytes.
282267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt
283267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
284267265Sjilles	eval $(stat -s output.txt)
285267265Sjilles	[ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m"
286267265Sjilles
287267265Sjilles	create_stderr_file
288267265Sjilles
289267265Sjilles	# Shrink the existing file to 1k.  We are using relative sizes.
290267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt
291267265Sjilles	atf_check -s exit:1 cmp -s output.txt /dev/zero
292267265Sjilles	eval $(stat -s output.txt)
293267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
294267265Sjilles}
295267265Sjilles
296267265Sjillesatf_test_case cannot_open
297267265Sjillescannot_open_head()
298267265Sjilles{
299267265Sjilles	atf_set "descr" "Verifies truncate handles open failures correctly" \
300267265Sjilles	    "in a list of files"
301267265Sjilles	atf_set "require.user" "unprivileged"
302267265Sjilles}
303267265Sjillescannot_open_body()
304267265Sjilles{
305267265Sjilles	# Create three files -- the middle file cannot allow writes.
306267265Sjilles	> before
307267265Sjilles	> 0000
308267265Sjilles	> after
309267265Sjilles	atf_check chmod 0000 0000
310267265Sjilles
311267265Sjilles	create_stderr_file "truncate: 0000: Permission denied"
312267265Sjilles
313267265Sjilles	# Create a new file and grow it to 1024 bytes.
314267265Sjilles	atf_check -s not-exit:0 -e file:stderr.txt \
315267265Sjilles	truncate -c -s1k before 0000 after
316267265Sjilles	eval $(stat -s before)
317267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
318267265Sjilles	eval $(stat -s after)
319267265Sjilles	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
320267265Sjilles	eval $(stat -s 0000)
321267265Sjilles	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
322267265Sjilles}
323267265Sjilles
324267265Sjillesatf_test_case reference
325267265Sjillesreference_head()
326267265Sjilles{
327267265Sjilles	atf_set "descr" "Verifies that truncate can use a reference file"
328267265Sjilles}
329267265Sjillesreference_body()
330267265Sjilles{
331267265Sjilles	# Create a 4 byte reference file.
332267265Sjilles	printf "123\n" > reference
333267265Sjilles	eval $(stat -s reference)
334267265Sjilles	[ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes"
335267265Sjilles
336267265Sjilles	create_stderr_file
337267265Sjilles
338267265Sjilles	# Create a new file and grow it to 4 bytes.
339267265Sjilles	atf_check -e file:stderr.txt truncate -r reference afile
340267265Sjilles	eval $(stat -s afile)
341267265Sjilles	[ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes"
342267265Sjilles}
343267265Sjilles
344267265Sjillesatf_test_case new_zero
345267265Sjillesnew_zero_head()
346267265Sjilles{
347267265Sjilles	atf_set "descr" "Verifies truncate can make and grow zero byte file"
348267265Sjilles}
349267265Sjillesnew_zero_body()
350267265Sjilles{
351267265Sjilles	create_stderr_file
352267265Sjilles
353267265Sjilles	# Create a new file and grow it to zero bytes.
354267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt
355267265Sjilles	eval $(stat -s output.txt)
356267265Sjilles	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
357267265Sjilles
358267265Sjilles	# Pretend to grow the file.
359267265Sjilles	atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt
360267265Sjilles	eval $(stat -s output.txt)
361267265Sjilles	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
362267265Sjilles}
363267265Sjilles
364267265Sjillesatf_test_case negative
365267265Sjillesnegative_head()
366267265Sjilles{
367267265Sjilles	atf_set "descr" "Verifies truncate treats negative sizes as zero"
368267265Sjilles}
369267265Sjillesnegative_body()
370267265Sjilles{
371267265Sjilles	# Create a 5 byte file.
372267265Sjilles	printf "abcd\n" > afile
373267265Sjilles	eval $(stat -s afile)
374267265Sjilles	[ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
375267265Sjilles
376267265Sjilles	create_stderr_file
377267265Sjilles
378267265Sjilles	# Create a new file and do a 100 byte negative relative shrink.
379267265Sjilles	atf_check -e file:stderr.txt truncate -s-100 afile
380267265Sjilles	eval $(stat -s afile)
381267265Sjilles	[ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes"
382267265Sjilles}
383267265Sjilles
384267265Sjillesatf_init_test_cases()
385267265Sjilles{
386267265Sjilles	atf_add_test_case illegal_option
387267265Sjilles	atf_add_test_case illegal_size
388267265Sjilles	atf_add_test_case too_large_size
389267265Sjilles	atf_add_test_case opt_c
390267265Sjilles	atf_add_test_case opt_rs
391267265Sjilles	atf_add_test_case no_files
392267265Sjilles	atf_add_test_case bad_refer
393267265Sjilles	atf_add_test_case bad_truncate
394267265Sjilles	atf_add_test_case cannot_open
395267265Sjilles	atf_add_test_case new_absolute_grow
396267265Sjilles	atf_add_test_case new_absolute_shrink
397267265Sjilles	atf_add_test_case new_relative_grow
398267265Sjilles	atf_add_test_case new_relative_shrink
399267265Sjilles	atf_add_test_case reference
400267265Sjilles	atf_add_test_case new_zero
401267265Sjilles	atf_add_test_case negative
402267265Sjilles}
403