mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12142 from ethereum/bash-assert-and-stack-traces
Assert and stack traces for Bash scripts
This commit is contained in:
commit
2162039c50
@ -19,6 +19,13 @@
|
|||||||
# (c) 2016-2019 solidity contributors.
|
# (c) 2016-2019 solidity contributors.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# The fail() function defined below requires set -e to be enabled.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Save the initial working directory so that printStackTrace() can access it even if the sourcing
|
||||||
|
# changes directory. The paths returned by `caller` are relative to it.
|
||||||
|
_initial_work_dir=$(pwd)
|
||||||
|
|
||||||
if [ "$CIRCLECI" ]
|
if [ "$CIRCLECI" ]
|
||||||
then
|
then
|
||||||
export TERM="${TERM:-xterm}"
|
export TERM="${TERM:-xterm}"
|
||||||
@ -33,12 +40,63 @@ else
|
|||||||
function printLog() { echo "$(tput setaf 3)$1$(tput sgr0)"; }
|
function printLog() { echo "$(tput setaf 3)$1$(tput sgr0)"; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
function printStackTrace
|
||||||
|
{
|
||||||
|
printWarning ""
|
||||||
|
printWarning "Stack trace:"
|
||||||
|
|
||||||
|
local frame=1
|
||||||
|
while caller "$frame" > /dev/null
|
||||||
|
do
|
||||||
|
local lineNumber line file function
|
||||||
|
|
||||||
|
# `caller` returns something that could already be printed as a stacktrace but we can make
|
||||||
|
# it more readable by rearranging the components.
|
||||||
|
# NOTE: This assumes that paths do not contain spaces.
|
||||||
|
lineNumber=$(caller "$frame" | cut --delimiter " " --field 1)
|
||||||
|
function=$(caller "$frame" | cut --delimiter " " --field 2)
|
||||||
|
file=$(caller "$frame" | cut --delimiter " " --field 3)
|
||||||
|
|
||||||
|
# Paths in the output from `caller` can be relative or absolute (depends on how the path
|
||||||
|
# with which the script was invoked) and if they're relative, they're not necessarily
|
||||||
|
# relative to the current working dir. This is a heuristic that will work if they're absolute,
|
||||||
|
# relative to current dir, or relative to the dir that was current when the script started.
|
||||||
|
# If neither works, it gives up.
|
||||||
|
line=$(
|
||||||
|
{
|
||||||
|
tail "--lines=+${lineNumber}" "$file" ||
|
||||||
|
tail "--lines=+${lineNumber}" "${_initial_work_dir}/${file}"
|
||||||
|
} 2> /dev/null |
|
||||||
|
head --lines=1 |
|
||||||
|
sed -e 's/^[[:space:]]*//'
|
||||||
|
) || line="<failed to find source line>"
|
||||||
|
|
||||||
|
>&2 printf " %s:%d in function %s()\n" "$file" "$lineNumber" "$function"
|
||||||
|
>&2 printf " %s\n" "$line"
|
||||||
|
|
||||||
|
((frame++))
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
function fail()
|
function fail()
|
||||||
{
|
{
|
||||||
printError "$@"
|
printError "$@"
|
||||||
|
|
||||||
|
# Using return rather than exit lets the invoking code handle the failure by suppressing the exit code.
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertFail()
|
||||||
|
{
|
||||||
|
printError ""
|
||||||
|
(( $# == 0 )) && printError "Assertion failed."
|
||||||
|
(( $# == 1 )) && printError "Assertion failed: $1"
|
||||||
|
printStackTrace
|
||||||
|
|
||||||
|
# Intentionally using exit here because assertion failures are not supposed to be handled.
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
function msg_on_error()
|
function msg_on_error()
|
||||||
{
|
{
|
||||||
local error_message
|
local error_message
|
||||||
@ -67,7 +125,7 @@ function msg_on_error()
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
fail "Invalid option for msg_on_error: $1"
|
assertFail "Invalid option for msg_on_error: $1"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@ -85,24 +143,30 @@ function msg_on_error()
|
|||||||
rm "$stdout_file" "$stderr_file"
|
rm "$stdout_file" "$stderr_file"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
printError "Command failed: $SOLC ${command[*]}"
|
printError ""
|
||||||
|
printError "Command failed: ${error_message}"
|
||||||
|
printError " command: $SOLC ${command[*]}"
|
||||||
if [[ -s "$stdout_file" ]]
|
if [[ -s "$stdout_file" ]]
|
||||||
then
|
then
|
||||||
printError "stdout:"
|
printError "--- stdout ---"
|
||||||
|
printError "-----------"
|
||||||
>&2 cat "$stdout_file"
|
>&2 cat "$stdout_file"
|
||||||
|
printError "--------------"
|
||||||
else
|
else
|
||||||
printError " stdout: <EMPTY>"
|
printError " stdout: <EMPTY>"
|
||||||
fi
|
fi
|
||||||
if [[ -s "$stderr_file" ]]
|
if [[ -s "$stderr_file" ]]
|
||||||
then
|
then
|
||||||
printError "stderr:"
|
printError "--- stderr ---"
|
||||||
>&2 cat "$stderr_file"
|
>&2 cat "$stderr_file"
|
||||||
|
printError "--------------"
|
||||||
else
|
else
|
||||||
printError " stderr: <EMPTY>"
|
printError " stderr: <EMPTY>"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printError "$error_message"
|
|
||||||
rm "$stdout_file" "$stderr_file"
|
rm "$stdout_file" "$stderr_file"
|
||||||
|
|
||||||
|
printStackTrace
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ echo "Using solc binary at ${SOLC}"
|
|||||||
INTERACTIVE=true
|
INTERACTIVE=true
|
||||||
if ! tty -s || [ "$CI" ]
|
if ! tty -s || [ "$CI" ]
|
||||||
then
|
then
|
||||||
INTERACTIVE=""
|
INTERACTIVE=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# extend stack size in case we run via ASAN
|
# extend stack size in case we run via ASAN
|
||||||
@ -123,7 +123,7 @@ function update_expectation {
|
|||||||
|
|
||||||
function ask_expectation_update
|
function ask_expectation_update
|
||||||
{
|
{
|
||||||
if [[ $INTERACTIVE != "" ]]
|
if [[ $INTERACTIVE == true ]]
|
||||||
then
|
then
|
||||||
local newExpectation="${1}"
|
local newExpectation="${1}"
|
||||||
local expectationFile="${2}"
|
local expectationFile="${2}"
|
||||||
@ -142,12 +142,13 @@ function ask_expectation_update
|
|||||||
e*) "$editor" "$expectationFile"; break;;
|
e*) "$editor" "$expectationFile"; break;;
|
||||||
u*) update_expectation "$newExpectation" "$expectationFile"; break;;
|
u*) update_expectation "$newExpectation" "$expectationFile"; break;;
|
||||||
s*) return;;
|
s*) return;;
|
||||||
q*) exit 1;;
|
q*) fail;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exit 1
|
[[ $INTERACTIVE == false ]] || assertFail
|
||||||
|
fail
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ EOF
|
|||||||
printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode."
|
printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode."
|
||||||
|
|
||||||
[[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file"
|
[[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file"
|
||||||
[[ $exit_code_expectation_file == "" ]] && exit 1
|
[[ $exit_code_expectation_file == "" ]] && fail
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$(cat "$stdout_path")" != "${stdout_expected}" ]]
|
if [[ "$(cat "$stdout_path")" != "${stdout_expected}" ]]
|
||||||
@ -266,7 +267,7 @@ EOF
|
|||||||
printError "When running $solc_command"
|
printError "When running $solc_command"
|
||||||
|
|
||||||
[[ $stdout_expectation_file != "" ]] && ask_expectation_update "$(cat "$stdout_path")" "$stdout_expectation_file"
|
[[ $stdout_expectation_file != "" ]] && ask_expectation_update "$(cat "$stdout_path")" "$stdout_expectation_file"
|
||||||
[[ $stdout_expectation_file == "" ]] && exit 1
|
[[ $stdout_expectation_file == "" ]] && fail
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]]
|
if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]]
|
||||||
@ -280,7 +281,7 @@ EOF
|
|||||||
printError "When running $solc_command"
|
printError "When running $solc_command"
|
||||||
|
|
||||||
[[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file"
|
[[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file"
|
||||||
[[ $stderr_expectation_file == "" ]] && exit 1
|
[[ $stderr_expectation_file == "" ]] && fail
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm "$stdout_path" "$stderr_path"
|
rm "$stdout_path" "$stderr_path"
|
||||||
@ -300,10 +301,10 @@ function test_solc_assembly_output()
|
|||||||
if [ -z "$empty" ]
|
if [ -z "$empty" ]
|
||||||
then
|
then
|
||||||
printError "Incorrect assembly output. Expected: "
|
printError "Incorrect assembly output. Expected: "
|
||||||
echo -e "${expected}"
|
>&2 echo -e "${expected}"
|
||||||
printError "with arguments ${solc_args[*]}, but got:"
|
printError "with arguments ${solc_args[*]}, but got:"
|
||||||
echo "${output}"
|
>&2 echo "${output}"
|
||||||
exit 1
|
fail
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +374,7 @@ printTask "Running general commandline tests..."
|
|||||||
then
|
then
|
||||||
printError "Ambiguous input. Found input files in multiple formats:"
|
printError "Ambiguous input. Found input files in multiple formats:"
|
||||||
echo -e "${inputFiles}"
|
echo -e "${inputFiles}"
|
||||||
exit 1
|
fail
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use printf to get rid of the trailing newline
|
# Use printf to get rid of the trailing newline
|
||||||
@ -475,7 +476,8 @@ echo "Done."
|
|||||||
|
|
||||||
printTask "Testing library checksum..."
|
printTask "Testing library checksum..."
|
||||||
echo '' | msg_on_error --no-stdout "$SOLC" - --link --libraries a=0x90f20564390eAe531E810af625A22f51385Cd222
|
echo '' | msg_on_error --no-stdout "$SOLC" - --link --libraries a=0x90f20564390eAe531E810af625A22f51385Cd222
|
||||||
echo '' | "$SOLC" - --link --libraries a=0x80f20564390eAe531E810af625A22f51385Cd222 &>/dev/null && exit 1
|
echo '' | "$SOLC" - --link --libraries a=0x80f20564390eAe531E810af625A22f51385Cd222 &>/dev/null && \
|
||||||
|
fail "solc --link did not reject a library address with an invalid checksum."
|
||||||
|
|
||||||
printTask "Testing long library names..."
|
printTask "Testing long library names..."
|
||||||
echo '' | msg_on_error --no-stdout "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname=0x90f20564390eAe531E810af625A22f51385Cd222
|
echo '' | msg_on_error --no-stdout "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname=0x90f20564390eAe531E810af625A22f51385Cd222
|
||||||
@ -503,7 +505,8 @@ SOLTMPDIR=$(mktemp -d)
|
|||||||
# First time it works
|
# First time it works
|
||||||
echo 'contract C {}' | msg_on_error --no-stderr "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create"
|
echo 'contract C {}' | msg_on_error --no-stderr "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create"
|
||||||
# Second time it fails
|
# Second time it fails
|
||||||
echo 'contract C {}' | "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create" 2>/dev/null && exit 1
|
echo 'contract C {}' | "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create" 2>/dev/null && \
|
||||||
|
fail "solc did not refuse to overwrite $SOLTMPDIR/non-existing-stuff-to-create."
|
||||||
# Unless we force
|
# Unless we force
|
||||||
echo 'contract C {}' | msg_on_error --no-stderr "$SOLC" - --overwrite --bin -o "$SOLTMPDIR/non-existing-stuff-to-create"
|
echo 'contract C {}' | msg_on_error --no-stderr "$SOLC" - --overwrite --bin -o "$SOLTMPDIR/non-existing-stuff-to-create"
|
||||||
)
|
)
|
||||||
@ -517,8 +520,8 @@ printTask "Testing assemble, yul, strict-assembly and optimize..."
|
|||||||
|
|
||||||
# Test options above in conjunction with --optimize.
|
# Test options above in conjunction with --optimize.
|
||||||
# Using both, --assemble and --optimize should fail.
|
# Using both, --assemble and --optimize should fail.
|
||||||
echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null && exit 1
|
echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null && fail "solc --assemble --optimize did not fail as expected."
|
||||||
echo '{}' | "$SOLC" - --yul --optimize &>/dev/null && exit 1
|
echo '{}' | "$SOLC" - --yul --optimize &>/dev/null && fail "solc --yul --optimize did not fail as expected."
|
||||||
|
|
||||||
# Test yul and strict assembly output
|
# Test yul and strict assembly output
|
||||||
# Non-empty code results in non-empty binary representation with optimizations turned off,
|
# Non-empty code results in non-empty binary representation with optimizations turned off,
|
||||||
@ -563,8 +566,8 @@ SOLTMPDIR=$(mktemp -d)
|
|||||||
cd "$SOLTMPDIR"
|
cd "$SOLTMPDIR"
|
||||||
if ! "$REPO_ROOT/scripts/ASTImportTest.sh"
|
if ! "$REPO_ROOT/scripts/ASTImportTest.sh"
|
||||||
then
|
then
|
||||||
rm -rf "$SOLTMPDIR"
|
rm -r "$SOLTMPDIR"
|
||||||
exit 1
|
fail
|
||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
rm -r "$SOLTMPDIR"
|
rm -r "$SOLTMPDIR"
|
||||||
|
Loading…
Reference in New Issue
Block a user