Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
],
"type": "module",
"scripts": {
"clean": "node scripts/run-workspace-scripts.mjs clean",
"clean-dist": "ut run clean --workspaces --if-present",
"build": "tsdown",
"prelint": "ut run clean-dist",
"lint": "oxlint --type-aware --type-check --quiet",
"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 && 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",
Expand Down
46 changes: 41 additions & 5 deletions packages/cluster/test/app_worker.test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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<boolean>((resolve) => {
const socket = createConnection(filepath);
socket.once('connect', () => {
socket.end();
resolve(true);
});
socket.once('error', () => {
socket.destroy();
resolve(false);
});
Comment thread
killagu marked this conversation as resolved.
Outdated
});
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
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports.schedule = {
type: 'worker',
interval: 10000,
interval: 20000,
Comment thread
killagu marked this conversation as resolved.
Outdated
};

exports.task = async function (ctx) {
Expand Down
4 changes: 3 additions & 1 deletion plugins/schedule/test/stop.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { existsSync } from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';

import { mm, type MockApplication } from '@eggjs/mock';
Expand All @@ -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') : '';
Comment thread
killagu marked this conversation as resolved.
Outdated
expect(contains(log, 'interval')).toBe(0);
});
});
74 changes: 74 additions & 0 deletions scripts/run-workspace-scripts.mjs
Original file line number Diff line number Diff line change
@@ -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 <script>');
process.exit(1);
}

const root = resolve(import.meta.dirname, '..');
const workspaceFile = join(root, 'pnpm-workspace.yaml');

function readWorkspacePatterns() {
const patterns = [];
let inPackages = false;

for (const line of readFileSync(workspaceFile, 'utf8').split('\n')) {
if (line.trim() === 'packages:') {
inPackages = true;
continue;
}
if (inPackages && line.length > 0 && !line.startsWith(' ')) {
break;
}

const match = /^\s+-\s+(.+?)\s*$/.exec(line);
if (inPackages && match) {
patterns.push(match[1].replace(/^['"]|['"]$/g, ''));
}
}

return patterns;
}

function expandWorkspacePattern(pattern) {
if (!pattern.endsWith('/*')) {
return [join(root, pattern)];
}

const baseDir = join(root, pattern.slice(0, -2));
return readdirSync(baseDir, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => join(baseDir, entry.name));
}

let matched = 0;
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';

for (const workspaceDir of readWorkspacePatterns().flatMap(expandWorkspacePattern)) {
Comment thread
killagu marked this conversation as resolved.
const packageJsonPath = join(workspaceDir, 'package.json');
if (!existsSync(packageJsonPath)) {
continue;
}

const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
if (!packageJson.scripts?.[script]) {
continue;
}

matched++;
console.log(`> ${packageJson.name ?? workspaceDir} ${script}`);
const result = spawnSync(npmCommand, ['run', '--silent', script], {
cwd: workspaceDir,
stdio: 'inherit',
});
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}

if (matched === 0) {
console.log(`No workspace scripts found for "${script}"`);
}
17 changes: 13 additions & 4 deletions tegg/plugin/tegg/test/ManifestCollection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ import { getAppBaseDir } from './utils.ts';

describe('plugin/tegg/test/ManifestCollection.test.ts', () => {
let app: MockApplication;
let teggExtCache: TeggManifestExtension | undefined;

function getTeggManifestExtension() {
teggExtCache ??=
(app.loader.manifest.getExtension(TEGG_MANIFEST_KEY) as TeggManifestExtension | undefined) ??
(app.loader.generateManifest().extensions[TEGG_MANIFEST_KEY] as TeggManifestExtension | undefined);
return teggExtCache;
}
Comment thread
killagu marked this conversation as resolved.

afterEach(async () => {
return mm.restore();
Expand All @@ -19,6 +27,7 @@ describe('plugin/tegg/test/ManifestCollection.test.ts', () => {
app = mm.app({
baseDir: getAppBaseDir('egg-app'),
});
teggExtCache = undefined;
await app.ready();
});

Expand All @@ -27,12 +36,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);

Expand All @@ -52,7 +61,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);

Expand All @@ -64,7 +73,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');
Expand Down
Loading