Skip to content
File

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

javascript524 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 * as wasi from 'node:wasi';
5import { strictEqual, deepStrictEqual, throws } from 'node:assert';
6 
7export const wasiTest = {
8 test() {
9 // Note: test was generated by claude with manual tweaks
10 
11 // Test that WASI class exists and is a constructor
12 strictEqual(typeof wasi.WASI, 'function');
13 
14 // Test constructor with default options - should throw ERR_METHOD_NOT_IMPLEMENTED
15 throws(
16 () => {
17 new wasi.WASI();
18 },
19 {
20 code: 'ERR_METHOD_NOT_IMPLEMENTED',
21 }
22 );
23 
24 // Test constructor with minimal valid options - should throw ERR_METHOD_NOT_IMPLEMENTED
25 throws(
26 () => {
27 new wasi.WASI({ version: 'unstable' });
28 },
29 {
30 code: 'ERR_METHOD_NOT_IMPLEMENTED',
31 }
32 );
33 
34 throws(
35 () => {
36 new wasi.WASI({ version: 'preview1' });
37 },
38 {
39 code: 'ERR_METHOD_NOT_IMPLEMENTED',
40 }
41 );
42 
43 // Test constructor argument validation - options must be an object
44 throws(
45 () => {
46 new wasi.WASI('invalid');
47 },
48 {
49 code: 'ERR_INVALID_ARG_TYPE',
50 }
51 );
52 
53 throws(
54 () => {
55 new wasi.WASI(null);
56 },
57 {
58 code: 'ERR_INVALID_ARG_TYPE',
59 }
60 );
61 
62 throws(
63 () => {
64 new wasi.WASI(123);
65 },
66 {
67 code: 'ERR_INVALID_ARG_TYPE',
68 }
69 );
70 
71 // Test version validation - must be 'unstable' or 'preview1'
72 throws(
73 () => {
74 new wasi.WASI({ version: 'invalid' });
75 },
76 {
77 code: 'ERR_INVALID_ARG_VALUE',
78 }
79 );
80 
81 throws(
82 () => {
83 new wasi.WASI({ version: 'v1' });
84 },
85 {
86 code: 'ERR_INVALID_ARG_VALUE',
87 }
88 );
89 
90 throws(
91 () => {
92 new wasi.WASI({ version: null });
93 },
94 {
95 code: 'ERR_INVALID_ARG_VALUE',
96 }
97 );
98 
99 throws(
100 () => {
101 new wasi.WASI({ version: 123 });
102 },
103 {
104 code: 'ERR_INVALID_ARG_VALUE',
105 }
106 );
107 
108 // Test args validation - must be an array if provided
109 throws(
110 () => {
111 new wasi.WASI({ version: 'unstable', args: 'invalid' });
112 },
113 {
114 code: 'ERR_INVALID_ARG_TYPE',
115 }
116 );
117 
118 throws(
119 () => {
120 new wasi.WASI({ version: 'unstable', args: {} });
121 },
122 {
123 code: 'ERR_INVALID_ARG_TYPE',
124 }
125 );
126 
127 throws(
128 () => {
129 new wasi.WASI({ version: 'unstable', args: 123 });
130 },
131 {
132 code: 'ERR_INVALID_ARG_TYPE',
133 }
134 );
135 
136 // Test valid args - should still throw ERR_METHOD_NOT_IMPLEMENTED but after validation
137 throws(
138 () => {
139 new wasi.WASI({ version: 'unstable', args: [] });
140 },
141 {
142 code: 'ERR_METHOD_NOT_IMPLEMENTED',
143 }
144 );
145 
146 throws(
147 () => {
148 new wasi.WASI({ version: 'unstable', args: ['arg1', 'arg2'] });
149 },
150 {
151 code: 'ERR_METHOD_NOT_IMPLEMENTED',
152 }
153 );
154 
155 // Test env validation - must be an object if provided
156 throws(
157 () => {
158 new wasi.WASI({ version: 'unstable', env: 'invalid' });
159 },
160 {
161 code: 'ERR_INVALID_ARG_TYPE',
162 }
163 );
164 
165 throws(
166 () => {
167 new wasi.WASI({ version: 'unstable', env: [] });
168 },
169 {
170 code: 'ERR_INVALID_ARG_TYPE',
171 }
172 );
173 
174 throws(
175 () => {
176 new wasi.WASI({ version: 'unstable', env: 123 });
177 },
178 {
179 code: 'ERR_INVALID_ARG_TYPE',
180 }
181 );
182 
183 // Test valid env - should still throw ERR_METHOD_NOT_IMPLEMENTED but after validation
184 throws(
185 () => {
186 new wasi.WASI({ version: 'unstable', env: {} });
187 },
188 {
189 code: 'ERR_METHOD_NOT_IMPLEMENTED',
190 }
191 );
192 
193 throws(
194 () => {
195 new wasi.WASI({ version: 'unstable', env: { PATH: '/usr/bin' } });
196 },
197 {
198 code: 'ERR_METHOD_NOT_IMPLEMENTED',
199 }
200 );
201 
202 // Test preopens validation - must be an object if provided
203 throws(
204 () => {
205 new wasi.WASI({ version: 'unstable', preopens: 'invalid' });
206 },
207 {
208 code: 'ERR_INVALID_ARG_TYPE',
209 }
210 );
211 
212 throws(
213 () => {
214 new wasi.WASI({ version: 'unstable', preopens: [] });
215 },
216 {
217 code: 'ERR_INVALID_ARG_TYPE',
218 }
219 );
220 
221 throws(
222 () => {
223 new wasi.WASI({ version: 'unstable', preopens: 123 });
224 },
225 {
226 code: 'ERR_INVALID_ARG_TYPE',
227 }
228 );
229 
230 // Test valid preopens - should still throw ERR_METHOD_NOT_IMPLEMENTED but after validation
231 throws(
232 () => {
233 new wasi.WASI({ version: 'unstable', preopens: {} });
234 },
235 {
236 code: 'ERR_METHOD_NOT_IMPLEMENTED',
237 }
238 );
239 
240 throws(
241 () => {
242 new wasi.WASI({ version: 'unstable', preopens: { '/': '.' } });
243 },
244 {
245 code: 'ERR_METHOD_NOT_IMPLEMENTED',
246 }
247 );
248 
249 // Test stdin validation - must be a valid int32 >= 0
250 throws(
251 () => {
252 new wasi.WASI({ version: 'unstable', stdin: -1 });
253 },
254 {
255 code: 'ERR_OUT_OF_RANGE',
256 }
257 );
258 
259 throws(
260 () => {
261 new wasi.WASI({ version: 'unstable', stdin: 'invalid' });
262 },
263 {
264 code: 'ERR_INVALID_ARG_TYPE',
265 }
266 );
267 
268 throws(
269 () => {
270 new wasi.WASI({ version: 'unstable', stdin: 2147483648 }); // > MAX_INT32
271 },
272 {
273 code: 'ERR_OUT_OF_RANGE',
274 }
275 );
276 
277 // Test valid stdin values - should still throw ERR_METHOD_NOT_IMPLEMENTED but after validation
278 throws(
279 () => {
280 new wasi.WASI({ version: 'unstable', stdin: 0 });
281 },
282 {
283 code: 'ERR_METHOD_NOT_IMPLEMENTED',
284 }
285 );
286 
287 throws(
288 () => {
289 new wasi.WASI({ version: 'unstable', stdin: 3 });
290 },
291 {
292 code: 'ERR_METHOD_NOT_IMPLEMENTED',
293 }
294 );
295 
296 // Test stdout validation - must be a valid int32 >= 0
297 throws(
298 () => {
299 new wasi.WASI({ version: 'unstable', stdout: -1 });
300 },
301 {
302 code: 'ERR_OUT_OF_RANGE',
303 }
304 );
305 
306 throws(
307 () => {
308 new wasi.WASI({ version: 'unstable', stdout: 'invalid' });
309 },
310 {
311 code: 'ERR_INVALID_ARG_TYPE',
312 }
313 );
314 
315 // Test valid stdout values
316 throws(
317 () => {
318 new wasi.WASI({ version: 'unstable', stdout: 1 });
319 },
320 {
321 code: 'ERR_METHOD_NOT_IMPLEMENTED',
322 }
323 );
324 
325 // Test stderr validation - must be a valid int32 >= 0
326 throws(
327 () => {
328 new wasi.WASI({ version: 'unstable', stderr: -1 });
329 },
330 {
331 code: 'ERR_OUT_OF_RANGE',
332 }
333 );
334 
335 throws(
336 () => {
337 new wasi.WASI({ version: 'unstable', stderr: 'invalid' });
338 },
339 {
340 code: 'ERR_INVALID_ARG_TYPE',
341 }
342 );
343 
344 // Test valid stderr values
345 throws(
346 () => {
347 new wasi.WASI({ version: 'unstable', stderr: 2 });
348 },
349 {
350 code: 'ERR_METHOD_NOT_IMPLEMENTED',
351 }
352 );
353 
354 // Test returnOnExit validation - must be a boolean if provided
355 throws(
356 () => {
357 new wasi.WASI({ version: 'unstable', returnOnExit: 'invalid' });
358 },
359 {
360 code: 'ERR_INVALID_ARG_TYPE',
361 }
362 );
363 
364 throws(
365 () => {
366 new wasi.WASI({ version: 'unstable', returnOnExit: 1 });
367 },
368 {
369 code: 'ERR_INVALID_ARG_TYPE',
370 }
371 );
372 
373 throws(
374 () => {
375 new wasi.WASI({ version: 'unstable', returnOnExit: {} });
376 },
377 {
378 code: 'ERR_INVALID_ARG_TYPE',
379 }
380 );
381 
382 // Test valid returnOnExit values
383 throws(
384 () => {
385 new wasi.WASI({ version: 'unstable', returnOnExit: true });
386 },
387 {
388 code: 'ERR_METHOD_NOT_IMPLEMENTED',
389 }
390 );
391 
392 throws(
393 () => {
394 new wasi.WASI({ version: 'unstable', returnOnExit: false });
395 },
396 {
397 code: 'ERR_METHOD_NOT_IMPLEMENTED',
398 }
399 );
400 
401 // Test complex valid options combination
402 throws(
403 () => {
404 new wasi.WASI({
405 version: 'preview1',
406 args: ['node', 'script.js'],
407 env: { NODE_ENV: 'production' },
408 preopens: { '/tmp': '/tmp' },
409 stdin: 0,
410 stdout: 1,
411 stderr: 2,
412 returnOnExit: true,
413 });
414 },
415 {
416 code: 'ERR_METHOD_NOT_IMPLEMENTED',
417 }
418 );
419 
420 // Test that getImportObject can be called on prototype (even though we can't instantiate)
421 strictEqual(typeof wasi.WASI.prototype.getImportObject, 'function');
422 
423 // Test getImportObject returns empty object
424 const importObject = wasi.WASI.prototype.getImportObject.call({});
425 strictEqual(typeof importObject, 'object');
426 deepStrictEqual(importObject, {});
427 
428 // Test that other methods exist on prototype
429 strictEqual(typeof wasi.WASI.prototype.finalizeBindings, 'function');
430 strictEqual(typeof wasi.WASI.prototype.start, 'function');
431 strictEqual(typeof wasi.WASI.prototype.initialize, 'function');
432 
433 // Test that other methods throw ERR_METHOD_NOT_IMPLEMENTED when called on prototype
434 throws(
435 () => {
436 wasi.WASI.prototype.finalizeBindings.call({}, {});
437 },
438 {
439 code: 'ERR_METHOD_NOT_IMPLEMENTED',
440 }
441 );
442 
443 throws(
444 () => {
445 wasi.WASI.prototype.start.call({}, {});
446 },
447 {
448 code: 'ERR_METHOD_NOT_IMPLEMENTED',
449 }
450 );
451 
452 throws(
453 () => {
454 wasi.WASI.prototype.initialize.call({}, {});
455 },
456 {
457 code: 'ERR_METHOD_NOT_IMPLEMENTED',
458 }
459 );
460 
461 // Test finalizeBindings with various parameters
462 throws(
463 () => {
464 wasi.WASI.prototype.finalizeBindings.call({}, {}, {});
465 },
466 {
467 code: 'ERR_METHOD_NOT_IMPLEMENTED',
468 }
469 );
470 
471 throws(
472 () => {
473 wasi.WASI.prototype.finalizeBindings.call({}, {}, { memory: null });
474 },
475 {
476 code: 'ERR_METHOD_NOT_IMPLEMENTED',
477 }
478 );
479 
480 // Test default export
481 strictEqual(typeof wasi.default, 'object');
482 strictEqual(wasi.default.WASI, wasi.WASI);
483 
484 // Test edge cases with undefined/null in options
485 throws(
486 () => {
487 new wasi.WASI({ version: 'unstable', args: undefined }); // undefined should be ok
488 },
489 {
490 code: 'ERR_METHOD_NOT_IMPLEMENTED',
491 }
492 );
493 
494 throws(
495 () => {
496 new wasi.WASI({ version: 'unstable', env: undefined }); // undefined should be ok
497 },
498 {
499 code: 'ERR_METHOD_NOT_IMPLEMENTED',
500 }
501 );
502 
503 throws(
504 () => {
505 new wasi.WASI({ version: 'unstable', preopens: undefined }); // undefined should be ok
506 },
507 {
508 code: 'ERR_METHOD_NOT_IMPLEMENTED',
509 }
510 );
511 
512 throws(
513 () => {
514 new wasi.WASI({ version: 'unstable', returnOnExit: undefined }); // undefined should be ok
515 },
516 {
517 code: 'ERR_METHOD_NOT_IMPLEMENTED',
518 }
519 );
520 
521 console.log('All wasi module tests passed!');
522 },
523};