mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-18 14:29:01 +08:00
3bc1cc248d
* chore: bump to msw v3 * refactor: anti-slop * test: use vi.stubEnv for REDIS_URL in redis error test * refactor: move remote debugging registration into a conditional block * chore: add code coverage upload for github
121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
import cluster from 'node:cluster';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const serve = vi.fn<(...args: any[]) => any>(() => ({ close: vi.fn() }));
|
|
const listen = vi.fn();
|
|
const createAdaptorServer = vi.fn<(...args: any[]) => any>(() => ({ listen, close: vi.fn() }));
|
|
const rmSync = vi.spyOn(fs, 'rmSync').mockImplementation(() => {});
|
|
const fork = vi.spyOn(cluster, 'fork').mockImplementation(() => new cluster.Worker());
|
|
const clusterState = { isPrimary: true };
|
|
vi.spyOn(cluster, 'isPrimary', 'get').mockImplementation(() => clusterState.isPrimary);
|
|
const availableParallelism = vi.spyOn(os, 'availableParallelism').mockReturnValue(2);
|
|
|
|
vi.mock('@hono/node-server', () => ({
|
|
serve,
|
|
createAdaptorServer,
|
|
}));
|
|
|
|
describe('index', () => {
|
|
afterEach(() => {
|
|
vi.resetModules();
|
|
vi.unstubAllEnvs();
|
|
serve.mockClear();
|
|
createAdaptorServer.mockClear();
|
|
listen.mockClear();
|
|
rmSync.mockClear();
|
|
fork.mockClear();
|
|
availableParallelism.mockClear();
|
|
clusterState.isPrimary = true;
|
|
});
|
|
|
|
it('starts a server when cluster is disabled', async () => {
|
|
vi.stubEnv('ENABLE_CLUSTER', '');
|
|
vi.stubEnv('LISTEN_INADDR_ANY', '');
|
|
vi.stubEnv('PORT', '12345');
|
|
|
|
const module = await import('@/index');
|
|
expect(module.default).toBeDefined();
|
|
expect(serve).toHaveBeenCalledTimes(1);
|
|
expect(serve.mock.calls[0][0]).toMatchObject({
|
|
hostname: '127.0.0.1',
|
|
port: 12345,
|
|
});
|
|
expect(createAdaptorServer).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('forks workers when cluster is enabled and primary', async () => {
|
|
clusterState.isPrimary = true;
|
|
vi.stubEnv('ENABLE_CLUSTER', 'true');
|
|
vi.stubEnv('LISTEN_INADDR_ANY', 'true');
|
|
vi.stubEnv('PORT', '12346');
|
|
availableParallelism.mockReturnValue(2);
|
|
|
|
await import('@/index');
|
|
|
|
expect(fork).toHaveBeenCalledTimes(2);
|
|
expect(serve).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('starts a worker server when cluster is enabled and not primary', async () => {
|
|
clusterState.isPrimary = false;
|
|
vi.stubEnv('ENABLE_CLUSTER', 'true');
|
|
vi.stubEnv('LISTEN_INADDR_ANY', '');
|
|
vi.stubEnv('PORT', '12347');
|
|
|
|
await import('@/index');
|
|
|
|
expect(serve).toHaveBeenCalledTimes(1);
|
|
expect(serve.mock.calls[0][0]).toMatchObject({
|
|
hostname: '127.0.0.1',
|
|
port: 12347,
|
|
});
|
|
});
|
|
|
|
it('listens on a unix socket instead of a port when SOCKET is set', async () => {
|
|
vi.stubEnv('ENABLE_CLUSTER', '');
|
|
vi.stubEnv('LISTEN_INADDR_ANY', '');
|
|
vi.stubEnv('SOCKET', '/tmp/rsshub-test.sock');
|
|
vi.stubEnv('PORT', 'null');
|
|
|
|
const module = await import('@/index');
|
|
expect(module.default).toBeDefined();
|
|
expect(rmSync).toHaveBeenCalledWith('/tmp/rsshub-test.sock', { force: true });
|
|
expect(createAdaptorServer).toHaveBeenCalledTimes(1);
|
|
expect(createAdaptorServer.mock.calls[0][0]).toMatchObject({
|
|
hostname: '127.0.0.1',
|
|
});
|
|
expect(listen).toHaveBeenCalledWith('/tmp/rsshub-test.sock');
|
|
expect(serve).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('cluster primary removes a stale unix socket before forking', async () => {
|
|
clusterState.isPrimary = true;
|
|
vi.stubEnv('ENABLE_CLUSTER', 'true');
|
|
vi.stubEnv('SOCKET', '/tmp/rsshub-test.sock');
|
|
availableParallelism.mockReturnValue(2);
|
|
|
|
await import('@/index');
|
|
|
|
expect(rmSync).toHaveBeenCalledWith('/tmp/rsshub-test.sock', { force: true });
|
|
expect(fork).toHaveBeenCalledTimes(2);
|
|
expect(createAdaptorServer).not.toHaveBeenCalled();
|
|
expect(serve).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('cluster worker listens on the unix socket without removing it', async () => {
|
|
clusterState.isPrimary = false;
|
|
vi.stubEnv('ENABLE_CLUSTER', 'true');
|
|
vi.stubEnv('SOCKET', '/tmp/rsshub-test.sock');
|
|
|
|
await import('@/index');
|
|
|
|
expect(rmSync).not.toHaveBeenCalled();
|
|
expect(createAdaptorServer).toHaveBeenCalledTimes(1);
|
|
expect(listen).toHaveBeenCalledWith('/tmp/rsshub-test.sock');
|
|
expect(serve).not.toHaveBeenCalled();
|
|
});
|
|
});
|