Skip to content

Commit

Permalink
feat: add a configurable solidity test runner timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
galargh committed Oct 16, 2024
1 parent c05fc5d commit 1923831
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import type { HardhatPlugin } from "../../../types/plugins.js";

import { ArgumentType } from "../../../types/arguments.js";
import { task } from "../../core/config.js";

const hardhatPlugin: HardhatPlugin = {
id: "builtin:solidity-test",
tasks: [
task(["test:solidity"], "Run the Solidity tests")
.setAction(import.meta.resolve("./task-action.js"))
.addOption({
name: "timeout",
description:
"The maximum time in milliseconds to wait for all the test suites to finish",
type: ArgumentType.INT,
defaultValue: 60 * 60 * 1000,
})
.build(),
],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,19 @@ import type {
import { Readable } from "node:stream";

import { runSolidityTests } from "@ignored/edr";
import { HardhatError } from "@ignored/hardhat-vnext-errors";

import { formatArtifactId } from "./formatters.js";

export interface RunOptions {
/**
* The maximum time in milliseconds to wait for all the test suites to finish.
*
* If not provided, the default is 1 hour.
*/
timeout?: number;
}

/**
* Run all the given solidity tests and returns the stream of results.
*
Expand All @@ -31,6 +41,7 @@ export function run(
artifacts: Artifact[],
testSuiteIds: ArtifactId[],
configArgs: SolidityTestRunnerConfigArgs,
options?: RunOptions,
): TestsStream {
const stream = new ReadableStream<TestEvent>({
start(controller) {
Expand All @@ -41,6 +52,19 @@ export function run(

const remainingSuites = new Set(testSuiteIds.map(formatArtifactId));

// NOTE: The timeout prevents the situation in which the stream is never
// closed. This can happen if we receive fewer suite results than the
// number of test suites. The timeout is set to 1 hour.
const duration = options?.timeout ?? 60 * 60 * 1000;
const timeout = setTimeout(() => {
controller.error(
new HardhatError(HardhatError.ERRORS.SOLIDITY_TESTS.RUNNER_TIMEOUT, {
duration,
suites: Array.from(remainingSuites).join(", "),
}),
);
}, duration);

runSolidityTests(
artifacts,
testSuiteIds,
Expand All @@ -52,10 +76,12 @@ export function run(
});
remainingSuites.delete(formatArtifactId(suiteResult.id));
if (remainingSuites.size === 0) {
clearTimeout(timeout);
controller.close();
}
},
(error) => {
clearTimeout(timeout);
controller.error(error);
},
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RunOptions } from "./runner.js";
import type { TestEvent } from "./types.js";
import type { NewTaskActionFunction } from "../../../types/tasks.js";

Expand All @@ -7,7 +8,7 @@ import { buildSolidityTestsInput } from "./helpers.js";
import { testReporter } from "./reporter.js";
import { run } from "./runner.js";

const runSolidityTests: NewTaskActionFunction = async (_arguments, hre) => {
const runSolidityTests: NewTaskActionFunction = async ({ timeout }, hre) => {
await hre.tasks.getTask("compile").run({ quiet: false });

console.log("\nRunning Solidity tests...\n");
Expand All @@ -33,7 +34,9 @@ const runSolidityTests: NewTaskActionFunction = async (_arguments, hre) => {
let includesFailures = false;
let includesErrors = false;

const runStream = run(artifacts, testSuiteIds, config);
const options: RunOptions = { timeout };

const runStream = run(artifacts, testSuiteIds, config, options);

runStream
.on("data", (event: TestEvent) => {
Expand Down

0 comments on commit 1923831

Please sign in to comment.