1 #!/bin/sh 2 3 # This tool runs the toolchain for each of the tests, optionally building and 4 # running the test programs. 5 # 6 # Copyright (C) 2016, 2017, 2021 Paul Boddie <paul@boddie.org.uk> 7 # 8 # This program is free software; you can redistribute it and/or modify it under 9 # the terms of the GNU General Public License as published by the Free Software 10 # Foundation; either version 3 of the License, or (at your option) any later 11 # version. 12 # 13 # This program is distributed in the hope that it will be useful, but WITHOUT 14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 # details. 17 # 18 # You should have received a copy of the GNU General Public License along with 19 # this program. If not, see <http://www.gnu.org/licenses/>. 20 21 PROGNAME=$0 22 OPTION=$1 23 shift 1 24 MAKE_OPTIONS="$*" 25 26 LPLC="./lplc" 27 DATADIR="_main.lplc" 28 TESTINPUT="_results/testinput.txt" 29 30 # Expect failure from the "bad" tests. 31 32 expect_failure() { 33 echo "$FILENAME" | grep -q '_bad[._/]' 34 return $? 35 } 36 37 # Check deduction output for type warnings, indicating that the program contains 38 # errors. 39 40 check_type_warnings() { 41 42 if [ -e "$DATADIR/_deduced/type_warnings" ] && \ 43 [ `stat -c %s "$DATADIR/_deduced/type_warnings"` -ne 0 ] ; then 44 45 echo "Type warnings in deduced information." 1>&2 46 return 1 47 fi 48 49 return 0 50 } 51 52 # Main program. 53 54 # Show help if requested. 55 56 if [ "$OPTION" = '--help' ] ; then 57 cat 1>&2 <<EOF 58 Usage: $0 [ --build | --build-only | --run-built ] [ <make options> ] 59 60 Run the toolchain over all tests in the tests directory. 61 62 If --build is specified, the generated program code will be compiled and run, 63 with the results collected in the _results directory. 64 65 If --build-only is specified, the generated programs themselves will be 66 collected in the _results directory, each taking their name from that of the 67 main program file used as input. 68 69 If --run-built is specified, any generated programs in the _results directory 70 will be run and their output collected in the _results directory. 71 72 By using --build-only on one system, copying the _results directory to another 73 system, and then running this script with the --run-built option on the other 74 system, it becomes possible to test the toolchain output on the other system 75 without needing to actually use the toolchain on that system. This permits the 76 testing of cross-compiled programs. 77 78 For example, to build on one system but not run the generated programs: 79 80 ARCH=mipsel-linux-gnu $PROGNAME --build-only 81 82 And to run the generated programs on another system: 83 84 $PROGNAME --run-built 85 86 Of course, this script will need to be copied to the target system if it is not 87 already available there. 88 89 Build and output logs are stored in the _results directory with the .build and 90 .out suffixes employed respectively, one of each kind for each generated 91 program. 92 93 The make options can be used to specify things like the number of processes 94 employed to perform a build of each program. For example: 95 96 $PROGNAME --build -j8 97 EOF 98 exit 1 99 fi 100 101 # If just running existing programs, do so now and exit. 102 103 if [ "$OPTION" = '--run-built' ] ; then 104 for FILENAME in _results/* ; do 105 TESTNAME=`basename "$FILENAME"` 106 107 # Skip non-program files. 108 109 if [ ! -x "$FILENAME" ]; then 110 continue 111 fi 112 113 echo "$FILENAME..." 1>&2 114 OUTLOG="_results/$TESTNAME.out" 115 OUTCODE="_results/$TESTNAME.exitcode" 116 117 echo " (run)..." 1>&2 118 "$FILENAME" > "$OUTLOG" < "$TESTINPUT" 119 echo $? > "$OUTCODE" 120 done 121 122 exit 0 123 fi 124 125 # Make any required results directory. 126 127 if [ "$OPTION" = '--build' ] || [ "$OPTION" = '--build-only' ] ; then 128 if [ ! -e "_results" ]; then 129 mkdir "_results" 130 else 131 rm "_results/"* 132 fi 133 134 cp "tests/testinput.txt" "$TESTINPUT" 135 fi 136 137 # Perform each test. 138 139 for FILENAME in tests/* ; do 140 TESTNAME=`basename "$FILENAME" .py` 141 142 # Detect tests in their own subdirectories. 143 144 if [ -d "$FILENAME" ] ; then 145 if [ -e "$FILENAME/main.py" ] ; then 146 FILENAME="$FILENAME/main.py" 147 else 148 continue 149 fi 150 fi 151 152 # Skip non-program files. 153 154 if [ `basename "$FILENAME"` = "$TESTNAME" ]; then 155 continue 156 fi 157 158 # Compile tests without an existing cache. 159 160 echo "$FILENAME..." 1>&2 161 if ! "$LPLC" -c -r "$FILENAME" ; then 162 if ! expect_failure ; then 163 exit 1 164 else 165 echo 1>&2 166 continue 167 fi 168 fi 169 170 # Check for unresolved names in the cache. 171 172 echo " (depends)..." 1>&2 173 for CACHEFILE in "$DATADIR/_cache/"* ; do 174 STARTLINE=`grep -n '^deferred:' "$CACHEFILE" | cut -d: -f 1` 175 if tail -n +$(($STARTLINE + 2)) "$CACHEFILE" | grep -q '<depends>' ; then 176 echo "Unresolved names in the cache." 1>&2 177 exit 1 178 fi 179 done 180 181 # Check for type warnings in deduction output. 182 183 echo " (warnings)..." 1>&2 184 if ! check_type_warnings ; then exit 1 ; fi 185 186 # Compile tests with an existing cache. 187 188 echo " (cached)..." 1>&2 189 if ! "$LPLC" -c "$FILENAME" ; then exit 1 ; fi 190 191 echo " (warnings)..." 1>&2 192 if ! check_type_warnings ; then exit 1 ; fi 193 194 # Build and run if appropriate. 195 196 if [ "$OPTION" = '--build' ] || [ "$OPTION" = "--build-only" ] ; then 197 BUILDLOG="_results/$TESTNAME.build" 198 OUTLOG="_results/$TESTNAME.out" 199 OUTCODE="_results/$TESTNAME.exitcode" 200 201 echo " (build)..." 1>&2 202 if ! make -C "$DATADIR/_generated" clean > "$BUILDLOG" 2>&1 || \ 203 ! make -C "$DATADIR/_generated" $MAKE_OPTIONS > "$BUILDLOG" 2>&1 ; then 204 exit 1 205 fi 206 207 if [ "$OPTION" = "--build-only" ]; then 208 mv "$DATADIR/_generated/main" "_results/$TESTNAME" 209 else 210 echo " (run)..." 1>&2 211 "$DATADIR/_generated/main" > "$OUTLOG" < "$TESTINPUT" 212 echo $? > "$OUTCODE" 213 fi 214 fi 215 216 echo 1>&2 217 done