|
1 | 1 | #!/usr/bin/env bash
|
| 2 | +# ------------------------------------------------------------------------------ |
| 3 | +# vim:ts=4:et |
| 4 | +# This file is part of solidity. |
| 5 | +# |
| 6 | +# solidity is free software: you can redistribute it and/or modify |
| 7 | +# it under the terms of the GNU General Public License as published by |
| 8 | +# the Free Software Foundation, either version 3 of the License, or |
| 9 | +# (at your option) any later version. |
| 10 | +# |
| 11 | +# solidity is distributed in the hope that it will be useful, |
| 12 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | +# GNU General Public License for more details. |
| 15 | +# |
| 16 | +# You should have received a copy of the GNU General Public License |
| 17 | +# along with solidity. If not, see <http://www.gnu.org/licenses/> |
| 18 | +# |
| 19 | +# (c) solidity contributors. |
| 20 | +# ------------------------------------------------------------------------------ |
| 21 | +# Bash script to test the import/exports. |
| 22 | +# ast import/export tests: |
| 23 | +# - first exporting a .sol file to JSON, then loading it into the compiler |
| 24 | +# and exporting it again. The second JSON should be identical to the first. |
| 25 | + |
| 26 | +set -euo pipefail |
2 | 27 |
|
3 |
| -set -e |
4 |
| - |
5 |
| -# Bash script to test the ast-import option of the compiler by |
6 |
| -# first exporting a .sol file to JSON, then loading it into the compiler |
7 |
| -# and exporting it again. The second JSON should be identical to the first |
8 | 28 | READLINK=readlink
|
9 | 29 | if [[ "$OSTYPE" == "darwin"* ]]; then
|
10 | 30 | READLINK=greadlink
|
11 | 31 | fi
|
12 | 32 | REPO_ROOT=$(${READLINK} -f "$(dirname "$0")"/..)
|
13 | 33 | SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-${REPO_ROOT}/build}
|
14 |
| -SOLC=${SOLIDITY_BUILD_DIR}/solc/solc |
15 |
| -SPLITSOURCES=${REPO_ROOT}/scripts/splitSources.py |
| 34 | +SOLC=$SOLIDITY_BUILD_DIR/solc/solc |
| 35 | +SPLITSOURCES=$REPO_ROOT/scripts/splitSources.py |
| 36 | + |
| 37 | +# shellcheck source=scripts/common.sh |
| 38 | +source "${REPO_ROOT}/scripts/common.sh" |
| 39 | + |
| 40 | +function print_usage |
| 41 | +{ |
| 42 | + fail "Usage: ${0} ast [--exit-on-error]." |
| 43 | +} |
| 44 | + |
| 45 | +function print_used_commands |
| 46 | +{ |
| 47 | + local test_directory="$1" |
| 48 | + local export_command="$2" |
| 49 | + local import_command="$3" |
| 50 | + printError "You can find the files used for this test here: ${test_directory}" |
| 51 | + printError "Used commands for test:" |
| 52 | + printError "# export" |
| 53 | + echo "$ ${export_command}" >&2 |
| 54 | + printError "# import" |
| 55 | + echo "$ ${import_command}" >&2 |
| 56 | +} |
| 57 | + |
| 58 | +function print_stderr_stdout |
| 59 | +{ |
| 60 | + local error_message="$1" |
| 61 | + local stderr_file="$2" |
| 62 | + local stdout_file="$3" |
| 63 | + printError "${error_message}" |
| 64 | + printError "" |
| 65 | + printError "stderr:" |
| 66 | + cat "${stderr_file}" >&2 |
| 67 | + printError "" |
| 68 | + printError "stdout:" |
| 69 | + cat "${stdout_file}" >&2 |
| 70 | +} |
| 71 | + |
| 72 | +IMPORT_TEST_TYPE= |
| 73 | +EXIT_ON_ERROR=0 |
| 74 | +for PARAM in "$@" |
| 75 | +do |
| 76 | + case "$PARAM" in |
| 77 | + ast) IMPORT_TEST_TYPE="ast" ;; |
| 78 | + --exit-on-error) EXIT_ON_ERROR=1 ;; |
| 79 | + *) print_usage ;; |
| 80 | + esac |
| 81 | +done |
16 | 82 |
|
17 | 83 | SYNTAXTESTS_DIR="${REPO_ROOT}/test/libsolidity/syntaxTests"
|
18 | 84 | ASTJSONTESTS_DIR="${REPO_ROOT}/test/libsolidity/ASTJSON"
|
19 |
| -NSOURCES="$(find "$SYNTAXTESTS_DIR" -type f | wc -l)" |
20 |
| - |
21 |
| -# DEV_DIR="${REPO_ROOT}/../tmp/contracts/" |
22 |
| -# NSOURCES="$(find $DEV_DIR -type f | wc -l)" #TODO use find command |
23 | 85 |
|
24 | 86 | FAILED=0
|
25 | 87 | UNCOMPILABLE=0
|
26 | 88 | TESTED=0
|
27 | 89 |
|
28 |
| -if [[ "$(find . -maxdepth 0 -type d -empty)" == "" ]]; then |
29 |
| - echo "Test directory not empty. Skipping!" |
30 |
| - exit 1 |
31 |
| -fi |
| 90 | +function ast_import_export_equivalence |
| 91 | +{ |
| 92 | + local sol_file="$1" |
| 93 | + local input_files=( "${@:2}" ) |
| 94 | + |
| 95 | + # export ast - save ast json as expected result (silently) |
| 96 | + local export_command="$SOLC --combined-json ast --pretty-json --json-indent 4 ${input_files[*]} > expected.json 2> stderr_export.txt" |
| 97 | + if ! $SOLC --combined-json ast --pretty-json --json-indent 4 "${input_files[@]}" > expected.json 2> stderr_export.txt |
| 98 | + then |
| 99 | + print_stderr_stdout "ERROR: AST export failed for input file $sol_file." ./stderr_export.txt ./expected.json |
| 100 | + print_used_commands "$(pwd)" "${export_command}" "${import_command}" |
| 101 | + return 1 |
| 102 | + fi |
32 | 103 |
|
33 |
| -# function tests whether exporting and importing again leaves the JSON ast unchanged |
| 104 | + # (re)import ast - and export it again as obtained result (silently) |
| 105 | + local import_command="$SOLC --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json > obtained.json 2> stderr_import.txt" |
| 106 | + if ! $SOLC --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json > obtained.json 2> stderr_import.txt |
| 107 | + then |
| 108 | + print_stderr_stdout "ERROR: AST export failed for input file $sol_file." ./stderr_import.txt ./obtained.json |
| 109 | + print_used_commands "$(pwd)" "${export_command}" "${import_command}" |
| 110 | + return 1 |
| 111 | + fi |
| 112 | + |
| 113 | + # compare expected and obtained ast's |
| 114 | + if diff_files expected.json obtained.json |
| 115 | + then |
| 116 | + echo -n "✅" |
| 117 | + else |
| 118 | + printError "❌ ERROR: AST reimport failed for ${sol_file}" |
| 119 | + if [[ $EXIT_ON_ERROR == 1 ]] |
| 120 | + then |
| 121 | + print_used_commands "$(pwd)" "${export_command}" "${import_command}" |
| 122 | + return 1 |
| 123 | + fi |
| 124 | + FAILED=$((FAILED + 1)) |
| 125 | + fi |
| 126 | + TESTED=$((TESTED + 1)) |
| 127 | +} |
| 128 | + |
| 129 | +# function tests whether exporting and importing again is equivalent. |
34 | 130 | # Results are recorded by adding to FAILED or UNCOMPILABLE.
|
35 |
| -# Also, in case of a mismatch a diff and the respective ASTs are printed |
| 131 | +# Also, in case of a mismatch a diff is printed |
36 | 132 | # Expected parameters:
|
37 | 133 | # $1 name of the file to be exported and imported
|
38 | 134 | # $2 any files needed to do so that might be in parent directories
|
39 | 135 | function testImportExportEquivalence {
|
40 |
| - local nth_input_file="$1" |
41 |
| - IFS=" " read -r -a all_input_files <<< "$2" |
| 136 | + local sol_file="$1" |
| 137 | + local input_files=( "${@:2}" ) |
42 | 138 |
|
43 |
| - if $SOLC "$nth_input_file" "${all_input_files[@]}" > /dev/null 2>&1 |
| 139 | + # if compilable |
| 140 | + if "$SOLC" --bin "${input_files[@]}" > compile_test_stderr_stdout.txt 2>&1 |
44 | 141 | then
|
45 |
| - ! [[ -e stderr.txt ]] || { echo "stderr.txt already exists. Refusing to overwrite."; exit 1; } |
46 |
| - |
47 |
| - # save exported json as expected result (silently) |
48 |
| - $SOLC --combined-json ast --pretty-json "$nth_input_file" "${all_input_files[@]}" > expected.json 2> /dev/null |
49 |
| - # import it, and export it again as obtained result (silently) |
50 |
| - if ! $SOLC --import-ast --combined-json ast --pretty-json expected.json > obtained.json 2> stderr.txt |
51 |
| - then |
52 |
| - # For investigating, use exit 1 here so the script stops at the |
53 |
| - # first failing test |
54 |
| - # exit 1 |
55 |
| - FAILED=$((FAILED + 1)) |
56 |
| - echo -e "ERROR: AST reimport failed for input file $nth_input_file" |
57 |
| - echo |
58 |
| - echo "Compiler stderr:" |
59 |
| - cat ./stderr.txt |
60 |
| - echo |
61 |
| - echo "Compiler stdout:" |
62 |
| - cat ./obtained.json |
63 |
| - return 1 |
64 |
| - fi |
65 |
| - DIFF="$(diff expected.json obtained.json)" |
66 |
| - if [ "$DIFF" != "" ] |
67 |
| - then |
68 |
| - if [ "$DIFFVIEW" == "" ] |
69 |
| - then |
70 |
| - echo -e "ERROR: JSONS differ for $1: \n $DIFF \n" |
71 |
| - echo "Expected:" |
72 |
| - cat ./expected.json |
73 |
| - echo "Obtained:" |
74 |
| - cat ./obtained.json |
75 |
| - else |
76 |
| - # Use user supplied diff view binary |
77 |
| - $DIFFVIEW expected.json obtained.json |
78 |
| - fi |
79 |
| - FAILED=$((FAILED + 1)) |
80 |
| - return 2 |
81 |
| - fi |
82 |
| - TESTED=$((TESTED + 1)) |
83 |
| - rm expected.json obtained.json |
84 |
| - rm -f stderr.txt |
| 142 | + case "$IMPORT_TEST_TYPE" in |
| 143 | + ast) ast_import_export_equivalence "${sol_file}" "${input_files[@]}" ;; |
| 144 | + *) fail "Unknown import test type '${IMPORT_TEST_TYPE}'. Aborting." ;; |
| 145 | + esac |
85 | 146 | else
|
86 |
| - # echo "contract $solfile could not be compiled " |
87 | 147 | UNCOMPILABLE=$((UNCOMPILABLE + 1))
|
88 | 148 | fi
|
89 |
| - # return 0 |
90 | 149 | }
|
91 |
| -echo "Looking at $NSOURCES .sol files..." |
92 | 150 |
|
93 | 151 | WORKINGDIR=$PWD
|
94 | 152 |
|
95 |
| -# for solfile in $(find $DEV_DIR -name *.sol) |
| 153 | +command_available "$SOLC" --version |
| 154 | +command_available jq --version |
| 155 | + |
| 156 | +case "$IMPORT_TEST_TYPE" in |
| 157 | + ast) TEST_DIRS=("${SYNTAXTESTS_DIR}" "${ASTJSONTESTS_DIR}") ;; |
| 158 | + *) print_usage ;; |
| 159 | +esac |
| 160 | + |
96 | 161 | # boost_filesystem_bug specifically tests a local fix for a boost::filesystem
|
97 | 162 | # bug. Since the test involves a malformed path, there is no point in running
|
98 |
| -# AST tests on it. See https://github.com/boostorg/filesystem/issues/176 |
99 |
| -# shellcheck disable=SC2044 |
100 |
| -for solfile in $(find "$SYNTAXTESTS_DIR" "$ASTJSONTESTS_DIR" -name "*.sol" -and -not -name "boost_filesystem_bug.sol") |
| 163 | +# tests on it. See https://github.com/boostorg/filesystem/issues/176 |
| 164 | +IMPORT_TEST_FILES=$(find "${TEST_DIRS[@]}" -name "*.sol" -and -not -name "boost_filesystem_bug.sol") |
| 165 | + |
| 166 | +NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)" |
| 167 | +echo "Looking at ${NSOURCES} .sol files..." |
| 168 | + |
| 169 | +for solfile in $IMPORT_TEST_FILES |
101 | 170 | do
|
102 |
| - echo -n "." |
| 171 | + echo -n "·" |
103 | 172 | # create a temporary sub-directory
|
104 | 173 | FILETMP=$(mktemp -d)
|
105 | 174 | cd "$FILETMP"
|
|
108 | 177 | OUTPUT=$("$SPLITSOURCES" "$solfile")
|
109 | 178 | SPLITSOURCES_RC=$?
|
110 | 179 | set -e
|
111 |
| - if [ ${SPLITSOURCES_RC} == 0 ] |
| 180 | + |
| 181 | + if [[ $SPLITSOURCES_RC == 0 ]] |
112 | 182 | then
|
113 |
| - # echo $OUTPUT |
114 |
| - NSOURCES=$((NSOURCES - 1)) |
115 |
| - for i in $OUTPUT; |
116 |
| - do |
117 |
| - testImportExportEquivalence "$i" "$OUTPUT" |
118 |
| - NSOURCES=$((NSOURCES + 1)) |
119 |
| - done |
120 |
| - elif [ ${SPLITSOURCES_RC} == 1 ] |
| 183 | + IFS=' ' read -ra OUTPUT_ARRAY <<< "$OUTPUT" |
| 184 | + testImportExportEquivalence "$solfile" "${OUTPUT_ARRAY[@]}" |
| 185 | + elif [ $SPLITSOURCES_RC == 1 ] |
121 | 186 | then
|
122 |
| - testImportExportEquivalence "$solfile" |
123 |
| - elif [ ${SPLITSOURCES_RC} == 2 ] |
| 187 | + testImportExportEquivalence "$solfile" "$solfile" |
| 188 | + elif [ $SPLITSOURCES_RC == 2 ] |
124 | 189 | then
|
125 | 190 | # The script will exit with return code 2, if an UnicodeDecodeError occurred.
|
126 | 191 | # This is the case if e.g. some tests are using invalid utf-8 sequences. We will ignore
|
127 | 192 | # these errors, but print the actual output of the script.
|
128 |
| - echo -e "\n${OUTPUT}\n" |
129 |
| - testImportExportEquivalence "$solfile" |
| 193 | + printError "\n\n${OUTPUT}\n\n" |
| 194 | + testImportExportEquivalence "$solfile" "$solfile" |
130 | 195 | else
|
131 | 196 | # All other return codes will be treated as critical errors. The script will exit.
|
132 |
| - echo -e "\nGot unexpected return code ${SPLITSOURCES_RC} from ${SPLITSOURCES}. Aborting." |
133 |
| - echo -e "\n${OUTPUT}\n" |
134 |
| - |
135 |
| - cd "$WORKINGDIR" |
136 |
| - # Delete temporary files |
137 |
| - rm -rf "$FILETMP" |
| 197 | + printError "\n\nGot unexpected return code ${SPLITSOURCES_RC} from ${SPLITSOURCES}. Aborting." |
| 198 | + printError "\n\n${OUTPUT}\n\n" |
138 | 199 |
|
139 | 200 | exit 1
|
140 | 201 | fi
|
141 | 202 |
|
142 |
| - cd "$WORKINGDIR" |
| 203 | + cd "${WORKINGDIR}" |
143 | 204 | # Delete temporary files
|
144 |
| - rm -rf "$FILETMP" |
| 205 | + rm -rf "${FILETMP}" |
145 | 206 | done
|
146 | 207 |
|
147 |
| -echo "" |
| 208 | +echo |
148 | 209 |
|
149 |
| -if [ "$FAILED" = 0 ] |
| 210 | +if (( FAILED == 0 )) |
150 | 211 | then
|
151 |
| - echo "SUCCESS: $TESTED syntaxTests passed, $FAILED failed, $UNCOMPILABLE could not be compiled ($NSOURCES sources total)." |
| 212 | + echo "SUCCESS: ${TESTED} tests passed, ${FAILED} failed, ${UNCOMPILABLE} could not be compiled (${NSOURCES} sources total)." |
152 | 213 | else
|
153 |
| - echo "FAILURE: Out of $NSOURCES sources, $FAILED failed, ($UNCOMPILABLE could not be compiled)." |
154 |
| - exit 1 |
| 214 | + fail "FAILURE: Out of ${NSOURCES} sources, ${FAILED} failed, (${UNCOMPILABLE} could not be compiled)." |
155 | 215 | fi
|
0 commit comments