From 76b584ff0630c32e0a44fce7e0c87b39ae6240c8 Mon Sep 17 00:00:00 2001 From: Patricio Palladino Date: Mon, 28 Oct 2024 19:45:39 +0000 Subject: [PATCH 1/4] [hardhat-utils] Add a stream utilities --- v-next/hardhat-utils/package.json | 1 + v-next/hardhat-utils/src/stream.ts | 16 +++++++ v-next/hardhat-utils/test/stream.ts | 65 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 v-next/hardhat-utils/src/stream.ts create mode 100644 v-next/hardhat-utils/test/stream.ts diff --git a/v-next/hardhat-utils/package.json b/v-next/hardhat-utils/package.json index 36675a1dc0..b5f2941a5d 100644 --- a/v-next/hardhat-utils/package.json +++ b/v-next/hardhat-utils/package.json @@ -32,6 +32,7 @@ "./request": "./dist/src/request.js", "./resolve": "./dist/src/resolve.js", "./string": "./dist/src/string.js", + "./stream": "./dist/src/stream.js", "./subprocess": "./dist/src/subprocess.js" }, "keywords": [ diff --git a/v-next/hardhat-utils/src/stream.ts b/v-next/hardhat-utils/src/stream.ts new file mode 100644 index 0000000000..bf0ee42c48 --- /dev/null +++ b/v-next/hardhat-utils/src/stream.ts @@ -0,0 +1,16 @@ +import { Writable } from "node:stream"; + +/** + * Creates a Tansform that writes everything to actualWritable, without closing it + * when finished. + * + * This is useful to pipe things to stdout, without closing it, while being + * able to await for the result of the pipe to finish. + */ +export function createNonClosingWriter(actualWritable: Writable): Writable { + return new Writable({ + write(chunk, encoding, callback) { + actualWritable.write(chunk, encoding, callback); + }, + }); +} diff --git a/v-next/hardhat-utils/test/stream.ts b/v-next/hardhat-utils/test/stream.ts new file mode 100644 index 0000000000..212353be77 --- /dev/null +++ b/v-next/hardhat-utils/test/stream.ts @@ -0,0 +1,65 @@ +import assert from "node:assert/strict"; +import { Readable, Writable } from "node:stream"; +import { pipeline } from "node:stream/promises"; +import { describe, it } from "node:test"; + +import { createNonClosingWriter } from "../src/stream.js"; + +function createFixedReadable(data: Buffer[]) { + const streamData = [...data]; + + const stream = new Readable({ + encoding: "utf8", + read(_size) { + const chunk = streamData.shift(); + + if (chunk === undefined) { + this.push(null); + return; + } + + this.push(chunk); + }, + }); + + return stream; +} + +function createWritable() { + const data: string[] = []; + const writable = new Writable({ + write(chunk, _encoding, callback) { + data.push(chunk); + + callback(); + }, + }); + + return { writable, data }; +} + +describe("stream", () => { + describe("createNonClosingWriter", () => { + const FIXTURE_DATA = [Buffer.from("a"), Buffer.from("b"), Buffer.from("c")]; + + it("Should not close the actual writable when finished", async () => { + const readable = createFixedReadable(FIXTURE_DATA); + const { writable } = createWritable(); + const writer = createNonClosingWriter(writable); + await pipeline(readable, writer); + + assert.equal(readable.closed, true); + assert.equal(writer.closed, true); + assert.equal(writable.closed, false); + }); + + it("Should write all the data to the actual writable", async () => { + const readable = createFixedReadable(FIXTURE_DATA); + const { writable, data } = createWritable(); + const writer = createNonClosingWriter(writable); + await pipeline(readable, writer); + + assert.deepEqual(data, FIXTURE_DATA); + }); + }); +}); From a5c6af9eb7cdaebbc92e040c9b474f7303c1d07f Mon Sep 17 00:00:00 2001 From: Patricio Palladino Date: Mon, 28 Oct 2024 20:06:48 +0000 Subject: [PATCH 2/4] Use the new utility in the solidity test runner --- .../builtin-plugins/solidity-test/task-action.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts index db58a9fdcb..2b256ec153 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts @@ -2,11 +2,12 @@ import type { RunOptions } from "./runner.js"; import type { TestEvent } from "./types.js"; import type { NewTaskActionFunction } from "../../../types/tasks.js"; -import { finished } from "node:stream/promises"; +import { finished, pipeline } from "node:stream/promises"; import { getArtifacts, isTestArtifact } from "./helpers.js"; import { testReporter } from "./reporter.js"; import { run } from "./runner.js"; +import { createNonClosingWriter } from "@ignored/hardhat-vnext-utils/stream"; interface TestActionArguments { timeout: number; @@ -53,19 +54,18 @@ const runSolidityTests: NewTaskActionFunction = async ( }) .compose(testReporter); - testReporterStream.pipe(process.stdout); + const outputStream = testReporterStream.pipe( + createNonClosingWriter(process.stdout), + ); try { // NOTE: We're awaiting the original run stream to finish to catch any // errors produced by the runner. await finished(runStream); - // We also await the test reporter stream to finish to catch any error, and + // We also await the output stream to finish, as we want to wait for it // to avoid returning before the whole output was generated. - // - // NOTE: We don't await the restult of piping it to stdout, as that is - // ignored. - await finished(testReporterStream); + await finished(outputStream); } catch (error) { console.error(error); includesErrors = true; From 6e997192fe98d58733759c033e91d632788fc353 Mon Sep 17 00:00:00 2001 From: Patricio Palladino Date: Mon, 28 Oct 2024 20:07:03 +0000 Subject: [PATCH 3/4] Use the new utility in the hardhat-node-test-runner --- v-next/hardhat-node-test-runner/src/task-action.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/v-next/hardhat-node-test-runner/src/task-action.ts b/v-next/hardhat-node-test-runner/src/task-action.ts index 27d24163fc..4f9d4a8806 100644 --- a/v-next/hardhat-node-test-runner/src/task-action.ts +++ b/v-next/hardhat-node-test-runner/src/task-action.ts @@ -2,12 +2,13 @@ import type { HardhatConfig } from "@ignored/hardhat-vnext/types/config"; import type { NewTaskActionFunction } from "@ignored/hardhat-vnext/types/tasks"; import type { LastParameter } from "@ignored/hardhat-vnext/types/utils"; -import { finished } from "node:stream/promises"; +import { pipeline } from "node:stream/promises"; import { run } from "node:test"; import { fileURLToPath } from "node:url"; import { hardhatTestReporter } from "@ignored/hardhat-vnext-node-test-reporter"; import { getAllFilesMatching } from "@ignored/hardhat-vnext-utils/fs"; +import { createNonClosingWriter } from "@ignored/hardhat-vnext-utils/stream"; interface TestActionArguments { testFiles: string[]; @@ -92,9 +93,7 @@ const testWithHardhat: NewTaskActionFunction = async ( }) .compose(customReporter); - reporterStream.pipe(process.stdout); - - await finished(reporterStream); + await pipeline(reporterStream, createNonClosingWriter(process.stdout)); return failures; } From 742556b02b699438f25138ec797363a0d1d12ab2 Mon Sep 17 00:00:00 2001 From: Patricio Palladino Date: Mon, 28 Oct 2024 20:30:14 +0000 Subject: [PATCH 4/4] Fix linter errors --- .../internal/builtin-plugins/solidity-test/task-action.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts index 2b256ec153..0ef4afaaa6 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts @@ -2,12 +2,13 @@ import type { RunOptions } from "./runner.js"; import type { TestEvent } from "./types.js"; import type { NewTaskActionFunction } from "../../../types/tasks.js"; -import { finished, pipeline } from "node:stream/promises"; +import { finished } from "node:stream/promises"; + +import { createNonClosingWriter } from "@ignored/hardhat-vnext-utils/stream"; import { getArtifacts, isTestArtifact } from "./helpers.js"; import { testReporter } from "./reporter.js"; import { run } from "./runner.js"; -import { createNonClosingWriter } from "@ignored/hardhat-vnext-utils/stream"; interface TestActionArguments { timeout: number;