|
| 1 | +name: CI |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: |
| 6 | + - master |
| 7 | + pull_request: |
| 8 | + schedule: |
| 9 | + # run CI every day even if no PRs/merges occur |
| 10 | + - cron: '0 12 * * *' |
| 11 | + |
| 12 | +jobs: |
| 13 | + # needs to run only on pull_request |
| 14 | + lint: |
| 15 | + runs-on: ubuntu-latest |
| 16 | + steps: |
| 17 | + - uses: actions/checkout@v1 |
| 18 | + - name: Set up Python 3.6 |
| 19 | + uses: actions/setup-python@v1 |
| 20 | + with: |
| 21 | + python-version: 3.6 |
| 22 | + - name: Lint |
| 23 | + if: github.event_name == 'pull_request' |
| 24 | + env: |
| 25 | + BASE_SHA: ${{ github.event.pull_request.base.sha }} |
| 26 | + HEAD_SHA: ${{ github.event.pull_request.head.sha }} |
| 27 | + run: | |
| 28 | + pip install -e .[lint] |
| 29 | + black --version |
| 30 | + git diff --name-only $BASE_SHA..$HEAD_SHA | python scripts/pyfile_exists.py | xargs black --diff --check |
| 31 | + mypy --version |
| 32 | + mypy |
| 33 | + tests: |
| 34 | + runs-on: ubuntu-latest |
| 35 | + strategy: |
| 36 | + matrix: |
| 37 | + type: ["examples", "ethereum", "ethereum_bench", "ethereum_vm", "native", "wasm", "other"] |
| 38 | + steps: |
| 39 | + - uses: actions/checkout@v1 |
| 40 | + - name: Set up Python 3.6 |
| 41 | + uses: actions/setup-python@v1 |
| 42 | + with: |
| 43 | + python-version: 3.6 |
| 44 | + - name: Install dependencies |
| 45 | + env: |
| 46 | + TEST_TYPE: ${{ matrix.type }} |
| 47 | + run: | |
| 48 | + # Install solc unconditionally because it only takes a second or two |
| 49 | + sudo wget -O /usr/bin/solc https://github.com/ethereum/solidity/releases/download/v0.4.24/solc-static-linux |
| 50 | + sudo chmod +x /usr/bin/solc |
| 51 | + EXTRAS="dev-noks" |
| 52 | + if [[ "$TEST_TYPE" != "ethereum"* ]]; then |
| 53 | + EXTRAS="dev" |
| 54 | + fi |
| 55 | + pip install -e .[$EXTRAS] |
| 56 | + - name: Run Tests |
| 57 | + env: |
| 58 | + TEST_TYPE: ${{ matrix.type }} |
| 59 | + run: | |
| 60 | + # Launches all examples; this assumes PWD is examples/script |
| 61 | + launch_examples() { |
| 62 | + # concolic assumes presence of ../linux/simpleassert |
| 63 | + echo "Running concolic.py..." |
| 64 | + HW=../linux/helloworld |
| 65 | + python ./concolic.py |
| 66 | + if [ $? -ne 0 ]; then |
| 67 | + return 1 |
| 68 | + fi |
| 69 | +
|
| 70 | + echo "Running count_instructions.py..." |
| 71 | + python ./count_instructions.py $HW |grep -q Executed |
| 72 | + if [ $? -ne 0 ]; then |
| 73 | + return 1 |
| 74 | + fi |
| 75 | +
|
| 76 | + echo "Running introduce_symbolic_bytes.py..." |
| 77 | + gcc -static -g src/state_explore.c -o state_explore |
| 78 | + ADDRESS=0x$(objdump -S state_explore | grep -A 1 '((value & 0xff) != 0)' | |
| 79 | + tail -n 1 | sed 's|^\s*||g' | cut -f1 -d:) |
| 80 | + python ./introduce_symbolic_bytes.py state_explore $ADDRESS |
| 81 | + if [ $? -ne 0 ]; then |
| 82 | + return 1 |
| 83 | + fi |
| 84 | +
|
| 85 | + echo "Running run_simple.py..." |
| 86 | + gcc -x c -static -o hello test_run_simple.c |
| 87 | + python ./run_simple.py hello |
| 88 | + if [ $? -ne 0 ]; then |
| 89 | + return 1 |
| 90 | + fi |
| 91 | +
|
| 92 | + echo "Running run_hook.py..." |
| 93 | + MAIN_ADDR=$(nm $HW|grep 'T main' | awk '{print "0x"$1}') |
| 94 | + python ./run_hook.py $HW $MAIN_ADDR |
| 95 | + if [ $? -ne 0 ]; then |
| 96 | + return 1 |
| 97 | + fi |
| 98 | +
|
| 99 | + echo "Running state_control.py..." |
| 100 | + # Straight from the header of state_control.py |
| 101 | + gcc -static -g src/state_explore.c -o state_explore |
| 102 | + SE_ADDR=0x$(objdump -S state_explore | grep -A 1 'value == 0x41' | |
| 103 | + tail -n 1 | sed 's|^\s*||g' | cut -f1 -d:) |
| 104 | + python ./state_control.py state_explore $SE_ADDR |
| 105 | + if [ $? -ne 0 ]; then |
| 106 | + return 1 |
| 107 | + fi |
| 108 | +
|
| 109 | + return 0 |
| 110 | + } |
| 111 | +
|
| 112 | + make_vmtests(){ |
| 113 | + DIR=`pwd` |
| 114 | + if [ ! -f ethereum_vm/.done ]; then |
| 115 | + echo "Automaking VMTests" `pwd` |
| 116 | + cd ./tests/ && mkdir -p ethereum_vm/VMTests_concrete && mkdir -p ethereum_vm/VMTests_symbolic |
| 117 | + rm -Rf vmtests; git clone https://github.com/ethereum/tests --depth=1 vmtests |
| 118 | + for i in ./vmtests/VMTests/*; do python ./auto_generators/make_VMTests.py $i; done |
| 119 | + for i in ./vmtests/VMTests/*; do python ./auto_generators/make_VMTests.py $i --symbolic; done |
| 120 | + rm -rf ./vmtests |
| 121 | + touch ethereum_vm/.done |
| 122 | + fi |
| 123 | + cd $DIR |
| 124 | + } |
| 125 | +
|
| 126 | + make_wasm_tests(){ |
| 127 | + DIR=`pwd` |
| 128 | + if [ ! -f .wasm_done ]; then |
| 129 | + echo "Automaking WASM Tests" `pwd` |
| 130 | + cd ./tests/wasm |
| 131 | + ./generate_tests.sh |
| 132 | + touch .wasm_done |
| 133 | + fi |
| 134 | + cd $DIR |
| 135 | + } |
| 136 | +
|
| 137 | + install_truffle(){ |
| 138 | + curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash |
| 139 | + source ~/.nvm/nvm.sh |
| 140 | + nvm install --lts |
| 141 | + nvm use --lts |
| 142 | +
|
| 143 | + npm install -g truffle |
| 144 | + } |
| 145 | +
|
| 146 | + run_truffle_tests(){ |
| 147 | + mkdir truffle_tests |
| 148 | + cd truffle_tests |
| 149 | + truffle unbox metacoin |
| 150 | + manticore . --contract MetaCoin --workspace output |
| 151 | + ### The original comment says we should get 41 states, but after implementing the shift |
| 152 | + ### insructions, we get 31. Was the original comment a typo? |
| 153 | +
|
| 154 | + # The correct answer should be 41 |
| 155 | + # but Manticore fails to explore the paths due to the lack of the 0x1f opcode support |
| 156 | + # see https://github.com/trailofbits/manticore/issues/1166 |
| 157 | + # if [ "$(ls output/*tx -l | wc -l)" != "41" ]; then |
| 158 | + if [ "$(ls output/*tx -l | wc -l)" != "13" ]; then |
| 159 | + echo "Truffle test failed" `ls output/*tx -l | wc -l` "!= 13" |
| 160 | + return 1 |
| 161 | + fi |
| 162 | + echo "Truffle test succeded" |
| 163 | + cd .. |
| 164 | + return 0 |
| 165 | + } |
| 166 | +
|
| 167 | + run_tests_from_dir() { |
| 168 | + DIR=$1 |
| 169 | + pytest --cov=manticore -n auto "tests/$DIR" |
| 170 | + coverage xml |
| 171 | + } |
| 172 | +
|
| 173 | + run_examples() { |
| 174 | + pushd examples/linux |
| 175 | + make |
| 176 | + for example in $(make list); do |
| 177 | + ./$example < /dev/zero > /dev/null |
| 178 | + done |
| 179 | + echo Built and ran Linux examples |
| 180 | + popd |
| 181 | +
|
| 182 | + pushd examples/script |
| 183 | + launch_examples |
| 184 | + RESULT=$? |
| 185 | + echo Ran example scripts |
| 186 | + popd |
| 187 | + return $RESULT |
| 188 | + } |
| 189 | +
|
| 190 | + # Test type |
| 191 | + case $TEST_TYPE in |
| 192 | + ethereum_vm) |
| 193 | + make_vmtests |
| 194 | + echo "Running only the tests from 'tests/$TEST_TYPE' directory" |
| 195 | + run_tests_from_dir $TEST_TYPE |
| 196 | + RV=$? |
| 197 | +
|
| 198 | + echo "Running truffle test" |
| 199 | + install_truffle |
| 200 | + run_truffle_tests |
| 201 | + RV=$(($RV + $?)) |
| 202 | + ;; |
| 203 | + wasm) |
| 204 | + make_wasm_tests ;& # Fallthrough |
| 205 | + native) ;& # Fallthrough |
| 206 | + ethereum) ;& # Fallthrough |
| 207 | + ethereum_bench) ;& # Fallthrough |
| 208 | + other) |
| 209 | + echo "Running only the tests from 'tests/$TEST_TYPE' directory" |
| 210 | + run_tests_from_dir $TEST_TYPE |
| 211 | + RV=$? |
| 212 | + ;; |
| 213 | +
|
| 214 | + examples) |
| 215 | + run_examples |
| 216 | + ;; |
| 217 | +
|
| 218 | + all) |
| 219 | + echo "Running all tests registered in travis_test.sh: examples, native, ethereum, ethereum_vm, other"; |
| 220 | +
|
| 221 | + # Functions should return 0 on success and 1 on failure |
| 222 | + RV=0 |
| 223 | + run_tests_from_dir native |
| 224 | + RV=$(($RV + $?)) |
| 225 | + run_tests_from_dir ethereum |
| 226 | + RV=$(($RV + $?)) |
| 227 | + make_vmtests; run_tests_from_dir ethereum_vm |
| 228 | + RV=$(($RV + $?)) |
| 229 | + make_wasm_tests; run_tests_from_dir wasm |
| 230 | + RV=$(($RV + $?)) |
| 231 | + run_tests_from_dir other |
| 232 | + RV=$(($RV + $?)) |
| 233 | + run_examples |
| 234 | + RV=$(($RV + $?)) |
| 235 | + ;; |
| 236 | +
|
| 237 | + *) |
| 238 | + echo "Usage: $0 [examples|native|ethereum|ethereum_vm|other|all]" |
| 239 | + exit 3; |
| 240 | + ;; |
| 241 | + esac |
| 242 | + - name: Coverage Upload |
| 243 | + uses: codecov/codecov-action@v1 |
| 244 | + with: |
| 245 | + token: ${{ secrets.CODECOV_TOKEN }} |
| 246 | + file: ./coverage.xml |
| 247 | + yml: ./codecov.yml |
0 commit comments