Skip to content
File

Blob: src/workerd/api/node/tests/cluster-nodejs-test.js

javascript289 lines
1// Copyright (c) 2025 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import cluster from 'node:cluster';
5import assert from 'node:assert';
6 
7export const clusterConstants = {
8 test() {
9 // Test scheduling constants
10 assert.strictEqual(cluster.SCHED_NONE, 1);
11 assert.strictEqual(cluster.SCHED_RR, 2);
12 
13 // Test the default scheduling policy
14 assert.strictEqual(cluster.schedulingPolicy, cluster.SCHED_RR);
15 },
16};
17 
18export const clusterMasterWorkerFlags = {
19 test() {
20 // Test master/primary flags
21 assert.strictEqual(cluster.isMaster, true);
22 assert.strictEqual(cluster.isPrimary, true);
23 assert.strictEqual(cluster.isWorker, false);
24 
25 // Test that isMaster and isPrimary are the same
26 assert.strictEqual(cluster.isMaster, cluster.isPrimary);
27 },
28};
29 
30export const clusterSettings = {
31 test() {
32 // Settings should be an empty object
33 assert.deepStrictEqual(cluster.settings, {});
34 assert.strictEqual(typeof cluster.settings, 'object');
35 },
36};
37 
38export const clusterWorkers = {
39 test() {
40 // Workers should be an empty object
41 assert.deepStrictEqual(cluster.workers, {});
42 assert.strictEqual(typeof cluster.workers, 'object');
43 },
44};
45 
46export const clusterForkMethod = {
47 test() {
48 // Test fork method throws ERR_METHOD_NOT_IMPLEMENTED
49 assert.throws(() => cluster.fork(), { code: 'ERR_METHOD_NOT_IMPLEMENTED' });
50 
51 // Test fork with env parameter
52 assert.throws(() => cluster.fork({ NODE_ENV: 'test' }), {
53 code: 'ERR_METHOD_NOT_IMPLEMENTED',
54 });
55 },
56};
57 
58export const clusterDisconnectMethod = {
59 test() {
60 // Test disconnect method throws ERR_METHOD_NOT_IMPLEMENTED
61 assert.throws(() => cluster.disconnect(), {
62 code: 'ERR_METHOD_NOT_IMPLEMENTED',
63 });
64 },
65};
66 
67export const clusterSetupMethods = {
68 test() {
69 // Test setupPrimary method throws ERR_METHOD_NOT_IMPLEMENTED
70 assert.throws(() => cluster.setupPrimary(), {
71 code: 'ERR_METHOD_NOT_IMPLEMENTED',
72 });
73 
74 // Test setupMaster method throws ERR_METHOD_NOT_IMPLEMENTED
75 assert.throws(() => cluster.setupMaster(), {
76 code: 'ERR_METHOD_NOT_IMPLEMENTED',
77 });
78 },
79};
80 
81export const clusterWorkerClass = {
82 test() {
83 // Create a Worker instance
84 const Worker = cluster.Worker;
85 const worker = new Worker();
86 
87 // Test initial properties
88 assert.strictEqual(worker._connected, false);
89 assert.strictEqual(worker.id, 0);
90 assert.strictEqual(worker.exitedAfterDisconnect, false);
91 
92 // Test isConnected method
93 assert.strictEqual(worker.isConnected(), false);
94 
95 // Test isDead method
96 assert.strictEqual(worker.isDead(), true);
97 
98 // Test send method always returns false
99 assert.strictEqual(worker.send('message'), false);
100 assert.strictEqual(worker.send('message', null), false);
101 assert.strictEqual(worker.send('message', null, {}), false);
102 assert.strictEqual(
103 worker.send('message', null, {}, () => {}),
104 false
105 );
106 
107 // Test kill method
108 worker._connected = true;
109 worker.kill();
110 assert.strictEqual(worker._connected, false);
111 
112 // Test kill with signal
113 worker._connected = true;
114 worker.kill('SIGTERM');
115 assert.strictEqual(worker._connected, false);
116 
117 // Test destroy method
118 worker._connected = true;
119 worker.destroy();
120 assert.strictEqual(worker._connected, false);
121 
122 // Test destroy with signal
123 worker._connected = true;
124 worker.destroy('SIGTERM');
125 assert.strictEqual(worker._connected, false);
126 
127 // Test disconnect method returns this
128 worker._connected = true;
129 const result = worker.disconnect();
130 assert.strictEqual(result, worker);
131 assert.strictEqual(worker._connected, false);
132 
133 // Test process property
134 assert.strictEqual(worker.process, globalThis.process);
135 
136 // Test Worker extends EventEmitter
137 assert.strictEqual(typeof worker.on, 'function');
138 assert.strictEqual(typeof worker.emit, 'function');
139 assert.strictEqual(typeof worker.removeListener, 'function');
140 },
141};
142 
143export const clusterEventEmitter = {
144 test() {
145 // Test that cluster extends EventEmitter
146 assert.strictEqual(typeof cluster.on, 'function');
147 assert.strictEqual(typeof cluster.emit, 'function');
148 assert.strictEqual(typeof cluster.once, 'function');
149 assert.strictEqual(typeof cluster.removeListener, 'function');
150 assert.strictEqual(typeof cluster.removeAllListeners, 'function');
151 assert.strictEqual(typeof cluster.setMaxListeners, 'function');
152 assert.strictEqual(typeof cluster.getMaxListeners, 'function');
153 assert.strictEqual(typeof cluster.listeners, 'function');
154 assert.strictEqual(typeof cluster.rawListeners, 'function');
155 assert.strictEqual(typeof cluster.listenerCount, 'function');
156 assert.strictEqual(typeof cluster.prependListener, 'function');
157 assert.strictEqual(typeof cluster.prependOnceListener, 'function');
158 assert.strictEqual(typeof cluster.eventNames, 'function');
159 
160 // Test adding and removing listeners
161 let called = false;
162 const listener = () => {
163 called = true;
164 };
165 
166 cluster.on('test', listener);
167 cluster.emit('test');
168 assert.strictEqual(called, true);
169 
170 called = false;
171 cluster.removeListener('test', listener);
172 cluster.emit('test');
173 assert.strictEqual(called, false);
174 },
175};
176 
177export const clusterInstanceProperties = {
178 test() {
179 // Test that cluster instance has all expected properties
180 assert.strictEqual(cluster.isMaster, true);
181 assert.strictEqual(cluster.isPrimary, true);
182 assert.strictEqual(cluster.isWorker, false);
183 assert.strictEqual(cluster.SCHED_NONE, 1);
184 assert.strictEqual(cluster.SCHED_RR, 2);
185 assert.strictEqual(cluster.schedulingPolicy, 2);
186 assert.deepStrictEqual(cluster.settings, {});
187 assert.deepStrictEqual(cluster.workers, {});
188 assert.strictEqual(typeof cluster.Worker, 'function');
189 assert.strictEqual(typeof cluster.setupPrimary, 'function');
190 assert.strictEqual(typeof cluster.setupMaster, 'function');
191 assert.strictEqual(typeof cluster.disconnect, 'function');
192 assert.strictEqual(typeof cluster.fork, 'function');
193 },
194};
195 
196export const clusterModuleExports = {
197 async test() {
198 // Test module exports
199 const clusterModule = await import('node:cluster');
200 
201 // Test default export
202 assert.strictEqual(typeof clusterModule.default, 'object');
203 assert.strictEqual(clusterModule.default.isPrimary, true);
204 
205 // Test named exports
206 assert.strictEqual(clusterModule.SCHED_NONE, 1);
207 assert.strictEqual(clusterModule.SCHED_RR, 2);
208 assert.strictEqual(clusterModule.isMaster, true);
209 assert.strictEqual(clusterModule.isPrimary, true);
210 assert.strictEqual(clusterModule.isWorker, false);
211 assert.strictEqual(clusterModule.schedulingPolicy, 2);
212 assert.deepStrictEqual(clusterModule.settings, {});
213 assert.deepStrictEqual(clusterModule.workers, {});
214 assert.strictEqual(typeof clusterModule.Worker, 'function');
215 assert.strictEqual(typeof clusterModule.Cluster, 'function');
216 assert.strictEqual(typeof clusterModule.fork, 'function');
217 assert.strictEqual(typeof clusterModule.disconnect, 'function');
218 assert.strictEqual(typeof clusterModule.setupPrimary, 'function');
219 assert.strictEqual(typeof clusterModule.setupMaster, 'function');
220 },
221};
222 
223export const clusterWorkerEventEmitter = {
224 test() {
225 const Worker = cluster.Worker;
226 const worker = new Worker();
227 
228 // Test Worker event emitter functionality
229 let eventFired = false;
230 const handler = () => {
231 eventFired = true;
232 };
233 
234 worker.on('custom', handler);
235 worker.emit('custom');
236 assert.strictEqual(eventFired, true);
237 
238 eventFired = false;
239 worker.removeListener('custom', handler);
240 worker.emit('custom');
241 assert.strictEqual(eventFired, false);
242 
243 // Test once
244 let onceCount = 0;
245 worker.once('once-event', () => {
246 onceCount++;
247 });
248 worker.emit('once-event');
249 worker.emit('once-event');
250 assert.strictEqual(onceCount, 1);
251 },
252};
253 
254export const clusterClassInstance = {
255 test() {
256 // Test creating a new Cluster instance
257 const ClusterClass = cluster.constructor;
258 const newCluster = new ClusterClass();
259 
260 // Test that the new instance has all expected properties
261 assert.strictEqual(newCluster.isMaster, true);
262 assert.strictEqual(newCluster.isPrimary, true);
263 assert.strictEqual(newCluster.isWorker, false);
264 assert.strictEqual(newCluster.SCHED_NONE, 1);
265 assert.strictEqual(newCluster.SCHED_RR, 2);
266 assert.strictEqual(newCluster.schedulingPolicy, 2);
267 assert.deepStrictEqual(newCluster.settings, {});
268 assert.deepStrictEqual(newCluster.workers, {});
269 assert.strictEqual(typeof newCluster.Worker, 'function');
270 
271 // Test that methods throw the expected errors
272 assert.throws(() => newCluster.setupPrimary(), {
273 code: 'ERR_METHOD_NOT_IMPLEMENTED',
274 });
275 
276 assert.throws(() => newCluster.setupMaster(), {
277 code: 'ERR_METHOD_NOT_IMPLEMENTED',
278 });
279 
280 assert.throws(() => newCluster.disconnect(), {
281 code: 'ERR_METHOD_NOT_IMPLEMENTED',
282 });
283 
284 assert.throws(() => newCluster.fork(), {
285 code: 'ERR_METHOD_NOT_IMPLEMENTED',
286 });
287 },
288};