wasmedge-hs-0.17.1.0: examples/Stress/WASILifecycle.hs
{-# LANGUAGE OverloadedStrings #-}
{- |
Module : Stress.WASILifecycle
Description : Full WASI module instance sandboxing and exit code lifecycle suite
Copyright : (c) 2026 Tushar Adhatrao
License : MIT
Stability : experimental
Exercises:
* 'createWASIModule' with custom args, envs, and preopens
* 'withWASIModule' scoped lifecycle
* 'initWASI' re-initialization
* 'getWASIExitCode'
* Registering WASI module into VM and Store
-}
module Stress.WASILifecycle
( runWASILifecycleSuite
, WASILifecycleMetrics (..)
) where
import Control.Monad (unless)
import Data.Word (Word32)
import System.Clock (Clock (Monotonic), diffTimeSpec, getTime, toNanoSecs)
import Text.Printf (printf)
import WasmEdge (createVM)
import WasmEdge.Module
( createWASIModule
, getModuleName
, getWASIExitCode
, initWASI
, withWASIModule
)
import WasmEdge.VM (deleteVM, registerModuleFromImport)
data WASILifecycleMetrics = WASILifecycleMetrics
{ wlmInitialExitCode :: !Word32
, wlmReinitExitCode :: !Word32
, wlmScopedSuccess :: !Bool
, wlmVMRegistrationOK :: !Bool
, wlmDurationSec :: !Double
}
deriving stock (Show)
runWASILifecycleSuite :: IO WASILifecycleMetrics
runWASILifecycleSuite = do
putStrLn "============================================================"
putStrLn " STRESS TEST: WASI Sandboxing, Exit Codes & Lifecycle"
putStrLn "============================================================"
t0 <- getTime Monotonic
-- 1. Create WASI module with custom environment and arguments
putStrLn "[1/4] Creating WASI module instance with custom args, envs, preopens..."
let args1 = ["my_guest_program", "--flag", "production_mode"]
envs1 = ["APP_ENV=prod", "LOG_LEVEL=info", "THREADS=8"]
preopens1 = [".:.", "/tmp:/tmp"]
wasiMod <- createWASIModule args1 envs1 preopens1
wasiModName <- getModuleName wasiMod
printf " WASI Module exported name: %s\n" (show wasiModName)
exitCode1 <- getWASIExitCode wasiMod
printf " Initial WASI exit code: %d\n" exitCode1
-- 2. Test re-initialization via initWASI
putStrLn "[2/4] Re-initializing WASI module via initWASI with new parameters..."
let args2 = ["my_guest_program", "--restarted", "true"]
envs2 = ["APP_ENV=staging", "RETRY_COUNT=3"]
preopens2 = ["/tmp:/tmp"]
initWASI wasiMod args2 envs2 preopens2
exitCode2 <- getWASIExitCode wasiMod
printf " Exit code after initWASI: %d\n" exitCode2
-- 3. Register WASI module into VM
putStrLn "[3/4] Registering WASI module into VM..."
vm <- createVM Nothing Nothing
resReg <- registerModuleFromImport vm wasiMod
regOK <- case resReg of
Left err -> fail $ "Failed to register WASI module into VM: " ++ show err
Right () -> do
putStrLn " WASI module registered into VM successfully."
deleteVM vm
pure True
-- 4. Scoped withWASIModule test
putStrLn "[4/4] Testing scoped withWASIModule..."
scopedOK <- withWASIModule ["scoped_app"] ["MODE=test"] [] $ \m -> do
code <- getWASIExitCode m
pure (code == 0 || code == 1 || code == 2) -- Valid exit code return
unless scopedOK $ fail "Scoped withWASIModule verification failed!"
putStrLn " Scoped withWASIModule completed successfully."
t1 <- getTime Monotonic
let dur = fromIntegral (toNanoSecs (diffTimeSpec t1 t0)) / 1e9 :: Double
printf ">>> WASI Lifecycle Suite completed in %.3f s\n\n" dur
pure
WASILifecycleMetrics
{ wlmInitialExitCode = exitCode1
, wlmReinitExitCode = exitCode2
, wlmScopedSuccess = scopedOK
, wlmVMRegistrationOK = regOK
, wlmDurationSec = dur
}