xref: /freebsd/usr.bin/stat/tests/stat_test.sh (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
164a82bcdSEnji Cooper#
264a82bcdSEnji Cooper# Copyright (c) 2017 Dell EMC
364a82bcdSEnji Cooper# All rights reserved.
464a82bcdSEnji Cooper#
564a82bcdSEnji Cooper# Redistribution and use in source and binary forms, with or without
664a82bcdSEnji Cooper# modification, are permitted provided that the following conditions
764a82bcdSEnji Cooper# are met:
864a82bcdSEnji Cooper# 1. Redistributions of source code must retain the above copyright
964a82bcdSEnji Cooper#    notice, this list of conditions and the following disclaimer.
1064a82bcdSEnji Cooper# 2. Redistributions in binary form must reproduce the above copyright
1164a82bcdSEnji Cooper#    notice, this list of conditions and the following disclaimer in the
1264a82bcdSEnji Cooper#    documentation and/or other materials provided with the distribution.
1364a82bcdSEnji Cooper#
1464a82bcdSEnji Cooper# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1564a82bcdSEnji Cooper# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1664a82bcdSEnji Cooper# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1764a82bcdSEnji Cooper# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1864a82bcdSEnji Cooper# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1964a82bcdSEnji Cooper# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2064a82bcdSEnji Cooper# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2164a82bcdSEnji Cooper# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2264a82bcdSEnji Cooper# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2364a82bcdSEnji Cooper# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2464a82bcdSEnji Cooper# SUCH DAMAGE.
2564a82bcdSEnji Cooper#
2664a82bcdSEnji Cooper
2764a82bcdSEnji Cooperatf_test_case F_flag
2864a82bcdSEnji CooperF_flag_head()
2964a82bcdSEnji Cooper{
3064a82bcdSEnji Cooper	atf_set	"descr" "Verify the output format for -F"
3164a82bcdSEnji Cooper}
3264a82bcdSEnji CooperF_flag_body()
3364a82bcdSEnji Cooper{
3464a82bcdSEnji Cooper	# TODO: socket, whiteout file
3564a82bcdSEnji Cooper	atf_check touch a
3664a82bcdSEnji Cooper	atf_check mkdir b
3764a82bcdSEnji Cooper	atf_check install -m 0777 /dev/null c
3864a82bcdSEnji Cooper	atf_check ln -s a d
3964a82bcdSEnji Cooper	atf_check mkfifo f
4064a82bcdSEnji Cooper
4164a82bcdSEnji Cooper	atf_check -o match:'.* a' stat -Fn a
4264a82bcdSEnji Cooper	atf_check -o match:'.* b/' stat -Fn b
4364a82bcdSEnji Cooper	atf_check -o match:'.* c\*' stat -Fn c
4464a82bcdSEnji Cooper	atf_check -o match:'.* d@' stat -Fn d
4564a82bcdSEnji Cooper	atf_check -o match:'.* f\|' stat -Fn f
4664a82bcdSEnji Cooper}
4764a82bcdSEnji Cooper
4864a82bcdSEnji Cooperatf_test_case l_flag
4964a82bcdSEnji Cooperl_flag_head()
5064a82bcdSEnji Cooper{
5164a82bcdSEnji Cooper	atf_set	"descr" "Verify the output format for -l"
5264a82bcdSEnji Cooper}
5364a82bcdSEnji Cooperl_flag_body()
5464a82bcdSEnji Cooper{
5564a82bcdSEnji Cooper	atf_check touch a
5664a82bcdSEnji Cooper	atf_check ln a b
5764a82bcdSEnji Cooper	atf_check ln -s a c
5864a82bcdSEnji Cooper	atf_check mkdir d
5964a82bcdSEnji Cooper
6064a82bcdSEnji Cooper	paths="a b c d"
6164a82bcdSEnji Cooper
62faef91faSEnji Cooper	ls_out=ls.output
63faef91faSEnji Cooper	stat_out=stat.output
64faef91faSEnji Cooper
6564a82bcdSEnji Cooper	# NOTE:
6664a82bcdSEnji Cooper	# - Even though stat -l claims to be equivalent to `ls -lT`, the
6764a82bcdSEnji Cooper	#   whitespace is a bit more liberal in the `ls -lT` output.
6864a82bcdSEnji Cooper	# - `ls -ldT` is used to not recursively list the contents of
6964a82bcdSEnji Cooper	#   directories.
7064a82bcdSEnji Cooper	for path in $paths; do
71faef91faSEnji Cooper		atf_check -o save:$ls_out ls -ldT $path
72faef91faSEnji Cooper		cat $ls_out
73faef91faSEnji Cooper		atf_check -o save:$stat_out stat -l $path
74faef91faSEnji Cooper		cat $stat_out
75faef91faSEnji Cooper		echo "Comparing normalized whitespace"
76faef91faSEnji Cooper		atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $ls_out
77faef91faSEnji Cooper		atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $stat_out
78faef91faSEnji Cooper		atf_check cmp $ls_out $stat_out
7964a82bcdSEnji Cooper	done
8064a82bcdSEnji Cooper}
8164a82bcdSEnji Cooper
8264a82bcdSEnji Cooperatf_test_case n_flag
8364a82bcdSEnji Coopern_flag_head()
8464a82bcdSEnji Cooper{
8564a82bcdSEnji Cooper	atf_set	"descr" "Verify that -n suppresses newline output for lines"
8664a82bcdSEnji Cooper}
8764a82bcdSEnji Coopern_flag_body()
8864a82bcdSEnji Cooper{
8964a82bcdSEnji Cooper	atf_check touch a b
9064a82bcdSEnji Cooper	atf_check -o inline:"$(stat a | tr -d '\n')" stat -n a
9164a82bcdSEnji Cooper	atf_check -o inline:"$(stat a b | tr -d '\n')" stat -n a b
9264a82bcdSEnji Cooper}
9364a82bcdSEnji Cooper
9464a82bcdSEnji Cooperatf_test_case q_flag
9564a82bcdSEnji Cooperq_flag_head()
9664a82bcdSEnji Cooper{
9764a82bcdSEnji Cooper	atf_set	"descr" "Verify that -q suppresses error messages from l?stat(2)"
9864a82bcdSEnji Cooper}
9964a82bcdSEnji Cooperq_flag_body()
10064a82bcdSEnji Cooper{
10164a82bcdSEnji Cooper	ln -s nonexistent broken-link
10264a82bcdSEnji Cooper
10364a82bcdSEnji Cooper	atf_check -s exit:1 stat -q nonexistent
10464a82bcdSEnji Cooper	atf_check -s exit:1 stat -q nonexistent
10564a82bcdSEnji Cooper	atf_check -o not-empty stat -q broken-link
10664a82bcdSEnji Cooper	atf_check -o not-empty stat -qL broken-link
10764a82bcdSEnji Cooper}
10864a82bcdSEnji Cooper
10964a82bcdSEnji Cooperatf_test_case r_flag
11064a82bcdSEnji Cooperr_flag_head()
11164a82bcdSEnji Cooper{
11264a82bcdSEnji Cooper	atf_set	"descr" "Verify that -r displays output in 'raw mode'"
11364a82bcdSEnji Cooper}
11464a82bcdSEnji Cooperr_flag_body()
11564a82bcdSEnji Cooper{
11664a82bcdSEnji Cooper	atf_check touch a
11764a82bcdSEnji Cooper	# TODO: add more thorough checks.
11864a82bcdSEnji Cooper	atf_check -o not-empty stat -r a
11964a82bcdSEnji Cooper}
12064a82bcdSEnji Cooper
12164a82bcdSEnji Cooperatf_test_case s_flag
12264a82bcdSEnji Coopers_flag_head()
12364a82bcdSEnji Cooper{
12464a82bcdSEnji Cooper	atf_set	"descr" "Verify the output format for -s"
12564a82bcdSEnji Cooper}
12664a82bcdSEnji Coopers_flag_body()
12764a82bcdSEnji Cooper{
12864a82bcdSEnji Cooper	atf_check touch a
12964a82bcdSEnji Cooper	atf_check ln a b
13064a82bcdSEnji Cooper	atf_check ln -s a c
13164a82bcdSEnji Cooper	atf_check mkdir d
13264a82bcdSEnji Cooper
13364a82bcdSEnji Cooper	paths="a b c d"
13464a82bcdSEnji Cooper
13564a82bcdSEnji Cooper	# The order/name of each of the fields is specified by stat(1) manpage.
13664a82bcdSEnji Cooper	fields="st_dev st_ino st_mode st_nlink"
13764a82bcdSEnji Cooper	fields="$fields st_uid st_gid st_rdev st_size"
13864a82bcdSEnji Cooper	fields="$fields st_uid st_gid st_mode"
13964a82bcdSEnji Cooper	fields="$fields st_atime st_mtime st_ctime st_birthtime"
14064a82bcdSEnji Cooper	fields="$fields st_blksize st_blocks st_flags"
14164a82bcdSEnji Cooper
14264a82bcdSEnji Cooper	# NOTE: the following...
14364a82bcdSEnji Cooper	# - ... relies on set -eu to ensure that the fields are set, as
14464a82bcdSEnji Cooper	#       documented, in stat(1).
14564a82bcdSEnji Cooper	# - ... uses a subshell to ensure that the eval'ed variables don't
14664a82bcdSEnji Cooper	#	pollute the next iteration's behavior.
14764a82bcdSEnji Cooper	for path in $paths; do
14864a82bcdSEnji Cooper		(
14964a82bcdSEnji Cooper		set -eu
15064a82bcdSEnji Cooper		eval $(stat -s $path)
15164a82bcdSEnji Cooper		for field in $fields; do
15264a82bcdSEnji Cooper			eval "$field=\$$field"
15364a82bcdSEnji Cooper		done
15464a82bcdSEnji Cooper		) || atf_fail 'One or more fields not set by stat(1)'
15564a82bcdSEnji Cooper	done
15664a82bcdSEnji Cooper}
15764a82bcdSEnji Cooper
15864a82bcdSEnji Cooperatf_test_case t_flag
15964a82bcdSEnji Coopert_flag_head()
16064a82bcdSEnji Cooper{
16164a82bcdSEnji Cooper	atf_set	"descr" "Verify the output format for -t"
16264a82bcdSEnji Cooper}
16364a82bcdSEnji Cooper
16464a82bcdSEnji Coopert_flag_body()
16564a82bcdSEnji Cooper{
16664a82bcdSEnji Cooper	atf_check touch foo
16764a82bcdSEnji Cooper	atf_check touch -d 1970-01-01T00:00:42 foo
16864a82bcdSEnji Cooper	atf_check -o inline:'42\n' \
16964a82bcdSEnji Cooper	    stat -t '%s' -f '%a' foo
17064a82bcdSEnji Cooper	atf_check -o inline:'1970-01-01 00:00:42\n' \
17164a82bcdSEnji Cooper	    stat -t '%F %H:%M:%S' -f '%Sa' foo
17264a82bcdSEnji Cooper}
17364a82bcdSEnji Cooper
17464a82bcdSEnji Cooperx_output_date()
17564a82bcdSEnji Cooper{
1765e8e7af3SEnji Cooper	local date_format='%a %b %e %H:%M:%S %Y'
17764a82bcdSEnji Cooper
17864a82bcdSEnji Cooper	stat -t "$date_format" "$@"
17964a82bcdSEnji Cooper}
18064a82bcdSEnji Cooper
18164a82bcdSEnji Cooperx_output()
18264a82bcdSEnji Cooper{
18364a82bcdSEnji Cooper	local path=$1; shift
18464a82bcdSEnji Cooper
18564a82bcdSEnji Cooper	local atime_s=$(x_output_date -f '%Sa' $path)
186*98ce554aSEdward Tomasz Napierala	local btime_s=$(x_output_date -f '%SB' $path)
18764a82bcdSEnji Cooper	local ctime_s=$(x_output_date -f '%Sc' $path)
18864a82bcdSEnji Cooper	local devid=$(stat -f '%Hd,%Ld' $path)
18964a82bcdSEnji Cooper	local file_type_s=$(stat -f '%HT' $path)
19064a82bcdSEnji Cooper	local gid=$(stat -f '%5g' $path)
19164a82bcdSEnji Cooper	local groupname=$(stat -f '%8Sg' $path)
19264a82bcdSEnji Cooper	local inode=$(stat -f '%i' $path)
19364a82bcdSEnji Cooper	local mode=$(stat -f '%Mp%Lp' $path)
19464a82bcdSEnji Cooper	local mode_s=$(stat -f '%Sp' $path)
19564a82bcdSEnji Cooper	local mtime_s=$(x_output_date -f '%Sm' $path)
19664a82bcdSEnji Cooper	local nlink=$(stat -f '%l' $path)
19764a82bcdSEnji Cooper	local size_a=$(stat -f '%-11z' $path)
19864a82bcdSEnji Cooper	local uid=$(stat -f '%5u' $path)
19964a82bcdSEnji Cooper	local username=$(stat -f '%8Su' $path)
20064a82bcdSEnji Cooper
20164a82bcdSEnji Cooper	cat <<EOF
20264a82bcdSEnji Cooper  File: "$path"
20364a82bcdSEnji Cooper  Size: $size_a  FileType: $file_type_s
20464a82bcdSEnji Cooper  Mode: ($mode/$mode_s)         Uid: ($uid/$username)  Gid: ($gid/$groupname)
20564a82bcdSEnji CooperDevice: $devid   Inode: $inode    Links: $nlink
20664a82bcdSEnji CooperAccess: $atime_s
20764a82bcdSEnji CooperModify: $mtime_s
20864a82bcdSEnji CooperChange: $ctime_s
209*98ce554aSEdward Tomasz Napierala Birth: $btime_s
21064a82bcdSEnji CooperEOF
21164a82bcdSEnji Cooper}
21264a82bcdSEnji Cooper
21364a82bcdSEnji Cooperatf_test_case x_flag
21464a82bcdSEnji Cooperx_flag_head()
21564a82bcdSEnji Cooper{
21664a82bcdSEnji Cooper	atf_set	"descr" "Verify the output format for -x"
21764a82bcdSEnji Cooper}
21864a82bcdSEnji Cooperx_flag_body()
21964a82bcdSEnji Cooper{
22064a82bcdSEnji Cooper	atf_check touch a
22164a82bcdSEnji Cooper	atf_check ln a b
22264a82bcdSEnji Cooper	atf_check ln -s a c
22364a82bcdSEnji Cooper	atf_check mkdir d
22464a82bcdSEnji Cooper
22564a82bcdSEnji Cooper	paths="a b c d"
22664a82bcdSEnji Cooper
22764a82bcdSEnji Cooper	for path in $paths; do
22864a82bcdSEnji Cooper		atf_check -o "inline:$(x_output $path)\n" stat -x $path
22964a82bcdSEnji Cooper	done
23064a82bcdSEnji Cooper}
23164a82bcdSEnji Cooper
23264a82bcdSEnji Cooperatf_init_test_cases()
23364a82bcdSEnji Cooper{
23464a82bcdSEnji Cooper	atf_add_test_case F_flag
23564a82bcdSEnji Cooper	#atf_add_test_case H_flag
23664a82bcdSEnji Cooper	#atf_add_test_case L_flag
23764a82bcdSEnji Cooper	#atf_add_test_case f_flag
23864a82bcdSEnji Cooper	atf_add_test_case l_flag
23964a82bcdSEnji Cooper	atf_add_test_case n_flag
24064a82bcdSEnji Cooper	atf_add_test_case q_flag
24164a82bcdSEnji Cooper	atf_add_test_case r_flag
24264a82bcdSEnji Cooper	atf_add_test_case s_flag
24364a82bcdSEnji Cooper	atf_add_test_case t_flag
24464a82bcdSEnji Cooper	atf_add_test_case x_flag
24564a82bcdSEnji Cooper}
246