1 #!/bin/ksh
2 #
3 # This file and its contents are supplied under the terms of the
4 # Common Development and Distribution License ("CDDL"), version 1.0.
5 # You may only use this file in accordance with the terms of version
6 # 1.0 of the CDDL.
7 #
8 # A full copy of the text of the CDDL should have accompanied this
9 # source. A copy of the CDDL is also available via the Internet at
10 # http://www.illumos.org/license/CDDL.
11 #
12
13 #
14 # Copyright 2019 Robert Mustacchi
15 # Copyright 2020 Joyent, Inc.
16 #
17
18 #
19 # Basic tests of sleep(1). sleep is a little hard to test, especially
20 # for longer running cases. Therefore to test it, we basically take
21 # advantage of our knowledge of how it is implemented. We see that it
22 # properly is sleeping for the right amount of time by looking at the
23 # call to nanosleep in libc and make sure that the structures time is
24 # what we expect.
25 #
26
27 unalias -a
28 set -o pipefail
29
30 #
31 # Set the locale for the start of the test to be C.UTF-8 to make sure
32 # that we have a good starting point and correct fractional
33 # interpretation.
34 #
35 export LC_ALL=C.UTF-8
36
37 sleep_arg0="$(basename $0)"
38 sleep_prog=/usr/bin/sleep
39 sleep_dir="$(dirname $0)"
40 sleep_dscript=$sleep_dir/sleep.d
41 sleep_awk=$sleep_dir/sleep.awk
42 sleep_exit=0
43
44 #
45 # This is the factor by which we're going to basically say that the slp
46 # microstate has to complete within. Because the system will usually
47 # have a bit of additional latency, we will usually be greater than that
48 # as well. This determines how much we should actually do that by.
49 #
50 sleep_factor=1.5
51
52 warn()
53 {
54 typeset msg="$*"
55 [[ -z "$msg" ]] && msg="failed"
56 echo "TEST FAILED: $sleep_arg0: $msg" >&2
57 }
58
59 sleep_bound()
60 {
61 typeset min=$1
62 typeset test="sleep $min: bounding"
63
64 ptime -m $sleep_prog $min 2>&1 | nawk -f $sleep_awk min=$min \
65 factor=$sleep_factor
66 if [[ $? -ne 42 ]]; then
67 warn "$test"
68 sleep_exit=1
69 else
70 printf "TEST PASSED: %s\n" "$test"
71 fi
72 }
73
74 sleep_one()
75 {
76 typeset arg=$1
77 typeset secs=$2
78 typeset nsecs=$3
79 typeset test="sleep $arg: $secs secs $nsecs ns"
80
81 if ! dtrace -qws $sleep_dscript -c "$sleep_prog $arg" $secs $nsecs; then
82 warn "$test"
83 sleep_exit=1
84 else
85 printf "TEST PASSED: %s\n" "$test"
86 fi
87 }
88
89 sleep_err()
90 {
91 typeset test="negative test: sleep $*"
92
93 if $sleep_prog $* 2>/dev/null; then
94 warn "$test"
95 sleep_exit=1
96 else
97 printf "TEST PASSED: %s\n" "$test"
98 fi
99 }
100
101 if [[ -n $SLEEP ]]; then
102 sleep_prog=$SLEEP
103 fi
104
105 #
106 # First test basic integer values. Both in base 10 and hex.
107 #
108 sleep_one 1 1 0
109 sleep_one 23 23 0
110 sleep_one 0xff 0xff 0
111 sleep_one 123456789 123456789 0
112 sleep_one 1e8 100000000 0
113
114 #
115 # Fractional values.
116 #
117 sleep_one 2.5 2 500000000
118 sleep_one 0.9 0 900000000
119 sleep_one 34.0051 34 5100000
120 sleep_one 0x654.100 0x654 62500000
121
122 #
123 # Large values that are basically the same as infinity. The current
124 # implementation will do a sleep in groups of INT32_MAX at a time. So
125 # make sure our large values are the same.
126 #
127 sleep_one Inf 0x7fffffff 0
128 sleep_one +Inf 0x7fffffff 0
129 sleep_one 1e100 0x7fffffff 0
130 sleep_one 0x123456789abc 0x7fffffff 0
131
132 #
133 # That all of our suffixes for time increments work and make sense.
134 #
135 sleep_one 1s 1 0
136 sleep_one 1m 60 0
137 sleep_one 1h 3600 0
138 sleep_one 1d 86400 0
139 sleep_one 1w 604800 0
140 sleep_one 1y 31536000 0
141
142 sleep_one 3.5s 3 500000000
143 sleep_one 3.6d 311040 0
144 sleep_one 2.001y 63103536 0
145
146 #
147 # Now we need to go through and use ptime -m to get the slp time for
148 # things and make sure it is always greater than what we asked for and
149 # less than a bound.
150 #
151 sleep_bound 0.01
152 sleep_bound 0.1
153 sleep_bound 0.25
154 sleep_bound 0.5
155 sleep_bound 0.75
156
157 #
158 # The next set of tests are negative tests that make sure that sleep
159 # does not correctly execute in these cases.
160 #
161 sleep_err \"\"
162 sleep_err 1 2 3
163 sleep_err 1@23
164 sleep_err 0,56
165 sleep_err "hello"
166 sleep_err s
167 sleep_err 1z
168 sleep_err -- -0.3
169
170 #
171 # Test a locale that uses a ',' character (de_DE.UTF-8 is one) as the
172 # decimal point to make sure that sleep is correctly using LC_NUMERIC.
173 export LC_ALL=de_DE.UTF-8
174 sleep_err 21.45
175 sleep_one 2,5 2 500000000
176 sleep_one 34,0051 34 5100000
177 sleep_one 3,6d 311040 0
178 export LC_ALL=C.UTF-8
179
180 exit $sleep_exit