No empty .Rs/.Re
[netbsd-mini2440.git] / tests / util / ps / t_ps.sh
blobf829aecc60478f4f6b9a9afe5aeb27946e991878
1 # $NetBSD: t_ps.sh,v 1.1 2007/11/12 15:14:02 jmmv Exp $
3 # Copyright (c) 2007 The NetBSD Foundation, Inc.
4 # All rights reserved.
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.
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
28 # the implementation of "ps" to test
29 : ${TEST_PS:="ps"}
30 # tab and newline characters
31 tab="$(printf '\t')"
32 # nl="$(printf '\n')" doesn't work
33 nl='
37 # Parse the "keywords" file into a load of shell variables
39 setup_keywords()
41 # Set variables representing the header text
42 # for all normal keywords (except aliases), and
43 # for regular expressions to match the text in left- or
44 # right-justified columns.
45 # For example, head_text_p_cpu="%CPU" head_regexp_p_cpu=" *%CPU".
46 while read keyword heading flag
48 case "$keyword" in
49 ''|\#*) continue
51 esac
52 [ x"$flag" = x"ALIAS" ] && continue
53 kvar="${keyword}"
54 case "${keyword}" in
55 %*) kvar="p_${keyword#%}"
57 esac
58 eval head_text_${kvar}=\'"${heading}"\'
59 case "${flag}" in
60 '') # right justified
61 eval head_regexp_${kvar}=\'" *${heading}"\'
63 LJUST) # left justified
64 eval head_regexp_${kvar}=\'"${heading} *"\'
66 *) atf_fail "unknown flag in keywords"
68 esac
69 done <"$(atf_get_srcdir)/keywords"
71 # Now do the aliases.
72 while read keyword heading flag
74 case "$keyword" in
75 ''|\#*) continue
77 esac
78 [ x"$flag" != x"ALIAS" ] && continue
79 kvar="${keyword}"
80 avar="${heading}"
81 case "${keyword}" in
82 %*) kvar="p_${keyword#%}"
84 esac
85 case "${heading}" in
86 %*) avar="p_${heading#%}"
88 esac
89 eval head_text_${kvar}=\"\$head_text_${avar}\"
90 eval head_regexp_${kvar}=\"\$head_regexp_${avar}\"
91 done <"$(atf_get_srcdir)/keywords"
93 # default sets of keywords
94 default_keywords='pid tty stat time command'
95 j_keywords='user pid ppid pgid sess jobc state tt time command'
96 l_keywords='uid pid ppid cpu pri nice vsz rss wchan state tt time command'
97 s_keywords='uid pid ppid cpu lid nlwp pri nice vsz rss wchan lstate tt time command'
98 u_keywords='user pid %cpu %mem vsz rss tt state start time command'
99 v_keywords='pid state time sl re pagein vsz rss lim tsiz %cpu %mem command'
102 # Convert a list of keywords like "pid comm" to a regexp
103 # like " *PID COMMAND *"
104 heading_keywords_to_regexp()
106 local keywords="$1"
107 local regexp
108 regexp="$(echo "$keywords" | \
109 sed -E -e 's/\%/p_/g' -e 's/(^| )/\1\$head_regexp_/g')"
110 eval regexp=\""${regexp}"\"
111 regexp="^${regexp}\$"
112 echo "$regexp"
116 # Check that a string matches a regexp; use the specified id
117 # in error or success messages.
119 check_regexp() {
120 local id="$1" string="$2" regexp="$3"
121 if ! expr "$string" : "$regexp" >/dev/null
122 then
123 atf_fail "${id}: expected [${regexp}], got [${string}]"
124 false
129 # Run "ps $args -p $$"; check that only one line is printed,
130 # without a preceding header line.
132 check_no_heading_line()
134 local args="$1"
135 local output="$(eval "${TEST_PS} $args -p $$")"
136 case "$output" in
137 *"$nl"*)
138 local firstline="${output%%${nl}*}"
139 atf_fail "check_no_heading_line [$args] got [$firstline]"
143 esac
147 # Run "ps $args"; check that the heading matches the expected regexp.
149 check_heading_regexp()
151 args="$1"
152 regexp="$2"
153 actual="$( eval "${TEST_PS} $args" | sed -e 1q )"
154 check_regexp "heading [$args]" "${actual}" "${regexp}"
158 # Run "ps $args"; check that the heading matches a regexp constructed
159 # from the specified keywords.
161 check_heading_keywords()
163 args="$1"
164 keywords="$2"
165 check_heading_regexp "$args" "$(heading_keywords_to_regexp "$keywords")"
169 # Try several variations on "ps $flag", "ps -$flag", etc.,
170 # and check that the heading always has the correct keywords.
172 check_heading_variations()
174 flag="$1"
175 keywords="$2"
176 for args in "$flag" "-$flag" "-$flag$flag -$flag"; do
177 check_heading_keywords "$args" "$keywords"
178 done
181 atf_test_case default_columns
182 default_columns_head()
184 atf_set "descr" "Checks that the default set of columns is correct" \
185 "and also check that the columns printed by the -j," \
186 "-l, -s, -u and -v flags alone are correct"
188 default_columns_body()
190 setup_keywords
191 check_heading_keywords '' "$default_keywords"
192 check_heading_variations 'j' "$j_keywords"
193 check_heading_variations 'l' "$l_keywords"
194 check_heading_variations 's' "$s_keywords"
195 check_heading_variations 'u' "$u_keywords"
196 check_heading_variations 'v' "$v_keywords"
199 atf_test_case minus_O
200 minus_O_head()
202 atf_set "descr" "Checks that 'ps -O foo' inserts columns just after" \
203 "the pid column"
205 minus_O_body()
207 setup_keywords
208 check_heading_keywords '-O %cpu,%mem' \
209 "$(echo "${default_keywords}" | sed -e 's/pid/pid %cpu %mem/')"
210 check_heading_keywords '-O %cpu -O %mem' \
211 "$(echo "${default_keywords}" | sed -e 's/pid/pid %cpu %mem/')"
212 check_heading_keywords '-O%cpu -O%mem' \
213 "$(echo "${default_keywords}" | sed -e 's/pid/pid %cpu %mem/')"
216 atf_test_case minus_o
217 minus_o_head()
219 atf_set "descr" "Checks simple cases of 'ps -o foo' to control which" \
220 "columns are printed; this does not test header" \
221 "overriding via 'ps -o foo=BAR'"
223 minus_o_body()
225 setup_keywords
226 # Keywords for "-o name" override the default display
227 check_heading_keywords '-o pid,%cpu,%mem' \
228 "pid %cpu %mem"
229 check_heading_keywords '-o pid -o %cpu,%mem' \
230 "pid %cpu %mem"
231 check_heading_keywords '-opid -o %cpu,%mem' \
232 "pid %cpu %mem"
233 # Space works like comma
234 check_heading_keywords '-opid -o "%cpu %mem"' \
235 "pid %cpu %mem"
236 # Check missing pid
237 check_heading_keywords '-o comm' \
238 "comm"
239 # Check pid present but not first
240 check_heading_keywords '-o comm,pid' \
241 "comm pid"
244 atf_test_case override_heading_simple
245 override_heading_simple_head()
247 atf_set "descr" "Tests simple uses of header overriding via" \
248 "'ps -o foo=BAR'. This does not test columns " \
249 "with null headings, or headings with embedded" \
250 "space, ',' or '='."
252 override_heading_simple_body()
254 setup_keywords
255 check_heading_regexp '-o pid=PPP -o comm' \
256 '^ *PPP '"${head_text_comm}"'$' # no trailing space
257 check_heading_regexp '-o pid=PPP -o comm=CCC' \
258 '^ *PPP CCC$'
259 check_heading_regexp '-o pid,comm=CCC' \
260 '^'"${head_regexp_pid}"' CCC$'
261 check_heading_regexp '-o pid -o comm=CCC' \
262 '^'"${head_regexp_pid}"' CCC$'
263 # Check missing pid
264 check_heading_regexp '-o comm=CCC' \
265 '^CCC$'
266 # Check pid present but not first
267 check_heading_regexp '-o comm=CCC -o pid=PPP' \
268 '^CCC *PPP$'
269 check_heading_regexp '-o comm,pid=PPP' \
270 '^'"${head_regexp_comm}"' *PPP$'
273 atf_test_case override_heading_embedded_specials
274 override_heading_embedded_specials_head()
276 atf_set "descr" "Tests header overriding with embedded space," \
277 "',' or '='. Everything after the first '='" \
278 "is part of the heading."
280 override_heading_embedded_specials_body()
282 setup_keywords
283 # Check embedded "," or "=" in override header.
284 check_heading_regexp '-o comm,pid==' \
285 '^'"${head_regexp_comm}"' *=$'
286 check_heading_regexp '-o comm,pid=,' \
287 '^'"${head_regexp_comm}"' *,$'
288 check_heading_regexp '-o pid=PPP,comm' \
289 '^ *PPP,comm$' # not like '-o pid=PPP -o comm'
290 check_heading_regexp '-o pid=PPP,comm=CCC' \
291 '^ *PPP,comm=CCC$' # not like '-o pid=PPP -o comm=CCC'
292 check_heading_regexp '-o comm,pid=PPP,QQQ' \
293 '^'"${head_regexp_comm}"' *PPP,QQQ$'
294 check_heading_regexp '-o comm,pid=ppid,tty=state' \
295 '^'"${head_regexp_comm}"' *ppid,tty=state$'
296 # Check embedded space or tab in override header.
297 check_heading_regexp '-o comm,pid="PPP QQQ"' \
298 '^'"${head_regexp_comm}"' *PPP QQQ$'
299 check_heading_regexp '-o comm,pid="PPP${tab}QQQ"' \
300 '^'"${head_regexp_comm}"' *PPP'"${tab}"'QQQ$'
303 atf_test_case override_heading_some_null
304 override_heading_some_null_head()
306 atf_set "descr" "Tests simple uses of null column headings" \
307 "overriding via 'ps -o foo=BAR -o baz='. This" \
308 "does not test the case where all columns have" \
309 "null headings."
311 override_heading_some_null_body()
313 setup_keywords
314 check_heading_regexp '-o pid=PPP -o comm=' \
315 '^ *PPP *$'
316 check_heading_regexp '-o pid= -o comm=CCC' \
317 '^ * CCC$'
318 check_heading_regexp '-o pid -o comm=' \
319 '^'"${head_regexp_pid}"' *$'
320 # Check missing pid
321 check_heading_regexp '-o ppid= -o comm=CCC' \
322 '^ * CCC$'
323 check_heading_regexp '-o ppid=PPP -o comm=' \
324 '^ *PPP *$'
325 # Check pid present but not first
326 check_heading_regexp '-o comm= -o pid=PPP' \
327 '^ * PPP$'
328 check_heading_regexp '-o comm,pid=' \
329 '^'"${head_regexp_comm}"' *$'
330 # A field with a null custom heading retains a minimum width
331 # derived from the default heading. This does not apply
332 # to a field with a very short (non-null) custom heading.
334 # We choose "holdcnt" as a column whose width is likely to be
335 # determined entirely by the header width, because the values
336 # are likely to be very small.
337 check_heading_regexp '-o holdcnt -o holdcnt -o holdcnt' \
338 '^HOLDCNT HOLDCNT HOLDCNT$'
339 check_heading_regexp '-o holdcnt -o holdcnt= -o holdcnt' \
340 '^HOLDCNT HOLDCNT$'
341 check_heading_regexp '-o holdcnt -o holdcnt=HH -o holdcnt' \
342 '^HOLDCNT HH HOLDCNT$'
345 atf_test_case override_heading_all_null
346 override_heading_all_null_head()
348 atf_set "descr" "Tests the use of 'ps -o foo= -o bar=' (with a" \
349 "null heading for every column). The heading" \
350 "should not be printed at all in this case."
352 override_heading_all_null_body()
354 setup_keywords
355 # A heading with a space is not a null heading,
356 # so should not be suppressed
357 check_heading_regexp '-o comm=" "' \
358 '^ *$'
359 # Null headings should be suppressed
360 check_no_heading_line '-o pid= -o comm='
361 check_no_heading_line '-o pid= -o comm='
362 # Check missing pid
363 check_no_heading_line '-o ppid='
364 check_no_heading_line '-o comm='
365 check_no_heading_line '-o command='
366 check_no_heading_line '-o ppid= -o comm='
367 check_no_heading_line '-o comm= -o ppid='
368 # Check pid present but not first
369 check_no_heading_line '-o comm= -o pid='
370 check_no_heading_line '-o ppid= -o pid= -o command='
373 atf_test_case duplicate_column
374 duplicate_column_head()
376 atf_set "descr" "Tests the use of -o options to display the" \
377 "same column more than once"
379 duplicate_column_body()
381 setup_keywords
382 # two custom headers
383 check_heading_regexp '-o pid=PPP -o pid=QQQ' \
384 '^ *PPP *QQQ$'
385 # one custom header, before and after default header
386 check_heading_regexp '-o pid=PPP -o pid' \
387 '^ *PPP '"${head_regexp_pid}"'$'
388 check_heading_regexp '-o pid -o pid=QQQ' \
389 '^'"${head_regexp_pid}"' *QQQ$'
390 # custom headers both before and after default header
391 check_heading_regexp '-o pid=PPP -o pid -o pid=QQQ' \
392 '^ *PPP '"${head_regexp_pid}"' *QQQ$'
395 atf_init_test_cases() {
396 atf_add_test_case default_columns
397 atf_add_test_case minus_O
398 atf_add_test_case minus_o
399 atf_add_test_case override_heading_simple
400 atf_add_test_case override_heading_embedded_specials
401 atf_add_test_case override_heading_some_null
402 atf_add_test_case override_heading_all_null
403 atf_add_test_case duplicate_column