feat: import resolver

This commit is contained in:
Anthony Laibe 2019-01-14 11:21:40 +00:00 committed by Iuri Matias
parent 0d8f23303a
commit 29db66be23
31 changed files with 392 additions and 426 deletions

View File

@ -206,6 +206,7 @@
"@types/node": "10.11.7", "@types/node": "10.11.7",
"@types/os-locale": "2.1.0", "@types/os-locale": "2.1.0",
"@types/pretty-ms": "3.2.0", "@types/pretty-ms": "3.2.0",
"@types/request": "2.48.1",
"@types/web3": "1.0.12", "@types/web3": "1.0.12",
"babel-plugin-dynamic-import-node": "2.2.0", "babel-plugin-dynamic-import-node": "2.2.0",
"chai": "4.1.2", "chai": "4.1.2",

View File

@ -652,7 +652,7 @@ class EmbarkController {
engine.startService("deployment", { engine.startService("deployment", {
trackContracts: false, trackContracts: false,
compileOnceOnly: true, compileOnceOnly: true,
disableOptimizations: options.coverage isCoverage: options.coverage
}); });
engine.startService("storage"); engine.startService("storage");
engine.startService("codeGenerator"); engine.startService("codeGenerator");

View File

@ -1,5 +1,4 @@
const fs = require('./fs.js'); const fs = require('./fs.js');
const File = require('./file.js');
const Plugins = require('./plugins.js'); const Plugins = require('./plugins.js');
const utils = require('../utils/utils.js'); const utils = require('../utils/utils.js');
const path = require('path'); const path = require('path');
@ -11,6 +10,7 @@ const cloneDeep = require('lodash.clonedeep');
import { replaceZeroAddressShorthand } from '../utils/addressUtils'; import { replaceZeroAddressShorthand } from '../utils/addressUtils';
import { unitRegex } from "../utils/regexConstants"; import { unitRegex } from "../utils/regexConstants";
import * as utilsContractsConfig from "../utils/contractsConfig"; import * as utilsContractsConfig from "../utils/contractsConfig";
import { File, Types } from "./file";
const DEFAULT_CONFIG_PATH = 'config/'; const DEFAULT_CONFIG_PATH = 'config/';
@ -59,13 +59,13 @@ var Config = function(options) {
resolver = resolver || function(callback) { resolver = resolver || function(callback) {
callback(fs.readFileSync(filename).toString()); callback(fs.readFileSync(filename).toString());
}; };
self.contractsFiles.push(new File({filename, type: File.types.custom, path: filename, resolver})); self.contractsFiles.push(new File({path: filename, type: Types.custom, resolver}));
}); });
self.events.on('file-remove', (fileType, removedPath) => { self.events.on('file-remove', (fileType, removedPath) => {
if(fileType !== 'contract') return; if(fileType !== 'contract') return;
const normalizedPath = path.normalize(removedPath); const normalizedPath = path.normalize(removedPath);
self.contractsFiles = self.contractsFiles.filter(file => path.normalize(file.filename) !== normalizedPath); self.contractsFiles = self.contractsFiles.filter(file => path.normalize(file.path) !== normalizedPath);
}); });
}; };
@ -127,7 +127,7 @@ Config.prototype.loadContractFiles = function() {
if (!this.contractFiles || newContractsFiles.length !== this.contractFiles.length || !deepEqual(newContractsFiles, this.contractFiles)) { if (!this.contractFiles || newContractsFiles.length !== this.contractFiles.length || !deepEqual(newContractsFiles, this.contractFiles)) {
this.contractsFiles = this.contractsFiles.concat(newContractsFiles).filter((file, index, arr) => { this.contractsFiles = this.contractsFiles.concat(newContractsFiles).filter((file, index, arr) => {
return !arr.some((file2, index2) => { return !arr.some((file2, index2) => {
return file.filename === file2.filename && index < index2; return file.path === file2.path && index < index2;
}); });
}); });
} }
@ -369,11 +369,11 @@ Config.prototype.loadExternalContractsFiles = function() {
return this.logger.error(__("HTTP contract file not found") + ": " + contract.file); return this.logger.error(__("HTTP contract file not found") + ": " + contract.file);
} }
const localFile = fileObj.filePath; const localFile = fileObj.filePath;
this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: fileObj.url, storageConfig: storageConfig})); this.contractsFiles.push(new File({path: localFile, type: Types.http, basedir: '', externalUrl: fileObj.url, storageConfig: storageConfig}));
} else if (fs.existsSync(contract.file)) { } else if (fs.existsSync(contract.file)) {
this.contractsFiles.push(new File({filename: contract.file, type: File.types.dapp_file, basedir: '', path: contract.file, storageConfig: storageConfig})); this.contractsFiles.push(new File({path: contract.file, type: Types.dappFile, basedir: '', storageConfig: storageConfig}));
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) { } else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
this.contractsFiles.push(new File({filename: path.join('./node_modules/', contract.file), type: File.types.dapp_file, basedir: '', path: path.join('./node_modules/', contract.file), storageConfig: storageConfig})); this.contractsFiles.push(new File({path: path.join('./node_modules/', contract.file), type: Types.dappFile, basedir: '', storageConfig: storageConfig}));
} else { } else {
this.logger.error(__("contract file not found") + ": " + contract.file); this.logger.error(__("contract file not found") + ": " + contract.file);
} }
@ -571,7 +571,7 @@ Config.prototype.loadFiles = function(files) {
return (file[0] === '$' || file.indexOf('.') >= 0); return (file[0] === '$' || file.indexOf('.') >= 0);
}).filter(function(file) { }).filter(function(file) {
let basedir = findMatchingExpression(file, files); let basedir = findMatchingExpression(file, files);
readFiles.push(new File({filename: file, type: File.types.dapp_file, basedir: basedir, path: file, storageConfig: storageConfig})); readFiles.push(new File({path: file, type: Types.dappFile, basedir: basedir, storageConfig: storageConfig}));
}); });
var filesFromPlugins = []; var filesFromPlugins = [];
@ -605,7 +605,7 @@ Config.prototype.loadPluginContractFiles = function() {
contractsPlugins.forEach(function(plugin) { contractsPlugins.forEach(function(plugin) {
plugin.contractsFiles.forEach(function(file) { plugin.contractsFiles.forEach(function(file) {
var filename = file.replace('./',''); var filename = file.replace('./','');
self.contractsFiles.push(new File({filename: filename, pluginPath: plugin.pluginPath, type: File.types.custom, path: filename, storageConfig: storageConfig, resolver: function(callback) { self.contractsFiles.push(new File({path: filename, pluginPath: plugin.pluginPath, type: Types.custom, storageConfig: storageConfig, resolver: function(callback) {
callback(plugin.loadPluginFile(file)); callback(plugin.loadPluginFile(file));
}})); }}));
}); });

View File

@ -212,7 +212,7 @@ class Engine {
} }
setupCompilerAndContractsManagerService(options) { setupCompilerAndContractsManagerService(options) {
this.registerModule('compiler', {plugins: this.plugins, disableOptimizations: options.disableOptimizations}); this.registerModule('compiler', {plugins: this.plugins, isCoverage: options.isCoverage});
this.registerModule('solidity', {ipc: this.ipc, useDashboard: this.useDashboard}); this.registerModule('solidity', {ipc: this.ipc, useDashboard: this.useDashboard});
this.registerModule('vyper'); this.registerModule('vyper');
this.registerModule('contracts_manager', {plugins: this.plugins, compileOnceOnly: options.compileOnceOnly}); this.registerModule('contracts_manager', {plugins: this.plugins, compileOnceOnly: options.compileOnceOnly});

View File

@ -1,210 +0,0 @@
const async = require('async');
const fs = require('./fs.js');
const path = require('path');
const request = require('request');
const utils = require('../utils/utils');
class File {
constructor(options) {
this.filename = options.filename.replace(/\\/g, '/');
this.type = options.type;
this.path = options.path;
this.basedir = options.basedir;
this.resolver = options.resolver;
this.pluginPath = options.pluginPath ? options.pluginPath : '';
this.downloadedImports = false;
this.importRemappings = []; // mapping downloaded imports to local file
this.storageConfig = options.storageConfig;
this.providerUrl = null;
}
addRemappings(prefix, httpFileObj, level, callback) {
let target = prefix;
if (httpFileObj) {
target = httpFileObj.filePath;
} else if (fs.existsSync(path.join(path.dirname(this.filename), prefix))) {
target = path.join(path.dirname(this.filename), prefix);
} else if (fs.existsSync(path.join("node_modules", prefix))) {
target = path.join("node_modules", prefix);
}
if (target === prefix) return callback();
target = fs.dappPath(target);
const remapping = {
prefix,
target
};
if (httpFileObj) return callback();
if (!this.importRemappings.some(existing => existing.prefix === remapping.prefix)) {
this.importRemappings.push(remapping);
}
fs.readFile(target, (err, importedContract) => {
if (err) return callback(err);
if (!importedContract) return callback(`File not found: ${target}`);
this._parseFileForImport(importedContract.toString(), false, ++level, callback);
});
}
_parseFileForImport(content, isHttpContract, level, callback) {
const self = this;
if (self.filename.indexOf('.sol') < 0) {
// Only supported in Solidity
return callback(null, content);
}
const regex = /import ["']([-a-zA-Z0-9@:%_+.~#?&\/=]+)["'];/g;
const filesToDownload = [];
const pathWithoutFile = path.dirname(self.path);
let newContent = content;
let storageConfig = self.storageConfig;
if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
self.providerUrl = storageConfig.upload.getUrl;
}
let m, matches = [];
while ((m = regex.exec(content))) {
matches.push(m[1]);
}
async.each(matches, (match, next) => {
const httpFileObj = utils.getExternalContractUrl(match, self.providerUrl);
const fileObj = {
fileRelativePath: path.join(path.dirname(self.filename), match),
url: `${pathWithoutFile}/${match}`
};
self.addRemappings(match, httpFileObj, level, (err) => {
if (err) return next(err);
if (httpFileObj) {
newContent = newContent.replace(match, httpFileObj.filePath);
fileObj.fileRelativePath = httpFileObj.filePath;
fileObj.url = httpFileObj.url;
} else if (!isHttpContract) {
// Just a normal import
return next();
}
filesToDownload.push(fileObj);
next();
});
}, (err) => {
callback(err, newContent, filesToDownload);
});
}
parseFileForImport(content, isHttpContract, callback) {
const self = this;
if (typeof isHttpContract === 'function') {
callback = isHttpContract;
isHttpContract = false;
}
this._parseFileForImport(content, isHttpContract, 0, (err, newContent, filesToDownload) => {
if (err) return callback(err);
if (self.downloadedImports) {
// We already parsed this file
return callback(null, newContent);
}
async.each(filesToDownload, ((fileObj, eachCb) => {
self.downloadFile(fileObj.fileRelativePath, fileObj.url, (_content) => {
eachCb();
});
}), (err) => {
self.downloadedImports = true;
callback(err, newContent);
});
});
}
downloadFile(filename, url, callback) {
const self = this;
async.waterfall([
function makeTheDir(next) {
fs.mkdirp(path.dirname(filename), (err) => {
if (err) {
return next(err);
}
next();
});
},
function downloadTheFile(next) {
let alreadyCalledBack = false;
function doCallback(err) {
if (alreadyCalledBack) {
return;
}
alreadyCalledBack = true;
next(err);
}
request(url)
.on('response', function (response) {
if (response.statusCode !== 200) {
doCallback('Getting file returned code ' + response.statusCode);
}
})
.on('error', doCallback)
.pipe(fs.createWriteStream(filename))
.on('finish', () => {
doCallback();
});
},
function readFile(next) {
fs.readFile(filename, next);
},
function parseForImports(content, next) {
self.parseFileForImport(content.toString(), true, (err) => {
next(err, content);
});
}
], (err, content) => {
if (err) {
console.error(__('Error while downloading the file'), url, err);
return callback('');
}
callback(content.toString());
});
}
content(callback) {
let content;
if (this.type === File.types.embark_internal) {
content = fs.readFileSync(fs.embarkPath(utils.joinPath('dist', this.path))).toString();
} else if (this.type === File.types.dapp_file) {
content = fs.readFileSync(this.path).toString();
} else if (this.type === File.types.custom) {
return this.resolver((theContent) => {
this.parseFileForImport(theContent, (err, newContent) => {
callback(newContent);
});
});
} else if (this.type === File.types.http) {
return this.downloadFile(this.filename, this.path, (content) => {
if (!content) {
return callback(content);
}
this.path = this.filename;
this.type = File.types.dapp_file;
callback(content);
});
} else {
throw new Error("unknown file: " + this.filename);
}
return this.parseFileForImport(content, (err, newContent) => {
callback(newContent);
});
}
}
File.types = {
embark_internal: 'embark_internal',
dapp_file: 'dapp_file',
custom: 'custom',
http: 'http'
};
module.exports = File;

77
src/lib/core/file.ts Normal file
View File

@ -0,0 +1,77 @@
import * as path from "path";
const fs = require("./fs.js");
const utils = require("../utils/utils");
export enum Types {
embarkInternal = "embark_internal",
dappFile = "dapp_file",
custom = "custom",
http = "http",
}
interface ImportRemapping {
prefix: string;
target: string;
}
export class File {
public type: Types;
public externalUrl: string = "";
public path: string;
public basedir: string;
public resolver: (callback: (content: string) => void) => void;
public pluginPath: string;
public storageConfig: any;
public providerUrl: string;
public importRemappings: ImportRemapping[] = [];
constructor(options: any) {
this.type = options.type;
this.basedir = options.basedir;
this.resolver = options.resolver;
this.pluginPath = options.pluginPath ? options.pluginPath : "";
this.storageConfig = options.storageConfig;
this.providerUrl = "";
if (this.type === Types.http) {
const external = utils.getExternalContractUrl(options.externalUrl, this.providerUrl);
this.externalUrl = external.url;
this.path = external.filePath;
} else {
this.path = options.path.replace(/\\/g, "/");
}
}
public get content(): Promise<string> {
return new Promise<string>((resolve) => {
switch (this.type) {
case Types.embarkInternal: {
const content = fs.readFileSync(fs.embarkPath(path.join("dist", this.path)), "utf-8");
return resolve(content);
}
case Types.dappFile: {
const content = fs.readFileSync(this.path, "utf-8").toString();
return resolve(content);
}
case Types.custom: {
return this.resolver((content: string) => {
resolve(content);
});
}
case Types.http: {
fs.ensureFileSync(this.path);
return utils.downloadFile(this.externalUrl, this.path, () => {
const content = fs.readFileSync(this.path, "utf-8");
resolve(content);
});
}
}
});
}
}

View File

@ -107,10 +107,14 @@ class BlockchainConnector {
if (type === 'vm') { if (type === 'vm') {
const sim = self._getSimulator(); const sim = self._getSimulator();
const options = Object.assign({}, self.config.contractsConfig.deployment, {gasPrice: "0x01", gasLimit: "0xfffffffffffff"}); const options = Object.assign({}, self.config.contractsConfig.deployment, {
self.provider = sim.provider(options); gasPrice: "0x01",
gasLimit: "0xfffffffffffff"
});
if (coverage) { if (coverage) {
options.allowUnlimitedContractSize = true;
self.provider = sim.provider(options);
// Here we patch the sendAsync method on the provider. The goal behind this is to force pure/constant/view calls to become // Here we patch the sendAsync method on the provider. The goal behind this is to force pure/constant/view calls to become
// transactions, so that we can pull in execution traces and account for those executions in code coverage. // transactions, so that we can pull in execution traces and account for those executions in code coverage.
// //
@ -143,6 +147,8 @@ class BlockchainConnector {
}); });
}); });
}; };
} else {
self.provider = sim.provider(options);
} }
self.web3.setProvider(self.provider); self.web3.setProvider(self.provider);

