1 #
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 #
24 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27 # ident "@(#)util_common.ksh 1.2 08/12/19 SMI"
28 #
29
30 #
31 # Common utilities for test functions
32 #
33
34 TMPDIR=/tmp
35 EXECUTION_RECORD=${TMPDIR}/execution_record_$$
36
37
38 #
39 # NAME:
40 # delete_execution_record
41 #
42 # SYNOPSIS:
43 # delete_execution_record
44 #
45 # DESCRIPTION:
46 # Delete the file created to contain the record of commands executed.
47 #
48 # RETURN VALUE:
49 # Undefined (not set)
50 #
51 function delete_execution_record {
52 $RM -f $EXECUTION_RECORD 2>/dev/null
53 }
54
55
56 #
57 # NAME:
58 # display_execution_record
59 #
60 # SYNOPSIS:
61 # display_execution_record
62 #
63 # DESCRIPTION:
64 # Show the contents of the file containing a record of commands executed
65 # by a test case. A header and footer are printed to visually separate
66 # the output from the rest of the journal file. This function is
67 # typically called by a failed test purpose in order to display the
68 # exact list of commands that were executed. (Note: Do to the
69 # mysteries of how UNIX shells work, it's not unusual for output from
70 # actions taken before or after this function is called to be mixed
71 # in with the output of this function in the journal file.)
72 #
73 # RETURN VALUE:
74 # Undefined (not set)
75 #
76 function display_execution_record {
77 if [[ -z "$EXECUTION_RECORD" ]]; then
78 return
79 fi
80
81 typeset output=${TMPDIR}/final_execution_record_$$
82 echo "------Record of commands executed------" >$output
83 echo "Phase Command" >>$output
84 echo "--------- ----------------------------" >> $output
85 cat $EXECUTION_RECORD >> $output
86 echo "------End of cmd execution record------" >> $output
87 cti_reportfile $output
88 $RM -f $output 2>/dev/null
89 delete_execution_record
90 }
91
92
93 #
94 # NAME:
95 # create_execution_record
96 #
97 # SYNOPSIS:
98 # create_execution_record
99 #
100 # DESCRIPTION:
101 # Create the file to contain the record of commands executed, after
102 # first deleting any pre-existing file. This function is typically
103 # called at the beginning of a test purpose, to create/clean-out
104 # the file that contains the record of commands executed.
105 #
106 # RETURN VALUE:
107 # Not set
108 #
109 function create_execution_record {
110 if [[ -z "$EXECUTION_RECORD" ]]; then
111 return
112 fi
113
114 delete_execution_record
115 touch $EXECUTION_RECORD
116 }
117
118
119 #
120 # NAME:
121 # record_cmd_execution
122 #
123 # SYNOPSIS:
124 # record_cmd_execution <command>
125 #
126 # DESCRIPTION:
127 # Copy the specified command into the record of commands executed.
128 #
129 # This function is intended to be used to build a record of the
130 # commands executed during the course of a test purpose. The tp
131 # function, as well as utility functions it calls that execute
132 # commands, should call this function for each command they execute.
133 # The resulting record of commands can then be displayed if the test
134 # purpose fails, providing a list of the exact commands executed as
135 # an aid in reproducing/troubleshooting the failure.
136 #
137 # RETURN VALUE:
138 # Not set
139 #
140 function record_cmd_execution {
141 if [[ -z "$EXECUTION_RECORD" ]]; then
142 return
143 fi
144
145 echo "${ex_phase} $*" >> $EXECUTION_RECORD
146 }
147
148
149 #
150 # NAME:
151 # execution_phase_setup
152 #
153 # SYNOPSIS:
154 # execution_phase_setup
155 #
156 # DESCRIPTION:
157 # Set the current execution phase (used by the record_execution_record)
158 # function to 'setup'.
159 #
160 # RETURN VALUE:
161 # Not set
162 #
163 function execution_phase_setup {
164 ex_phase="setup "
165 }
166
167
168 #
169 # NAME:
170 # execution_phase_assert
171 #
172 # SYNOPSIS:
173 # execution_phase_assert
174 #
175 # DESCRIPTION:
176 # Set the current execution phase (used by the record_execution_record)
177 # function to 'assert'.
178 #
179 # RETURN VALUE:
180 # Not set
181 #
182 function execution_phase_assert {
183 ex_phase="assertion"
184 }
185
186
187 #
188 # NAME:
189 # execution_phase_cleanup
190 #
191 # SYNOPSIS:
192 # execution_phase_cleanup
193 #
194 # DESCRIPTION:
195 # Set the current execution phase (used by the record_execution_record)
196 # function to 'cleanup'.
197 #
198 # RETURN VALUE:
199 # Not set
200 #
201 function execution_phase_cleanup {
202 ex_phase="cleanup "
203 }
204
205
206 #
207 # NAME:
208 # extract_assertion_info
209 #
210 # SYNOPSIS:
211 # extract_assertion_info <test_source_filename>
212 #
213 # DESCRIPTION:
214 # A function to extract the assertion information from the test source
215 # file. It prints out the assertion information in a standard format to
216 # stdout (and thus to the journal file).
217 #
218 #
219 # ARGUMENTS:
220 # $1 - the file where the header information is. Typically this is the
221 # test case source file.
222 # $2 - this optional argument identifies a specific assertion for a file
223 # that contains multiple assertions. If provided, only this
224 # assertion will be extracted.
225 #
226 # RETURNS:
227 # No return code is set. The function prints information to stdout
228 # (and thus to the journal file).
229 #
230 function extract_assertion_info {
231
232 typeset tmpfile=${TMPDIR}/extract_assertion_info_$$
233
234 # Extract the assertion info from the test source file and
235 # place it in a temporary file.
236 nawk -v specific_assert=$2 '
237
238 BEGIN {
239 in_assertion = 0;
240 turn_off_printing = 0;
241 }
242
243
244 #
245 # End of the .spec content. This finds the end of the assertion
246 #
247 /^# +end +__stc_assertion/ {
248 in_assertion = 0;
249 next;
250 }
251
252
253
254 #
255 # Beginning of the .spec content. This finds the beginning
256 # of the assertion.
257 #
258 /^# +start +__stc_assertion__/ {
259 in_assertion = 1;
260 next;
261 }
262
263
264 #
265 # This grabs the "ASSERTION: testname" line. If no specific
266 # assertion was identified we will grab any "ASSERTION:" line we
267 # find. If a specific assertion was identified, make sure the
268 # "ASSERTION:" line matches it -- if not, this assertion is not
269 # the one we are looking for.
270 #
271 /^.+ASSERTION:/ && (in_assertion) {
272 if ( specific_assert == "" || specific_assert == $NF ) {
273 a=substr($0, index($0, "#") + length("#"));
274 #remove any leading spaces
275 sub(/^ +/, "", a);
276 printf("%s\n\n", a);
277 turn_off_printing = 1;
278 next;
279 } else {
280 in_assertion = 0;
281 }
282 }
283
284 #
285 # This prints the actual assertion statement. STC calls this the
286 # description and requires one for every ASSERTION:.
287
288 #
289 /^.+DESCRIPTION:/ && (in_assertion) {
290 a=substr($0, index($0, "DESCRIPTION:") + length("DESCRIPTION:"));
291 a=substr($0, index($0, "#") + length("#"));
292 #remove any leading spaces
293 sub(/^ +/, "", a);
294 printf("%s\n\n", a);
295 turn_off_printing = 0;
296 next;
297 }
298
299 #
300 # List of interfaces targeted by the current assertion. STC requires
301 # one of these for every ASSERTION:
302 #
303 #/^.+INTERFACES:/ && (in_assertion) {
304 # in_assertion = 0;
305 #}
306
307 /^.+STRATEGY:/ && (in_assertion) {
308 #use in_assertion =1 to print the strategy.
309 in_assertion = 0;
310
311 #use in_assertion =1 to print the strategy.
312 in_assertion = 0;
313 }
314
315 # Body of the assertion comments.
316 #
317 (in_assertion) && length && !(turn_off_printing) {
318 a=substr($0,index($0,"#")+1);
319 printf("%s\n", a);
320 }
321
322 ' $1 > $tmpfile
323
324 # Copy the extracted information into the journal and then
325 # clean up after ourselves.
326 cti_reportfile $tmpfile
327 rm -rf $tmpfile
328 }
329
330
331 #
332 # NAME:
333 # extract_line_from_file
334 #
335 # SYNOPSIS:
336 # extract_line_from_file <filename> <line number>
337 #
338 # DESCRIPTION:
339 # Verify that the specified file exists and is readable, then extract
340 # the specified line from the file. The line extracted is echoed to
341 # stdout so that it can be captured by the calling function.
342 #
343 # RETURN VALUES:
344 # 0 Successfully extracted the specified line from the file.
345 # 1 Unable to access file.
346 # 2 Could not locate the specified line in the file.
347 #
348 function extract_line_from_file {
349 typeset filename="$1"
350 typeset line_number="$2"
351
352 # Make sure the file exists and is readable.
353 if [[ ! -r "$filename" ]]; then
354 cti_report "File $filename doesn't exist or isn't readable" \
355 "by this process"
356 return 1
357 fi
358
359 # Read in each line of the file until we've obtained the Nth line
360 # (where N equals the argument passed in specifying the desired line
361 # number).
362 typeset line_num=0
363 typeset matching_line=""
364 { while read line; do
365 let line_num=$line_num+1
366 if (( $line_num == $line_number )); then
367 matching_line="$line"
368 break
369 fi
370 done } < $filename
371
372 # Make sure we actually obtained something.
373 if [[ -z "$matching_line" ]]; then
374 cti_report "Unable to find line number $line_number in file" \
375 "$filename"
376 return 2
377 fi
378
379 # Print the line to stdout so that the calling function can capture it.
380 echo $matching_line
381
382 return 0
383 }
384
385
386 #
387 # NAME
388 # tp_within_parameters
389 #
390 # SYNOPSIS
391 # tp_within_parameters <list name> <param> [<list name> <param> ...]
392 #
393 # DESCRIPTION
394 # This function was designed primarily for use by dynamically generated
395 # tests. In these tests the same test purposes is reused multiple
396 # times, executing with a different combination of parameter values each
397 # time. The suite allows users to restrict which parameters values are
398 # desired by setting variables in the file:
399 #
400 # $TET_SUITE_ROOT/lofi/config/test_config
401 #
402 # (or by making the same variable assignments on the command line).
403 # This function is called by such test purposes to determine if the
404 # set of parameters for the current iteration fits within any
405 # restrictions the user might have set.
406 #
407 # For each parameter the test purpose is concerned about, it passes in
408 # the name of the variable containing the list of desired parameters
409 # along with the current value of that parameter. If the list variable
410 # specified is not set then the user has not placed restrictions on that
411 # particular parameter. If the variable is set, then the function
412 # compares the current parameter value against the list of desired
413 # values. If the parameter value is not on the 'desired' list the test
414 # purpose should not be run.
415 #
416 # Multiple parameter lists and current values can be specified in one
417 # call to this function (see SYNOPSIS). The function evaluates all of
418 # them, and if any one parameter value is found to be missing from the
419 # corresponding list of desired values then the function calls
420 # cti_unsupported() and gives a return value of 1. When this happens,
421 # the calling test purpose should return immediately.
422 #
423 # Note that while this function was written for test purposes using
424 # dynamically-generated test parameters, static test purposes can make
425 # use of it as well.
426 #
427 # RETURN VALUES
428 # 0 Test purpose fits within current paramters and should be run
429 # 1 Test purpose doesn't fit current parameters and should not run
430 function tp_within_parameters {
431
432 typeset param_list_name param_list current_param match
433 typeset status=0
434
435 while [[ -n "$@" ]]; do
436 # Extract first variable name and current parameter value from
437 # the head of the list.
438 unset match
439 param_list_name="$1"
440 current_param="$2"
441 shift 2
442
443 # Use 'eval' to get at the contents of the specified variable,
444 # which will provide us with the list of desired values.
445 eval param_list=\$$param_list_name
446
447 # If the list of desired values is empty, the user placed no
448 # restrictions on this paramter and we can skip over it. If
449 # the list isn't empty, see if the current parameter value is
450 # on the 'desired' list.
451 if [[ -n "$param_list" ]]; then
452 for param in $param_list; do
453 if [[ "$param" = "$current_param" ]]; then
454 match=1
455 fi
456 done
457 if [[ -z "$match" ]]; then
458 cti_report "Parameter '$current_param' not" \
459 "in $param_list_name ('$param_list')"
460 status=1
461 fi
462 fi
463 done
464
465 if (( $status != 0 )); then
466 cti_untested "Test purpose does not fit user-defined" \
467 "execution criteria"
468 fi
469 return $status
470 }