@@ -422,6 +422,102 @@ pub fn run_wasm_with_result(
422422 } )
423423}
424424
425+ /// Run a compiled WASM file using WasiRunner with a custom stdin.
426+ ///
427+ /// Useful for testing syscalls that block on stdin (e.g. fd_read): pass the
428+ /// receiving end of a `Pipe::channel()` and keep the sending end alive in the
429+ /// caller so that stdin never returns EOF while the guest is running.
430+ #[ allow( unused) ]
431+ pub fn run_wasm_with_stdin (
432+ wasm_path : & PathBuf ,
433+ dir : & Path ,
434+ stdin : Box < dyn wasmer_wasix:: VirtualFile + Send + Sync > ,
435+ ) -> Result < WasmRunResult , anyhow:: Error > {
436+ let wasm_bytes = std:: fs:: read ( wasm_path) ?;
437+ let engine = create_engine_for_wasm ( & wasm_bytes) ;
438+ let module_data = HashedModuleData :: new ( wasm_bytes) ;
439+ let hash = * module_data. hash ( ) ;
440+
441+ let stdout_buffer = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
442+ let stderr_buffer = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
443+ let stdout_capture = Box :: new ( CaptureFile :: new ( stdout_buffer. clone ( ) ) ) ;
444+ let stderr_capture = Box :: new ( CaptureFile :: new ( stderr_buffer. clone ( ) ) ) ;
445+
446+ let rt = create_runtime ( ) ;
447+ let result = rt. block_on ( async {
448+ let cache_dir = get_cache_dir ( ) ;
449+ std:: fs:: create_dir_all ( & cache_dir) . ok ( ) ;
450+
451+ let rt_handle = wasmer_wasix:: runtime:: task_manager:: tokio:: RuntimeOrHandle :: Handle (
452+ tokio:: runtime:: Handle :: current ( ) ,
453+ ) ;
454+ let tokio_task_manager =
455+ Arc :: new ( wasmer_wasix:: runtime:: task_manager:: tokio:: TokioTaskManager :: new ( rt_handle) ) ;
456+ let module_cache = wasmer_wasix:: runtime:: module_cache:: SharedCache :: default ( )
457+ . with_fallback ( wasmer_wasix:: runtime:: module_cache:: FileSystemCache :: new (
458+ cache_dir,
459+ tokio_task_manager,
460+ ) ) ;
461+ let arc_cache = Arc :: new ( module_cache) ;
462+
463+ let module = wasmer_wasix:: runtime:: load_module (
464+ & engine,
465+ & arc_cache,
466+ wasmer_wasix:: runtime:: ModuleInput :: Hashed ( Cow :: Borrowed ( & module_data) ) ,
467+ None ,
468+ )
469+ . await
470+ . map_err ( |e| anyhow:: anyhow!( "Failed to load module: {}" , e) ) ?;
471+
472+ tokio:: task:: block_in_place ( move || {
473+ let mut runner = WasiRunner :: new ( ) ;
474+ runner
475+ . with_mapped_directories ( [ MappedDirectory {
476+ guest : dir. to_string_lossy ( ) . to_string ( ) ,
477+ host : dir. to_path_buf ( ) ,
478+ } ] )
479+ . with_mapped_directories ( [ MappedDirectory {
480+ guest : "/lib" . to_string ( ) ,
481+ host : dir. to_path_buf ( ) ,
482+ } ] )
483+ . with_current_dir ( dir. to_string_lossy ( ) . to_string ( ) )
484+ . with_stdin ( stdin)
485+ . with_stdout ( stdout_capture)
486+ . with_stderr ( stderr_capture) ;
487+ runner. run_wasm (
488+ RuntimeOrEngine :: Engine ( engine) ,
489+ wasm_path. to_string_lossy ( ) . as_ref ( ) ,
490+ module,
491+ hash,
492+ )
493+ } )
494+ } ) ;
495+
496+ let stdout = stdout_buffer. lock ( ) . unwrap ( ) . clone ( ) ;
497+ let stderr = stderr_buffer. lock ( ) . unwrap ( ) . clone ( ) ;
498+ let exit_code = match & result {
499+ Ok ( _) => Some ( 0 ) ,
500+ Err ( e) => {
501+ let error_msg = e. to_string ( ) ;
502+ if let Some ( code_str) = error_msg. split ( "ExitCode::" ) . nth ( 1 ) {
503+ if let Some ( code) = code_str. split_whitespace ( ) . next ( ) {
504+ code. parse :: < i32 > ( ) . ok ( )
505+ } else {
506+ None
507+ }
508+ } else {
509+ None
510+ }
511+ }
512+ } ;
513+
514+ Ok ( WasmRunResult {
515+ stdout,
516+ stderr,
517+ exit_code,
518+ } )
519+ }
520+
425521/// Run a compiled WASM file using WasiRunner
426522#[ allow( unused) ]
427523pub fn run_wasm ( wasm_path : & PathBuf , dir : & Path ) -> Result < ( ) , anyhow:: Error > {
0 commit comments