diff --git a/.circleci/config.yml b/.circleci/config.yml index 17d63cc969..2f87db9f05 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,13 +46,14 @@ jobs: - checkout - restore_cache: keys: - - dep-bundle-3-{{ checksum "package.json" }} + - dep-bundle-4-{{ checksum "package.json" }} - run: npm install - save_cache: - key: dep-bundle-3-{{ checksum "package.json" }} + key: dep-bundle-4-{{ checksum "package.json" }} paths: - ~/repo/node_modules - - run: cd src/app/debugger/remix-debugger && ./ci/browser_tests.sh + - run: npm run build_debugger + - run: ./ci/browser_tests_debugger.sh workflows: version: 2 diff --git a/src/app/debugger/remix-debugger/ci/browser_tests.sh b/ci/browser_tests_debugger.sh similarity index 92% rename from src/app/debugger/remix-debugger/ci/browser_tests.sh rename to ci/browser_tests_debugger.sh index fb1fa5a9bd..5d80223ca2 100755 --- a/src/app/debugger/remix-debugger/ci/browser_tests.sh +++ b/ci/browser_tests_debugger.sh @@ -19,7 +19,6 @@ SAUCECONNECT_JOBIDENTIFIER="remix_tests_${BUILD_ID}" SAUCECONNECT_READYFILE="sc.ready" TEST_EXITCODE=0 -npm install && npm run build npm run serve & wget $SAUCECONNECT_URL @@ -29,7 +28,7 @@ while [ ! -f $SAUCECONNECT_READYFILE ]; do sleep .5 done -npm run nightwatch_remote_parallel || TEST_EXITCODE=1 +npm run nightwatch_remote_debugger_parallel || TEST_EXITCODE=1 node ci/sauceDisconnect.js $SAUCECONNECT_USERNAME $SAUCECONNECT_ACCESSKEY $SAUCECONNECT_JOBIDENTIFIER diff --git a/src/app/debugger/remix-debugger/nightwatch.js b/nightwatch_debugger.js similarity index 95% rename from src/app/debugger/remix-debugger/nightwatch.js rename to nightwatch_debugger.js index b81c8176b5..ad88f23acb 100644 --- a/src/app/debugger/remix-debugger/nightwatch.js +++ b/nightwatch_debugger.js @@ -2,8 +2,8 @@ var buildId = process.env.CIRCLE_BUILD_NUM || process.env.TRAVIS_JOB_NUMBER module.exports = { - 'src_folders': ['./test-browser/test'], - 'output_folder': './test-browser/test/reports', + 'src_folders': ['./test-browser-debugger/test'], + 'output_folder': './test-browser-debugger/test/reports', 'custom_commands_path': '', 'custom_assertions_path': '', 'globals_path': '', diff --git a/package.json b/package.json index d201648fcf..12a7fc62ce 100644 --- a/package.json +++ b/package.json @@ -142,6 +142,7 @@ "linkremixsolidity": "cd node_modules && rm -rf remix-solidity && ln -s ../remix/remix-solidity remix-solidity && cd ..", "linkremixdebugger": "cd node_modules && rm -rf remix-debugger && ln -s ../remix/remix-debugger remix-debugger && cd ..", "build": "browserify src/index.js -o build/app.js", + "build_debugger": "browserify src/app/debugger/remix-debugger/index.js -o src/app/debugger/remix-debugger/build/app.js", "browsertest": "sleep 5 && npm run nightwatch_local", "csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='assets/css/font-awesome.min.css' assets/css/", "downloadsolc": "rimraf soljson.js && cd node_modules/solc && wget --no-check-certificate https://solc-bin.ethereum.org/soljson.js && cd ../../", @@ -154,13 +155,15 @@ "nightwatch_remote_firefox": "nightwatch --config nightwatch.js --env default", "nightwatch_remote_ie": "nightwatch --config nightwatch.js --env ie", "nightwatch_remote_parallel": "nightwatch --config nightwatch.js --env safari,chrome,default", - "nightwatch_remote_safari": "nightwatch --config nightwatch.js --env safari", + "nightwatch_remote_safari": "nightwatch --config nightwatch.js --env safari", + "nightwatch_remote_debugger_parallel": "nightwatch --config nightwatch_debugger.js --env local", "onchange": "onchange build/app.js -- npm-run-all lint", "prepublish": "mkdirp build; npm-run-all -ls downloadsolc_root build", "remixd": "node ./node_modules/remixd/src/main.js -s ./contracts", "selenium": "execr --silent selenium-standalone start", "selenium-install": "selenium-standalone install", "serve": "execr --silent http-server .", + "serve_debugger": "execr --silent http-server src/app/debugger/remix-debugger", "sourcemap": "exorcist --root ../ build/app.js.map > build/app.js", "start": "npm-run-all -lpr serve watch onchange remixd", "test": "npm run csslint; standard && node test/index.js", diff --git a/src/app/debugger/remix-debugger/README.md b/src/app/debugger/remix-debugger/README.md deleted file mode 100644 index 99745fc323..0000000000 --- a/src/app/debugger/remix-debugger/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# `remix-debugger` - -The Remix Debugger is a webapp to debug the Ethereum VM and transactions. - -+ [Installation](#installation) -+ [Development](#development) -+ [First steps](#firststeps) -+ [Tests](#tests) - -## Installation - -Make sure Node is [installed on your setup](https://docs.npmjs.com/getting-started/installing-node), and that a [local `geth`/`eth` node is running](../README.md#how-to-use). - -```bash -git clone https://github.com/ethereum/remix -cd remix/remix-debugger -npm install -``` - -This will build the debugger. Start it by opening `index.html` in your browser. - -## Development - -Run `npm run start_dev` to start a local webserver, accessible at `http://127.0.0.1:8080`. Your browser will reload when files are updated. - -## First steps - -Once Remix is connected to a node, you will be able to debug transactions. - -You can do that: - - using a block number and a transaction index. - - using a transaction hash. - -After loading the transaction succeeded, the hash, from and to field will show up. The VM trace is then loaded. - -The debugger itself contains several controls that allow stepping over the trace and seing the current state of a selected step: - -#### Slider and Stepping action - -The slider allows to move quickly from a state to another. - -Stepping actions are: -- Step Into Back -- Step Over Back -- Step Over Forward -- Step Into Forward -- Jump Next Call: this will select the next state that refers to a context changes - CALL, CALLCODE, DELEGATECALL, CREATE. - -#### State Viewer - -The upper right panel contains basic informations about the current step: -- VMTraceStep: the index in the trace of the current step. -- Step -- Add memory -- Gas: gas used by this step -- Remaining gas: gas left -- Loaded address: the current code loaded, refers to the executing code. - -The other 6 panels describe the current selected state: - - Instructions list: list of all the instruction that defines the current executing code. - - Stack - - Storage Changes - - Memory - - Call Data$ - - Call Stack - -## Tests - -* To run unit tests, run `npm test`. - -* For local headless browser tests: - * To install `selenium`: `npm run selenium-install` - * Every time you want to run local browser tests, run: `npm run test-browser` diff --git a/src/app/debugger/remix-debugger/ci/deploy_from_travis.sh b/src/app/debugger/remix-debugger/ci/deploy_from_travis.sh deleted file mode 100755 index e80aba8e47..0000000000 --- a/src/app/debugger/remix-debugger/ci/deploy_from_travis.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -set -e - -SHA=`git rev-parse --verify HEAD` - -git config user.name "Travis CI" -git config user.email "builds@ethereum.org" -git checkout --orphan gh-pages -git rm --cached -r . -echo "# Automatic build" > README.md -echo "Built website from {$SHA}. See https://github.com/ethereum/remix/ for details." >> README.md -# -f is needed because "build" is part of .gitignore - -# copying file to the root folder -cp remix-debugger/index.html index.html -mkdir build -cp remix-debugger/build/app.js build/app.js -mkdir assets -cp -R remix-debugger/assets/. assets/ - -git add -f README.md index.html build/app.js assets -git commit -m "Built website from {$SHA}." - -ENCRYPTION_LABEL=fade88419824 -ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" -ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" -ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} -ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} -openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ci/deploy_key.enc -out deploy_key -d -chmod 600 deploy_key -eval `ssh-agent -s` -ssh-add deploy_key - -git push -f git@github.com:ethereum/remix.git gh-pages diff --git a/src/app/debugger/remix-debugger/ci/deploy_key.enc b/src/app/debugger/remix-debugger/ci/deploy_key.enc deleted file mode 100644 index 99ddf96eee..0000000000 Binary files a/src/app/debugger/remix-debugger/ci/deploy_key.enc and /dev/null differ diff --git a/src/app/debugger/remix-debugger/ci/sauceDisconnect.js b/src/app/debugger/remix-debugger/ci/sauceDisconnect.js deleted file mode 100644 index b29328db5c..0000000000 --- a/src/app/debugger/remix-debugger/ci/sauceDisconnect.js +++ /dev/null @@ -1,72 +0,0 @@ -const https = require('https') - -var userName = process.argv[2] -var accessKey = process.argv[3] -var tunnelName = process.argv[4] - -function removeTunnel () { - const requestPath = `/rest/v1/${userName}/tunnels` - console.log(requestPath) - callSauce(requestPath, 'GET', function (error, result) { - if (error) { - console.log(error) - } else { - var data = JSON.parse(result) - for (var k in data) { - retrieveTunnel(data[k], function (error, result) { - if (error) { - console.log(error) - } else if (result.identtifier === tunnelName) { - deleteTunnel(result.id, function () { - console.log('tunnel deleted ' + data[k] + ' ' + tunnelName) - }) - } - }) - } - } - }) -} - -function retrieveTunnel (tunnelid, callback) { - const requestPath = `/rest/v1/${userName}/tunnels/${tunnelid}` - callSauce(requestPath, 'GET', function (error, result) { - if (error) { - callback(error) - } else { - callback(null, {'identtifier': JSON.parse(result).tunnel_identifier, 'id': tunnelid}) - } - }) -} - -function deleteTunnel (tunnelid, callback) { - const requestPath = `/rest/v1/${userName}/tunnels/${tunnelid}` - callSauce(requestPath, 'DELETE', callback) -} - -function callSauce (requestPath, type, callback) { - function responseCallback (res) { - res.setEncoding('utf8') - console.log('Response: ', res.statusCode, JSON.stringify(res.headers)) - res.on('data', function onData (chunk) { - console.log('BODY: ' + chunk) - callback(null, chunk) - }) - res.on('end', function onEnd () {}) - } - - var req = https.request({ - hostname: 'saucelabs.com', - path: requestPath, - method: type, - auth: userName + ':' + accessKey - }, responseCallback) - - req.on('error', function onError (e) { - console.log('problem with request: ' + e.message) - callback(e.message) - }) - req.write('') - req.end() -} - -removeTunnel() diff --git a/src/app/debugger/remix-debugger/findClient.js b/src/app/debugger/remix-debugger/findClient.js deleted file mode 100644 index 8ceb9bce00..0000000000 --- a/src/app/debugger/remix-debugger/findClient.js +++ /dev/null @@ -1,43 +0,0 @@ -var which = require('which') - -var geth = null -var eth = null - -try { - geth = which.sync('geth') -} catch (e) { -} - -try { - eth = which.sync('eth') -} catch (e) { -} -if (process.argv.length > 2) { - if (geth && process.argv[2] === 'geth') { - runGeth() - } else if (eth && process.argv[2] === 'eth') { - runEth() - } -} else if (geth && eth) { - console.log('both eth and geth has been found in your system') - console.log('restart the command with the desired client:') - console.log('npm run start_eth') - console.log('or') - console.log('npm run start_geth') -} else if (geth) { - runGeth() -} else if (eth) { - runEth() -} else { - console.log('neither eth or geth has been found in your system') -} - -function runEth () { - console.log('starting eth...') - process.exit(20) -} - -function runGeth () { - console.log('starting geth...') - process.exit(21) -} diff --git a/src/app/debugger/remix-debugger/package.json b/src/app/debugger/remix-debugger/package.json deleted file mode 100644 index 00fbfc8bcb..0000000000 --- a/src/app/debugger/remix-debugger/package.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "name": "remix-debugger", - "version": "0.1.2", - "description": "Ethereum IDE and tools for the web", - "contributors": [ - { - "name": "Yann Levreau", - "email": "yann@ethdev.com" - }, - { - "name": "Liana Husikyan", - "email": "liana@ethdev.com" - } - ], - "main": "./index.js", - "devDependencies": { - "babel-eslint": "^7.1.1", - "babel-plugin-transform-object-assign": "^6.22.0", - "babel-plugin-yo-yoify": "^0.3.3", - "babel-polyfill": "^6.22.0", - "babel-preset-env": "^1.6.1", - "babel-preset-es2015": "^6.24.0", - "babel-preset-stage-0": "^6.24.1", - "babelify": "^7.3.0", - "browserify": "^13.0.1", - "browserify-livereload": "^1.0.10", - "clipboard-copy": "^1.2.0", - "csjs-inject": "^1.0.1", - "ethereum-common": "0.0.18", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.1.1", - "ethereumjs-util": "^4.5.0", - "ethereumjs-vm": "2.3.1", - "fast-async": "^6.1.2", - "http-server": "^0.9.0", - "nightwatch": "^0.9.5", - "notify-error": "^1.2.0", - "npm-run-all": "^4.1.2", - "onchange": "^3.3.0", - "remix-core": "latest", - "remix-lib": "latest", - "remix-solidity": "latest", - "selenium-standalone": "^6.0.1", - "solc": "^0.4.13", - "standard": "^7.0.1", - "standard-reporter": "^1.0.5", - "tape": "^4.6.0", - "watchify": "^3.9.0", - "web3": "^0.15.3", - "yo-yo": "^1.2.1", - "yo-yoify": "^3.1.0" - }, - "scripts": { - "build": "mkdirp build; browserify index.js > build/app.js", - "lint": "standard | notify-error", - "nightwatch_local": "nightwatch --config nightwatch.js --env local", - "nightwatch_remote_chrome": "nightwatch --config nightwatch.js --env chrome", - "nightwatch_remote_firefox": "nightwatch --config nightwatch.js --env default", - "nightwatch_remote_ie": "nightwatch --config nightwatch.js --env ie", - "nightwatch_remote_parallel": "nightwatch --config nightwatch.js --env safari,chrome,default", - "nightwatch_remote_safari": "nightwatch --config nightwatch.js --env safari", - "onchange": "onchange build/app.js -- npm run lint", - "selenium": "selenium-standalone start", - "selenium-install": "selenium-standalone install", - "serve": "http-server .", - "start": "./runNode.sh", - "start_dev": "npm-run-all -lpr serve watch onchange", - "start_eth": "npm run warning_message; eth -j --rpccorsdomain '*'", - "start_geth": "npm run warning_message; geth --rpc --rpcapi 'web3,eth,debug' --rpcport 8545 --rpccorsdomain '*'", - "test": "standard && tape ./test/tests.js && ./ci/browser_tests.sh", - "test-browser": "npm-run-all -lpr selenium serve waittest", - "waittest": "sleep 5 && npm run nightwatch_local", - "warning_message": "echo 'DO NOT DO THIS IF eth/geth STORES PRIVATE KEYS!! External system might be able to access your node through the RPC server.\n\n';", - "watch": "mkdirp build; watchify index.js -p [ browserify-livereload --host 127.0.0.1 --port 1337 ] -dv -o build/app.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/ethereum/remix.git" - }, - "author": "cpp-ethereum team", - "license": "MIT", - "bugs": { - "url": "https://github.com/ethereum/remix/issues" - }, - "homepage": "https://github.com/ethereum/remix#readme", - "standard": { - "ignore": [ - "node_modules/*", - "build/*", - "test/resources/*" - ] - }, - "babel": { - "plugins": [ - "transform-es2015-template-literals", - "transform-es2015-literals", - "transform-es2015-function-name", - "transform-es2015-arrow-functions", - "transform-es2015-block-scoped-functions", - "transform-es2015-classes", - "transform-es2015-object-super", - "transform-es2015-shorthand-properties", - "transform-es2015-duplicate-keys", - "transform-es2015-computed-properties", - "transform-es2015-for-of", - "transform-es2015-sticky-regex", - "transform-es2015-unicode-regex", - "check-es2015-constants", - "transform-es2015-spread", - "transform-es2015-parameters", - "transform-es2015-destructuring", - "transform-es2015-block-scoping", - "transform-object-assign" - ] - }, - "browserify": { - "transform": [ - [ - "babelify", - { - "sourceMapsAbsolute": false, - "sourceMaps": true, - "plugins": [ - [ - "fast-async", - { - "runtimePattern": null, - "compiler": { - "es7": true, - "noRuntime": true, - "promises": true, - "wrapAwait": true - } - } - ], - [ - "yo-yoify" - ], - [ - "transform-object-assign" - ] - ], - "presets": [ - "es2015" - ] - } - ] - ] - } -} diff --git a/src/app/debugger/remix-debugger/runNode.sh b/src/app/debugger/remix-debugger/runNode.sh deleted file mode 100755 index 79575a46f2..0000000000 --- a/src/app/debugger/remix-debugger/runNode.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -node findClient.js $1 -RUNCLIENT=$? -if [ $RUNCLIENT -eq '20' ] -then - npm run start_eth -fi - -if [ $RUNCLIENT -eq '21' ] -then - echo $? - npm run start_geth -fi \ No newline at end of file diff --git a/src/app/debugger/remix-debugger/test-browser/resources/insertTestWeb3.js b/src/app/debugger/remix-debugger/test-browser-debugger/resources/insertTestWeb3.js similarity index 94% rename from src/app/debugger/remix-debugger/test-browser/resources/insertTestWeb3.js rename to src/app/debugger/remix-debugger/test-browser-debugger/resources/insertTestWeb3.js index 833c7198e1..0d0b2614b7 100644 --- a/src/app/debugger/remix-debugger/test-browser/resources/insertTestWeb3.js +++ b/src/app/debugger/remix-debugger/test-browser-debugger/resources/insertTestWeb3.js @@ -70,7 +70,8 @@ function waitForRemix (data) { }, 500) } -loadJSON('/test-browser/resources/testWeb3.json', function (result) { +console.log('injecting test web3...') +loadJSON('/test-browser-debugger/resources/testWeb3.json', function (result) { var data = JSON.parse(result) waitForRemix(data) }) diff --git a/src/app/debugger/remix-debugger/test-browser/resources/testWeb3.json b/src/app/debugger/remix-debugger/test-browser-debugger/resources/testWeb3.json similarity index 100% rename from src/app/debugger/remix-debugger/test-browser/resources/testWeb3.json rename to src/app/debugger/remix-debugger/test-browser-debugger/resources/testWeb3.json diff --git a/src/app/debugger/remix-debugger/test-browser/test/init.js b/src/app/debugger/remix-debugger/test-browser-debugger/test/init.js similarity index 100% rename from src/app/debugger/remix-debugger/test-browser/test/init.js rename to src/app/debugger/remix-debugger/test-browser-debugger/test/init.js diff --git a/src/app/debugger/remix-debugger/test-browser/test/sauce.js b/src/app/debugger/remix-debugger/test-browser-debugger/test/sauce.js similarity index 100% rename from src/app/debugger/remix-debugger/test-browser/test/sauce.js rename to src/app/debugger/remix-debugger/test-browser-debugger/test/sauce.js diff --git a/src/app/debugger/remix-debugger/test-browser/test/vmdebugger.js b/src/app/debugger/remix-debugger/test-browser-debugger/test/vmdebugger.js similarity index 100% rename from src/app/debugger/remix-debugger/test-browser/test/vmdebugger.js rename to src/app/debugger/remix-debugger/test-browser-debugger/test/vmdebugger.js diff --git a/test-browser-debugger/test/init.js b/test-browser-debugger/test/init.js new file mode 100644 index 0000000000..9d54e25785 --- /dev/null +++ b/test-browser-debugger/test/init.js @@ -0,0 +1,173 @@ +module.exports = function (browser, callback) { + extendBrowser(browser) + browser + .url('http://127.0.0.1:8080') + .injectScript('test-browser-debugger/resources/insertTestWeb3.js', function () { + // wait for the script to load test web3... + console.log('waiting for script ..') + setTimeout(function () { + callback() + }, 5000) + }) +} + +function extendBrowser (browser) { + browser.multipleClick = function (id, time) { + for (var k = 0; k < time; k++) { + browser.click(id) + } + return browser + } + + browser.assertCurrentSelectedItem = function (expected) { + browser.execute(function (id) { + var node = document.querySelector('#asmcodes div div[selected="selected"] span') + return node.innerText + }, [''], function (returnValue) { + browser.assert.equal(returnValue.value, expected) + }) + return browser + } + + browser.retrieveInnerText = function (selector, callback) { + browser.execute(function (selector) { + var node = document.querySelector(selector) + return node ? node.innerText : '' + }, [selector], function (returnValue) { + callback(returnValue.value) + }) + return browser + } + + browser.assertStepDetail = function (vmtracestepinfo, stepinfo, addmemoryinfo, gasinfo, remaininggasinfo, loadedaddressinfo) { + assertPanel('#stepdetail', browser, ['vmtracestep:' + vmtracestepinfo, 'executionstep:' + stepinfo, 'addmemory:' + addmemoryinfo, 'gas:' + gasinfo, 'remaininggas:' + remaininggasinfo, 'loadedaddress:' + loadedaddressinfo]) + return browser + } + + browser.assertStack = function (value) { + return assertPanel('#stackpanel', browser, value) + } + + browser.assertStorageChanges = function (value) { + return assertPanel('#storagepanel', browser, value) + } + + browser.assertMemory = function (value) { + return assertPanel('#memorypanel', browser, value) + } + + browser.assertCallData = function (value) { + return assertPanel('#calldatapanel', browser, value) + } + + browser.assertCallStack = function (value) { + return assertPanel('#callstackpanel', browser, value) + } + + browser.assertStackValue = function (index, value) { + return assertPanelValue('#stackpanel', browser, index, value) + } + + browser.assertStorageChangesValue = function (index, value) { + return assertPanelValue('#storagepanel', browser, index, value) + } + + browser.assertMemoryValue = function (index, value) { + return assertPanelValue('#memorypanel', browser, index, value) + } + + browser.assertCallStackValue = function (index, value) { + return assertPanelValue('#callstackpanel', browser, index, value) + } + + browser.debugerKeyCode = { + 'Enter': 13, + 'Up': 38, + 'Down': 40, + 'Right': '39', + 'Left': 37, + 'Esc': 27, + 'SpaceBar': 32, + 'Ctrl': 17, + 'Alt': 18, + 'Shift': 16 + } + +/* browser.sendKeys is not working for safari */ +/* still not working properly +browser.fireEvent = function (el, key, times, callback) { + var data = { + 'id': el.substring(1), + 'key': key, + 'times': times + } + browser.execute(function (data) { + data = JSON.parse(data) + var el = document.getElementById(data.id) + var eventObj + console.log(el) + console.log(data) + var k = 0 + if (document.createEventObject) { + eventObj = document.createEventObject() + eventObj.keyCode = data.key + while (k < data.times) { + console.log('firing brfore createEventObject') + el.fireEvent('onkeypress', eventObj) + console.log('firing') + k++ + } + } else if (typeof (KeyboardEvent) === 'function') { + eventObj = new KeyboardEvent('keyup') + eventObj.key = data.key + eventObj.which = data.key + while (k < data.times) { + console.log('firing brfore createEvent') + el.dispatchEvent(eventObj) + console.log('firing') + k++ + } + } + }, [JSON.stringify(data)], function () { + callback() + }) +} +*/ +} + +function assertPanel (id, browser, value) { + var selector = '.dropdownpanel div.dropdowncontent ul' + browser.execute(function (id, selector) { + var el = document.getElementById(id.replace('#', '').replace('.', '')) + var node = el.querySelector(selector) + var ret = [] + for (var k = 0; k < node.children.length; k++) { + if (node.children[k].innerText) { + ret.push(node.children[k].innerText) + } + } + return ret + }, [id, selector], function (returnValues) { + value.map(function (item, index) { + if (returnValues.value.length) { + var testValue = returnValues.value[index].replace(/\r\n/g, '').replace(/\t/g, '').replace(/\s/g, '') + browser.assert.equal(testValue, value[index]) + } else { + browser.assert.equal(item, '') + } + }) + }) + return browser +} + +function assertPanelValue (id, browser, index, value) { + var selector = id + ' .dropdownpanel .dropdowncontent ul' + browser.execute(function (id, index) { + var node = document.querySelector(id) + return node.children[index].innerText + }, [selector, index], function (returnValues) { + var testValue = returnValues.value.replace(/\r\n/g, '').replace(/\t/g, '').replace(/\s/g, '') + browser.assert.equal(testValue, value) + }) + return browser +} diff --git a/test-browser-debugger/test/sauce.js b/test-browser-debugger/test/sauce.js new file mode 100644 index 0000000000..4a41fe5930 --- /dev/null +++ b/test-browser-debugger/test/sauce.js @@ -0,0 +1,61 @@ +const https = require('https') + +module.exports = function sauce (callback) { + const currentTest = this.client.currentTest + const username = this.client.options.username + const sessionId = this.client.capabilities['webdriver.remote.sessionid'] + const accessKey = this.client.options.accessKey + + if (!this.client.launch_url.match(/saucelabs/)) { + console.log('Not saucelabs ...') + return callback() + } + + if (!username || !accessKey || !sessionId) { + console.log(this.client) + console.log('No username, accessKey or sessionId') + return callback() + } + + const passed = currentTest.results.passed === currentTest.results.tests + + const data = JSON.stringify({passed}) + + const requestPath = `/rest/v1/${username}/jobs/${sessionId}` + + function responseCallback (res) { + res.setEncoding('utf8') + console.log('Response: ', res.statusCode, JSON.stringify(res.headers)) + res.on('data', function onData (chunk) { + console.log('BODY: ' + chunk) + }) + res.on('end', function onEnd () { + console.info('Finished updating saucelabs') + callback() + }) + } + + try { + console.log('Updating saucelabs', requestPath) + + const req = https.request({ + hostname: 'saucelabs.com', + path: requestPath, + method: 'PUT', + auth: `${username}:${accessKey}`, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': data.length + } + }, responseCallback) + + req.on('error', function onError (e) { + console.log('problem with request: ' + e.message) + }) + req.write(data) + req.end() + } catch (error) { + console.log('Error', error) + callback() + } +} diff --git a/test-browser-debugger/test/vmdebugger.js b/test-browser-debugger/test/vmdebugger.js new file mode 100644 index 0000000000..f84555a0f3 --- /dev/null +++ b/test-browser-debugger/test/vmdebugger.js @@ -0,0 +1,192 @@ +'use strict' +var init = require('./init') +var sauce = require('./sauce') + +module.exports = { + beforeEach: function (browser, done) { + try { + init(browser, function () { + done() + }) + } catch (e) { + var mes = 'error ' + e.message + console.log(mes) + done(mes) + } + }, + + 'vmdebugger': function (browser) { + loadTraceNotFound(browser) + .click('#unload') + loadTrace(browser) + .click('#unload') + panels(browser) + .click('#unload') + slider(browser) + .click('#unload') + stepping(browser) + .click('#unload') + stepdetail(browser) + .end() + }, + + tearDown: sauce +} + +function loadTraceNotFound (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942zcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .click('#txinfo .title') + .execute(function () { + return document.querySelector('#txinfo .dropdownpanel .dropdownrawcontent').innerHTML + }, [], function (result) { + console.log(result.value) + if (result.value.indexOf('not found') === -1) { + browser.assert.fail(' txinput panel does not contain ', 'info about error', '') + } + }) + return browser +} + +function loadTrace (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .click('#txinfo .title') + .execute(function () { + return document.querySelector('#txinfo .dropdownpanel .dropdownrawcontent').innerHTML + }, [], function (result) { + if (result.value.indexOf('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') === -1) { + browser.assert.fail(' txinput panel does not contain 0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51 ', 'info about error', '') + } + }) + .click('#unload') + .waitForElementNotVisible('#vmdebugger', 1000) + return browser +} + +function panels (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .multipleClick('#intoforward', 63) + .assertStack(['0:0x', '1:0x60', '2:0x65', '3:0x38', '4:0x55', '5:0x60fe47b1']) + .assertStorageChanges(['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563:Objectkey:0x00value:0x38']) + .assertCallData(['0:0x60fe47b10000000000000000000000000000000000000000000000000000000000000038']) + .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5']) + .assertStackValue(1, '1:0x60') + .assertMemoryValue(6, '0x60:60606040526040516020806045833981????R??Q????E?9?') + .assertMemoryValue(7, '0x70:01604052808051906020019091905050???R??Q???????PP') + .assertMemoryValue(8, '0x80:5b806001016000600050819055505b50?????????P??UP?P') + .click('#intoforward') // CREATE + .assertStack(['']) + .assertStorageChanges([]) + .assertMemory(['']) + .assertCallData(['0:0x0000000000000000000000000000000000000000000000000000000000000000000000000000006060606040526040516020806045833981016040528080519060200190919050505b806001016000600050819055']) + .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', '1:(ContractCreation-Step63)']) + return browser +} + +function slider (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + /* + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.RIGHT_ARROW) + .sendKeys('#slider', browser.Keys.LEFT_ARROW) + */ + .assertCurrentSelectedItem('041 PUSH4 60fe47b1') + return browser +} + +function stepping (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .click('#intoforward') + .click('#intoforward') + .assertCurrentSelectedItem('004 MSTORE') + .click('#intoforward') + .click('#intoback') + .click('#intoback') + .assertCurrentSelectedItem('002 PUSH1 40') + .multipleClick('#intoforward', 62) + .assertCurrentSelectedItem('181 CREATE') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#overforward') + .assertCurrentSelectedItem('007 MLOAD') + .click('#intoback') + .click('#intoback') + .click('#intoback') + .click('#intoback') + .click('#intoback') + .click('#overforward') + .assertCurrentSelectedItem('182 PUSH1 01') + .click('#overforward') + .assertCurrentSelectedItem('184 PUSH1 00') + .click('#intoback') + .click('#intoback') + .click('#overback') + .assertCurrentSelectedItem('181 CREATE') + return browser +} + +function stepdetail (browser) { + browser + .clearValue('#txinput') + .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + .click('#load') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + .click('#intoforward') + /* + .fireEvent('#slider', browser.debugerKeyCode.Right, 4, function () { + browser.assertSticker('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + .click('#nextcall') + .assertSticker('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + .click('#intoforward') + .click('#overforward') + .assertSticker('108', '44', '', '0', '27145', '(Contract Creation - Step 63)') + .click('#intoforward') + .assertSticker('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + .end() + }) + */ + .assertStepDetail('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + .multipleClick('#intoforward', 57) + .assertStepDetail('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + .click('#overforward') + .click('#intoback') + .assertStepDetail('108', '44', '', '0', '27145', '(ContractCreation-Step63)') + .click('#intoforward') + .assertStepDetail('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + return browser +}