diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b75269e4a..85e8bdbd2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -57,6 +57,34 @@ steps: architecture: x64 versionSpec: $(pythonVersion) +- script: | + mkdir -p ../Downloads + cd ../Downloads + curl -L -o "solc" "https://github.com/ethereum/solidity/releases/download/v0.6.4/solc-static-linux" + chmod +x solc + displayName: Linux install Solc + condition: eq( variables['Agent.OS'], 'Linux' ) + +# NOTICE: +# Solc installation disabled for now until solc provides binaries for download. +# Installation on Mac via brew takes too long. +# +#- script: | +# brew update +# brew upgrade +# brew tap ethereum/ethereum +# brew install solidity +# displayName: Mac install Solc +# condition: eq( variables['Agent.OS'], 'Darwin' ) + +- powershell: | + mkdir -p ../Downloads + $client = new-object System.Net.WebClient + $client.DownloadFile("https://github.com/ethereum/solidity/releases/download/v0.6.4/solidity-windows.zip", "..\Downloads\solidity-windows.zip") + Expand-Archive –Path “..\Downloads\solidity-windows.zip” –Destination “..\Downloads\solidity-windows” + displayName: Windows install Solc + condition: eq( variables['Agent.OS'], 'Windows_NT' ) + - bash: | mkdir -p ../Downloads cd ../Downloads @@ -109,6 +137,7 @@ steps: pushd "$PWD" &>/dev/null cd ../Downloads export PATH="${PWD}/go-ipfs:${PATH}" + export PATH="${PWD}:${PATH}" export PATH="${HOME}/.yarn/bin:${HOME}/.config/yarn/global/node_modules/.bin:${PATH}" yarn config set cache-folder "${YARN_CACHE_FOLDER}" &>/dev/null popd &>/dev/null @@ -120,6 +149,7 @@ steps: pushd cd ..\Downloads $env:PATH="$($PWD.Path)\go-ipfs;$($env:PATH)" + $env:PATH="$($PWD.Path)\solidity-windows;$($env:PATH)" $env:PATH="$($env:USERPROFILE)\.yarn\bin;$($env:USERPROFILE)\.config\yarn\global\node_modules\.bin;$($env:PATH)" yarn config set cache-folder "$($YARN_CACHE_FOLDER)" | out-null popd diff --git a/packages/core/utils/src/file.ts b/packages/core/utils/src/file.ts index a3e96db31..66591ead4 100644 --- a/packages/core/utils/src/file.ts +++ b/packages/core/utils/src/file.ts @@ -23,7 +23,6 @@ export class File { public basedir: string; public resolver: (callback: (content: string) => void) => void; public pluginPath: string; - public storageConfig: any; public providerUrl: string; public importRemappings: ImportRemapping[] = []; public originalPath: string; @@ -34,7 +33,6 @@ export class File { this.basedir = options.basedir || ''; this.resolver = options.resolver; this.pluginPath = options.pluginPath ? options.pluginPath : ''; - this.storageConfig = options.storageConfig; this.providerUrl = ''; this.originalPath = options.originalPath || ''; diff --git a/packages/embark/src/test/config.js b/packages/embark/src/test/config.js index c5e4e03d2..3ba0bd998 100644 --- a/packages/embark/src/test/config.js +++ b/packages/embark/src/test/config.js @@ -288,7 +288,6 @@ describe('embark.Config', function () { "basedir": "", "importRemappings": [], "resolver": undefined, - "storageConfig": undefined, "providerUrl": "" }, { @@ -300,7 +299,6 @@ describe('embark.Config', function () { "basedir": "", "importRemappings": [], "resolver": undefined, - "storageConfig": undefined, "providerUrl": "" }, { @@ -312,7 +310,6 @@ describe('embark.Config', function () { "basedir": "", "importRemappings": [], "resolver": undefined, - "storageConfig": undefined, "providerUrl": "" } ]; diff --git a/packages/plugins/solc/package.json b/packages/plugins/solc/package.json index fed841ff0..f062b50b3 100644 --- a/packages/plugins/solc/package.json +++ b/packages/plugins/solc/package.json @@ -36,30 +36,58 @@ "_typecheck": "npm run solo -- typecheck", "ci": "npm run qa", "clean": "npm run reset", - "lint": "eslint src/", + "lint": "eslint src/ test/", "qa": "npm-run-all lint _typecheck _build", "reset": "npx rimraf dist embark-*.tgz package", - "solo": "embark-solo" + "solo": "embark-solo", + "test": "jest" }, "eslintConfig": { - "extends": "../../../.eslintrc.json" + "extends": [ + "../../../.eslintrc.json", + "plugin:jest/recommended", + "plugin:jest/style" + ] }, "dependencies": { "@babel/runtime-corejs3": "7.8.4", "async": "3.2.0", - "core-js": "3.4.3", - "semver": "5.6.0", + "core-js": "3.6.4", + "global": "4.4.0", + "semver": "7.1.3", "shelljs": "0.8.3" }, "devDependencies": { + "@babel/core": "7.8.6", + "babel-jest": "25.1.0", "embark-solo": "^5.2.3", + "embark-testing": "^5.3.0-nightly.14", + "embark-utils": "^5.3.0-nightly.14", "eslint": "6.8.0", + "eslint-plugin-jest": "22.5.1", + "jest": "25.1.0", "npm-run-all": "4.1.5", - "rimraf": "3.0.0" + "rimraf": "3.0.0", + "sinon": "7.4.2" }, "engines": { "node": ">=10.17.0", "npm": ">=6.11.3", "yarn": ">=1.19.1" + }, + "jest": { + "collectCoverage": true, + "testEnvironment": "node", + "testMatch": [ + "**/test/**/*.js" + ], + "transform": { + "\\.js$": [ + "babel-jest", + { + "rootMode": "upward" + } + ] + } } } diff --git a/packages/plugins/solc/src/lib/Compiler.js b/packages/plugins/solc/src/lib/Compiler.js index 7d2a7ee44..3e81cfe2a 100644 --- a/packages/plugins/solc/src/lib/Compiler.js +++ b/packages/plugins/solc/src/lib/Compiler.js @@ -3,8 +3,11 @@ const shelljs = require('shelljs'); const fs = require('fs'); const path = require('path'); +const isWin = process.platform === "win32"; + function compileSolcContract(logger, compileSettings, allowedDirectories, callback) { - const command = `solc --standard-json --allow-paths ${allowedDirectories.join(',')}`; + const binary = isWin ? 'solc.exe' : 'solc'; + const command = `${binary} --standard-json --allow-paths ${allowedDirectories.join(',')}`; shelljs.ShellString(JSON.stringify(compileSettings)).exec(command, {silent: true}, (code, stdout, stderr) => { if (stderr) { @@ -48,7 +51,7 @@ function compileSolc(embark, contractFiles, contractDirectories, options, callba } const logger = embark.logger; - const outputBinary = embark.pluginConfig.outputBinary; + const outputBinary = embark.config.pluginConfig.outputBinary; const outputDir = embark.config.buildDir + embark.config.contractDirectories[0]; const solcConfig = embark.config.embarkConfig.options.solc; @@ -188,12 +191,12 @@ function compileSolc(embark, contractFiles, contractDirectories, options, callba compiledObject[className].filename = filename; const normalized = path.normalize(filename); const origContract = contractFiles.find(contractFile => normalized.includes(path.normalize(contractFile.originalPath))); + if (origContract) { compiledObject[className].originalFilename = path.normalize(origContract.originalPath); } } } - next(null, compiledObject); } diff --git a/packages/plugins/solc/test/solc.spec.js b/packages/plugins/solc/test/solc.spec.js new file mode 100644 index 000000000..9e16702e9 --- /dev/null +++ b/packages/plugins/solc/test/solc.spec.js @@ -0,0 +1,137 @@ +import sinon from 'sinon'; +import assert from 'assert'; +import { fakeEmbark } from 'embark-testing'; +import Compiler from '../src/lib/Compiler'; + +function MockFile(options) { + this.path = options.path; + this.type = options.type; + this.originalPath = options.originalPath; + this.importRemappings = []; +} + +const isMac = process.platform === 'darwin'; + +describe('plugin/solc', () => { + + let embark, originalCompileSolcContract; + + beforeEach(() => { + + const testBed = fakeEmbark({ + pluginConfig: { + outputBinary: false + }, + embarkConfig: { + options: { + solc: {} + } + }, + contractDirectories: [] + }); + + embark = testBed.embark; + originalCompileSolcContract = Compiler.compileSolcContract; + Compiler.compileSolcContract = sinon.spy((logger, _settings, _directories, cb) => { + cb(null, 'compileString'); + }); + + MockFile.prototype.prepareForCompilation = sinon.spy(() => Promise.resolve('')); + }); + + afterEach(() => { + Compiler.compileSolcContract = originalCompileSolcContract; + embark.teardown(); + sinon.restore(); + }); + + it('should ensure testsuite has at least one test', () => { + expect(true).toBe(true); + }); + + // TODO(pascal): + // Remove this condition once there's a `solc` binary provided by the + // solidity project. We need to turn off tests for Mac on CI because + // we don't install `solc` on that platform. Reason being is that it + // takes too long to install via brew. + if (!isMac) { + it('should get solc version', () => { + return new Promise(done => { + Compiler.getSolcVersion(embark.logger, (err, version) => { + assert(version); + done(); + }); + }); + }); + + it('should compile solc contract', () => { + const EMPTY_TEST_CONTRACT = ` + pragma solidity ^0.6.0; + + contract TestContract { + + } + `; + + MockFile.prototype.prepareForCompilation = sinon.spy(_isCoverage => { + return Promise.resolve(EMPTY_TEST_CONTRACT); + }); + + let mockFile = new MockFile({ + type: 'dapp_file', + path: 'test_file.sol', + originalPath: 'test_file.sol' + }); + + const contractFiles = [mockFile]; + + const contractDirectories = ['contracts']; + const options = {}; + + return new Promise(done => { + Compiler.compileSolc(embark, contractFiles, contractDirectories, options, (err, result) => { + assert(mockFile.prepareForCompilation.called); + + assert(result.TestContract); + assert(result.TestContract.code); + assert(result.TestContract.runtimeBytecode); + assert(result.TestContract.realRuntimeBytecode); + assert(result.TestContract.swarmHash); + done(); + }); + }); + }); + + it('should emit error when compilation fails', () => { + + const ERROR_CONTRACT = ` + + ontract ErrorContract { + + } + `; + + MockFile.prototype.prepareForCompilation = sinon.spy(_isCoverage => { + return Promise.resolve(ERROR_CONTRACT); + }); + + let mockFile = new MockFile({ + type: 'dapp_file', + path: 'test_file.sol', + originalPath: 'test_file.sol' + }); + + const contractFiles = [mockFile]; + + const contractDirectories = ['contracts']; + const options = {}; + + return new Promise(done => { + Compiler.compileSolc(embark, contractFiles, contractDirectories, options, (err, _result) => { + assert(err); + done(); + }); + }); + }); + } +}); diff --git a/packages/plugins/solc/tsconfig.json b/packages/plugins/solc/tsconfig.json index 3494b2b51..8bc767233 100644 --- a/packages/plugins/solc/tsconfig.json +++ b/packages/plugins/solc/tsconfig.json @@ -8,5 +8,13 @@ "extends": "../../../tsconfig.base.json", "include": [ "src/**/*" + ], + "references": [ + { + "path": "../../core/utils" + }, + { + "path": "../../utils/testing" + } ] } diff --git a/yarn.lock b/yarn.lock index 92813ce41..af41a050d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10936,7 +10936,7 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" -global@^4.3.2, global@^4.4.0: +global@4.4.0, global@^4.3.2, global@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== @@ -20105,6 +20105,11 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== +semver@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" + integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== + semver@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.1.tgz#29104598a197d6cbe4733eeecbe968f7b43a9667"