truffle
Version:
Truffle - Simple development framework for Ethereum
1,244 lines (1,146 loc) • 69.2 kB
JavaScript
#!/usr/bin/env node
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 89244:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
__webpack_require__(20406);
const pkg = __webpack_require__(73755);
module.exports = {
build: __webpack_require__(60627),
create: __webpack_require__(89664),
// TODO: update this to non-legacy the next breaking change
contracts: __webpack_require__(81969),
test: (__webpack_require__(26158).Test),
version: pkg.version,
ganache: __webpack_require__(11651)
};
/***/ }),
/***/ 60627:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const fse = __webpack_require__(55674);
const del = __webpack_require__(95752);
const WorkflowCompile = (__webpack_require__(37017)["default"]);
const BuildError = __webpack_require__(42863);
const { spawn } = __webpack_require__(32081);
const spawnargs = __webpack_require__(72255);
const _ = __webpack_require__(96486);
const expect = __webpack_require__(14096);
function CommandBuilder(command) {
this.command = command;
}
CommandBuilder.prototype.build = function (options, callback) {
console.log("Running `" + this.command + "`...");
const args = spawnargs(this.command);
const ps = args.shift();
const cmd = spawn(ps, args, {
detached: false,
cwd: options.working_directory,
env: _.merge(process.env, {
WORKING_DIRECTORY: options.working_directory,
BUILD_DESTINATION_DIRECTORY: options.destination_directory,
BUILD_CONTRACTS_DIRECTORY: options.contracts_build_directory
})
});
cmd.stdout.on("data", function (data) {
console.log(data.toString());
});
cmd.stderr.on("data", function (data) {
console.error(data);
});
cmd.on("close", function (code) {
let error = null;
if (code !== 0) {
error = "Command exited with code " + code;
}
callback(error);
});
};
const Build = {
clean: async function (options) {
const destination = options.build_directory;
const contracts_build_directory = options.contracts_build_directory;
// Clean first.
await del([destination + "/*", "!" + contracts_build_directory]);
fse.ensureDirSync(destination);
},
build: async function (options) {
expect.options(options, [
"build_directory",
"working_directory",
"contracts_build_directory",
"networks"
]);
const logger = options.logger || console;
let builder = options.build;
// Duplicate build directory for legacy purposes
options.destination_directory = options.build_directory;
if (builder === null || typeof builder === "undefined") {
logger.log(
"No build configuration found. Preparing to compile contracts."
);
} else if (typeof builder === "string") {
builder = new CommandBuilder(builder);
} else if (typeof builder === "function") {
// If they've only provided a build function, use that.
builder = { build: builder };
} else if (builder.build == null) {
throw new BuildError(
"Build configuration can no longer be specified as an object. Please see our documentation for an updated list of supported build configurations."
);
}
// Use our own clean method unless the builder supplies one.
let clean = this.clean;
if (builder && builder.hasOwnProperty("clean")) {
clean = builder.clean;
}
await clean(options);
// If necessary. This prevents errors due to the .sol.js files not existing.
await WorkflowCompile.compileAndSave(options);
if (builder) {
builder.build(options, function (err) {
if (typeof err === "string") {
throw new BuildError(err);
}
});
}
}
};
module.exports = Build;
/***/ }),
/***/ 89664:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const path = __webpack_require__(71017);
const fse = __webpack_require__(55674);
const templates = {
test: {
filename: path.join(__dirname, "templates", "example.js"),
variable: "example"
},
contract: {
filename: path.join(__dirname, "templates", "Example.sol"),
name: "Example",
license: "MIT",
variable: "example"
},
migration: {
filename: path.join(__dirname, "templates", "migration.js")
}
};
const replaceContents = (filePath, find, replacement) => {
const data = fse.readFileSync(filePath, { encoding: "utf8" });
if (typeof find === "string") {
find = new RegExp(find, "g");
}
const result = data.replace(find, replacement);
fse.writeFileSync(filePath, result, { encoding: "utf8" });
};
const toUnderscoreFromCamel = (string) => {
string = string.replace(/([A-Z])/g, function ($1) {
return "_" + $1.toLowerCase();
});
if (string[0] === "_") {
string = string.substring(1);
}
return string;
};
// getLicense return the license property value from Truffle config first and
// in case that the file doesn't exist it will fallback to package.json
const getLicense = (options) => {
try {
const license = (__webpack_require__(20553).detect)(options).license;
if (license) {
return license;
}
} catch (err) {
console.log(err);
}
try {
return __webpack_require__(76775)(path.join(process.cwd(), "package.json")).license;
} catch {}
};
const Create = {
contract: function (directory, name, options) {
const from = templates.contract.filename;
const to = path.join(directory, name + ".sol");
if (!options.force && fse.existsSync(to)) {
throw new Error("Can not create " + name + ".sol: file exists");
}
fse.copySync(from, to);
replaceContents(to, templates.contract.name, name);
const license = getLicense(options);
if (license) {
replaceContents(to, templates.contract.license, license);
}
},
test: function (directory, name, options) {
let underscored = toUnderscoreFromCamel(name);
underscored = underscored.replace(/\./g, "_");
const from = templates.test.filename;
const to = path.join(directory, underscored + ".js");
if (!options.force && fse.existsSync(to)) {
throw new Error("Can not create " + underscored + ".js: file exists");
}
fse.copySync(from, to);
replaceContents(to, templates.contract.name, name);
replaceContents(to, templates.contract.variable, underscored);
},
migration: function (directory, name, options) {
let underscored = toUnderscoreFromCamel(name || "");
underscored = underscored.replace(/\./g, "_");
const from = templates.migration.filename;
let filename = (new Date().getTime() / 1000) | 0; // Only do seconds.
if (name != null && name !== "") {
filename += "_" + underscored;
}
filename += ".js";
const to = path.join(directory, filename);
if (!options.force && fse.existsSync(to)) {
throw new Error("Can not create " + filename + ": file exists");
}
fse.copySync(from, to);
}
};
module.exports = Create;
/***/ }),
/***/ 42863:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const colors = __webpack_require__(83196);
const TruffleError = __webpack_require__(73321);
class BuildError extends TruffleError {
constructor(message) {
message =
"Error building:\n\n" +
message +
"\n\n" +
colors.red("Build failed. See above.");
super(message);
}
}
module.exports = BuildError;
/***/ }),
/***/ 76775:
/***/ ((module) => {
function webpackEmptyContext(req) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
webpackEmptyContext.keys = () => ([]);
webpackEmptyContext.resolve = webpackEmptyContext;
webpackEmptyContext.id = 76775;
module.exports = webpackEmptyContext;
/***/ }),
/***/ 48511:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Resolver = void 0;
const resolver_1 = __webpack_require__(43563);
Object.defineProperty(exports, "Resolver", ({ enumerable: true, get: function () { return resolver_1.Resolver; } }));
exports["default"] = resolver_1.Resolver;
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 64956:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SolidityTest = void 0;
// @ts-ignore
const test_js_1 = __importDefault(__webpack_require__(50210));
// @ts-ignore
const suite_js_1 = __importDefault(__webpack_require__(83794));
const deployer_1 = __importDefault(__webpack_require__(669));
const compile_solidity_1 = __webpack_require__(4273);
const compile_common_1 = __webpack_require__(29833);
const debug_1 = __importDefault(__webpack_require__(15158));
const debug = (0, debug_1.default)("lib:testing:soliditytest");
exports.SolidityTest = {
define(abstraction, dependencyPaths, runner, mocha) {
return __awaiter(this, void 0, void 0, function* () {
const self = this;
const suite = new suite_js_1.default(abstraction.contract_name, {});
suite.timeout(runner.beforeTimeout);
// Set up our runner's needs first.
suite.beforeAll("prepare suite", function () {
return __awaiter(this, void 0, void 0, function* () {
// This compiles some native contracts (including the assertion library
// contracts) which need to be compiled before initializing the runner
yield self.compileNewAbstractInterface.bind(this)(runner);
yield runner.initialize.bind(runner)();
runner.disableChecksOnEventDecoding(); //for handling of test events on Solidity <0.7.6 due to empty string problem
yield self.deployTestDependencies.bind(this)(abstraction, dependencyPaths, runner);
});
});
suite.afterAll("clean up", function () {
runner.reEnableChecksOnEventDecoding();
});
suite.beforeEach("before test", function () {
return __awaiter(this, void 0, void 0, function* () {
yield runner.startTest(this);
});
});
// Function that checks transaction logs to see if a test failed.
function checkResultForFailure(result) {
return __awaiter(this, void 0, void 0, function* () {
const logs = result.receipt.rawLogs;
for (const log of logs) {
const decodings = yield runner.decoder.decodeLog(log, {
disableChecks: true
});
for (const decoding of decodings) {
//check: is this a TestEvent?
//note: we don't check the argument names
if (decoding.abi.name === "TestEvent" &&
decoding.arguments.length === 2 &&
decoding.arguments[0].value.type.typeClass === "bool" &&
decoding.arguments[0].indexed &&
decoding.arguments[1].value.type.typeClass === "string" &&
!decoding.arguments[1].indexed) {
//if so: did the test fail?
if (!decoding.arguments[0].value.value.asBoolean) {
//if so: extract the message
let messageDecoding = decoding.arguments[1].value;
let message;
switch (messageDecoding.value.kind) {
case "valid":
message = messageDecoding.value.asString;
break;
case "malformed":
//use buffer to convert hex to string
//(this causes malformed UTF-8 to become U+FFFD)
message = Buffer.from(messageDecoding.value.asHex.slice(2), "hex").toString();
}
throw new Error(message);
}
}
}
}
});
}
// Add functions from test file.
for (const item of abstraction.abi) {
if (item.type !== "function") {
continue;
}
const hookTypes = ["beforeAll", "beforeEach", "afterAll", "afterEach"];
for (const hookType of hookTypes) {
if (item.name.startsWith(hookType)) {
suite[hookType](item.name, () => __awaiter(this, void 0, void 0, function* () {
let deployed = yield abstraction.deployed();
yield checkResultForFailure(yield deployed[item.name]());
}));
}
}
if (item.name.startsWith("test")) {
const test = new test_js_1.default(item.name, () => __awaiter(this, void 0, void 0, function* () {
let deployed = yield abstraction.deployed();
yield checkResultForFailure(yield deployed[item.name]());
}));
test.timeout(runner.testTimeout);
suite.addTest(test);
}
}
suite.afterEach("after test", function () {
return __awaiter(this, void 0, void 0, function* () {
yield runner.endTest(this);
});
});
mocha.suite.addSuite(suite);
});
},
compileNewAbstractInterface(runner) {
return __awaiter(this, void 0, void 0, function* () {
debug("compiling");
const config = runner.config;
const truffleLibraries = [
"truffle/Assert.sol",
"truffle/AssertAddress.sol",
"truffle/AssertAddressArray.sol",
"truffle/AssertBalance.sol",
"truffle/AssertBool.sol",
"truffle/AssertBytes32.sol",
"truffle/AssertBytes32Array.sol",
"truffle/AssertGeneral.sol",
"truffle/AssertInt.sol",
"truffle/AssertIntArray.sol",
"truffle/AssertString.sol",
"truffle/AssertUint.sol",
"truffle/AssertUintArray.sol",
"truffle/DeployedAddresses.sol",
"truffle/SafeSend.sol",
"truffle/Console.sol"
];
const { compilations } = yield compile_solidity_1.Compile.sourcesWithDependencies({
paths: truffleLibraries,
options: runner.config.with({
quiet: true
})
});
const contracts = compilations.reduce((a, compilation) => {
return a.concat(compilation.contracts);
}, []);
// Set network values.
for (let contract of contracts) {
contract.network_id = config.network_id;
contract.default_network = config.default_network;
}
yield config.artifactor.saveAll(contracts.map(compile_common_1.Shims.NewToLegacy.forContract));
debug("compiled");
});
},
deployTestDependencies(abstraction, dependencyPaths, runner) {
return __awaiter(this, void 0, void 0, function* () {
debug("deploying %s", abstraction.contract_name);
const deployer = new deployer_1.default(runner.config.with({
logger: { log() { } }
}));
debug("starting deployer");
yield deployer.start();
const testLibraries = [
"Assert",
"AssertAddress",
"AssertAddressArray",
"AssertBalance",
"AssertBool",
"AssertBytes32",
"AssertBytes32Array",
"AssertGeneral",
"AssertInt",
"AssertIntArray",
"AssertString",
"AssertUint",
"AssertUintArray",
"DeployedAddresses",
"Console"
];
const testAbstractions = testLibraries.map(name => runner.config.resolver.require(`truffle/${name}.sol`));
const SafeSend = runner.config.resolver.require("SafeSend");
debug("deploying test libs");
for (const testLib of testAbstractions) {
yield deployer.deploy(testLib);
yield deployer.link(testLib, abstraction);
}
debug("linking dependencies");
for (const dependencyPath of dependencyPaths) {
const dependency = runner.config.resolver.require(dependencyPath);
if (dependency.isDeployed()) {
yield deployer.link(dependency, abstraction);
}
}
debug("deploying contract");
yield deployer.deploy(abstraction);
const deployed = yield abstraction.deployed();
let balance;
if (deployed.initialBalance) {
balance = yield deployed.initialBalance.call();
}
else {
balance = 0;
}
if (balance !== 0) {
yield deployer.deploy(SafeSend);
const safeSend = yield SafeSend.deployed();
yield safeSend.deliver(deployed.address, { value: balance });
}
debug("deployed %s", abstraction.contract_name);
});
}
};
//# sourceMappingURL=SolidityTest.js.map
/***/ }),
/***/ 83725:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Test = void 0;
const colors_1 = __importDefault(__webpack_require__(83196));
const chai_1 = __importDefault(__webpack_require__(14960));
const path = __webpack_require__(71017);
const interface_adapter_1 = __webpack_require__(36339);
const config_1 = __importDefault(__webpack_require__(20553));
const workflow_compile_1 = __importDefault(__webpack_require__(37017));
const resolver_1 = __webpack_require__(48511);
const TestRunner_1 = __webpack_require__(34036);
const SolidityTest_1 = __webpack_require__(64956);
const rangeUtils_1 = __importDefault(__webpack_require__(32739));
const expect = __importStar(__webpack_require__(14096));
const migrate_1 = __importDefault(__webpack_require__(22478));
const profiler_1 = __webpack_require__(22860);
const original_require_1 = __importDefault(__webpack_require__(44516));
const Codec = __importStar(__webpack_require__(20102));
const debug_1 = __importDefault(__webpack_require__(15158));
const debug = (0, debug_1.default)("lib:test");
const debugger_1 = __importDefault(__webpack_require__(92851));
let Mocha; // Late init with "mocha" or "mocha-parallel-tests"
chai_1.default.use((__webpack_require__(1465)["default"]));
exports.Test = {
run: function (options, createInTestDebugFunction) {
return __awaiter(this, void 0, void 0, function* () {
expect.options(options, [
"contracts_directory",
"contracts_build_directory",
"migrations_directory",
"test_files",
"network",
"network_id",
"provider"
]);
// if test is used standalone, this function won't be setup like in core
if (createInTestDebugFunction === undefined) {
createInTestDebugFunction = () => {
return () => {
config.logger.log(`${colors_1.default.bold("Warning:")} Use of in-test debugging is only available when running ` +
`truffle test --debug.`);
};
};
}
const config = config_1.default.default().merge(options);
config.test_files = config.test_files.map((testFile) => {
return path.resolve(testFile);
});
const interfaceAdapter = (0, interface_adapter_1.createInterfaceAdapter)({
provider: config.provider,
networkType: config.networks[config.network].type
});
// `accounts` will be populated before each contract() invocation
// and passed to it so tests don't have to call it themselves.
const web3 = new interface_adapter_1.Web3Shim({
provider: config.provider,
networkType: config.networks[config.network].type
? config.networks[config.network].type
: "web3js"
});
// Override console.warn() because web3 outputs gross errors to it.
// e.g., https://github.com/ethereum/web3.js/blob/master/lib/web3/allevents.js#L61
// Output looks like this during tests: https://gist.github.com/tcoulter/1988349d1ec65ce6b958
const warn = config.logger.warn;
config.logger.warn = function (message) {
if (message === "cannot find event for log") {
return;
}
else {
if (warn)
warn.apply(console, arguments);
}
};
const mocha = this.createMocha(config);
// set up a promise on this instance to resolve to
// Mocha's "runner" returned by `mocha.run(...)`.
//
// do this upfront so that the promise is available
// immediately, even though mocha.run happens at the very
// end of this setup.
let setMochaRunner;
this.mochaRunner = new Promise(resolve => {
setMochaRunner = resolve;
});
const jsTests = config.test_files.filter((file) => {
return path.extname(file) !== ".sol";
});
const solTests = config.test_files.filter((file) => {
return path.extname(file) === ".sol";
});
// Add Javascript tests because there's nothing we need to do with them.
// Solidity tests will be handled later.
jsTests.forEach((file) => {
// There's an idiosyncracy in Mocha where the same file can't be run twice
// unless we delete the `require` cache.
// https://github.com/mochajs/mocha/issues/995
delete original_require_1.default.cache[file];
mocha.addFile(file);
});
const accounts = yield this.getAccounts(interfaceAdapter);
const testResolver = new resolver_1.Resolver(config);
const { compilations } = yield this.compileContractsWithTestFilesIfNeeded(solTests, config, testResolver);
const testContracts = solTests.map((testFilePath) => {
return testResolver.require(testFilePath);
});
const runner = new TestRunner_1.TestRunner(config);
if (config.migrateNone || config["migrate-none"]) {
if (config.events) {
config.events.emit("test:migration:skipped");
}
}
else {
yield this.performInitialDeploy(config, testResolver);
}
const sourcePaths = []
.concat(...compilations.map((compilation) => compilation.sourceIndexes) //we don't need the indices here, just the paths
)
.filter(path => path); //make sure we don't pass in any undefined
yield this.defineSolidityTests(mocha, testContracts, sourcePaths, runner);
const debuggerCompilations = Codec.Compilations.Utils.shimCompilations(compilations);
//for stack traces, we'll need to set up a light-mode debugger...
let bugger;
if (config.stacktrace) {
debug("stacktraces on!");
bugger = yield debugger_1.default.forProject({
compilations: debuggerCompilations,
provider: config.provider,
lightMode: true
});
}
yield this.setJSTestGlobals({
config,
web3,
interfaceAdapter,
accounts,
testResolver,
runner,
compilations: debuggerCompilations,
bugger,
createInTestDebugFunction
});
// Finally, run mocha.
process.on("unhandledRejection", reason => {
throw reason;
});
return new Promise(resolve => {
const mochaRunner = mocha.run((failures) => {
config.logger.warn = warn;
resolve(failures);
});
// finish setting up the mocha runner so that the
// previously-made promise resolves.
setMochaRunner(mochaRunner);
});
});
},
createMocha: function (config) {
// Allow people to specify config.mocha in their config.
const mochaConfig = config.mocha || {};
// Propagate --bail option to mocha
mochaConfig.bail = config.bail;
// If the command line overrides color usage, use that.
if (config.color != null) {
mochaConfig.color = config.color;
}
else if (config.colors != null) {
// --colors is a mocha alias for --color
mochaConfig.color = config.colors;
}
// Default to true if configuration isn't set anywhere.
if (mochaConfig.color == null) {
mochaConfig.color = true;
}
Mocha = mochaConfig.package || __webpack_require__(3270);
delete mochaConfig.package;
const mocha = new Mocha(mochaConfig);
return mocha;
},
getAccounts: function (interfaceAdapter) {
return interfaceAdapter.getAccounts();
},
compileContractsWithTestFilesIfNeeded: function (solidityTestFiles, config, testResolver) {
return __awaiter(this, void 0, void 0, function* () {
const updated = (yield profiler_1.Profiler.updated(config.with({ resolver: testResolver }))) || [];
const compiler = config.compileNone || config["--compile-none"] ? "none" : config.compiler;
let compileConfig = config.with({
all: config.compileAll === true,
compiler,
files: updated.concat(solidityTestFiles),
resolver: testResolver,
quiet: config.runnerOutputOnly || config.quiet,
quietWrite: true
});
if (config.compileAllDebug) {
let versionString = ((compileConfig.compilers || {}).solc || {}).version;
versionString = rangeUtils_1.default.resolveToRange(versionString);
if (rangeUtils_1.default.rangeContainsAtLeast(versionString, "0.6.3")) {
compileConfig = compileConfig.merge({
compilers: {
solc: {
settings: {
debug: {
revertStrings: "debug"
}
}
}
}
});
}
else {
config.logger.log(`\n${colors_1.default.bold("Warning:")} Extra revert string info requires Solidity v0.6.3 or higher. For more\n information, see release notes <https://github.com/ethereum/solidity/releases/tag/v0.6.3>`);
}
}
// Compile project contracts and test contracts
const { contracts, compilations } = yield workflow_compile_1.default.compileAndSave(compileConfig);
return {
contracts,
compilations
};
});
},
performInitialDeploy: function (config, resolver) {
const migrateConfig = config.with({
reset: true,
resolver: resolver,
quiet: true
});
return migrate_1.default.run(migrateConfig);
},
defineSolidityTests: (mocha, contracts, dependencyPaths, runner) => __awaiter(void 0, void 0, void 0, function* () {
for (const contract of contracts) {
yield SolidityTest_1.SolidityTest.define(contract, dependencyPaths, runner, mocha);
debug("defined solidity tests for %s", contract.contractName);
}
}),
setJSTestGlobals: function ({ config, web3, interfaceAdapter, accounts, testResolver, runner, compilations, bugger, //for stacktracing
createInTestDebugFunction }) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
// @ts-ignore
global.interfaceAdapter = interfaceAdapter;
// @ts-ignore
global.web3 = web3;
const resolvedChai = (_b = (_a = config.chai) === null || _a === void 0 ? void 0 : _a.package) !== null && _b !== void 0 ? _b : chai_1.default;
// @ts-ignore
global.assert = resolvedChai.assert;
// @ts-ignore
global.expect = resolvedChai.expect;
// @ts-ignore
global.artifacts = {
require: (importPath) => {
let contract = testResolver.require(importPath);
//HACK: both of the following should go by means
//of the provisioner, but I'm not sure how to make
//that work at the moment
contract.reloadJson = function () {
const reloaded = testResolver.require(importPath);
this._json = reloaded._json;
};
if (bugger) {
contract.debugger = bugger;
}
return contract;
}
};
// @ts-ignore
global.config = config.normalize(config);
// @ts-ignore
global[config.debugGlobal] = createInTestDebugFunction({
compilations,
mochaRunner: this.mochaRunner,
config
});
const template = function (tests) {
this.timeout(runner.testTimeout);
// @ts-ignore
before("prepare suite", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(runner.beforeTimeout);
yield runner.initialize();
});
});
// @ts-ignore
beforeEach("before test", function () {
return __awaiter(this, void 0, void 0, function* () {
yield runner.startTest();
});
});
// @ts-ignore
afterEach("after test", function () {
return __awaiter(this, void 0, void 0, function* () {
yield runner.endTest(this);
});
});
tests(accounts);
};
// @ts-ignore
global.contract = function (name, tests) {
Mocha.describe("Contract: " + name, function () {
template.bind(this, tests)();
});
};
// @ts-ignore
global.contract.only = function (name, tests) {
Mocha.describe.only("Contract: " + name, function () {
template.bind(this, tests)();
});
};
// @ts-ignore
global.contract.skip = function (name, tests) {
Mocha.describe.skip("Contract: " + name, function () {
template.bind(this, tests)();
});
};
});
}
};
//# sourceMappingURL=Test.js.map
/***/ }),
/***/ 34036:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TestRunner = void 0;
const interface_adapter_1 = __webpack_require__(36339);
const web3_utils_1 = __importDefault(__webpack_require__(18269));
const config_1 = __importDefault(__webpack_require__(20553));
const migrate_1 = __importDefault(__webpack_require__(22478));
const resolver_1 = __webpack_require__(48511);
const expect = __importStar(__webpack_require__(14096));
const util_1 = __importDefault(__webpack_require__(73837));
const fs_1 = __importDefault(__webpack_require__(57147));
const path_1 = __importDefault(__webpack_require__(71017));
const debug_1 = __importDefault(__webpack_require__(15158));
const debug = (0, debug_1.default)("lib:testing:testrunner");
const Decoder = __importStar(__webpack_require__(18852));
const Codec = __importStar(__webpack_require__(20102));
const os_1 = __importDefault(__webpack_require__(22037));
class TestRunner {
constructor(options) {
expect.options(options, [
"resolver",
"provider",
"contracts_build_directory"
]);
this.config = config_1.default.default().merge(options);
this.logger = options.logger || console;
this.provider = options.provider;
this.canSnapshot = false;
this.firstSnapshot = true;
this.initialSnapshot = null;
this.interfaceAdapter = (0, interface_adapter_1.createInterfaceAdapter)({
provider: options.provider,
networkType: options.networks[options.network].type
});
this.decoder = null;
// For each test
this.currentTestStartBlock = null;
this.beforeTimeout =
(options.mocha && options.mocha.before_timeout) || 120000;
this.testTimeout = (options.mocha && options.mocha.timeout) || 300000;
}
disableChecksOnEventDecoding() {
this.disableChecks = true; //used by Solidity testing due to empty string problem on Solidity <0.7.6
}
reEnableChecksOnEventDecoding() {
this.disableChecks = false;
}
initialize() {
return __awaiter(this, void 0, void 0, function* () {
debug("initializing");
this.config.resolver = new resolver_1.Resolver(this.config);
if (this.firstSnapshot) {
debug("taking first snapshot");
try {
const initialSnapshot = yield this.snapshot();
this.canSnapshot = true;
this.initialSnapshot = initialSnapshot;
}
catch (error) {
debug("first snapshot failed");
debug("Error: %O", error);
}
this.firstSnapshot = false;
}
else {
yield this.resetState();
}
//set up decoder
let files = fs_1.default
.readdirSync(this.config.contracts_build_directory)
.filter(file => path_1.default.extname(file) === ".json");
let data = files.map(file => fs_1.default.readFileSync(path_1.default.join(this.config.contracts_build_directory, file), "utf8"));
let artifacts = data.map(text => JSON.parse(text));
this.decoder = yield Decoder.forProject({
provider: this.provider,
projectInfo: { artifacts }
});
});
}
deploy() {
return __awaiter(this, void 0, void 0, function* () {
yield migrate_1.default.run(this.config.with({
reset: true,
quiet: true
}));
});
}
resetState() {
return __awaiter(this, void 0, void 0, function* () {
if (this.canSnapshot) {
debug("reverting...");
yield this.revert(this.initialSnapshot);
this.initialSnapshot = yield this.snapshot();
}
else {
debug("redeploying...");
yield this.deploy();
}
});
}
startTest() {
return __awaiter(this, void 0, void 0, function* () {
const blockNumber = web3_utils_1.default.toBN(yield this.interfaceAdapter.getBlockNumber());
const one = web3_utils_1.default.toBN(1);
// Add one in base 10
this.currentTestStartBlock = blockNumber.add(one);
});
}
endTest(mocha) {
return __awaiter(this, void 0, void 0, function* () {
// Skip logging if test passes and `show-events` option is not true
if (mocha.currentTest.state !== "failed" && !this.config["show-events"]) {
return;
}
function indent(input, indentation, initialPrefix = "") {
const unindented = input.split(/\r?\n/);
return unindented
.map((line, index) => index === 0
? initialPrefix +
" ".repeat(indentation - initialPrefix.length) +
line
: " ".repeat(indentation) + line)
.join(os_1.default.EOL);
}
function printEvent(decoding, indentation = 0, initialPrefix = "") {
debug("raw event: %O", decoding);
const inspected = util_1.default.inspect(new Codec.Export.LogDecodingInspector(decoding), {
depth: null,
colors: true,
maxArrayLength: null,
breakLength: 80 - indentation //should this include prefix lengths as well?
});
return indent(inspected, indentation, initialPrefix);
}
if (this.decoder === null) {
throw new Error("Decoder has not yet been initialized.");
}
if (this.currentTestStartBlock === null) {
throw new Error("`currentTestStartBlock` has not been initialized. You must " +
"call `startTest` before calling `endTest`.");
}
const logs = yield this.decoder.events({
//NOTE: block numbers shouldn't be over 2^53 so this
//should be fine, but should change this once decoder
//accepts more general types for blocks
fromBlock: this.currentTestStartBlock.toNumber(),
extras: "necessary",
disableChecks: this.disableChecks //for Solidity testing
});
const userDefinedEventLogs = logs.filter(log => {
return log.decodings.every(decoding => decoding.abi.name !== "TestEvent");
});
if (userDefinedEventLogs.length === 0) {
this.logger.log(" > No events were emitted");
return;
}
this.logger.log("\n Events emitted during test:");
this.logger.log(" ---------------------------");
this.logger.log("");
for (const log of userDefinedEventLogs) {
switch (log.decodings.length) {
case 0:
this.logger.log(` Warning: Could not decode event!`);
this.logger.log("");
break;
case 1:
this.logger.log(printEvent(log.decodings[0], 4));
this.logger.log("");
break;
default:
this.logger.log(` Ambiguous event, possible interpretations:`);
for (const decoding of log.decodings) {
this.logger.log(printEvent(decoding, 6, " * "));
}
this.logger.log("");
break;
}
}
this.logger.log("\n ---------------------------");
});
}
snapshot() {
return __awaiter(this, void 0, void 0, function* () {
return (yield this.rpc("evm_snapshot")).result;
});
}
revert(snapshot_id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.rpc("evm_revert", [snapshot_id]);
});
}
rpc(method, arg) {
return __awaiter(this, void 0, void 0, function* () {
let request = {
jsonrpc: "2.0",
method: method,
id: Date.now(),
params: arg
};
let result = yield util_1.default.promisify(this.provider.send)(request);
if (result.error != null) {
throw new Error("RPC Error: " + (result.error.message || result.error));
}
return result;
});
}
}
exports.TestRunner = TestRunner;
//# sourceMappingURL=TestRunner.js.map
/***/ }),
/***/ 1465:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const web3_utils_1 = __importDefault(__webpack_require__(18269));
function default_1(chai, _utils) {
const assert = chai.assert;
chai.Assertion.addProperty("address", function () {
this.assert(this._obj.length === 42, "expected #{this} to be a 42 character address (0x...)", "expected #{this} to not be a 42 character address (0x...)");
// Convert address to a number. Make sure it's not zero.
// Controversial: Technically there is that edge case where
// all zeroes could be a valid address. But: This catches all
// those cases where Ethereum returns 0x0000... if something fails.
const number = web3_utils_1.default.toBN(this._obj);
this.assert(!number.isZero(), "expected address #{this} to not be zero", "you shouldn't ever see this.");
});
assert.isAddress = function (val, _exp, msg) {
return new chai.Assertion(val, msg).to.be.address;
};
}
exports["default"] = default_1;
//# sourceMappingURL=assertions.js.map
/***/ }),
/***/ 26158:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var __webpack_unused_export__;
__webpack_unused_export__ = ({ value: true });
__webpack_unused_export__ = __webpack_unused_export__ = exports.Test = void 0;
var Test_1 = __webpack_require__(83725);
Object.defineProperty(exports, "Test", ({ enumerable: true, get: function () { return Test_1.Test; } }));
var SolidityTest_1 = __webpack_require__(64956);
__webpack_unused_export__ = ({ enumerable: true, get: function () { return SolidityTest_1.SolidityTest; } });
var TestRunner_1 = __webpack_require__(34036);
__webpack_unused_export__ = ({ enumerable: true, get: function () { return TestRunner_1.TestRunner; } });
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 81969:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const debug = __webpack_require__(15158)("workflow-compile");
const fse = __webpack_require__(55674);
const externalCompile = __webpack_require__(96412);
const solcCompile = __webpack_require__(4273);
const vyperCompile = __webpack_require__(74269);
const { Shims } = __webpack_require__(29833);
const expect = __webpack_require__(14096);
const Config = __webpack_require__(20553);
const Artifactor = __webpack_require__(29463);
const Resolver = (__webpack_require__(48511)["default"]);
const SUPPORTED_COMPILERS = {
solc: solcCompile,
vyper: vyperCompile,
external: externalCompile
};
function prepareConfig(options) {
expect.options(options, ["contracts_build_directory"]);
expect.one(options, ["contracts_directory", "files"]);
// Use a config object to ensure we get the default sources.
const config = Config.default().merge(options);
config.compilersInfo = {};
if (!config.resolver) config.resolver = new Resolver(config);
if (!config.artifactor) {
config.artifactor = new Artifactor(config.contracts_build_directory);
}
return config;
}
const WorkflowCompile = {
collectCompilations: async compilations => {
let result = { outputs: {}, contracts: {} };
for (let compilation of await Promise.all(compilations)) {
let { compiler, output, contracts } = compilation;
result.outputs[compiler] = output;
for (let [name, abstraction] of Object.entries(contracts)) {
result.contracts[name] = abstraction;
}
}
return result;
},