View File

@ -9,7 +9,7 @@ This module abstracts the compiler interface. It exposes a plugin api to registe
arguments: arguments:
* `contractFiles` - <array of embark File Objects> * `contractFiles` - <array of embark File Objects>
* `options` - <object> config object `{disableOptimizations: boolean (default: false)}` * `options` - <object> config object `{isCoverage: boolean (default: false)}`
response: response:
@ -33,8 +33,8 @@ response:
example: example:
``` ```
const File = require('src/lib/core/file.js'); import { File } from 'src/lib/core/file.js';
const contractFiles = [(new File({filename: "simplestorage.sol", type: "custom", path: "simplestorage.sol", resolver: (cb) => { return cb(".. contract code...") }}))]; const contractFiles = [(new File({path: "simplestorage.sol", type: "custom", resolver: (cb) => { return cb(".. contract code...") }}))];
embark.events.request("compiler:contracts", contractFiles, {}, (err, compiledObject) => { embark.events.request("compiler:contracts", contractFiles, {}, (err, compiledObject) => {
}) })

View File

@ -7,17 +7,17 @@ import { CompilerPluginObject, Plugins } from "../../../typings/plugins";
class Compiler { class Compiler {
private logger: any; private logger: any;
private plugins: Plugins; private plugins: Plugins;
private disableOptimizations: any; private isCoverage: boolean;
constructor(embark: Embark, options: any) { constructor(embark: Embark, options: any) {
this.logger = embark.logger; this.logger = embark.logger;
this.plugins = options.plugins; this.plugins = options.plugins;
this.disableOptimizations = options.disableOptimizations; this.isCoverage = options.isCoverage;
embark.events.setCommandHandler("compiler:contracts", this.compile_contracts.bind(this)); embark.events.setCommandHandler("compiler:contracts", this.compile_contracts.bind(this));
} }
private compile_contracts(contractFiles: any[], options: any, cb: any) { private compile_contracts(contractFiles: any[], cb: any) {
if (contractFiles.length === 0) { if (contractFiles.length === 0) {
return cb(null, {}); return cb(null, {});
} }
@ -25,7 +25,7 @@ class Compiler {
const compiledObject: {[index: string]: any} = {}; const compiledObject: {[index: string]: any} = {};
const compilerOptions = { const compilerOptions = {
disableOptimizations: this.disableOptimizations || options.disableOptimizations, isCoverage: this.isCoverage,
}; };
async.eachObject(this.getAvailableCompilers(), async.eachObject(this.getAvailableCompilers(),
@ -60,7 +60,7 @@ class Compiler {
}, },
(err: any) => { (err: any) => {
contractFiles.filter((f: any) => !f.compiled).forEach((file: any) => { contractFiles.filter((f: any) => !f.compiled).forEach((file: any) => {
this.logger.warn(__("%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.", file.filename)); this.logger.warn(__("%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.", file.path));
}); });
cb(err, compiledObject); cb(err, compiledObject);
@ -81,7 +81,7 @@ class Compiler {
private filesMatchingExtension(extension: string) { private filesMatchingExtension(extension: string) {
return (file: any) => { return (file: any) => {
const fileMatch = file.filename.match(/\.[0-9a-z]+$/); const fileMatch = file.path.match(/\.[0-9a-z]+$/);
if (fileMatch && (fileMatch[0] === extension)) { if (fileMatch && (fileMatch[0] === extension)) {
file.compiled = true; file.compiled = true;
return true; return true;

View File

@ -19,7 +19,6 @@ class ContractsManager {
this.deployOnlyOnConfig = false; this.deployOnlyOnConfig = false;
this.compileError = false; this.compileError = false;
this.compileOnceOnly = options.compileOnceOnly; this.compileOnceOnly = options.compileOnceOnly;
this.disableOptimizations = options.disableOptimizations;
self.events.setCommandHandler('contracts:list', (cb) => { self.events.setCommandHandler('contracts:list', (cb) => {
cb(self.compileError, self.listContracts()); cb(self.compileError, self.listContracts());
@ -270,8 +269,6 @@ class ContractsManager {
let self = this; let self = this;
self.contracts = {}; self.contracts = {};
let compilerOptions = {disableOptimizations: this.disableOptimizations};
if(resetContracts) self.contracts = {}; if(resetContracts) self.contracts = {};
async.waterfall([ async.waterfall([
function beforeBuild(callback) { function beforeBuild(callback) {
@ -308,7 +305,7 @@ class ContractsManager {
if (self.compileOnceOnly && hasCompiledContracts && allContractsCompiled) { if (self.compileOnceOnly && hasCompiledContracts && allContractsCompiled) {
return callback(); return callback();
} }
self.events.request("compiler:contracts", self.contractsFiles, compilerOptions, function (err, compiledObject) { self.events.request("compiler:contracts", self.contractsFiles, function (err, compiledObject) {
self.compiledContracts = compiledObject; self.compiledContracts = compiledObject;
callback(err); callback(err);
}); });

View File

@ -7,9 +7,9 @@ import { Injector } from "./injector";
import { Instrumenter } from "./instrumenter"; import { Instrumenter } from "./instrumenter";
import { InstrumentWalker } from "./instrumentWalker"; import { InstrumentWalker } from "./instrumentWalker";
import { coverageContractsPath } from "./path"; import { coverageContractsPath } from "./path";
import { Suppressor } from "./suppressor";
import { BranchType, Coverage } from "./types"; import { BranchType, Coverage } from "./types";
const File = require("../../core/file");
const fs = require("../../core/fs"); const fs = require("../../core/fs");
const STATEMENT_EVENT = "__StatementCoverage"; const STATEMENT_EVENT = "__StatementCoverage";
@ -24,10 +24,10 @@ function nextId() {
export class ContractEnhanced { export class ContractEnhanced {
public id: number; public id: number;
public coverage: Coverage; public coverage: Coverage;
public coverageFilepath: string;
public originalSource: string; public originalSource: string;
public source: string; public source: string;
private ast: parser.ASTNode; private ast: parser.ASTNode;
private coverageFilepath: string;
private functionsBodyLocation: {[id: number]: Location} = {}; private functionsBodyLocation: {[id: number]: Location} = {};
constructor(public filepath: string, public solcVersion: string) { constructor(public filepath: string, public solcVersion: string) {
@ -52,7 +52,6 @@ export class ContractEnhanced {
} }
public instrument() { public instrument() {
new Suppressor(this).process();
const instrumenter = new Instrumenter(this); const instrumenter = new Instrumenter(this);
const instrumentWalker = new InstrumentWalker(instrumenter); const instrumentWalker = new InstrumentWalker(instrumenter);
instrumentWalker.walk(this.ast); instrumentWalker.walk(this.ast);

View File

@ -4,6 +4,7 @@ import Web3Contract from "web3/eth/contract";
import { Contract } from "../../../typings/contract"; import { Contract } from "../../../typings/contract";
import { Embark } from "../../../typings/embark"; import { Embark } from "../../../typings/embark";
import { removePureView } from "../../utils/solidity/code";
import { ContractEnhanced } from "./contractEnhanced"; import { ContractEnhanced } from "./contractEnhanced";
import { coverageContractsPath } from "./path"; import { coverageContractsPath } from "./path";
import { Coverage as ICoverage } from "./types"; import { Coverage as ICoverage } from "./types";
@ -23,8 +24,11 @@ export default class Coverage {
this.contracts = this.getContracts(); this.contracts = this.getContracts();
this.instrumentContracts(); this.embark.events.setCommandHandler("coverage:prepareContracts", async (done) => {
this.swapContracts(); await this.prepareContracts();
this.swapContracts();
done();
});
this.embark.events.on("tests:ready", this.pushDeployedContracts.bind(this)); this.embark.events.on("tests:ready", this.pushDeployedContracts.bind(this));
this.embark.events.on("tests:finished", this.produceCoverageReport.bind(this)); this.embark.events.on("tests:finished", this.produceCoverageReport.bind(this));
@ -41,15 +45,16 @@ export default class Coverage {
.map((filepath) => new ContractEnhanced(filepath, solcVersion)); .map((filepath) => new ContractEnhanced(filepath, solcVersion));
} }
private instrumentContracts() { private async prepareContracts() {
this.contracts.forEach((contract) => contract.instrument()); const promises = this.contracts.map(async (contract) => {
contract.instrument();
contract.save();
});
await Promise.all(promises);
removePureView(coverageContractsPath());
} }
private swapContracts() { private swapContracts() {
this.contracts.forEach((contract) => {
contract.save();
});
this.embark.config.embarkConfig.contracts = this.contractsDir.reduce((acc: string[], value: string) => ( this.embark.config.embarkConfig.contracts = this.contractsDir.reduce((acc: string[], value: string) => (
acc.concat(path.join(coverageContractsPath(), value)) acc.concat(path.join(coverageContractsPath(), value))
), []); ), []);

View File

@ -71,7 +71,7 @@ export class Instrumenter {
this.contract.addBranch(node.loc.start.line, "if", locations); this.contract.addBranch(node.loc.start.line, "if", locations);
} }
private addInjectionPoints(type: InjectionPointType, id: number, location: Location, locationIdx?: number) { private addInjectionPoints(type: InjectionPointType, id: number, location: Location) {
this.injectionPoints.push({type, id, location, locationIdx}); this.injectionPoints.push({type, id, location});
} }
} }

View File

@ -2,4 +2,4 @@ import * as path from "path";
const fs = require("../../core/fs"); const fs = require("../../core/fs");
export const coverageContractsPath = () => path.join(fs.dappPath(), "coverage", "instrumentedContracts"); export const coverageContractsPath = () => path.join("coverage", "instrumentedContracts");

View File

@ -1,12 +0,0 @@
import { ContractEnhanced } from "./contractEnhanced";
export class Suppressor {
constructor(private contract: ContractEnhanced) {
}
public process() {
this.contract.source = this.contract.source.replace(/pure/g, "");
this.contract.source = this.contract.source.replace(/view/g, "");
}
}

View File

@ -7,7 +7,6 @@ export interface InjectionPoint {
type: InjectionPointType; type: InjectionPointType;
id: number; id: number;
location: Location; location: Location;
locationIdx?: number;
} }
export interface Coverage { export interface Coverage {

View File

@ -287,11 +287,10 @@ class Pipeline {
} }
async.map( async.map(
files, files,
function (file, fileCb) { async function (file, fileCb) {
self.logger.trace("reading " + file.filename); self.logger.trace("reading " + file.path);
return file.content(fileContent => { const fileContent = await file.content;
self.runPlugins(file, fileContent, fileCb); self.runPlugins(file, fileContent, fileCb);
});
}, },
function (err, contentFiles) { function (err, contentFiles) {
if (err) { if (err) {
@ -310,7 +309,7 @@ class Pipeline {
} }
async.each(contentFiles, function (file, eachCb) { async.each(contentFiles, function (file, eachCb) {
let filename = file.filename.replace(file.basedir + '/', ''); let filename = file.path.replace(file.basedir + '/', '');
self.logger.info(`${'Pipeline:'.cyan} writing file ` + (utils.joinPath(self.buildDir, targetDir, filename)).bold.dim); self.logger.info(`${'Pipeline:'.cyan} writing file ` + (utils.joinPath(self.buildDir, targetDir, filename)).bold.dim);
fs.copy(file.path, utils.joinPath(self.buildDir, targetDir, filename), {overwrite: true}, eachCb); fs.copy(file.path, utils.joinPath(self.buildDir, targetDir, filename), {overwrite: true}, eachCb);
@ -387,21 +386,21 @@ class Pipeline {
runPlugins(file, fileContent, fileCb) { runPlugins(file, fileContent, fileCb) {
const self = this; const self = this;
if (self.pipelinePlugins.length <= 0) { if (self.pipelinePlugins.length <= 0) {
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true}); return fileCb(null, {content: fileContent, path: file.path, basedir: file.basedir, modified: true});
} }
async.eachSeries(self.pipelinePlugins, (plugin, pluginCB) => { async.eachSeries(self.pipelinePlugins, (plugin, pluginCB) => {
if (file.options && file.options.skipPipeline) { if (file.options && file.options.skipPipeline) {
return pluginCB(); return pluginCB();
} }
fileContent = plugin.runPipeline({targetFile: file.filename, source: fileContent}); fileContent = plugin.runPipeline({targetFile: file.path, source: fileContent});
file.modified = true; file.modified = true;
pluginCB(); pluginCB();
}, err => { }, err => {
if (err) { if (err) {
self.logger.error(err.message); self.logger.error(err.message);
} }
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true}); return fileCb(null, {content: fileContent, path: file.path, basedir: file.basedir, modified: true});
}); });
} }

View File

@ -1,5 +1,6 @@
let async = require('../../utils/async_extend.js'); let async = require('../../utils/async_extend.js');
let SolcW = require('./solcW.js'); let SolcW = require('./solcW.js');
const remapImports = require('../../utils/solidity/remapImports');
class Solidity { class Solidity {
@ -21,7 +22,7 @@ class Solidity {
'post', 'post',
'/embark-api/contract/compile', '/embark-api/contract/compile',
(req, res) => { (req, res) => {
if(typeof req.body.code !== 'string'){ if (typeof req.body.code !== 'string') {
return res.send({error: 'Body parameter \'code\' must be a string'}); return res.send({error: 'Body parameter \'code\' must be a string'});
} }
const input = {[req.body.name]: {content: req.body.code.replace(/\r\n/g, '\n')}}; const input = {[req.body.name]: {content: req.body.code.replace(/\r\n/g, '\n')}};
@ -39,7 +40,7 @@ class Solidity {
self.solcW.compile(jsonObj, function (err, output) { self.solcW.compile(jsonObj, function (err, output) {
self.events.emit('contracts:compile:solc', jsonObj); self.events.emit('contracts:compile:solc', jsonObj);
if(err){ if (err) {
return callback(err); return callback(err);
} }
if (output.errors && returnAllErrors) { if (output.errors && returnAllErrors) {
@ -47,7 +48,7 @@ class Solidity {
} }
if (output.errors) { if (output.errors) {
for (let i=0; i<output.errors.length; i++) { for (let i = 0; i < output.errors.length; i++) {
if (output.errors[i].type === 'Warning') { if (output.errors[i].type === 'Warning') {
self.logger.warn(output.errors[i].formattedMessage); self.logger.warn(output.errors[i].formattedMessage);
} }
@ -70,10 +71,10 @@ class Solidity {
if (self.solcAlreadyLoaded) { if (self.solcAlreadyLoaded) {
return callback(); return callback();
} }
let storageConfig = self.storageConfig; let storageConfig = self.storageConfig;
if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) { if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
self.providerUrl = storageConfig.upload.getUrl; self.providerUrl = storageConfig.upload.getUrl;
} }
self.solcW = new SolcW(self.embark, {logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard, providerUrl: self.providerUrl}); self.solcW = new SolcW(self.embark, {logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard, providerUrl: self.providerUrl});
@ -90,7 +91,7 @@ class Solidity {
sources: codeInputs, sources: codeInputs,
settings: { settings: {
optimizer: { optimizer: {
enabled: (!options.disableOptimizations && self.options.optimize), enabled: (!options.isCoverage && self.options.optimize),
runs: self.options["optimize-runs"] runs: self.options["optimize-runs"]
}, },
outputSelection: { outputSelection: {
@ -168,23 +169,23 @@ class Solidity {
function prepareInput(callback) { function prepareInput(callback) {
async.each(contractFiles, async.each(contractFiles,
function (file, fileCb) { function (file, fileCb) {
let filename = file.filename; let filename = file.path;
for (let directory of self.embark.config.contractDirectories) { for (let directory of self.embark.config.contractDirectories) {
let match = new RegExp("^" + directory); let match = new RegExp("^" + directory);
filename = filename.replace(match, ''); filename = filename.replace(match, '');
} }
originalFilepath[filename] = file.filename; originalFilepath[filename] = file.path;
file.content(function (fileContent) { remapImports.prepareForCompilation(file, options.isCoverage)
if (!fileContent) { .then(fileContent => {
input[filename] = {content: fileContent.replace(/\r\n/g, '\n')};
fileCb();
}).catch((_e) => {
self.logger.error(__('Error while loading the content of ') + filename); self.logger.error(__('Error while loading the content of ') + filename);
return fileCb(); fileCb();
} });
input[filename] = {content: fileContent.replace(/\r\n/g, '\n')};
fileCb();
});
}, },
function (err) { function (err) {
callback(err); callback(err);

View File

@ -192,6 +192,13 @@ class Test {
function checkDeploymentOpts(next) { function checkDeploymentOpts(next) {
self.checkDeploymentOptions(options, next); self.checkDeploymentOptions(options, next);
}, },
function prepareContracts(next) {
if (!self.firstDeployment || !self.options.coverage) {
return next();
}
console.info('Preparing contracts for coverage'.cyan);
self.events.request("coverage:prepareContracts", next);
},
function compileContracts(next) { function compileContracts(next) {
if (!self.firstDeployment) { if (!self.firstDeployment) {
return next(); return next();
@ -262,6 +269,13 @@ class Test {
return instance; return instance;
} }
track(jsonInterface, address) {
this.events.request('blockchain:get', (web3) => {
const instance = new web3.eth.Contract(jsonInterface, address);
this.events.emit("tests:manualDeploy", instance);
});
}
async _deploy(config, callback) { async _deploy(config, callback) {
const self = this; const self = this;
async.waterfall([ async.waterfall([

View File

@ -0,0 +1,16 @@
import * as globule from "globule";
import * as path from "path";
const fs = require("../../core/fs");
export const removePureView = (dir: string) => {
globule.find(path.join(dir, "**/*.sol")).forEach((filepath) => {
let source = fs.readFileSync(filepath, "utf-8");
source = replacePureView(source);
fs.writeFileSync(filepath, source);
});
};
export const replacePureView = (source: string) => {
return source.replace(/pure/g, "").replace(/view/g, "");
};

View File

@ -0,0 +1,144 @@
import * as path from "path";
import { File, Types } from "../../core/file";
import { removePureView, replacePureView } from "./code";
const { urlJoin, groupBy } = require("../../utils/utils");
const fs = require("../../core/fs");
const FIND_IMPORTS_REGEX = /^import[\s]*(['"])(.*)\1;/gm;
const FIND_FILE_REGEX = /import[\s]*(['"])(.*)\1;/;
interface RemapImport {
path: string;
searchValue: string;
replaceValue: string;
}
const getImports = (source: string) => {
const importStatements = source.match(FIND_IMPORTS_REGEX) || [];
return importStatements.map((importStatement) => {
const fileStatement = FIND_FILE_REGEX.exec(importStatement) || [];
if (fileStatement.length < 3) {
return "";
}
return fileStatement[2];
}).filter((fileImport) => fileImport.length);
};
const prepareInitialFile = async (file: File) => {
if (file.type === Types.http) {
return await file.content;
}
const destination = path.join(".embark", file.path);
if (file.type === Types.dappFile) {
fs.copySync(file.path, destination);
}
if (file.type === Types.custom) {
fs.writeFileSync(destination);
}
file.path = destination;
};
const buildNewFile = (file: File, importPath: string) => {
let from: string;
let to: string;
// started with HTTP file that then further imports local paths in
// it's own repo/directory
if (file.type === Types.http && !isHttp(importPath)) {
const externalUrl = urlJoin(file.externalUrl, importPath);
return new File({ externalUrl, type: Types.http });
}
// http import
if (isHttp(importPath)) {
return new File({ externalUrl: importPath, type: Types.http });
}
// imported from node_modules, ie import "@aragon/os/contracts/acl/ACL.sol"
if (isNodeModule(importPath)) {
from = path.join("node_modules", importPath);
to = path.join(".embark", from);
fs.copySync(from, to);
return new File({ path: to, type: Types.dappFile });
}
// started with node_modules then further imports local paths in it's own repo/directory
if (isEmbarkNodeModule(file.path)) {
from = path.join(path.dirname(file.path.replace(".embark", ".")), importPath);
to = path.join(path.dirname(file.path), importPath);
fs.copySync(from, to);
return new File({ path: to, type: Types.dappFile });
}
// local import, ie import "../path/to/contract" or "./path/to/contract"
from = path.join(path.dirname(file.path.replace(".embark", ".")), importPath);
to = path.join(".embark", from);
fs.copySync(from, to);
return new File({ path: to, type: Types.dappFile });
};
const rescursivelyFindRemapImports = async (file: File) => {
let remapImports: RemapImport[] = [];
const content = await file.content;
const imports = getImports(content);
// if no imports, break recursion
if (!imports.length) {
return [];
}
for (const importPath of imports) {
const newFile = buildNewFile(file, importPath);
file.importRemappings.push({prefix: importPath, target: newFile.path});
remapImports.push({path: file.path, searchValue: importPath, replaceValue: newFile.path});
remapImports = remapImports.concat(
await rescursivelyFindRemapImports(newFile),
);
}
return remapImports;
};
const isEmbarkNodeModule = (input: string) => {
return input.startsWith(".embark/node_modules");
};
const isNodeModule = (input: string) => {
return !input.startsWith("..") && fs.existsSync(path.join("./node_modules/", input));
};
const isHttp = (input: string) => {
return input.startsWith("https://") || input.startsWith("http://");
};
const replaceImports = (remapImports: RemapImport[]) => {
const byPath: {[path: string]: [{searchValue: string, replaceValue: string}]} = groupBy(remapImports, "path");
Object.keys(byPath).forEach((p) => {
let source = fs.readFileSync(p, "utf-8");
byPath[p].forEach(({searchValue, replaceValue}) => {
source = source.replace(`import "${searchValue}";`, `import "${replaceValue}";`);
});
fs.writeFileSync(p, source);
});
};
export const prepareForCompilation = async (file: File, isCoverage = false) => {
await prepareInitialFile(file);
const remapImports = await rescursivelyFindRemapImports(file);
replaceImports(remapImports);
const content = await file.content;
if (!isCoverage) {
return content;
}
removePureView(path.join(".embark"));
return replacePureView(content);
};

View File

@ -624,6 +624,22 @@ function isEs6Module(module) {
return typeof module === 'object' && typeof module.default === 'function' && module.__esModule; return typeof module === 'object' && typeof module.default === 'function' && module.__esModule;
} }
function urlJoin(url, path) {
let urlChunks = url.split('/');
let levels = path.split('../');
// remove relative path parts from end of url
urlChunks = urlChunks.slice(0, urlChunks.length - levels.length);
// remove relative path parts from start of match
levels.splice(0, levels.length - 1);
// add on our match so we can join later
urlChunks = urlChunks.concat(levels.join().replace('./', ''));
return urlChunks.join('/');
}
module.exports = { module.exports = {
joinPath, joinPath,
dirname, dirname,
@ -674,5 +690,6 @@ module.exports = {
jsonFunctionReplacer, jsonFunctionReplacer,
getWindowSize, getWindowSize,
toposort, toposort,
isEs6Module isEs6Module,
urlJoin
}; };

View File

@ -189,40 +189,37 @@ describe('embark.Config', function () {
]; ];
const expected = [ const expected = [
{ {
"filename": ".embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol",
"type": "http", "type": "http",
"path": "https://raw.githubusercontent.com/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol", "externalUrl": "https://raw.githubusercontent.com/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol",
"path": ".embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol",
"pluginPath": '', "pluginPath": '',
"importRemappings": [],
"basedir": "", "basedir": "",
"importRemappings": [],
"resolver": undefined, "resolver": undefined,
"storageConfig": undefined, "storageConfig": undefined,
"providerUrl": undefined, "providerUrl": ""
"downloadedImports": false
}, },
{ {
"filename": ".embark/contracts/status-im/contracts/master/contracts/identity/ERC725.sol",
"type": "http", "type": "http",
"path": "https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol", "externalUrl": "https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol",
"path": ".embark/contracts/status-im/contracts/master/contracts/identity/ERC725.sol",
"pluginPath": '', "pluginPath": '',
"importRemappings": [],
"basedir": "", "basedir": "",
"importRemappings": [],
"resolver": undefined, "resolver": undefined,
"storageConfig": undefined, "storageConfig": undefined,
"providerUrl": undefined, "providerUrl": ""
"downloadedImports": false
}, },
{ {
"filename": ".embark/contracts/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63", "externalUrl": "https://swarm-gateways.net/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63",
"path": ".embark/contracts/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63",
"type": "http", "type": "http",
"path": "https://swarm-gateways.net/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63",
"pluginPath": '', "pluginPath": '',
"importRemappings": [],
"basedir": "", "basedir": "",
"importRemappings": [],
"resolver": undefined, "resolver": undefined,
"storageConfig": undefined, "storageConfig": undefined,
"providerUrl": undefined, "providerUrl": ""
"downloadedImports": false
} }
]; ];
config.loadExternalContractsFiles(); config.loadExternalContractsFiles();

View File

@ -1,8 +1,9 @@
/*globals describe, it*/ /*globals describe, it*/
import { File, Types } from "../lib/core/file";
let ContractsManager = require('../lib/modules/contracts_manager/index.js'); let ContractsManager = require('../lib/modules/contracts_manager/index.js');
let Compiler = require('../lib/modules/compiler/'); let Compiler = require('../lib/modules/compiler/');
let Logger = require('../lib/core/logger.js'); let Logger = require('../lib/core/logger.js');
let File = require('../lib/core/file.js');
let TestLogger = require('../lib/utils/test_logger'); let TestLogger = require('../lib/utils/test_logger');
let Events = require('../lib/core/events'); let Events = require('../lib/core/events');
let Ipc = require('../lib/core/ipc.js'); let Ipc = require('../lib/core/ipc.js');
@ -12,7 +13,7 @@ let assert = require('assert');
let Plugins = require('../lib/core/plugins.js'); let Plugins = require('../lib/core/plugins.js');
let readFile = function(file) { let readFile = function(file) {
return new File({filename: file, type: File.types.dapp_file, path: file}); return new File({filename: file, type: Types.dappFile, path: file});
}; };
const currentSolcVersion = require('../../package.json').dependencies.solc; const currentSolcVersion = require('../../package.json').dependencies.solc;

View File

@ -1,111 +0,0 @@
/*globals describe, it*/
const File = require('../lib/core/file');
const fs = require('fs-extra');
const path = require('path');
const assert = require('assert');
const sinon = require('sinon');
describe('embark.File', function () {
describe('parseFileForImport', () => {
it('should find all the imports', function (done) {
const contract = fs.readFileSync('./dist/test/contracts/contract_with_import.sol').toString();
const file = new File({filename: '.embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol',
path: 'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/test_app/app/contracts/simple_storage.sol'});
const downloadFileStub = sinon.stub(file, 'downloadFile')
.callsFake((path, url, cb) => {
cb();
});
file.parseFileForImport(contract, true, () => {
assert.strictEqual(downloadFileStub.callCount, 1);
assert.strictEqual(downloadFileStub.firstCall.args[0],
path.normalize('.embark/contracts/embark-framework/embark/master/test_app/app/contracts/ownable.sol'));
assert.strictEqual(downloadFileStub.firstCall.args[1],
'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/test_app/app/contracts/./ownable.sol');
done();
});
});
it('should find and add remappings for all recursive imports', function (done) {
const contract = fs.readFileSync('./dist/test/contracts/recursive_test_0.sol').toString();
const file = new File({filename: './dist/test/contracts/recursive_test_0.sol',
path: path.join(__dirname, './contracts/recursive_test_0.sol')});
file.parseFileForImport(contract, () => {
assert.deepEqual(file.importRemappings[0], {
prefix: "./recursive_test_1.sol",
target: path.join(__dirname, "./contracts/recursive_test_1.sol")
});
assert.deepEqual(file.importRemappings[1], {
prefix: "./recursive_test_2.sol",
target: path.join(__dirname, "./contracts/recursive_test_2.sol")
});
assert.deepEqual(file.importRemappings[2], {
prefix: "embark-test-contract-0/recursive_test_3.sol",
target: path.resolve(path.join("node_modules", "./embark-test-contract-0/recursive_test_3.sol"))
});
assert.deepEqual(file.importRemappings[3], {
prefix: "embark-test-contract-1/recursive_test_4.sol",
target: path.resolve(path.join("node_modules", "./embark-test-contract-1/recursive_test_4.sol"))
});
done();
});
});
it('should find all the imports but not call download because not a http contract', function (done) {
const contract = fs.readFileSync('./dist/test/contracts/contract_with_import.sol').toString();
const file = new File({filename: '.embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol',
path: 'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/test_app/app/contracts/simple_storage.sol'});
const downloadFileStub = sinon.stub(file, 'downloadFile')
.callsFake((path, url, cb) => {
cb();
});
file.parseFileForImport(contract, () => {
assert.strictEqual(downloadFileStub.callCount, 0);
done();
});
});
it('should find all the imports and call downlaod because it is an http import', function (done) {
const contract = fs.readFileSync('./dist/test/contracts/contract_with_http_import.sol').toString();
const file = new File({filename: '.embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol',
path: 'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/test_app/app/contracts/simple_storage.sol'});
const downloadFileStub = sinon.stub(file, 'downloadFile')
.callsFake((path, url, cb) => {
cb();
});
file.parseFileForImport(contract, () => {
assert.strictEqual(downloadFileStub.callCount, 1);
assert.strictEqual(downloadFileStub.firstCall.args[0],
'.embark/contracts/embark-framework/embark/master/test_apps/contracts_app/contracts/contract_args.sol');
assert.strictEqual(downloadFileStub.firstCall.args[1],
'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/contracts_app/contracts/contract_args.sol');
done();
});
});
it('should find all the imports but only once if called twice', function (done) {
const contract = fs.readFileSync('./dist/test/contracts/contract_with_http_import.sol').toString();
const file = new File({filename: '.embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol',
path: 'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/test_app/app/contracts/simple_storage.sol'});
const downloadFileStub = sinon.stub(file, 'downloadFile')
.callsFake((path, url, cb) => {
cb();
});
file.parseFileForImport(contract, () => {
// Parse again
file.parseFileForImport(contract, () => {
assert.strictEqual(downloadFileStub.callCount, 1);
assert.strictEqual(downloadFileStub.firstCall.args[0],
'.embark/contracts/embark-framework/embark/master/test_apps/contracts_app/contracts/contract_args.sol');
assert.strictEqual(downloadFileStub.firstCall.args[1],
'https://raw.githubusercontent.com/embark-framework/embark/master/test_apps/contracts_app/contracts/contract_args.sol');
done();
});
});
});
});
});

View File

@ -1,17 +1,18 @@
/*globals describe, it*/ /*globals describe, it*/
import { File, Types } from "../../../lib/core/file";
const assert = require('assert'); const assert = require('assert');
// TODO: need to rethink i18n and how that is required in each module // TODO: need to rethink i18n and how that is required in each module
require('../../../lib/core/i18n/i18n'); require('../../../lib/core/i18n/i18n');
const Compiler = require('../../../lib/modules/compiler'); const Compiler = require('../../../lib/modules/compiler');
const File = require('../../../lib/core/file.js');
const Plugins = require('../../../lib/core/plugins.js'); const Plugins = require('../../../lib/core/plugins.js');
const TestLogger = require('../../../lib/utils/test_logger'); const TestLogger = require('../../../lib/utils/test_logger');
const Events = require('../../../lib/core/events'); const Events = require('../../../lib/core/events');
const readFile = function(file) { const readFile = function(file) {
return new File({filename: file, type: File.types.dapp_file, path: file}); return new File({filename: file, type: Types.dappFile, path: file});
}; };
const currentSolcVersion = require('../../../../package.json').dependencies.solc; const currentSolcVersion = require('../../../../package.json').dependencies.solc;
@ -67,7 +68,7 @@ describe('embark.Compiler', function() {
readFile('dist/test/contracts/simple_storage.sol'), readFile('dist/test/contracts/simple_storage.sol'),
readFile('dist/test/contracts/token.sol'), readFile('dist/test/contracts/token.sol'),
readFile('dist/test/contracts/erc20.vy') readFile('dist/test/contracts/erc20.vy')
], {}, (err, compiledObject) => { ], (err, compiledObject) => {
assert.deepEqual(compiledObject, { contractA: 'solResult', contractB: 'vyResult' }) assert.deepEqual(compiledObject, { contractA: 'solResult', contractB: 'vyResult' })
done(); done();
}) })

View File

@ -1,12 +1,12 @@
/*globals describe, it*/ /*globals describe, it*/
import { File, Types } from "../../../lib/core/file.js";
let SolidityCompiler = require('../../../lib/modules/solidity'); let SolidityCompiler = require('../../../lib/modules/solidity');
let TestLogger = require('../../../lib/utils/test_logger'); let TestLogger = require('../../../lib/utils/test_logger');
let File = require('../../../lib/core/file.js');
let Ipc = require('../../../lib/core/ipc.js'); let Ipc = require('../../../lib/core/ipc.js');
let assert = require('assert');
let readFile = function(file) { let readFile = function(file) {
return new File({filename: file, type: File.types.dapp_file, path: file}); return new File({filename: file, type: Types.dappFile, path: file});
}; };
let ipcObject = new Ipc({ let ipcObject = new Ipc({

View File

@ -14,5 +14,4 @@ contract SimpleStorage {
function get() public view returns (uint retVal) { function get() public view returns (uint retVal) {
return storedData; return storedData;
} }
} }

View File

@ -1,6 +1,6 @@
pragma solidity ^0.4.17; pragma solidity ^0.4.17;
import "another_folder/another_test.sol"; import "../another_folder/another_test.sol";
import "zeppelin-solidity/contracts/ownership/Ownable.sol"; import "zeppelin-solidity/contracts/ownership/Ownable.sol";
contract SimpleStorageTest is Ownable { contract SimpleStorageTest is Ownable {

View File

@ -3,7 +3,6 @@ const fs = require('fs-extra');
const assert = require('assert'); const assert = require('assert');
describe('http contracts', () => { describe('http contracts', () => {
it('should have downloaded the file in .embark/contracts', (done) => { it('should have downloaded the file in .embark/contracts', (done) => {
const contractPath = '.embark/contracts/status-im/contracts/151-embark31/contracts/token/StandardToken.sol'; const contractPath = '.embark/contracts/status-im/contracts/151-embark31/contracts/token/StandardToken.sol';
fs.access(contractPath, (err) => { fs.access(contractPath, (err) => {

View File

@ -846,6 +846,11 @@
"@types/connect" "*" "@types/connect" "*"
"@types/node" "*" "@types/node" "*"
"@types/caseless@*":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a"
integrity sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==
"@types/connect@*": "@types/connect@*":
version "3.4.32" version "3.4.32"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28"
@ -904,6 +909,13 @@
"@types/express-serve-static-core" "*" "@types/express-serve-static-core" "*"
"@types/serve-static" "*" "@types/serve-static" "*"
"@types/form-data@*":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e"
integrity sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==
dependencies:
"@types/node" "*"
"@types/fs-extra@^5.0.2": "@types/fs-extra@^5.0.2":
version "5.0.4" version "5.0.4"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.4.tgz#b971134d162cc0497d221adde3dbb67502225599" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.4.tgz#b971134d162cc0497d221adde3dbb67502225599"
@ -992,6 +1004,16 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/request@2.48.1":
version "2.48.1"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.1.tgz#e402d691aa6670fbbff1957b15f1270230ab42fa"
integrity sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==
dependencies:
"@types/caseless" "*"
"@types/form-data" "*"
"@types/node" "*"
"@types/tough-cookie" "*"
"@types/semver@^5.5.0": "@types/semver@^5.5.0":
version "5.5.0" version "5.5.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
@ -1012,6 +1034,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/tough-cookie@*":
version "2.3.4"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.4.tgz#821878b81bfab971b93a265a561d54ea61f9059f"
integrity sha512-Set5ZdrAaKI/qHdFlVMgm/GsAv/wkXhSTuZFkJ+JI7HK+wIkIlOaUXSXieIvJ0+OvGIqtREFoE+NHJtEq0gtEw==
"@types/underscore@*": "@types/underscore@*":
version "1.8.9" version "1.8.9"
resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.8.9.tgz#fef41f800cd23db1b4f262ddefe49cd952d82323" resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.8.9.tgz#fef41f800cd23db1b4f262ddefe49cd952d82323"