diff --git a/.github/scripts/install-solc.sh b/.github/scripts/install-solc.sh index 1f8b14d21..22478aaed 100755 --- a/.github/scripts/install-solc.sh +++ b/.github/scripts/install-solc.sh @@ -22,7 +22,10 @@ fetch_solc_linux() { mv solc-static-linux $HOME/.local/bin/solc-0.4.25; wget https://github.com/ethereum/solidity/releases/download/v0.5.7/solc-static-linux; chmod +x solc-static-linux; - mv solc-static-linux $HOME/.local/bin/solc-0.5.7; + mv solc-static-linux ~/.local/bin/solc-0.5.7; + wget https://github.com/ethereum/solidity/releases/download/v0.6.2/solc-static-linux; + chmod +x solc-static-linux; + mv solc-static-linux ~/.local/bin/solc-0.6.2; } if [ "$HOST_OS" = "Linux" ]; then diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 963ec5eb4..262c06b72 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: export PATH="${PATH}:$HOME/.local/bin" if [ "${{ runner.os }}" == "Linux" ]; then - for VER in "0.4.25" "0.5.7" ; do + for VER in "0.4.25" "0.5.7" "0.6.2" ; do cp "$HOME/.local/bin/solc-$VER" "$HOME/.local/bin/solc" stack test --ghc-options="-Werror" --extra-include-dirs=$HOME/.local/include --extra-lib-dirs=$HOME/.local/lib done diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..aaa59fb73 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,59 @@ +# Adapted from https://github.com/ChrisPenner/haskell-stack-travis-ci +language: python +python: + - 3.6 + +sudo: true + +cache: + directories: + - $HOME/.ghc + - $HOME/.cabal + - $HOME/.stack + - .stack-work + - /usr/local/include + - /usr/local/lib + timeout: 1000 + +matrix: + fast_finish: true + include: + # Add build targets here + - env: CACHE_NAME=linux BUILD_BINARY=1 + - env: CACHE_NAME=osx BUILD_BINARY=1 + STACK_OPTS="--no-run-tests --extra-include-dirs=/usr/local/opt/readline/include --extra-lib-dirs=/usr/local/opt/readline/lib" + LDFLAGS=-L/usr/local/opt/readline/lib CFLAGS=-I/usr/local/opt/readline/include + os: osx + language: minimal + +install: + - unset CC + - export PATH=$HOME/.local/bin:$PATH + - ./.travis/install-libsecp256k1.sh + - ./.travis/install-libff.sh + - ./.travis/install-ghr.sh + - ./.travis/install-stack.sh + - ./.travis/install-solc.sh + - ./.travis/install-crytic-compile.sh + +script: + - PATH=$HOME/.local/bin:$PATH + - echo "$(stack ghc -- --version) [$(stack ghc -- --print-project-git-commit-id 2> /dev/null || echo '?')]" + - GHC_OPTIONS="-Werror" + - STACK_OPTS="$STACK_OPTS --extra-include-dirs=/usr/local/include --extra-lib-dirs=/usr/local/lib" + - | + set -ex + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + + run_tests_using () { + cp ~/.local/bin/$1 ~/.local/bin/solc || true + stack --no-terminal test --ghc-options="$GHC_OPTIONS" $STACK_OPTS + } + + run_tests_using "solc-0.4.25" + run_tests_using "solc-0.5.7" + run_tests_using "solc-0.6.2" + set +ex + +notifications: + email: false diff --git a/src/test/Spec.hs b/src/test/Spec.hs index f332dae64..e2a84ad4f 100644 --- a/src/test/Spec.hs +++ b/src/test/Spec.hs @@ -157,7 +157,7 @@ integrationTests = testGroup "Solidity Integration Testing" , testContract "basic/nearbyMining.sol" (Just "coverage/test.yaml") [ ("echidna_findNearby passed", solved "echidna_findNearby") ] - , testContract' "basic/smallValues.sol" Nothing (Just "coverage/test.yaml") False + , testContract' "basic/smallValues.sol" Nothing (Just "coverage/test.yaml") False Nothing [ ("echidna_findSmall passed", solved "echidna_findSmall") ] , testContract "basic/multisender.sol" (Just "basic/multisender.yaml") $ @@ -180,7 +180,7 @@ integrationTests = testGroup "Solidity Integration Testing" [ ("echidna_found_sender failed", solved "echidna_found_sender") ] , testContract "basic/rconstants.sol" Nothing [ ("echidna_found failed", solved "echidna_found") ] - , testContract' "basic/cons-create-2.sol" (Just "C") Nothing True + , testContract' "basic/cons-create-2.sol" (Just "C") Nothing True Nothing [ ("echidna_state failed", solved "echidna_state") ] -- single.sol is really slow and kind of unstable. it also messes up travis. -- , testContract "coverage/single.sol" (Just "coverage/test.yaml") @@ -191,7 +191,7 @@ integrationTests = testGroup "Solidity Integration Testing" [ ("echidna_balance failed", passed "echidna_balance") ] , testContract "basic/library.sol" (Just "basic/library.yaml") [ ("echidna_library_call failed", solved "echidna_library_call") ] - , testContract "basic/fallback.sol" Nothing + , testContract' "basic/fallback.sol" Nothing Nothing True (Just ["0.4.25", "0.5.7"]) [ ("echidna_fallback failed", solved "echidna_fallback") ] , testContract "basic/darray.sol" Nothing [ ("echidna_darray passed", solved "echidna_darray") @@ -207,14 +207,9 @@ integrationTests = testGroup "Solidity Integration Testing" [ ("echidna_construct passed", solved "echidna_construct") ] , testContract "basic/gasprice.sol" Nothing [ ("echidna_state passed", solved "echidna_state") ] - , let fp = "basic_multicontract/contracts/Foo.sol"; cfg = Just "basic_multicontract/echidna_config.yaml" in - testCase fp $ - do sv <- readProcess "solc" ["--version"] "" - when ("Version: 0.4.25" `isInfixOf` sv) $ do - c <- set (sConf . quiet) True <$> maybe (pure testConfig) (fmap _econfig . parseConfig) cfg - res <- runContract fp (Just "Foo") c - assertBool "echidna_test passed" $ solved "echidna_test" res - , testContract' "basic/multi-abi.sol" (Just "B") (Just "basic/multi-abi.yaml") True + , testContract' "basic_multicontract/contracts/Foo.sol" Nothing (Just "basic_multicontract/echidna_config.yaml") True (Just ["0.4.25"]) + [ ("echidna_test passed", solved "echidna_test") ] + , testContract' "basic/multi-abi.sol" (Just "B") (Just "basic/multi-abi.yaml") True Nothing [ ("echidna_test passed", solved "echidna_test") ] , testContract "abiv2/Ballot.sol" Nothing [ ("echidna_test passed", solved "echidna_test") ] @@ -253,15 +248,22 @@ testConfig = defaultConfig & sConf . quiet .~ True & cConf .~ (defaultConfig ^. cConf) { testLimit = 10000, shrinkLimit = 2500 } testContract :: FilePath -> Maybe FilePath -> [(String, Campaign -> Bool)] -> TestTree -testContract fp cfg = testContract' fp Nothing cfg True - -testContract' :: FilePath -> Maybe Text -> Maybe FilePath -> Bool -> [(String, Campaign -> Bool)] -> TestTree -testContract' fp n cfg s as = testCase fp $ do - c <- set (sConf . quiet) True <$> maybe (pure testConfig) (fmap _econfig . parseConfig) cfg - let c' = c & sConf . quiet .~ True - & if s then cConf .~ (c ^. cConf) { testLimit = 10000, shrinkLimit = 2500 } else id - res <- runContract fp n c' - mapM_ (\(t,f) -> assertBool t $ f res) as +testContract fp cfg = + testContract' fp Nothing cfg True Nothing + +testContract' :: FilePath -> Maybe Text -> Maybe FilePath -> Bool -> Maybe [String] -> [(String, Campaign -> Bool)] -> TestTree +testContract' fp n cfg s vs as = testCase fp $ + case vs of + Just vs' -> do + sv <- readProcess "solc" ["--version"] "" + when (any (`isInfixOf` sv) (("Version: " <>) <$> vs')) doTest + Nothing -> doTest + where doTest = do + c <- set (sConf . quiet) True <$> maybe (pure testConfig) (fmap _econfig . parseConfig) cfg + let c' = c & sConf . quiet .~ True + & if s then cConf .~ (c ^. cConf) { testLimit = 10000, shrinkLimit = 2500 } else id + res <- runContract fp n c' + mapM_ (\(t,f) -> assertBool t $ f res) as runContract :: FilePath -> Maybe Text -> EConfig -> IO Campaign runContract fp n c = @@ -309,7 +311,6 @@ solvedLen i t = (== Just i) . fmap length . solnFor t solvedWith :: SolCall -> Text -> Campaign -> Bool solvedWith c t = maybe False (any $ (== SolCall c) . view call) . solnFor t - -- Encoding JSON tests instance Arbitrary Addr where