BoundaryTests.hs (2360B)
1 {-# LANGUAGE ScopedTypeVariables #-} 2 -- Inject bottoms through the Haskell-side registry for boundary fault tests. 3 module Main where 4 import qualified EmbeddingCore as E 5 import qualified Embedding as Host 6 import Control.Monad (unless) 7 import Control.Monad.IO.Class (liftIO) 8 import Control.Concurrent 9 import Runtime.Tree (T(..)) 10 import Runtime.Value (ofString, ofNumber) 11 import Foreign 12 import Data.Word 13 import Control.Exception (evaluate) 14 15 assert :: Bool -> IO () 16 assert ok = unless ok (fail "embedding boundary assertion failed") 17 main :: IO () 18 main = alloca $ \ctxOut -> alloca $ \out -> do 19 E.contextNew ctxOut >>= assert . (== 0) 20 ctx <- peek ctxOut 21 E.withContext ctx (E.publish out (error "boundary poison")) >>= assert . (== 0) 22 poison <- peek out 23 poke out 987 24 E.reduce ctx poison out >>= assert . (== 5) 25 peek out >>= assert . (== 987) 26 -- Even application of a bottom function is suspended by the boundary. 27 E.application ctx poison poison out >>= assert . (== 0) 28 suspended <- peek out 29 E.release ctx suspended >>= assert . (== 0) 30 E.leaf ctx out >>= assert . (== 0) 31 leaf <- peek out 32 E.fork ctx leaf leaf out >>= assert . (== 0) 33 constant <- peek out 34 E.application ctx constant poison out >>= assert . (== 0) 35 discarded <- peek out 36 E.reduce ctx discarded out >>= assert . (== 0) 37 value <- peek out 38 E.toU64 ctx value out >>= assert . (== 0) 39 peek out >>= assert . (== (0 :: Word64)) 40 41 -- Terminal task diagnostics remain opaque across the native boundary. 42 E.withContext ctx (E.publish out 43 (Fork (ofString "tricuIO") (Fork (ofNumber 2) 44 (Fork (ofNumber 2) (error "opaque diagnostic"))))) >>= assert . (== 0) 45 program <- peek out 46 alloca $ \tag -> alloca $ \reason -> alloca $ \cleanup -> do 47 Host.runIO ctx program tag reason cleanup >>= assert . (== 0) 48 peek tag >>= assert . (== 1) 49 failed <- peek reason 50 E.reduce ctx failed out >>= assert . (== 5) 51 -- An interrupted call restores the context lock and contains its exception. 52 entered <- newEmptyMVar 53 done <- newEmptyMVar 54 thread <- forkIO $ E.withContext ctx (do 55 liftIO (putMVar entered () >> threadDelay 10000000) 56 pure (pure ())) >>= putMVar done 57 takeMVar entered 58 killThread thread 59 takeMVar done >>= assert . (== 5) 60 E.leaf ctx out >>= assert . (== 0) 61 E.contextFree ctx >>= assert . (== 0) 62 _ <- evaluate poison 63 pure ()