diff --git a/.circleci/config.yml b/.circleci/config.yml index 9b2577bd3..b9bda6924 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -86,7 +86,7 @@ jobs: command: | test/solcjsTests.sh /tmp/workspace/soljson.js $(cat /tmp/workspace/version.txt) - test_emscripten_external: + test_emscripten_external_gnosis: docker: - image: circleci/node:10 environment: @@ -96,14 +96,23 @@ jobs: - attach_workspace: at: /tmp/workspace - run: - name: Install external tests deps + name: External GnosisSafe tests command: | - node --version - npm --version + test/externalTests/gnosis.sh /tmp/workspace/soljson.js || test/externalTests/gnosis.sh /tmp/workspace/soljson.js + + test_emscripten_external_zeppelin: + docker: + - image: circleci/node:10 + environment: + TERM: xterm + steps: + - checkout + - attach_workspace: + at: /tmp/workspace - run: - name: External tests + name: External Zeppelin tests command: | - test/externalTests.sh /tmp/workspace/soljson.js || test/externalTests.sh /tmp/workspace/soljson.js + test/externalTests/zeppelin.sh /tmp/workspace/soljson.js || test/externalTests/zeppelin.sh /tmp/workspace/soljson.js build_x86_linux: docker: @@ -393,7 +402,11 @@ workflows: <<: *build_on_tags requires: - build_emscripten - - test_emscripten_external: + - test_emscripten_external_zeppelin: + <<: *build_on_tags + requires: + - build_emscripten + - test_emscripten_external_gnosis: <<: *build_on_tags requires: - build_emscripten @@ -431,7 +444,11 @@ workflows: - develop jobs: - build_emscripten: *build_on_tags - - test_emscripten_external: + - test_emscripten_external_zeppelin: + <<: *build_on_tags + requires: + - build_emscripten + - test_emscripten_external_gnosis: <<: *build_on_tags requires: - build_emscripten diff --git a/test/externalTests.sh b/test/externalTests.sh index c55aa01f8..482819458 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -28,17 +28,6 @@ set -e -if [ "$CIRCLECI" ] -then - function printTask() { echo ""; echo "$(tput bold)$(tput setaf 2)$1$(tput setaf 7)"; } - function printError() { echo ""; echo "$(tput setaf 1)$1$(tput setaf 7)"; } - function printLog() { echo "$(tput setaf 3)$1$(tput setaf 7)"; } -else - function printTask() { echo ""; echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; } - function printError() { echo ""; echo "$(tput setaf 1)$1$(tput sgr0)"; } - function printLog() { echo "$(tput setaf 3)$1$(tput sgr0)"; } -fi - if [ ! -f "$1" ] then echo "Usage: $0 " @@ -46,208 +35,14 @@ then fi SOLJSON="$1" -SOLCVERSION="UNDEFINED" +REPO_ROOT="$(dirname "$0")" -function setup_solcjs -{ - printLog "Setting up solc-js..." - cd "$1" - git clone --depth 1 -b v0.5.0 https://github.com/ethereum/solc-js.git solc +source test/externalTests/common.sh - cd solc - npm install - cp "$SOLJSON" soljson.js - SOLCVERSION=$(./solcjs --version) - cd .. - echo "Using solcjs version $SOLCVERSION" -} +printTask "Running external tests..." -function download_project -{ - local repo="$1" - local branch="$2" - local dir="$3" - - printLog "Cloning $branch of $repo..." - git clone --depth 1 "$repo" -b "$branch" "$dir/ext" - cd ext - echo "Current commit hash: `git rev-parse HEAD`" -} - -function setup -{ - local repo="$1" - local branch="$2" - local dir="$3" - - setup_solcjs "$dir" - download_project "$repo" "$branch" "$dir" - - replace_version_pragmas -} - -function replace_version_pragmas -{ - # Replace fixed-version pragmas in Gnosis (part of Consensys best practice) - printLog "Replacing fixed-version pragmas..." - find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity [\^0-9\.]*/pragma solidity >=0.0/' -} - -function force_abi_v2 -{ - # Add "pragma experimental ABIEncoderV2" to all files. - printLog "Forcibly enabling ABIEncodreV2..." - find contracts test -name '*.sol' -type f -print0 | \ - while IFS= read -r -d '' file - do - # Only add the pragma if it is not already there. - if grep -q -v 'pragma experimental ABIEncoderV2' "$file" - then - sed -i -e '1 i pragma experimental ABIEncoderV2;' "$file" - fi - done -} - -function replace_libsolc_call -{ - # Change "compileStandard" to "compile" (needed for pre-5.x Truffle) - printLog "Replacing libsolc compile call in Truffle..." - sed -i s/solc.compileStandard/solc.compile/ "node_modules/truffle/build/cli.bundled.js" -} - -function find_truffle_config -{ - local config_file="truffle.js" - local alt_config_file="truffle-config.js" - - if [ ! -f "$config_file" ] && [ ! -f "$alt_config_file" ]; then - printError "No matching Truffle config found." - fi - if [ ! -f "$config_file" ]; then - config_file=alt_config_file - fi - echo "$config_file" -} - -function force_solc_truffle_modules -{ - # Replace solc package by v0.5.0 and then overwrite with current version. - printLog "Forcing solc version for all Truffle modules..." - for d in node_modules node_modules/truffle/node_modules - do - ( - if [ -d "$d" ] - then - cd $d - rm -rf solc - git clone --depth 1 -b v0.5.0 https://github.com/ethereum/solc-js.git solc - cp "$1" solc/soljson.js - fi - ) - done -} - -function force_solc -{ - local config_file="$1" - local dir="$2" - - printLog "Forcing solc version..." - cat >> "$config_file" <> "$config_file" - echo "module.exports['compilers']['solc']['settings'] = { optimizer: $settings, evmVersion: \"$evmVersion\" };" >> "$config_file" -} - -function verify_compiler_version -{ - local solc_version="$1" - - printLog "Verify that the correct version ($solc_version) of the compiler was used to compile the contracts..." - grep -e "$solc_version" -r build/contracts > /dev/null -} - -function clean -{ - rm -rf build || true -} - -# Since Zeppelin 2.1.1 it supports Solidity 0.5.0. -printTask "Testing Zeppelin..." -echo "===========================" -DIR=$(mktemp -d) -( - setup https://github.com/OpenZeppelin/openzeppelin-solidity.git master "$DIR" - - npm install - - CONFIG="truffle-config.js" - - replace_libsolc_call - force_solc_truffle_modules "$SOLJSON" - force_solc "$CONFIG" "$DIR" - - for optimize in "{ enabled: false }" "{ enabled: true }" "{ enabled: true, details: { yul: true } }" - do - clean - force_solc_settings "$CONFIG" "$optimize" "petersburg" - # Force ABIEncoderV2 in the last step. Has to be the last because code is modified. - [[ "$optimize" =~ yul ]] && force_abi_v2 - - npx truffle compile - verify_compiler_version "$SOLCVERSION" - npm run test - done -) -rm -rf "$DIR" -echo "Done." - -printTask "Testing GnosisSafe..." -echo "===========================" -DIR=$(mktemp -d) -( - setup https://github.com/gnosis/safe-contracts.git development "$DIR" - - npm install - - CONFIG=$(find_truffle_config) - - force_solc_truffle_modules "$SOLJSON" - force_solc "$CONFIG" "$DIR" - - for optimize in "{ enabled: false }" "{ enabled: true }" "{ enabled: true, details: { yul: true } }" - do - clean - force_solc_settings "$CONFIG" "$optimize" "petersburg" - # Force ABIEncoderV2 in the last step. Has to be the last because code is modified. - [[ "$optimize" =~ yul ]] && force_abi_v2 - - npx truffle compile - verify_compiler_version "$SOLCVERSION" - npm test - done -) -rm -rf "$DIR" -echo "Done." -echo "All external tests passed." +$REPO_ROOT/externalTests/zeppelin.sh "$SOLJSON" +$REPO_ROOT/externalTests/gnosis.sh "$SOLJSON" # Disabled temporarily as it needs to be updated to latest Truffle first. #test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 diff --git a/test/externalTests/common.sh b/test/externalTests/common.sh new file mode 100644 index 000000000..0eade0fad --- /dev/null +++ b/test/externalTests/common.sh @@ -0,0 +1,249 @@ +#!/usr/bin/env bash + +# ------------------------------------------------------------------------------ +# This file is part of solidity. +# +# solidity is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# solidity is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with solidity. If not, see +# +# (c) 2019 solidity contributors. +#------------------------------------------------------------------------------ +set -e + +if [ "$CIRCLECI" ] +then + function printTask() { echo ""; echo "$(tput bold)$(tput setaf 2)$1$(tput setaf 7)"; } + function printError() { echo ""; echo "$(tput setaf 1)$1$(tput setaf 7)"; } + function printLog() { echo "$(tput setaf 3)$1$(tput setaf 7)"; } +else + function printTask() { echo ""; echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; } + function printError() { echo ""; echo "$(tput setaf 1)$1$(tput sgr0)"; } + function printLog() { echo "$(tput setaf 3)$1$(tput sgr0)"; } +fi + +function verify_input +{ + if [ ! -f "$1" ]; then + printError "Usage: $0 " + exit 1 + fi +} + +function setup_solcjs +{ + local dir="$1" + local soljson="$2" + + cd "$dir" + printLog "Setting up solc-js..." + git clone --depth 1 -b v0.5.0 https://github.com/ethereum/solc-js.git solc + + cd solc + npm install + cp "$soljson" soljson.js + SOLCVERSION=$(./solcjs --version) + printLog "Using solcjs version $SOLCVERSION" + cd .. +} + +function download_project +{ + local repo="$1" + local branch="$2" + local dir="$3" + + printLog "Cloning $branch of $repo..." + git clone --depth 1 "$repo" -b "$branch" "$dir/ext" + cd ext + echo "Current commit hash: `git rev-parse HEAD`" +} + +function setup +{ + local repo="$1" + local branch="$2" + + setup_solcjs "$DIR" "$SOLJSON" + download_project "$repo" "$branch" "$DIR" + + replace_version_pragmas +} + +function replace_version_pragmas +{ + # Replace fixed-version pragmas in Gnosis (part of Consensys best practice) + printLog "Replacing fixed-version pragmas..." + find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity [\^0-9\.]*/pragma solidity >=0.0/' +} + +function replace_libsolc_call +{ + # Change "compileStandard" to "compile" (needed for pre-5.x Truffle) + printLog "Replacing libsolc compile call in Truffle..." + sed -i s/solc.compileStandard/solc.compile/ "node_modules/truffle/build/cli.bundled.js" +} + +function find_truffle_config +{ + local config_file="truffle.js" + local alt_config_file="truffle-config.js" + + if [ ! -f "$config_file" ] && [ ! -f "$alt_config_file" ]; then + printError "No matching Truffle config found." + fi + if [ ! -f "$config_file" ]; then + config_file=alt_config_file + fi + echo "$config_file" +} + +function force_solc_truffle_modules +{ + # Replace solc package by v0.5.0 and then overwrite with current version. + printLog "Forcing solc version for all Truffle modules..." + for d in node_modules node_modules/truffle/node_modules + do + ( + if [ -d "$d" ]; then + cd $d + rm -rf solc + git clone --depth 1 -b v0.5.0 https://github.com/ethereum/solc-js.git solc + cp "$1" solc/soljson.js + fi + ) + done +} + +function force_solc +{ + local config_file="$1" + local dir="$2" + local soljson="$3" + + force_solc_truffle_modules "$soljson" + + printLog "Forcing solc version..." + cat >> "$config_file" <> "$config_file" + echo "module.exports['compilers']['solc']['settings'] = { optimizer: $settings, evmVersion: \"$evmVersion\" };" >> "$config_file" +} + +function force_abi_v2 +{ + # Add "pragma experimental ABIEncoderV2" to all files. + printLog "Forcibly enabling ABIEncodreV2..." + find contracts test -name '*.sol' -type f -print0 | \ + while IFS= read -r -d '' file + do + # Only add the pragma if it is not already there. + if grep -q -v 'pragma experimental ABIEncoderV2' "$file"; then + sed -i -e '1 i pragma experimental ABIEncoderV2;' "$file" + fi + done +} + +function verify_compiler_version +{ + local solc_version="$1" + + printLog "Verify that the correct version ($solc_version) of the compiler was used to compile the contracts..." + grep -e "$solc_version" -r build/contracts > /dev/null +} + +function clean +{ + rm -rf build || true +} + +function run_install +{ + local init_fn="$1" + printLog "Running install function..." + $init_fn +} + +function run_test +{ + local compile_fn="$1" + local test_fn="$2" + + force_solc "$CONFIG" "$DIR" "$SOLJSON" + + printLog "Checking optimizer level..." + if [ -z "$OPTIMIZER_LEVEL" ]; then + printError "Optimizer level not found. Please define OPTIMIZER_LEVEL=[1, 2, 3]" + exit 1 + fi + if [[ "$OPTIMIZER_LEVEL" == 1 ]]; then + declare -a optimizer_settings=("{ enabled: false }" "{ enabled: true }" "{ enabled: true, details: { yul: true } }") + fi + if [[ "$OPTIMIZER_LEVEL" == 2 ]]; then + declare -a optimizer_settings=("{ enabled: true }" "{ enabled: true, details: { yul: true } }") + fi + if [[ "$OPTIMIZER_LEVEL" == 3 ]]; then + declare -a optimizer_settings=("{ enabled: true, details: { yul: true } }") + fi + + for optimize in "${optimizer_settings[@]}" + do + clean + force_solc_settings "$CONFIG" "$optimize" "petersburg" + # Force ABIEncoderV2 in the last step. Has to be the last because code is modified. + [[ "$optimize" =~ yul ]] && force_abi_v2 + + printLog "Running compile function..." + $compile_fn + verify_compiler_version "$SOLCVERSION" + printLog "Running test function..." + $test_fn + done +} + +function external_test +{ + local name="$1" + local main_fn="$2" + + printTask "Testing $name..." + echo "===========================" + DIR=$(mktemp -d) + ( + if [ -z "$main_fn" ]; then + printError "Test main function not defined." + exit 1 + fi + $main_fn + ) + rm -rf "$DIR" + echo "Done." +} + diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh new file mode 100755 index 000000000..095207acc --- /dev/null +++ b/test/externalTests/gnosis.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# ------------------------------------------------------------------------------ +# This file is part of solidity. +# +# solidity is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# solidity is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with solidity. If not, see +# +# (c) 2019 solidity contributors. +#------------------------------------------------------------------------------ +source test/externalTests/common.sh + +verify_input "$1" +SOLJSON="$1" + +function install_fn { npm install; } +function compile_fn { npx truffle compile; } +function test_fn { npm test; } + +function gnosis_safe_test +{ + OPTIMIZER_LEVEL=1 + setup https://github.com/gnosis/safe-contracts.git development + run_install install_fn + + CONFIG=$(find_truffle_config) + replace_libsolc_call + + run_test compile_fn test_fn +} + +external_test Gnosis-Safe gnosis_safe_test + diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh new file mode 100755 index 000000000..b85309921 --- /dev/null +++ b/test/externalTests/zeppelin.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# ------------------------------------------------------------------------------ +# This file is part of solidity. +# +# solidity is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# solidity is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with solidity. If not, see +# +# (c) 2019 solidity contributors. +#------------------------------------------------------------------------------ +source test/externalTests/common.sh + +verify_input "$1" +SOLJSON="$1" + +function install_fn { npm install; } +function compile_fn { npx truffle compile; } +function test_fn { npm run test; } + +function zeppelin_test +{ + OPTIMIZER_LEVEL=1 + setup https://github.com/OpenZeppelin/openzeppelin-solidity.git master + run_install install_fn + + CONFIG="truffle-config.js" + replace_libsolc_call + + run_test compile_fn test_fn +} + +external_test Zeppelin zeppelin_test