Initial commit
[authen-passphrase-scrypt.git] / scrypt-1.2.1 / tests / shared_test_functions.sh
1 #!/bin/sh
2
3 ### Definitions
4 #
5 # This test suite uses the following terminology:
6 # - scenario: a series of commands to test. Each must be in a
7 # separate file, and must be completely self-contained
8 # (other than the variables listed below).
9 # - check: a series of commands that produces an exit code which
10 # the test suite should check. A scenario may contain any
11 # number of checks.
12 #
13 ### Design
14 #
15 # The main function is scenario_runner(scenario_filename), which
16 # takes a scenario file as the argument, and runs a
17 # scenario_cmd()
18 # function which was defined in that file.
19 #
20 ### Variables
21 #
22 # Wherever possible, this suite uses local variables and
23 # explicitly-passed arguments, with the following exceptions:
24 # - s_basename: this is the basename for the scenario's temporary
25 # and log files.
26 # - s_val_basename: this is the basename for the scenario's
27 # valgrind log files.
28 # - s_count: this is the count of the scenario's checks (so that
29 # each check can have distinct files).
30 # - s_retval: this is the overall exit code of the scenario.
31 # - c_exitfile: this contains the exit code of each check.
32 # - c_valgrind_min: this is the minimum value of USE_VALGRIND
33 # which will enable valgrind checking for this check.
34 # - c_valgrind_cmd: this is the valgrind command (including
35 # appropriate log file) if necessary, or is "" otherwise.
36
37 set -o nounset
38
39 ### Constants
40 out="tests-output"
41 out_valgrind="tests-valgrind"
42 valgrind_suppressions="${out_valgrind}/suppressions"
43 valgrind_suppressions_log="${out_valgrind}/suppressions.pre"
44
45 # Keep the user-specified ${USE_VALGRIND}, or initialize to 0.
46 USE_VALGRIND=${USE_VALGRIND:-0}
47
48 # A non-zero value unlikely to be used as an exit code by the programs being
49 # tested.
50 valgrind_exit_code=108
51
52 ## prepare_directories():
53 # Delete any old directories, and create new ones as necessary. Must be run
54 # after check_optional_valgrind().
55 prepare_directories() {
56 # Clean up previous directories.
57 if [ -d "${out}" ]; then
58 rm -rf ${out}
59 fi
60 if [ -d "${out_valgrind}" ]; then
61 rm -rf ${out_valgrind}
62 fi
63
64 # Make new directories.
65 mkdir ${out}
66 if [ "$USE_VALGRIND" -gt 0 ]; then
67 mkdir ${out_valgrind}
68 fi
69 }
70
71 ## find_system (cmd, args...):
72 # Looks for ${cmd} in the $PATH, and ensure that it supports ${args}.
73 find_system() {
74 cmd=$1
75 cmd_with_args=$@
76 # Look for ${cmd}.
77 system_binary=`command -v ${cmd}`
78 if [ -z "${system_binary}" ]; then
79 system_binary=""
80 printf "System ${cmd} not found.\n" 1>&2
81 # If the command exists, check it ensures the ${args}.
82 elif ${cmd_with_args} 2>&1 >/dev/null | \
83 grep -qE "(invalid|illegal) option"; then
84 system_binary=""
85 printf "Cannot use system ${cmd}; does not" 1>&2
86 printf " support necessary arguments.\n" 1>&2
87 fi
88 echo "${system_binary}"
89 }
90
91 ## check_optional_valgrind ():
92 # Return a $USE_VALGRIND variable defined; if it was previously defined and
93 # was greater than 0, then check that valgrind is available in the $PATH.
94 check_optional_valgrind() {
95 if [ "$USE_VALGRIND" -gt 0 ]; then
96 # Look for valgrind in $PATH.
97 if ! command -v valgrind >/dev/null 2>&1; then
98 printf "valgrind not found\n" 1>&2
99 exit 1
100 fi
101 fi
102 }
103
104 ## ensure_valgrind_suppresssion (potential_memleaks_binary):
105 # Runs the ${potential_memleaks_binary} through valgrind, keeping
106 # track of any apparent memory leak in order to suppress reporting
107 # those leaks when testing other binaries.
108 ensure_valgrind_suppression() {
109 potential_memleaks_binary=$1
110
111 # Quit if we're not using valgrind.
112 if [ ! "$USE_VALGRIND" -gt 0 ]; then
113 return
114 fi;
115 printf "Generating valgrind suppressions... "
116
117 # Run valgrind on the binary, sending it a "\n" so that
118 # a test which uses STDIN will not wait for user input.
119 printf "\n" | (valgrind --leak-check=full --show-leak-kinds=all \
120 --gen-suppressions=all \
121 --log-file=${valgrind_suppressions_log} \
122 ${potential_memleaks_binary})
123
124 # Strip out useless parts from the log file, as well as
125 # removing references to the main and "pl_*" ("potential
126 # loss") functions so that the suppressions can apply to
127 # other binaries.
128 (grep -v "^==" ${valgrind_suppressions_log} \
129 | grep -v " fun:pl_" - \
130 | grep -v " fun:main" - \
131 > ${valgrind_suppressions} )
132
133 # Clean up
134 rm -f ${valgrind_suppressions_log}
135 printf "done.\n"
136 }
137
138 ## setup_check_variables ():
139 # Set up the "check" variables ${c_exitfile} and ${c_valgrind_cmd}, the
140 # latter depending on the previously-defined ${c_valgrind_min}.
141 # Advances the number of checks ${s_count} so that the next call to this
142 # function will set up new filenames.
143 setup_check_variables() {
144 # Set up the "exit" file.
145 c_exitfile="${s_basename}-`printf %02d ${s_count}`.exit"
146
147 # If we don't have a suppressions file, don't try to use it.
148 if [ ! -e ${valgrind_suppressions} ]; then
149 valgrind_suppressions=/dev/null
150 fi
151
152 # Set up the valgrind command if $USE_VALGRIND is greater
153 # than or equal to ${valgrind_min}; otherwise, produce an
154 # empty string. Using --error-exitcode means that if
155 # there is a serious problem (such that scrypt calls
156 # exit(1)) *and* a memory leak, the test suite reports an
157 # exit value of ${valgrind_exit_code}. However, if there
158 # is a serious problem but no memory leak, we still
159 # receive a non-zero exit code. The most important thing
160 # is that we only receive an exit code of 0 if both the
161 # program and valgrind are happy.
162 if [ "$USE_VALGRIND" -ge "${c_valgrind_min}" ]; then
163 val_logfilename=${s_val_basename}-`printf %02d ${s_count}`.log
164 c_valgrind_cmd="valgrind \
165 --log-file=${val_logfilename} \
166 --leak-check=full --show-leak-kinds=all \
167 --errors-for-leak-kinds=all \
168 --suppressions=${valgrind_suppressions} \
169 --error-exitcode=${valgrind_exit_code} "
170 else
171 c_valgrind_cmd=""
172 fi
173
174 # Advances the number of checks.
175 s_count=$((s_count + 1))
176 }
177
178 ## get_val_logfile (val_basename, exitfile):
179 # Return the valgrind logfile corresponding to ${exitfile}.
180 get_val_logfile() {
181 val_basename=$1
182 exitfile=$2
183 num=`echo "${exitfile}" | rev | cut -c 1-7 | rev | cut -c 1-2 `
184 echo "${val_basename}-${num}.log"
185 }
186
187 ## notify_success_or_fail (log_basename, val_log_basename):
188 # Examine all "exit code" files beginning with ${log_basename} and
189 # print "SUCCESS!" or "FAILED!" as appropriate. If the test failed
190 # with the code ${valgrind_exit_code}, output the appropriate
191 # valgrind logfile to stdout.
192 notify_success_or_fail() {
193 log_basename=$1
194 val_log_basename=$2
195
196 # Check each exitfile.
197 for exitfile in `ls ${log_basename}-*.exit | sort`; do
198 ret=`cat ${exitfile}`
199 if [ "${ret}" -lt 0 ]; then
200 echo "SKIP!"
201 return
202 fi
203 if [ "${ret}" -gt 0 ]; then
204 echo "FAILED!"
205 retval=${ret}
206 if [ "${ret}" -eq "${valgrind_exit_code}" ]; then
207 val_logfilename=$( get_val_logfile \
208 ${val_log_basename} ${exitfile} )
209 cat ${val_logfilename}
210 fi
211 s_retval=${ret}
212 return
213 fi
214 done
215
216 echo "SUCCESS!"
217 }
218
219 ## scenario_runner (scenario_filename):
220 # Runs a test scenario from ${scenario_filename}.
221 scenario_runner() {
222 scenario_filename=$1
223 basename=`basename ${scenario_filename} .sh`
224 printf " ${basename}... " 1>&2
225
226 # Initialize "scenario" and "check" variables.
227 s_basename=${out}/${basename}
228 s_val_basename=${out_valgrind}/${basename}
229 s_count=0
230 c_exitfile=/dev/null
231 c_valgrind_min=9
232 c_valgrind_cmd=""
233
234 # Load scenario_cmd() from the scenario file.
235 unset scenario_cmd
236 . ${scenario_filename}
237 if ! command -v scenario_cmd 1>/dev/null ; then
238 printf "ERROR: scenario_cmd() is not defined in\n"
239 printf " ${scenario_filename}\n"
240 exit 1
241 fi
242
243 # Run the scenario command.
244 scenario_cmd
245
246 # Print PASS or FAIL, and return result.
247 s_retval=0
248 notify_success_or_fail ${s_basename} ${s_val_basename}
249
250 return "${s_retval}"
251 }
252
253 ## run_scenarios (scenario_filenames):
254 # Runs all scenarios matching ${scenario_filenames}.
255 run_scenarios() {
256 printf -- "Running tests\n"
257 printf -- "-------------\n"
258 scenario_filenames=$@
259 for scenario in ${scenario_filenames}; do
260 # We can't call this function with $( ... ) because we
261 # want to allow it to echo values to stdout.
262 scenario_runner ${scenario}
263 retval=$?
264 if [ ${retval} -gt 0 ]; then
265 exit ${retval}
266 fi
267 done
268 }
This page took 0.030627 seconds and 4 git commands to generate.