diff options
author | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-03-16 23:34:02 +0800 |
---|---|---|
committer | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-03-21 22:12:18 +0800 |
commit | 8b52793f2fa21bcb23a3c38b6d3773cfc20186fd (patch) | |
tree | 82ec9791f2d31d1a60e3ddf019da42b3ee4af2e1 | |
parent | 18b9fe525622d9e18491f76136d7697806996a09 (diff) | |
download | dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar.gz dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar.bz2 dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar.lz dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar.xz dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.tar.zst dexon-sol-tools-8b52793f2fa21bcb23a3c38b6d3773cfc20186fd.zip |
Add tests for compiler utils
-rw-r--r-- | packages/deployer/package.json | 5 | ||||
-rw-r--r-- | packages/deployer/src/globals.d.ts | 2 | ||||
-rw-r--r-- | packages/deployer/src/utils/compiler.ts | 5 | ||||
-rw-r--r-- | packages/deployer/src/utils/fs_wrapper.ts | 1 | ||||
-rw-r--r-- | packages/deployer/test/compiler_test.ts | 47 | ||||
-rw-r--r-- | packages/deployer/test/compiler_utils_test.ts | 74 | ||||
-rw-r--r-- | packages/deployer/test/deployer_test.ts (renamed from packages/deployer/test/deploy_test.ts) | 77 |
7 files changed, 159 insertions, 52 deletions
diff --git a/packages/deployer/package.json b/packages/deployer/package.json index 3982c0067..77f017ef3 100644 --- a/packages/deployer/package.json +++ b/packages/deployer/package.json @@ -7,7 +7,8 @@ "scripts": { "build:watch": "tsc -w", "build": "yarn clean && copyfiles 'test/fixtures/contracts/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "test": "npm run build; mocha lib/test/*_test.js", + "test": "run-s build run_mocha", + "run_mocha": "mocha lib/test/*_test.js", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "compile": "npm run build; node lib/src/cli.js compile", @@ -37,6 +38,7 @@ "@types/yargs": "^11.0.0", "chai": "^4.0.1", "copyfiles": "^1.2.0", + "dirty-chai": "^2.0.1", "ethers-typescript-typings": "^0.0.4", "mocha": "^4.0.1", "nyc": "^11.0.1", @@ -51,6 +53,7 @@ "@0xproject/types": "^0.4.1", "@0xproject/utils": "^0.4.3", "@0xproject/web3-wrapper": "^0.3.1", + "npm-run-all": "^4.1.2", "ethereumjs-util": "^5.1.1", "isomorphic-fetch": "^2.2.1", "lodash": "^4.17.4", diff --git a/packages/deployer/src/globals.d.ts b/packages/deployer/src/globals.d.ts index 3cff8a909..83db346f9 100644 --- a/packages/deployer/src/globals.d.ts +++ b/packages/deployer/src/globals.d.ts @@ -1,3 +1,5 @@ +declare module 'dirty-chai'; + // tslint:disable:completed-docs declare module 'solc' { import * as Web3 from 'web3'; diff --git a/packages/deployer/src/utils/compiler.ts b/packages/deployer/src/utils/compiler.ts index 3fb35e9ed..1d21d7d31 100644 --- a/packages/deployer/src/utils/compiler.ts +++ b/packages/deployer/src/utils/compiler.ts @@ -48,7 +48,7 @@ export async function createArtifactsDirIfDoesNotExistAsync(artifactsDir: string * @return Solc compiler version range. */ export function parseSolidityVersionRange(source: string): string { - const SOLIDITY_VERSION_RANGE_REGEX = /pragma solidity (.*);/; + const SOLIDITY_VERSION_RANGE_REGEX = /pragma\s+solidity\s+(.*);/; const solcVersionRangeMatch = source.match(SOLIDITY_VERSION_RANGE_REGEX); if (_.isNull(solcVersionRangeMatch)) { throw new Error('Could not find Solidity version range in source'); @@ -104,9 +104,6 @@ export function parseDependencies(source: string): string[] { */ export function findImportIfExist(contractSources: ContractSources, importPath: string): solc.ImportContents { const fileName = path.basename(importPath); - if (_.isUndefined(contractSources)) { - throw new Error('Contract sources not yet initialized'); - } const source = contractSources[fileName]; if (_.isUndefined(source)) { throw new Error(`Contract source not found for ${fileName}`); diff --git a/packages/deployer/src/utils/fs_wrapper.ts b/packages/deployer/src/utils/fs_wrapper.ts index 34c7caa0e..e02c83f27 100644 --- a/packages/deployer/src/utils/fs_wrapper.ts +++ b/packages/deployer/src/utils/fs_wrapper.ts @@ -7,5 +7,6 @@ export const fsWrapper = { writeFileAsync: promisify<undefined>(fs.writeFile), mkdirAsync: promisify<undefined>(fs.mkdir), doesPathExistSync: fs.existsSync, + rmdirSync: fs.rmdirSync, removeFileAsync: promisify<undefined>(fs.unlink), }; diff --git a/packages/deployer/test/compiler_test.ts b/packages/deployer/test/compiler_test.ts new file mode 100644 index 000000000..1c4d3c697 --- /dev/null +++ b/packages/deployer/test/compiler_test.ts @@ -0,0 +1,47 @@ +import * as chai from 'chai'; +import 'mocha'; + +import { Compiler } from '../src/compiler'; +import { fsWrapper } from '../src/utils/fs_wrapper'; +import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types'; + +import { exchange_binary } from './fixtures/exchange_bin'; +import { constants } from './util/constants'; + +const expect = chai.expect; + +describe('#Compiler', () => { + const artifactsDir = `${__dirname}/fixtures/artifacts`; + const contractsDir = `${__dirname}/fixtures/contracts`; + const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; + const compilerOpts: CompilerOptions = { + artifactsDir, + contractsDir, + networkId: constants.networkId, + optimizerEnabled: constants.optimizerEnabled, + specifiedContracts: new Set(constants.specifiedContracts), + }; + const compiler = new Compiler(compilerOpts); + beforeEach(function(done: DoneCallback) { + this.timeout(constants.timeoutMs); + (async () => { + if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { + await fsWrapper.removeFileAsync(exchangeArtifactPath); + } + await compiler.compileAsync(); + done(); + })().catch(done); + }); + it('should create an Exchange artifact with the correct unlinked binary', async () => { + const opts = { + encoding: 'utf8', + }; + const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts); + const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); + const exchangeContractData: ContractNetworkData = exchangeArtifact.networks[constants.networkId]; + // The last 43 bytes of the binaries are metadata which may not be equivalent + const unlinkedBinaryWithoutMetadata = exchangeContractData.bytecode.slice(0, -86); + const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86); + expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); + }); +}); diff --git a/packages/deployer/test/compiler_utils_test.ts b/packages/deployer/test/compiler_utils_test.ts new file mode 100644 index 000000000..f86a44862 --- /dev/null +++ b/packages/deployer/test/compiler_utils_test.ts @@ -0,0 +1,74 @@ +import * as chai from 'chai'; +import * as dirtyChai from 'dirty-chai'; +import 'mocha'; + +import { + createArtifactsDirIfDoesNotExistAsync, + getNormalizedErrMsg, + parseDependencies, + parseSolidityVersionRange, +} from '../src/utils/compiler'; +import { fsWrapper } from '../src/utils/fs_wrapper'; + +chai.use(dirtyChai); +const expect = chai.expect; + +describe.only('Compiler utils', () => { + describe('#getNormalizedErrorMessage', () => { + it('normalizes the error message', () => { + const errMsg = 'base/Token.sol:6:46: Warning: Unused local variable'; + const normalizedErrMsg = getNormalizedErrMsg(errMsg); + expect(normalizedErrMsg).to.be.equal('Token.sol:6:46: Warning: Unused local variable'); + }); + }); + describe('#createArtifactsDirIfDoesNotExistAsync', () => { + it('creates artifacts dir', async () => { + const artifactsDir = `${__dirname}/artifacts`; + expect(fsWrapper.doesPathExistSync(artifactsDir)).to.be.false(); + await createArtifactsDirIfDoesNotExistAsync(artifactsDir); + expect(fsWrapper.doesPathExistSync(artifactsDir)).to.be.true(); + fsWrapper.rmdirSync(artifactsDir); + expect(fsWrapper.doesPathExistSync(artifactsDir)).to.be.false(); + }); + }); + describe('#parseSolidityVersionRange', () => { + it('correctly parses the version range', () => { + expect(parseSolidityVersionRange('pragma solidity ^0.0.1;')).to.be.equal('^0.0.1'); + expect(parseSolidityVersionRange('\npragma solidity 0.0.1;')).to.be.equal('0.0.1'); + expect(parseSolidityVersionRange('pragma solidity <=1.0.1;')).to.be.equal('<=1.0.1'); + expect(parseSolidityVersionRange('pragma solidity ~1.0.1;')).to.be.equal('~1.0.1'); + }); + // TODO: For now that doesn't work. This will work after we switch to a grammar-based parser + it.skip('correctly parses the version range with comments', () => { + expect(parseSolidityVersionRange('// pragma solidity ~1.0.1;\npragma solidity ~1.0.2;')).to.be.equal( + '~1.0.2', + ); + }); + }); + describe('#parseDependencies', () => { + it('correctly parses Exchange dependencies', async () => { + const exchangeSource = await fsWrapper.readFileAsync(`${__dirname}/fixtures/contracts/Exchange.sol`, { + encoding: 'utf8', + }); + expect(parseDependencies(exchangeSource)).to.be.deep.equal([ + 'TokenTransferProxy.sol', + 'Token.sol', + 'SafeMath.sol', + ]); + }); + it('correctly parses TokenTransferProxy dependencies', async () => { + const exchangeSource = await fsWrapper.readFileAsync( + `${__dirname}/fixtures/contracts/TokenTransferProxy.sol`, + { + encoding: 'utf8', + }, + ); + expect(parseDependencies(exchangeSource)).to.be.deep.equal(['Token.sol', 'Ownable.sol']); + }); + // TODO: For now that doesn't work. This will work after we switch to a grammar-based parser + it.skip('correctly parses commented out dependencies', async () => { + const contractWithCommentedOutDependencies = `// import "./TokenTransferProxy.sol";`; + expect(parseDependencies(contractWithCommentedOutDependencies)).to.be.deep.equal([]); + }); + }); +}); diff --git a/packages/deployer/test/deploy_test.ts b/packages/deployer/test/deployer_test.ts index f67cd8234..9c34d74aa 100644 --- a/packages/deployer/test/deploy_test.ts +++ b/packages/deployer/test/deployer_test.ts @@ -10,55 +10,38 @@ import { constructor_args, exchange_binary } from './fixtures/exchange_bin'; import { constants } from './util/constants'; const expect = chai.expect; -const artifactsDir = `${__dirname}/fixtures/artifacts`; -const contractsDir = `${__dirname}/fixtures/contracts`; -const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; -const compilerOpts: CompilerOptions = { - artifactsDir, - contractsDir, - networkId: constants.networkId, - optimizerEnabled: constants.optimizerEnabled, - specifiedContracts: new Set(constants.specifiedContracts), -}; -const compiler = new Compiler(compilerOpts); -const deployerOpts = { - artifactsDir, - networkId: constants.networkId, - jsonrpcUrl: constants.jsonrpcUrl, - defaults: { - gasPrice: constants.gasPrice, - }, -}; -const deployer = new Deployer(deployerOpts); -/* tslint:disable */ -beforeEach(function(done: DoneCallback) { - this.timeout(constants.timeoutMs); - (async () => { - if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { - await fsWrapper.removeFileAsync(exchangeArtifactPath); - } - await compiler.compileAsync(); - done(); - })().catch(done); -}); -/* tslint:enable */ - -describe('#Compiler', () => { - it('should create an Exchange artifact with the correct unlinked binary', async () => { - const opts = { - encoding: 'utf8', - }; - const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts); - const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); - const exchangeContractData: ContractNetworkData = exchangeArtifact.networks[constants.networkId]; - // The last 43 bytes of the binaries are metadata which may not be equivalent - const unlinkedBinaryWithoutMetadata = exchangeContractData.bytecode.slice(0, -86); - const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86); - expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); - }); -}); describe('#Deployer', () => { + const artifactsDir = `${__dirname}/fixtures/artifacts`; + const contractsDir = `${__dirname}/fixtures/contracts`; + const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; + const compilerOpts: CompilerOptions = { + artifactsDir, + contractsDir, + networkId: constants.networkId, + optimizerEnabled: constants.optimizerEnabled, + specifiedContracts: new Set(constants.specifiedContracts), + }; + const compiler = new Compiler(compilerOpts); + const deployerOpts = { + artifactsDir, + networkId: constants.networkId, + jsonrpcUrl: constants.jsonrpcUrl, + defaults: { + gasPrice: constants.gasPrice, + }, + }; + const deployer = new Deployer(deployerOpts); + beforeEach(function(done: DoneCallback) { + this.timeout(constants.timeoutMs); + (async () => { + if (fsWrapper.doesPathExistSync(exchangeArtifactPath)) { + await fsWrapper.removeFileAsync(exchangeArtifactPath); + } + await compiler.compileAsync(); + done(); + })().catch(done); + }); describe('#deployAsync', () => { it('should deploy the Exchange contract without updating the Exchange artifact', async () => { const exchangeConstructorArgs = [constants.zrxTokenAddress, constants.tokenTransferProxyAddress]; |