1#!/bin/sh
2#
3# Copyright (C) 2009-2020 Free Software Foundation, Inc.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <https://www.gnu.org/licenses/>.
17#
18
19# This program is a test driver that supports running a test under valgrind.
20# Usage: run-test CHECKER PROGRAM [ARGUMENT...]
21
22progname=$0
23
24# func_usage
25# outputs to stdout the --help usage message.
26func_usage ()
27{
28  echo "\
29Usage: run-test [OPTION...] CHECKER PROGRAM [ARGUMENT...]
30
31Runs PROGRAM under the control of CHECKER.
32
33CHECKER may be empty or a valgrind command with some options, such as
34'valgrind --tool=memcheck --num-callers=20 --leak-check=yes --leak-resolution=high --show-reachable=yes'.
35
36When CHECKER is not empty, it is recommended that the package has been
37configured with
38  --disable-shared     so that tests are real executables and not libtool
39                       wrapper scripts, and
40  CFLAGS=\"-g\"          so that valgrind shows line numbers.
41
42Report bugs to Bruno Haible."
43}
44
45# func_version
46# outputs to stdout the --version message.
47func_version ()
48{
49  echo "\
50run-test (GNU gnulib)
51Copyright (C) 2020 Free Software Foundation, Inc.
52License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
53This is free software: you are free to change and redistribute it.
54There is NO WARRANTY, to the extent permitted by law.
55
56Written by" "Bruno Haible"
57}
58
59# func_fatal_error message
60# outputs to stderr a fatal error message, and terminates the program.
61# Input:
62# - progname                 name of this program
63func_fatal_error ()
64{
65  echo "$progname: *** $1" 1>&2
66  echo "$progname: *** Stop." 1>&2
67  func_exit 1
68}
69
70# Command-line option processing.
71# Removes the OPTIONS from the arguments. Sets the variables:
72# - checker        wrapper program for executables
73{
74  while test $# -gt 0; do
75    case "$1" in
76      --help | --hel | --he | --h )
77        func_usage
78        exit $? ;;
79      --version | --versio | --versi | --vers | --ver | --ve | --v )
80        func_version
81        exit $? ;;
82      -- )
83        # Stop option processing
84        shift
85        break ;;
86      -* )
87        echo "run-test: unknown option $1" 1>&2
88        echo "Try 'run-test --help' for more information." 1>&2
89        exit 1 ;;
90      * )
91        break ;;
92    esac
93  done
94
95  if test $# -lt 2; then
96    echo "run-test: too few arguments" 1>&2
97    echo "Try 'run-test --help' for more information." 1>&2
98    exit 1
99  fi
100
101  checker="$1"
102  shift
103}
104
105if test -z "$checker"; then
106  # No checker. Run the test directly.
107  case "$1" in
108    *.sh)
109     # Support environments where sh exists but not /bin/sh.
110     exec sh "$@"
111     ;;
112    *)
113     exec "$@"
114     ;;
115  esac
116else
117  # Using valgrind. We want to apply valgrind only to executables, not to
118  # shell scripts, because
119  # 1. we don't want to look for memory leaks in bash,
120  # 2. on a bi-arch system, we would get an error message such as
121  #    "valgrind: wrong executable class (eg. 32-bit instead of 64-bit)".
122  case "$1" in
123    *.sh)
124      # A shell script. Ignore the checker.
125      # Support environments where sh exists but not /bin/sh.
126      exec sh "$@"
127      ;;
128    *)
129      # The 'file' command is not portable enough. So, look
130      # at the first two bytes of the file. Are they '#!'?
131      if { if od -A x < /dev/null >/dev/null 2>/dev/null; then
132             # Use POSIX od.
133             firstbytes=`od -A n -t o1 -N 2 < "$1" | tr -d ' '`
134           else
135             # Use BSD hexdump.
136             firstbytes=`dd if="$1" bs=1 count=2 2>/dev/null | hexdump -e '1/1 "%03o"'`
137           fi
138           test "$firstbytes" = "043041"
139         }; then
140        # A shell script. Ignore the checker.
141        exec "$@"
142      else
143        # An executable. Use the checker.
144        exec $checker "$@"
145      fi
146      ;;
147  esac
148fi
149