UNPKG

truffle

Version:

Truffle - Simple development framework for Ethereum

1,311 lines (1,209 loc) 54.7 kB
#!/usr/bin/env node exports.id = 6394; exports.ids = [6394]; exports.modules = { /***/ 93622: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const copyArtifactsToTempDir = async config => { const fse = __webpack_require__(55674); const OS = __webpack_require__(22037); const tmp = __webpack_require__(36276); tmp.setGracefulCleanup(); // Copy all the built files over to a temporary directory, because we // don't want to save any tests artifacts. Only do this if the build directory // exists. const temporaryDirectory = tmp.dirSync({ unsafeCleanup: true, prefix: "test-" }).name; try { fse.statSync(config.contracts_build_directory); } catch (_error) { return { temporaryDirectory }; } fse.copySync(config.contracts_build_directory, temporaryDirectory); if (config.runnerOutputOnly !== true) { config.logger.log("Using network '" + config.network + "'." + OS.EOL); } return { temporaryDirectory }; }; module.exports = { copyArtifactsToTempDir }; /***/ }), /***/ 13799: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const determineTestFilesToRun = ({ inputFile, inputArgs = [], config }) => { const path = __webpack_require__(71017); const fs = __webpack_require__(57147); const glob = __webpack_require__(12884); let filesToRun = []; if (inputFile) { filesToRun.push(inputFile); } else if (inputArgs.length > 0) { inputArgs.forEach(inputArg => filesToRun.push(inputArg)); } if (filesToRun.length === 0) { const directoryContents = glob.sync( `${config.test_directory}${path.sep}**${path.sep}*` ); filesToRun = directoryContents.filter(item => fs.statSync(item).isFile()) || []; } return filesToRun.filter(file => { return file.match(config.test_file_extension_regexp) !== null; }); }; module.exports = { determineTestFilesToRun }; /***/ }), /***/ 55472: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const colors = __webpack_require__(83196); const createInTestDebugFunction = function ({ mochaRunner, compilations, config }) { return async operation => { if (!config.debug) { config.logger.log( `${colors.bold( "Warning:" )} Invoked in-test debugger without --debug flag. ` + `Try: \`truffle test --debug\`` ); return operation; } // wrapped inside function so as not to load debugger on every test const { CLIDebugHook } = __webpack_require__(12834); const hook = new CLIDebugHook(config, compilations, mochaRunner); return await hook.debug(operation); }; }; const prepareConfigAndRunTests = ({ config, temporaryDirectory, files }) => { const Artifactor = __webpack_require__(29463); const { Test } = __webpack_require__(26158); // Set a new artifactor; don't rely on the one created by Environments. // TODO: Make the test artifactor configurable. config.artifactor = new Artifactor(temporaryDirectory); const testConfig = config.with({ test_files: files, contracts_build_directory: temporaryDirectory }); return Test.run(testConfig, createInTestDebugFunction); }; module.exports = { prepareConfigAndRunTests }; /***/ }), /***/ 46394: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const parseCommandLineFlags = options => { // parse out command line flags to merge in to the config const grep = options.grep || options.g; const bail = options.bail || options.b; const reporter = options.reporter || options.r; /** * Reporter value passed on the command line has precedence over a reporter value in the config. * If neither exist, then nothing is passed to mocha and it uses its default reporter type "spec". * Note: It is important that reporter be completely omitted, and not be set to undefined! * As setting it to undefined will ignore the reporter value specified in the config. */ return reporter === undefined ? { mocha: { grep, bail } } : { mocha: { grep, bail, reporter } }; }; module.exports = async function (options) { const Config = __webpack_require__(20553); const { Environment, Develop } = __webpack_require__(76765); const { copyArtifactsToTempDir } = __webpack_require__(93622); const { determineTestFilesToRun } = __webpack_require__(13799); const { prepareConfigAndRunTests } = __webpack_require__(55472); const { configureManagedGanache } = __webpack_require__(84973); const optionsToMerge = parseCommandLineFlags(options); const config = Config.detect(options).merge(optionsToMerge); // if "development" exists, default to using that for testing if (!config.network && config.networks.development) { config.network = "development"; } if (!config.network) { config.network = "test"; } else { await Environment.detect(config); } // Start managed ganache network async function startGanacheAndRunTests( ipcOptions, ganacheOptions, truffleConfig ) { const { disconnect } = await Develop.connectOrStart( ipcOptions, ganacheOptions, truffleConfig?.solidityLog?.displayPrefix ?? "" ); const ipcDisconnect = disconnect; await Environment.develop(truffleConfig, ganacheOptions); const { temporaryDirectory } = await copyArtifactsToTempDir(truffleConfig); const numberOfFailures = await prepareConfigAndRunTests({ config: truffleConfig, files, temporaryDirectory }); ipcDisconnect(); return numberOfFailures; } if (config.stacktraceExtra) { config.stacktrace = true; config.compileAllDebug = true; } // enables in-test debug() interrupt, or stacktraces, forcing compileAll if (config.debug || config.stacktrace || config.compileAllDebug) { config.compileAll = true; } const { file } = options; const inputArgs = options._; const files = determineTestFilesToRun({ config, inputArgs, inputFile: file }); const configuredNetwork = config.networks[config.network]; const testNetworkDefinedAndUsed = configuredNetwork && config.network === "test"; const noProviderHostOrUrlConfigured = configuredNetwork && !configuredNetwork.provider && !configuredNetwork.host && !configuredNetwork.url; let numberOfFailures; if ( (testNetworkDefinedAndUsed && noProviderHostOrUrlConfigured) || !configuredNetwork ) { const defaultPort = await __webpack_require__(15959)(); const defaultMnemonic = "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat"; // configuredNetwork will spread only when it is defined and ignored when undefined const managedNetworkOptions = { port: defaultPort, ...configuredNetwork }; const mnemonic = managedNetworkOptions.mnemonic || defaultMnemonic; const ganacheOptions = configureManagedGanache( config, managedNetworkOptions, mnemonic ); const ipcOptions = { network: "test" }; numberOfFailures = await startGanacheAndRunTests( ipcOptions, ganacheOptions, config ); } else { // Use unmanaged network with user specified config if provider, host or url exists await Environment.detect(config); const { temporaryDirectory } = await copyArtifactsToTempDir(config); numberOfFailures = await prepareConfigAndRunTests({ config, files, temporaryDirectory }); } return numberOfFailures; }; /***/ }), /***/ 84973: /***/ ((module) => { function resolveNetworkId(network_id) { // Use default network_id if "*" is defined in config if (network_id === "*") { return Date.now(); } const parsedNetworkId = parseInt(network_id, 10); if (isNaN(parsedNetworkId)) { const error = `The network id specified in the truffle config ` + `(${network_id}) is not valid. Please properly configure the network id as an integer value.`; throw new Error(error); } return parsedNetworkId; } // This function returns the first defined argument value const getFirstDefinedValue = (...values) => values.find(value => value !== undefined); function configureManagedGanache(config, networkConfig, mnemonic) { const host = getFirstDefinedValue( networkConfig.host, "127.0.0.1" // Use as default host ); const port = getFirstDefinedValue( networkConfig.port, 9545 // Use as default port ); const network_id = getFirstDefinedValue( networkConfig.network_id, 5777 // Use as default network_id ); const resolvedNetworkId = resolveNetworkId(network_id); const total_accounts = getFirstDefinedValue( networkConfig.accounts, networkConfig.total_accounts, 10 // Use as default number of accounts ); const default_balance_ether = getFirstDefinedValue( networkConfig.defaultEtherBalance, networkConfig.default_balance_ether, 100 // Use as default ether balance for each account ); const blockTime = getFirstDefinedValue( networkConfig.blockTime, 0 // Use as default block time ); const gasLimit = getFirstDefinedValue( networkConfig.gasLimit, 0x6691b7 // Use as default gasLimit ); const gasPrice = getFirstDefinedValue( networkConfig.gasPrice, 0x77359400 // Use default gas price 2000000000 wei ); const genesisTime = getFirstDefinedValue( // Higher precedence is given to the networkConfig.time or networkConfig.genesis_time networkConfig.time, networkConfig.genesis_time, config.time, config.genesis_time ); const fork = networkConfig.fork; const hardfork = networkConfig.hardfork; const ganacheOptions = { host, port, network_id: resolvedNetworkId, total_accounts, default_balance_ether, blockTime, fork, hardfork, mnemonic, gasLimit, gasPrice, time: genesisTime, miner: { instamine: "eager" } }; return ganacheOptions; } module.exports = { configureManagedGanache, getFirstDefinedValue }; /***/ }), /***/ 12834: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { const debugModule = __webpack_require__(15158); const debug = debugModule("lib:debug:mocha"); const colors = __webpack_require__(83196); const util = __webpack_require__(73837); const { CLIDebugger } = __webpack_require__(458); const execute = __webpack_require__(41441); class CLIDebugHook { constructor(config, compilations, runner) { this.config = config; this.compilations = compilations; this.runner = runner; // mocha runner (**not** lib/test/testrunner) } async debug(operation) { // turn off timeouts for the current runnable // HACK we don't turn it back on because it doesn't work... // tests that take a long time _after_ debug break just won't timeout await this.disableTimeout(); const { txHash, result, method } = await this.invoke(operation); debug("txHash: %o", txHash); this.printStartTestHook(method); const interpreter = await new CLIDebugger(this.config, { compilations: this.compilations, txHash }).run(); await interpreter.start(); this.printStopTestHook(); return result; } async start() {} async disableTimeout() { (await this.runner).currentRunnable.timeout(0); } async invoke(operation) { const method = await this.detectMethod(operation); const { action } = method; switch (action) { case "deploy": { const result = await operation; return { txHash: result.transactionHash, // different name; who knew method, result }; } case "send": { const result = await operation; return { txHash: result.tx, method, result }; } case "call": { // replays as send const { contract, fn, abi, args, address } = method; // get the result of the call const result = await operation; // and replay it as a transaction so we can debug // bit of a HACK: properly making a call act like a tx requires forking const { tx: txHash } = await execute.send.call( contract, fn, abi, address )(...args); return { txHash, method, result }; } default: { throw new Error(`Unsupported action for debugging: ${action}`); } } } detectMethod(promiEvent) { return new Promise(accept => { for (let action of ["send", "call", "deploy"]) { promiEvent.on( `execute:${action}:method`, ({ fn, abi, args, contract, address }) => { accept({ fn, abi, args, address, contract, action }); } ); } }); } printStartTestHook(method) { const formatOperation = ({ action, contract: { contractName }, abi, args }) => { switch (action) { case "deploy": { return colors.bold( `${contractName}.new(${args.map(util.inspect).join(", ")})` ); } case "call": case "send": { return colors.bold( `${contractName}.${abi.name}(${args.map(util.inspect).join(", ")})` ); } } }; this.config.logger.log(""); this.config.logger.log(" ..."); this.config.logger.log( colors.cyan( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" ) ); this.config.logger.log(" Test run interrupted."); this.config.logger.log(` Debugging ${formatOperation(method)}`); this.config.logger.log( colors.cyan( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" ) ); this.config.logger.log(""); } printStopTestHook() { this.config.logger.log(""); this.config.logger.log(""); this.config.logger.log( colors.cyan( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" ) ); this.config.logger.log(" Debugger stopped. Test resuming"); this.config.logger.log( colors.cyan( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" ) ); this.config.logger.log(" ..."); this.config.logger.log(""); } } module.exports = { CLIDebugHook }; /***/ }), /***/ 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