Merge pull request #1327 from ethereum/resolve_test_imports

import supported in test contract
pull/7/head
Aniket 5 years ago committed by GitHub
commit b109475bf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 100
      remix-tests/src/compiler.ts
  2. 22
      remix-tests/tests/examples_5/contract/simple_storage.sol
  3. 15
      remix-tests/tests/examples_5/lib/EvenOdd.sol
  4. 24
      remix-tests/tests/examples_5/test/simple_storage_test.sol
  5. 27
      remix-tests/tests/testRunner.ts

@ -21,39 +21,84 @@ function writeTestAccountsContract (accounts: string[]) {
return testAccountContract.replace('>accounts<', body)
}
/**
* @dev Check if path includes name of a remix test file
* @param path file path to check
*/
function isRemixTestFile(path: string) {
return ['tests.sol', 'remix_tests.sol', 'remix_accounts.sol'].some(name => path.includes(name))
}
/**
* @dev Process file to prepare sources object to be passed in solc compiler input
*
* See: https://solidity.readthedocs.io/en/latest/using-the-compiler.html#input-description
*
* @param filePath path of file to process
* @param sources existing 'sources' object in which keys are the "global" names of the source files and
* value is object containing content of corresponding file with under key 'content'
* @param isRoot True, If file is a root test contract file which is getting processed, not an imported file
*/
function processFile(filePath: string, sources: SrcIfc, isRoot: boolean = false) {
const importRegEx: RegExp = /import ['"](.+?)['"];/g;
let group: RegExpExecArray| null = null;
const isFileAlreadyInSources: boolean = Object.keys(sources).includes(filePath)
// Return if file is a remix test file or already processed
if(isRemixTestFile(filePath) || isFileAlreadyInSources)
return
let content: string = fs.readFileSync(filePath, { encoding: 'utf-8' });
const testFileImportRegEx: RegExp = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
// import 'remix_tests.sol', if file is a root test contract file and doesn't already have it
if (isRoot && filePath.includes('_test.sol') && regexIndexOf(content, testFileImportRegEx) < 0) {
const includeTestLibs: string = '\nimport \'remix_tests.sol\';\n'
content = includeTestLibs.concat(content)
}
sources[filePath] = {content};
importRegEx.exec(''); // Resetting state of RegEx
// Process each 'import' in file content
while (group = importRegEx.exec(content)) {
const importedFile: string = group[1];
const importedFilePath: string = path.join(path.dirname(filePath), importedFile);
processFile(importedFilePath, sources)
}
}
const userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'
const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1)
// TODO: replace this with remix's own compiler code
export function compileFileOrFiles(filename: string, isDirectory: boolean, opts: any, cb: Function) {
let compiler: any
let accounts = opts.accounts || []
const sources = {
const accounts: string[] = opts.accounts || []
const sources: SrcIfc = {
'tests.sol': { content: require('../sol/tests.sol.js') },
'remix_tests.sol': { content: require('../sol/tests.sol.js') },
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) }
}
const filepath = (isDirectory ? filename : path.dirname(filename))
// TODO: for now assumes filepath dir contains all tests, later all this
// should be replaced with remix's & browser solidity compiler code
// This logic is wrong
// We should only look into current file if a full file name with path is given
// We should only walk through directory if a directory name is passed
const filepath: string = (isDirectory ? filename : path.dirname(filename))
try {
// walkSync only if it is a directory
fs.walkSync(filepath, (foundpath: string) => {
// only process .sol files
if (foundpath.split('.').pop() === 'sol') {
let c = fs.readFileSync(foundpath).toString()
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
let includeTestLibs = '\nimport \'remix_tests.sol\';\n'
if (foundpath.indexOf('_test.sol') > 0 && regexIndexOf(c, s) < 0) {
c = includeTestLibs.concat(c)
}
sources[foundpath] = { content: c }
if(!isDirectory && fs.existsSync(filename)) {
if (filename.split('.').pop() === 'sol') {
processFile(filename, sources, true)
} else {
throw new Error('Not a solidity file')
}
})
} else {
// walkSync only if it is a directory
fs.walkSync(filepath, (foundpath: string) => {
// only process .sol files
if (foundpath.split('.').pop() === 'sol') {
processFile(foundpath, sources, true)
}
})
}
} catch (e) {
throw e
} finally {
@ -85,19 +130,20 @@ export function compileFileOrFiles(filename: string, isDirectory: boolean, opts:
}
}
export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWorker: any, importFileCb: any, opts: any, cb: Function) {
export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWorker: boolean, importFileCb: any, opts: any, cb: Function) {
let compiler, filepath: string
let accounts = opts.accounts || []
const accounts: string[] = opts.accounts || []
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) {
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') }
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) }
}
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
let includeTestLibs = '\nimport \'remix_tests.sol\';\n'
const testFileImportRegEx: RegExp = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm
let includeTestLibs: string = '\nimport \'remix_tests.sol\';\n'
for (let file in sources) {
const c = sources[file].content
if (file.indexOf('_test.sol') > 0 && c && regexIndexOf(c, s) < 0) {
const c: string = sources[file].content
if (file.includes('_test.sol') && c && regexIndexOf(c, testFileImportRegEx) < 0) {
sources[file].content = includeTestLibs.concat(c)
}
}

@ -0,0 +1,22 @@
pragma solidity ^0.5.0;
import "../../examples_4/SafeMath.sol";
import "../lib/EvenOdd.sol";
contract SimpleStorage is EvenOdd{
using SafeMath for uint256;
uint public storedData;
constructor() public {
storedData = 100;
}
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint retVal) {
return storedData;
}
}

@ -0,0 +1,15 @@
pragma solidity ^0.5.0;
contract EvenOdd {
/**
* @dev Tells whether a number is even or odd
* @param num Number to check
*/
function check(int num) public pure returns (string memory){
if(num % 2 == 0)
return "EVEN";
return "ODD";
}
}

@ -0,0 +1,24 @@
pragma solidity ^0.5.0;
import "./../contract/simple_storage.sol";
contract StorageResolveTest {
SimpleStorage foo;
function beforeAll() public {
foo = new SimpleStorage();
}
function initialValueShouldBe100() public returns (bool) {
return Assert.equal(foo.get(), 100, "initial value is not correct");
}
//Test imported contract functions
function checkIfEven() public returns (bool) {
return Assert.equal(foo.check(10), 'EVEN', "value is odd");
}
function checkIfOdd() public returns (bool) {
return Assert.equal(foo.check(11), 'ODD', "value is even");
}
}

@ -183,6 +183,33 @@ describe('testRunner', () => {
})
})
// Test multiple directory import in test contract
describe('test multiple directory import in test contract', function () {
let filename = 'tests/examples_5/test/simple_storage_test.sol'
before(function (done) {
compileAndDeploy(filename, (_err, compilationData, contracts, accounts) => {
runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], { accounts }, testCallback, resultsCallback(done))
})
})
after(() => { tests = [] })
it('should 3 passing tests', function () {
assert.equal(results.passingNum, 3)
})
it('should return 4 messages', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StorageResolveTest', filename: 'tests/examples_5/test/simple_storage_test.sol' },
{ type: 'testPass', value: 'Initial value should be100', context: 'StorageResolveTest' },
{ type: 'testPass', value: 'Check if odd', context: 'StorageResolveTest' },
{ type: 'testPass', value: 'Check if even', context: 'StorageResolveTest' }
], ['time'])
})
})
//Test signed/unsigned integer weight
describe('test number weight', function () {
let filename = 'tests/number/number_test.sol'

Loading…
Cancel
Save