From c1db165bd7efea5d859b88fa1d5d17973fe8bc3e Mon Sep 17 00:00:00 2001 From: killa Date: Sat, 2 May 2026 01:15:41 +0800 Subject: [PATCH 1/7] test: stabilize ci benchmark baseline --- package.json | 3 +- packages/cluster/test/app_worker.test.ts | 46 +++++++++++++++++-- .../app-listen-path/config/config.default.js | 2 +- .../fixtures/stop/app/schedule/interval.js | 2 +- plugins/schedule/test/stop.test.ts | 4 +- .../tegg/test/ManifestCollection.test.ts | 15 ++++-- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 778ef17f26..538bdd5de2 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ ], "type": "module", "scripts": { + "clean": "pnpm -r --filter '!@eggjs/monorepo' --if-present run clean", "clean-dist": "ut run clean --workspaces --if-present", "build": "tsdown", "prelint": "ut run clean-dist", @@ -20,7 +21,7 @@ "fmt": "oxfmt", "typecheck": "ut run clean-dist && ut run typecheck --workspaces --if-present", "fmtcheck": "oxfmt --check .", - "pretest": "ut run clean-dist && ut run pretest --workspaces --if-present", + "pretest": "ut run clean-dist && pnpm -r --filter '!@eggjs/monorepo' --if-present run pretest", "test": "vitest run --bail 1 --retry 2 --testTimeout 20000 --hookTimeout 20000", "test:cov": "ut run test -- --coverage", "preci": "ut run pretest --workspaces --if-present", diff --git a/packages/cluster/test/app_worker.test.ts b/packages/cluster/test/app_worker.test.ts index 61a2d0cfa4..af61586746 100644 --- a/packages/cluster/test/app_worker.test.ts +++ b/packages/cluster/test/app_worker.test.ts @@ -1,5 +1,9 @@ import { strict as assert } from 'node:assert'; +import { randomBytes } from 'node:crypto'; import { rm } from 'node:fs/promises'; +import { createConnection } from 'node:net'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; import { scheduler } from 'node:timers/promises'; import { mm, type MockApplication } from '@eggjs/mock'; @@ -8,7 +12,29 @@ import { ip } from 'address'; import urllib from 'urllib'; import { describe, it, afterEach, beforeEach, beforeAll, afterAll } from 'vitest'; -import { cluster, getFilepath } from './utils.ts'; +import { cluster } from './utils.ts'; + +async function waitForSocket(filepath: string) { + const start = Date.now(); + while (Date.now() - start < 5000) { + const connected = await new Promise((resolve) => { + const socket = createConnection(filepath); + socket.once('connect', () => { + socket.end(); + resolve(true); + }); + socket.once('error', () => { + socket.destroy(); + resolve(false); + }); + }); + if (connected) { + return; + } + await scheduler.wait(50); + } + throw new Error(`Socket ${filepath} did not become connectable`); +} // node v24 will hang when test this file // FIXME: should enable this test after node v24 is stable @@ -204,15 +230,16 @@ describe.skipIf(process.version.startsWith('v24') || process.platform === 'win32 }); describe('listen config', () => { - const sockFile = getFilepath('apps/app-listen-path/my.sock'); - beforeEach(() => { + const sockFile = path.join(tmpdir(), `egg-app-listen-path-${process.pid}-${randomBytes(4).toString('hex')}.sock`); + beforeEach(async () => { mm.env('default'); + await rm(sockFile, { force: true }); }); afterEach(async () => { await app.close(); await mm.restore(); }); - afterEach(() => rm(sockFile, { force: true, recursive: true })); + afterEach(() => rm(sockFile, { force: true })); it.skip('should set default port 170xx then config.listen.port is null', async () => { app = cluster('apps/app-listen-without-port'); @@ -276,13 +303,22 @@ describe.skipIf(process.version.startsWith('v24') || process.platform === 'win32 }); it('should use path in config', async () => { - app = cluster('apps/app-listen-path'); + app = cluster('apps/app-listen-path', { + opt: { + execArgv: [], + env: { + ...process.env, + EGG_APP_LISTEN_PATH_SOCKET: sockFile, + }, + }, + }); // app.debug(); await app.ready(); app.expect('code', 0); app.expect('stdout', new RegExp(`egg started on ${sockFile}`)); + await waitForSocket(sockFile); const sock = encodeURIComponent(sockFile); await request(`http+unix://${sock}`).get('/').expect('done').expect(200); }); diff --git a/packages/cluster/test/fixtures/apps/app-listen-path/config/config.default.js b/packages/cluster/test/fixtures/apps/app-listen-path/config/config.default.js index 1db6860b4e..e289bde542 100644 --- a/packages/cluster/test/fixtures/apps/app-listen-path/config/config.default.js +++ b/packages/cluster/test/fixtures/apps/app-listen-path/config/config.default.js @@ -7,7 +7,7 @@ module.exports = (app) => { keys: '123', cluster: { listen: { - path: path.join(app.baseDir, 'my.sock'), + path: process.env.EGG_APP_LISTEN_PATH_SOCKET || path.join(app.baseDir, 'my.sock'), }, }, }; diff --git a/plugins/schedule/test/fixtures/stop/app/schedule/interval.js b/plugins/schedule/test/fixtures/stop/app/schedule/interval.js index 57ca2bfa38..8164572e6e 100644 --- a/plugins/schedule/test/fixtures/stop/app/schedule/interval.js +++ b/plugins/schedule/test/fixtures/stop/app/schedule/interval.js @@ -2,7 +2,7 @@ exports.schedule = { type: 'worker', - interval: 10000, + interval: 20000, }; exports.task = async function (ctx) { diff --git a/plugins/schedule/test/stop.test.ts b/plugins/schedule/test/stop.test.ts index 06b1c20e3d..d53375b985 100644 --- a/plugins/schedule/test/stop.test.ts +++ b/plugins/schedule/test/stop.test.ts @@ -1,3 +1,4 @@ +import { existsSync } from 'node:fs'; import { setTimeout as sleep } from 'node:timers/promises'; import { mm, type MockApplication } from '@eggjs/mock'; @@ -16,7 +17,8 @@ describe.skipIf(process.platform === 'win32')('test/stop.test.ts', () => { it('should thrown', async () => { await sleep(10000); - const log = getLogContent('stop'); + const logPath = getFixtures('stop/logs/stop/stop-web.log'); + const log = existsSync(logPath) ? getLogContent('stop') : ''; expect(contains(log, 'interval')).toBe(0); }); }); diff --git a/tegg/plugin/tegg/test/ManifestCollection.test.ts b/tegg/plugin/tegg/test/ManifestCollection.test.ts index 765276d3ba..30d3446d41 100644 --- a/tegg/plugin/tegg/test/ManifestCollection.test.ts +++ b/tegg/plugin/tegg/test/ManifestCollection.test.ts @@ -10,6 +10,13 @@ import { getAppBaseDir } from './utils.ts'; describe('plugin/tegg/test/ManifestCollection.test.ts', () => { let app: MockApplication; + function getTeggManifestExtension() { + return ( + (app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension | undefined) ?? + (app.loader.generateManifest().extensions[TEGG_MANIFEST_KEY] as TeggManifestExtension | undefined) + ); + } + afterEach(async () => { return mm.restore(); }); @@ -27,12 +34,12 @@ describe('plugin/tegg/test/ManifestCollection.test.ts', () => { }); it('should collect tegg manifest extension after ready', () => { - const teggExt = app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension | undefined; + const teggExt = getTeggManifestExtension(); assert.ok(teggExt, 'tegg manifest extension should be set'); }); it('should have moduleReferences matching app.moduleReferences', () => { - const teggExt = app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension; + const teggExt = getTeggManifestExtension()!; assert.ok(teggExt.moduleReferences); assert.ok(teggExt.moduleReferences.length > 0); @@ -52,7 +59,7 @@ describe('plugin/tegg/test/ManifestCollection.test.ts', () => { }); it('should have moduleDescriptors with decoratedFiles', () => { - const teggExt = app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension; + const teggExt = getTeggManifestExtension()!; assert.ok(teggExt.moduleDescriptors); assert.ok(teggExt.moduleDescriptors.length > 0); @@ -64,7 +71,7 @@ describe('plugin/tegg/test/ManifestCollection.test.ts', () => { }); it('should have non-empty decoratedFiles for modules with prototypes', () => { - const teggExt = app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension; + const teggExt = getTeggManifestExtension()!; // At least one module should have decorated files const hasFiles = teggExt.moduleDescriptors.some((d) => d.decoratedFiles.length > 0); assert.ok(hasFiles, 'at least one module should have decorated files'); From 9b7597fe021002e494b447dad790ad14f1d60654 Mon Sep 17 00:00:00 2001 From: killa Date: Sat, 2 May 2026 01:31:12 +0800 Subject: [PATCH 2/7] test: avoid pnpm in root workspace scripts --- package.json | 4 +- scripts/run-workspace-scripts.mjs | 74 +++++++++++++++++++ .../tegg/test/ManifestCollection.test.ts | 8 +- 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 scripts/run-workspace-scripts.mjs diff --git a/package.json b/package.json index 538bdd5de2..408dbb529c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "type": "module", "scripts": { - "clean": "pnpm -r --filter '!@eggjs/monorepo' --if-present run clean", + "clean": "node scripts/run-workspace-scripts.mjs clean", "clean-dist": "ut run clean --workspaces --if-present", "build": "tsdown", "prelint": "ut run clean-dist", @@ -21,7 +21,7 @@ "fmt": "oxfmt", "typecheck": "ut run clean-dist && ut run typecheck --workspaces --if-present", "fmtcheck": "oxfmt --check .", - "pretest": "ut run clean-dist && pnpm -r --filter '!@eggjs/monorepo' --if-present run pretest", + "pretest": "ut run clean-dist && node scripts/run-workspace-scripts.mjs pretest", "test": "vitest run --bail 1 --retry 2 --testTimeout 20000 --hookTimeout 20000", "test:cov": "ut run test -- --coverage", "preci": "ut run pretest --workspaces --if-present", diff --git a/scripts/run-workspace-scripts.mjs b/scripts/run-workspace-scripts.mjs new file mode 100644 index 0000000000..ea5a644cb3 --- /dev/null +++ b/scripts/run-workspace-scripts.mjs @@ -0,0 +1,74 @@ +import { spawnSync } from 'node:child_process'; +import { existsSync, readdirSync, readFileSync } from 'node:fs'; +import { join, resolve } from 'node:path'; + +const script = process.argv[2]; +if (!script) { + console.error('Usage: node scripts/run-workspace-scripts.mjs