|
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 | +IMPORT_TEST_TYPE= |
| 46 | +EXIT_ON_ERROR=0 |
| 47 | +for PARAM in "$@" |
| 48 | +do |
| 49 | + case "$PARAM" in |
| 50 | + ast) IMPORT_TEST_TYPE="ast" ;; |
| 51 | + --exit-on-error) EXIT_ON_ERROR=1 ;; |
| 52 | + *) print_usage ;; |
| 53 | + esac |
| 54 | +done |
16 | 55 |
|
17 | 56 | SYNTAXTESTS_DIR="${REPO_ROOT}/test/libsolidity/syntaxTests"
|
18 | 57 | 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 | 58 |
|
24 | 59 | FAILED=0
|
25 | 60 | UNCOMPILABLE=0
|
26 | 61 | TESTED=0
|
27 | 62 |
|
28 |
| -if [[ "$(find . -maxdepth 0 -type d -empty)" == "" ]]; then |
29 |
| - echo "Test directory not empty. Skipping!" |
30 |
| - exit 1 |
31 |
| -fi |
| 63 | +function ast_import_export_equivalence |
| 64 | +{ |
| 65 | + local sol_file="$1" |
| 66 | + local input_files=( "${@:2}" ) |
32 | 67 |
|
33 |
| -# function tests whether exporting and importing again leaves the JSON ast unchanged |
| 68 | + # save ast json as expected result (silently) |
| 69 | + if ! $SOLC --combined-json ast --pretty-json --json-indent 4 "${input_files[@]}" > expected.json 2> stderr_export.txt |
| 70 | + then |
| 71 | + printError "ERROR: AST export failed for input file $sol_file." |
| 72 | + printError "" |
| 73 | + printError "Compiler stderr:" |
| 74 | + cat ./stderr_export.txt >&2 |
| 75 | + printError "" |
| 76 | + printError "Compiler stdout:" |
| 77 | + cat ./expected.json >&2 |
| 78 | + return 1 |
| 79 | + fi |
| 80 | + |
| 81 | + # import it, and export it again as obtained result (silently) |
| 82 | + if ! $SOLC --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json > obtained.json 2> stderr_import.txt |
| 83 | + then |
| 84 | + printError "ERROR: AST import failed for input file $sol_file" |
| 85 | + printError "" |
| 86 | + printError "Compiler stderr:" |
| 87 | + cat ./stderr_import.txt >&2 |
| 88 | + printError "" |
| 89 | + printError "Compiler stdout:" |
| 90 | + cat ./obtained.json >&2 |
| 91 | + return 1 |
| 92 | + fi |
| 93 | + |
| 94 | + if diff_files expected.json obtained.json |
| 95 | + then |
| 96 | + echo -n "✅" |
| 97 | + else |
| 98 | + printError "❌ ERROR: AST reimport failed for ${sol_file}" |
| 99 | + if [[ $EXIT_ON_ERROR == 1 ]] |
| 100 | + then |
| 101 | + printError "You can find the files used for this test here: $(pwd)" |
| 102 | + printError "Used commands for test:" |
| 103 | + printError "# export" |
| 104 | + printError "$ solc --combined-json ast --pretty-json --json-indent 4 ${input_files[*]} > expected.json 2> stderr_export.txt" |
| 105 | + printError "# import" |
| 106 | + printError "$ solc --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json > obtained.json 2> stderr_import.txt" |
| 107 | + # to simplify potential problem investigations - copy used solidity sources to test directory. |
| 108 | + cp "${input_files[@]}" "$(pwd)" |
| 109 | + exit 1 |
| 110 | + fi |
| 111 | + FAILED=$((FAILED + 1)) |
| 112 | + fi |
| 113 | + TESTED=$((TESTED + 1)) |
| 114 | +} |
| 115 | + |
| 116 | +# function tests whether exporting and importing again is equivalent. |
34 | 117 | # Results are recorded by adding to FAILED or UNCOMPILABLE.
|
35 |
| -# Also, in case of a mismatch a diff and the respective ASTs are printed |
| 118 | +# Also, in case of a mismatch a diff is printed |
36 | 119 | # Expected parameters:
|
37 | 120 | # $1 name of the file to be exported and imported
|
38 | 121 | # $2 any files needed to do so that might be in parent directories
|
39 | 122 | function testImportExportEquivalence {
|
40 |
| - local nth_input_file="$1" |
41 |
| - IFS=" " read -r -a all_input_files <<< "$2" |
| 123 | + local sol_file="$1" |
| 124 | + local input_files=( "${@:2}" ) |
42 | 125 |
|
43 |
| - if $SOLC "$nth_input_file" "${all_input_files[@]}" > /dev/null 2>&1 |
| 126 | + # if compilable |
| 127 | + if "$SOLC" --bin "${input_files[@]}" > /dev/null 2>&1 |
44 | 128 | 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 |
| 129 | + case "$IMPORT_TEST_TYPE" in |
| 130 | + ast) ast_import_export_equivalence "${sol_file}" "${input_files[@]}" ;; |
| 131 | + *) fail "Unknown import test type '${IMPORT_TEST_TYPE}'. Aborting." ;; |
| 132 | + esac |
85 | 133 | else
|
86 |
| - # echo "contract $solfile could not be compiled " |
87 | 134 | UNCOMPILABLE=$((UNCOMPILABLE + 1))
|
88 | 135 | fi
|
89 |
| - # return 0 |
90 | 136 | }
|
91 |
| -echo "Looking at $NSOURCES .sol files..." |
92 | 137 |
|
93 | 138 | WORKINGDIR=$PWD
|
94 | 139 |
|
95 |
| -# for solfile in $(find $DEV_DIR -name *.sol) |
| 140 | +command_available "$SOLC" --version |
| 141 | +command_available jq --version |
| 142 | + |
| 143 | +case "$IMPORT_TEST_TYPE" in |
| 144 | + ast) TEST_DIRS=("${SYNTAXTESTS_DIR}" "${ASTJSONTESTS_DIR}") ;; |
| 145 | + *) print_usage ;; |
| 146 | +esac |
| 147 | + |
96 | 148 | # boost_filesystem_bug specifically tests a local fix for a boost::filesystem
|
97 | 149 | # 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") |
| 150 | +# tests on it. See https://github.com/boostorg/filesystem/issues/176 |
| 151 | +IMPORT_TEST_FILES=$(find "${TEST_DIRS[@]}" -name "*.sol" -and -not -name "boost_filesystem_bug.sol") |
| 152 | + |
| 153 | +NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)" |
| 154 | +echo "Looking at ${NSOURCES} .sol files..." |
| 155 | + |
| 156 | +for solfile in $IMPORT_TEST_FILES |
101 | 157 | do
|
102 |
| - echo -n "." |
| 158 | + echo -n "·" |
103 | 159 | # create a temporary sub-directory
|
104 | 160 | FILETMP=$(mktemp -d)
|
105 | 161 | cd "$FILETMP"
|
|
108 | 164 | OUTPUT=$("$SPLITSOURCES" "$solfile")
|
109 | 165 | SPLITSOURCES_RC=$?
|
110 | 166 | set -e
|
111 |
| - if [ ${SPLITSOURCES_RC} == 0 ] |
| 167 | + |
| 168 | + if [[ $SPLITSOURCES_RC == 0 ]] |
112 | 169 | 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 ] |
| 170 | + IFS=' ' read -ra OUTPUT_ARRAY <<< "$OUTPUT" |
| 171 | + testImportExportEquivalence "$solfile" "${OUTPUT_ARRAY[@]}" |
| 172 | + elif [ $SPLITSOURCES_RC == 1 ] |
121 | 173 | then
|
122 |
| - testImportExportEquivalence "$solfile" |
123 |
| - elif [ ${SPLITSOURCES_RC} == 2 ] |
| 174 | + testImportExportEquivalence "$solfile" "$solfile" |
| 175 | + elif [ $SPLITSOURCES_RC == 2 ] |
124 | 176 | then
|
125 | 177 | # The script will exit with return code 2, if an UnicodeDecodeError occurred.
|
126 | 178 | # This is the case if e.g. some tests are using invalid utf-8 sequences. We will ignore
|
127 | 179 | # these errors, but print the actual output of the script.
|
128 |
| - echo -e "\n${OUTPUT}\n" |
129 |
| - testImportExportEquivalence "$solfile" |
| 180 | + printError "\n\n${OUTPUT}\n\n" |
| 181 | + testImportExportEquivalence "$solfile" "$solfile" |
130 | 182 | else
|
131 | 183 | # 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" |
| 184 | + printError "\n\nGot unexpected return code ${SPLITSOURCES_RC} from ${SPLITSOURCES}. Aborting." |
| 185 | + printError "\n\n${OUTPUT}\n\n" |
138 | 186 |
|
139 | 187 | exit 1
|
140 | 188 | fi
|
141 | 189 |
|
142 |
| - cd "$WORKINGDIR" |
| 190 | + cd "${WORKINGDIR}" |
143 | 191 | # Delete temporary files
|
144 |
| - rm -rf "$FILETMP" |
| 192 | + rm -rf "${FILETMP}" |
145 | 193 | done
|
146 | 194 |
|
147 |
| -echo "" |
| 195 | +echo |
148 | 196 |
|
149 |
| -if [ "$FAILED" = 0 ] |
| 197 | +if (( FAILED == 0 )) |
150 | 198 | then
|
151 |
| - echo "SUCCESS: $TESTED syntaxTests passed, $FAILED failed, $UNCOMPILABLE could not be compiled ($NSOURCES sources total)." |
| 199 | + echo "SUCCESS: ${TESTED} tests passed, ${FAILED} failed, ${UNCOMPILABLE} could not be compiled (${NSOURCES} sources total)." |
152 | 200 | else
|
153 |
| - echo "FAILURE: Out of $NSOURCES sources, $FAILED failed, ($UNCOMPILABLE could not be compiled)." |
154 |
| - exit 1 |
| 201 | + fail "FAILURE: Out of ${NSOURCES} sources, ${FAILED} failed, (${UNCOMPILABLE} could not be compiled)." |
155 | 202 | fi
|
0 commit comments