From ba2d67f5e97ebf7441f397d7dcb8888a910c53b5 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 20 Oct 2016 16:16:23 +0200 Subject: [PATCH] mock compiler --- ci/browser_tests.sh | 2 +- ci/makeMockCompiler.js | 56 +++++++++++++++++ nightwatch.js | 7 ++- test-browser/helpers/contracts.js | 23 +++++++ test-browser/mockcompiler/compiler.js | 41 ++++++++++++ test-browser/mockcompiler/requests.js | 77 +++++++++++++++++++++++ test-browser/tests/ballot.js | 31 +++++++++ test-browser/{ => tests}/debugger.js | 2 +- test-browser/{ => tests}/new-file-test.js | 2 +- test-browser/tests/simpleContract.js | 28 +++++++++ test-browser/{ => tests}/smoke-test.js | 2 +- 11 files changed, 265 insertions(+), 6 deletions(-) create mode 100644 ci/makeMockCompiler.js create mode 100644 test-browser/helpers/contracts.js create mode 100644 test-browser/mockcompiler/compiler.js create mode 100644 test-browser/mockcompiler/requests.js create mode 100644 test-browser/tests/ballot.js rename test-browser/{ => tests}/debugger.js (80%) rename test-browser/{ => tests}/new-file-test.js (82%) create mode 100644 test-browser/tests/simpleContract.js rename test-browser/{ => tests}/smoke-test.js (82%) diff --git a/ci/browser_tests.sh b/ci/browser_tests.sh index eeb94fb7c2..96eac86159 100755 --- a/ci/browser_tests.sh +++ b/ci/browser_tests.sh @@ -8,7 +8,7 @@ SAUCECONNECT_JOBIDENTIFIER="browsersolidity_tests_${TRAVIS_JOB_NUMBER}" SAUCECONNECT_READYFILE="sc.ready" TEST_EXITCODE=0 -npm run build +node ci/makeMockCompiler.js npm run serve & wget "$SAUCECONNECT_URL" diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js new file mode 100644 index 0000000000..a957754346 --- /dev/null +++ b/ci/makeMockCompiler.js @@ -0,0 +1,56 @@ +var fs = require('fs'); +var solc = require('solc/wrapper'); +var soljson = require('../soljson'); +var compiler = solc(soljson); +var inputs = require('../test-browser/mockcompiler/requests.js'); +var compilationResult = gatherCompilationResults(inputs); +replaceSolCompiler(compilationResult); + +function gatherCompilationResults (sol) { + var compilationResult = {}; + for (var k in sol) { + var item = sol[k]; + var result = compile(item, 1); + compilationResult[result.key] = result; + result = compile(item, 0); + compilationResult[result.key] = result; + } + return compilationResult; +} + +function compile (source, optimization) { + var missingInputs = []; + var result = compiler.compile(source, optimization, function (path) { + missingInputs.push(path); + }); + var key = optimization.toString(); + for (var k in source.sources) { + key += k + source.sources[k]; + } + key = key.replace(/(\t)|(\n)|( )/g, ''); + return { + key: key, + source: source, + optimization: optimization, + missingInputs: missingInputs, + result: result + }; +} + +function replaceSolCompiler (results) { + fs.readFile('./test-browser/mockcompiler/compiler.js', 'utf8', function (error, data) { + if (error) { + console.log(error); + process.exit(1); + return; + } + data = data + '\n\nvar mockData = ' + JSON.stringify(results) + ';\n'; + fs.writeFile('./soljson.js', data, 'utf8', function (error) { + if (error) { + console.log(error); + process.exit(1); + return; + } + }); + }); +} diff --git a/nightwatch.js b/nightwatch.js index 3bdd1939ce..cce0dc85e8 100644 --- a/nightwatch.js +++ b/nightwatch.js @@ -3,7 +3,7 @@ var TRAVIS_JOB_NUMBER = process.env.TRAVIS_JOB_NUMBER module.exports = { - 'src_folders': ['test-browser'], + 'src_folders': ['test-browser/tests'], 'output_folder': 'reports', 'custom_commands_path': '', 'custom_assertions_path': '', @@ -50,7 +50,8 @@ module.exports = { 'desiredCapabilities': { 'browserName': 'safari', 'javascriptEnabled': true, - 'platform': 'MAC', + 'platform': 'OS X 10.10', + 'version': '8.0', 'acceptSslCerts': true, 'build': 'build-' + TRAVIS_JOB_NUMBER, 'tunnel-identifier': 'browsersolidity_tests_' + TRAVIS_JOB_NUMBER @@ -62,6 +63,8 @@ module.exports = { 'browserName': 'internet explorer', 'javascriptEnabled': true, 'acceptSslCerts': true, + 'platform': 'WIN8.1', + 'version': '11', 'build': 'build-' + TRAVIS_JOB_NUMBER, 'tunnel-identifier': 'browsersolidity_tests_' + TRAVIS_JOB_NUMBER } diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js new file mode 100644 index 0000000000..3046ccc037 --- /dev/null +++ b/test-browser/helpers/contracts.js @@ -0,0 +1,23 @@ +module.exports = { + checkCompiledContracts: function (browser, compiled, callback) { + browser.execute(function () { + var contracts = document.querySelectorAll('.udapp .contract'); + var ret = []; + for (var k in contracts) { + var el = contracts[k]; + if (el.querySelector) { + ret.push({ + name: el.querySelector('.title').innerText.replace(el.querySelector('.size').innerText, '').replace(/(\t)|(\r)|(\n)/g, '') // IE/firefox add \r\n + }); + } + } + return ret; + }, [''], function (result) { + browser.assert.equal(result.value.length, compiled.length); + result.value.map(function (item, i) { + browser.assert.equal(item.name, compiled[i]); + }); + callback(); + }); + } +}; diff --git a/test-browser/mockcompiler/compiler.js b/test-browser/mockcompiler/compiler.js new file mode 100644 index 0000000000..0c032a0763 --- /dev/null +++ b/test-browser/mockcompiler/compiler.js @@ -0,0 +1,41 @@ +var Module = { // eslint-disable-line + cwrap: function () { return arguments[0] === 'version' ? version : compile; }, + writeStringToMemory: function () {}, + setValue: function () {}, + Pointer_stringify: function () {}, + Runtime: { + addFunction: function () {}, + removeFunction: function () {} + }, + _compileJSONMulti: {}, + _compileJSONCallback: {}, + _compileJSON: {} +}; + +function compile (source, optimization, missingInputs) { + if (typeof source === 'string') { + source = JSON.parse(source); + } + var key = optimization.toString(); + for (var k in source.sources) { + key += k + source.sources[k]; + } + key = key.replace(/(\t)|(\n)|( )/g, ''); + var data = mockData[key]; // eslint-disable-line + if (data === undefined) { + return JSON.stringify({ + errors: ['mock compiler: source not found'] + }); + } else { + data.missingInputs.map(function (item, i) { + if (missingInputs) { + missingInputs(item); + } + }); + } + return JSON.stringify(data.result); +} + +function version () { + return 'mock compiler'; +} diff --git a/test-browser/mockcompiler/requests.js b/test-browser/mockcompiler/requests.js new file mode 100644 index 0000000000..4d293b4087 --- /dev/null +++ b/test-browser/mockcompiler/requests.js @@ -0,0 +1,77 @@ +module.exports = { + 'testSimpleContract': { + 'sources': { + 'Untitled1': 'contract test1 {} contract test2 {}' + } + }, + 'ballot': { + 'sources': { + 'Untitled1': `pragma solidity ^0.4.0; +contract Ballot { + + struct Voter { + uint weight; + bool voted; + uint8 vote; + address delegate; + } + struct Proposal { + uint voteCount; + } + + address chairperson; + mapping(address => Voter) voters; + Proposal[] proposals; + + /// Create a new ballot with $(_numProposals) different proposals. + function Ballot(uint8 _numProposals) { + chairperson = msg.sender; + voters[chairperson].weight = 1; + proposals.length = _numProposals; + } + + /// Give $(voter) the right to vote on this ballot. + /// May only be called by $(chairperson). + function giveRightToVote(address voter) { + if (msg.sender != chairperson || voters[voter].voted) return; + voters[voter].weight = 1; + } + + /// Delegate your vote to the voter $(to). + function delegate(address to) { + Voter sender = voters[msg.sender]; // assigns reference + if (sender.voted) return; + while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) + to = voters[to].delegate; + if (to == msg.sender) return; + sender.voted = true; + sender.delegate = to; + Voter delegate = voters[to]; + if (delegate.voted) + proposals[delegate.vote].voteCount += sender.weight; + else + delegate.weight += sender.weight; + } + + /// Give a single vote to proposal $(proposal). + function vote(uint8 proposal) { + Voter sender = voters[msg.sender]; + if (sender.voted || proposal >= proposals.length) return; + sender.voted = true; + sender.vote = proposal; + proposals[proposal].voteCount += sender.weight; + } + + function winningProposal() constant returns (uint8 winningProposal) { + uint256 winningVoteCount = 0; + for (uint8 proposal = 0; proposal < proposals.length; proposal++) + if (proposals[proposal].voteCount > winningVoteCount) { + winningVoteCount = proposals[proposal].voteCount; + winningProposal = proposal; + } + } +} +` + } + } +}; diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js new file mode 100644 index 0000000000..ffa302fa7c --- /dev/null +++ b/test-browser/tests/ballot.js @@ -0,0 +1,31 @@ +'use strict'; +var testData = require('../mockcompiler/requests'); +// var contractHelper = require('../helpers/contracts'); + +module.exports = { + 'Ballot': function (browser) { + runTests(browser, testData); + } +}; + +function runTests (browser, testData) { + browser + .url('http://127.0.0.1:8080/#version=builtin') + .waitForElementVisible('.newFile', 10000); + browser.assert.notEqual(testData, null); + // TODO add Ballot tests. -> setValue('#input textarea', ... ) is not working properly with that contract. + /* testBallot(browser, testData.ballot.sources.Untitled1, function () { + browser.end(); + });*/ +} + +/* +function testBallot (browser, contract, callback) { + browser + .click('.newFile') + .clearValue('#input textarea') + .setValue('#input textarea', contract, function () { + browser.pause('10000'); + contractHelper.checkCompiledContracts(browser, ['Ballot'], callback); + }); +}*/ diff --git a/test-browser/debugger.js b/test-browser/tests/debugger.js similarity index 80% rename from test-browser/debugger.js rename to test-browser/tests/debugger.js index 92b4edd859..d0f8baa3f5 100644 --- a/test-browser/debugger.js +++ b/test-browser/tests/debugger.js @@ -3,7 +3,7 @@ module.exports = { 'Debugger Render': function (browser) { browser - .url('http://127.0.0.1:8080') + .url('http://127.0.0.1:8080/#version=builtin') .waitForElementPresent('#debugger', 10000) .waitForElementPresent('#debugger #slider', 10000) .end(); diff --git a/test-browser/new-file-test.js b/test-browser/tests/new-file-test.js similarity index 82% rename from test-browser/new-file-test.js rename to test-browser/tests/new-file-test.js index 1e8e8210ba..410c9b71c4 100644 --- a/test-browser/new-file-test.js +++ b/test-browser/tests/new-file-test.js @@ -3,7 +3,7 @@ module.exports = { 'New file test': function (browser) { browser - .url('http://127.0.0.1:8080') + .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) .click('.newFile') .pause('10000') diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js new file mode 100644 index 0000000000..887d6a3d35 --- /dev/null +++ b/test-browser/tests/simpleContract.js @@ -0,0 +1,28 @@ +'use strict'; +var testData = require('../mockcompiler/requests'); +var contractHelper = require('../helpers/contracts'); + +module.exports = { + 'Simple Contract': function (browser) { + runTests(browser, testData); + } +}; + +function runTests (browser, testData) { + browser + .url('http://127.0.0.1:8080/#version=builtin') + .waitForElementVisible('.newFile', 10000); + browser.assert.notEqual(testData, null); + testSimpleContract(browser, testData.testSimpleContract.sources.Untitled1, function () { + browser.end(); + }); +} + +function testSimpleContract (browser, contract, callback) { + browser + .click('.newFile') + .clearValue('#input textarea') + .setValue('#input textarea', contract) + .pause('5000'); + contractHelper.checkCompiledContracts(browser, ['test1', 'test2'], callback); +} diff --git a/test-browser/smoke-test.js b/test-browser/tests/smoke-test.js similarity index 82% rename from test-browser/smoke-test.js rename to test-browser/tests/smoke-test.js index 9ce6a9742e..0a71df1fc1 100644 --- a/test-browser/smoke-test.js +++ b/test-browser/tests/smoke-test.js @@ -3,7 +3,7 @@ module.exports = { 'Smoke test': function (browser) { browser - .url('http://127.0.0.1:8080') + .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('#righthand-panel', 10000) .pause('10000') .assert.containsText('#righthand-panel', 'Solidity version')