xref: /freebsd/usr.bin/stat/tests/stat_test.sh (revision fe75646a0234a261c0013bf1840fdac4acaf0cec)
1#
2# Copyright (c) 2017 Dell EMC
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24# SUCH DAMAGE.
25#
26
27atf_test_case F_flag
28F_flag_head()
29{
30	atf_set	"descr" "Verify the output format for -F"
31}
32F_flag_body()
33{
34	# TODO: socket, whiteout file
35	atf_check touch a
36	atf_check mkdir b
37	atf_check install -m 0777 /dev/null c
38	atf_check ln -s a d
39	atf_check mkfifo f
40
41	atf_check -o match:'.* a' stat -Fn a
42	atf_check -o match:'.* b/' stat -Fn b
43	atf_check -o match:'.* c\*' stat -Fn c
44	atf_check -o match:'.* d@' stat -Fn d
45	atf_check -o match:'.* f\|' stat -Fn f
46}
47
48atf_test_case l_flag
49l_flag_head()
50{
51	atf_set	"descr" "Verify the output format for -l"
52}
53l_flag_body()
54{
55	atf_check touch a
56	atf_check ln a b
57	atf_check ln -s a c
58	atf_check mkdir d
59
60	paths="a b c d"
61
62	ls_out=ls.output
63	stat_out=stat.output
64
65	# NOTE:
66	# - Even though stat -l claims to be equivalent to `ls -lT`, the
67	#   whitespace is a bit more liberal in the `ls -lT` output.
68	# - `ls -ldT` is used to not recursively list the contents of
69	#   directories.
70	for path in $paths; do
71		atf_check -o save:$ls_out ls -ldT $path
72		cat $ls_out
73		atf_check -o save:$stat_out stat -l $path
74		cat $stat_out
75		echo "Comparing normalized whitespace"
76		atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $ls_out
77		atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $stat_out
78		atf_check cmp $ls_out $stat_out
79	done
80}
81
82atf_test_case n_flag
83n_flag_head()
84{
85	atf_set	"descr" "Verify that -n suppresses newline output for lines"
86}
87n_flag_body()
88{
89	atf_check touch a b
90	atf_check -o inline:"$(stat a | tr -d '\n')" stat -n a
91	atf_check -o inline:"$(stat a b | tr -d '\n')" stat -n a b
92}
93
94atf_test_case q_flag
95q_flag_head()
96{
97	atf_set	"descr" "Verify that -q suppresses error messages from l?stat(2)"
98}
99q_flag_body()
100{
101	ln -s nonexistent broken-link
102
103	atf_check -s exit:1 stat -q nonexistent
104	atf_check -s exit:1 stat -q nonexistent
105	atf_check -o not-empty stat -q broken-link
106	atf_check -o not-empty stat -qL broken-link
107}
108
109atf_test_case r_flag
110r_flag_head()
111{
112	atf_set	"descr" "Verify that -r displays output in 'raw mode'"
113}
114r_flag_body()
115{
116	atf_check touch a
117	# TODO: add more thorough checks.
118	atf_check -o not-empty stat -r a
119}
120
121atf_test_case s_flag
122s_flag_head()
123{
124	atf_set	"descr" "Verify the output format for -s"
125}
126s_flag_body()
127{
128	atf_check touch a
129	atf_check ln a b
130	atf_check ln -s a c
131	atf_check mkdir d
132
133	paths="a b c d"
134
135	# The order/name of each of the fields is specified by stat(1) manpage.
136	fields="st_dev st_ino st_mode st_nlink"
137	fields="$fields st_uid st_gid st_rdev st_size"
138	fields="$fields st_uid st_gid st_mode"
139	fields="$fields st_atime st_mtime st_ctime st_birthtime"
140	fields="$fields st_blksize st_blocks st_flags"
141
142	# NOTE: the following...
143	# - ... relies on set -eu to ensure that the fields are set, as
144	#       documented, in stat(1).
145	# - ... uses a subshell to ensure that the eval'ed variables don't
146	#	pollute the next iteration's behavior.
147	for path in $paths; do
148		(
149		set -eu
150		eval $(stat -s $path)
151		for field in $fields; do
152			eval "$field=\$$field"
153		done
154		) || atf_fail 'One or more fields not set by stat(1)'
155	done
156}
157
158atf_test_case t_flag
159t_flag_head()
160{
161	atf_set	"descr" "Verify the output format for -t"
162}
163
164t_flag_body()
165{
166	atf_check touch foo
167	atf_check touch -d 1970-01-01T00:00:42 foo
168	atf_check -o inline:'42\n' \
169	    stat -t '%s' -f '%a' foo
170	atf_check -o inline:'1970-01-01 00:00:42\n' \
171	    stat -t '%F %H:%M:%S' -f '%Sa' foo
172}
173
174x_output_date()
175{
176	local date_format='%a %b %e %H:%M:%S %Y'
177
178	stat -t "$date_format" "$@"
179}
180
181x_output()
182{
183	local path=$1; shift
184
185	local atime_s=$(x_output_date -f '%Sa' $path)
186	local btime_s=$(x_output_date -f '%SB' $path)
187	local ctime_s=$(x_output_date -f '%Sc' $path)
188	local devid=$(stat -f '%Hd,%Ld' $path)
189	local file_type_s=$(stat -f '%HT' $path)
190	local gid=$(stat -f '%5g' $path)
191	local groupname=$(stat -f '%8Sg' $path)
192	local inode=$(stat -f '%i' $path)
193	local mode=$(stat -f '%Mp%Lp' $path)
194	local mode_s=$(stat -f '%Sp' $path)
195	local mtime_s=$(x_output_date -f '%Sm' $path)
196	local nlink=$(stat -f '%l' $path)
197	local size_a=$(stat -f '%-11z' $path)
198	local uid=$(stat -f '%5u' $path)
199	local username=$(stat -f '%8Su' $path)
200
201	cat <<EOF
202  File: "$path"
203  Size: $size_a  FileType: $file_type_s
204  Mode: ($mode/$mode_s)         Uid: ($uid/$username)  Gid: ($gid/$groupname)
205Device: $devid   Inode: $inode    Links: $nlink
206Access: $atime_s
207Modify: $mtime_s
208Change: $ctime_s
209 Birth: $btime_s
210EOF
211}
212
213atf_test_case x_flag
214x_flag_head()
215{
216	atf_set	"descr" "Verify the output format for -x"
217}
218x_flag_body()
219{
220	atf_check touch a
221	atf_check ln a b
222	atf_check ln -s a c
223	atf_check mkdir d
224
225	paths="a b c d"
226
227	for path in $paths; do
228		atf_check -o "inline:$(x_output $path)\n" stat -x $path
229	done
230}
231
232atf_init_test_cases()
233{
234	atf_add_test_case F_flag
235	#atf_add_test_case H_flag
236	#atf_add_test_case L_flag
237	#atf_add_test_case f_flag
238	atf_add_test_case l_flag
239	atf_add_test_case n_flag
240	atf_add_test_case q_flag
241	atf_add_test_case r_flag
242	atf_add_test_case s_flag
243	atf_add_test_case t_flag
244	atf_add_test_case x_flag
245}
246