packages feed

oath-0.0: tests/test.hs

import qualified Oath
import qualified Futures
import qualified Control.Concurrent.Promise.Unsafe as UP
import qualified Control.Concurrent.Promise as Promise
import qualified Control.Concurrent.Async as Async
import Control.Applicative
import Control.Concurrent
import Control.Exception
import Data.Functor.Compose
import qualified Streamly.Prelude as S

action :: Int -> String -> Double -> IO ()
action order name dur = do
  -- delay a bit so that "Begin" gets printed in a consistent order
  threadDelay $ 1000 * 10 * order
  putStrLn $ "    Begin " <> name
  threadDelay (floor $ 1000000 * dur)
  putStrLn $ "    End " <> name
  `onException` putStrLn ("    Killed " <> name)

tester :: Applicative m => (m () -> IO ()) -> (IO () -> m ()) -> IO ()
tester run lift = do
  putStrLn "  Left:"
  run $ (lift (action 0 "foo" 0.1) *> lift (action 1 "bar" 0.3)) *> lift (action 2 "baz" 0.2)
  putStrLn "  Right:"
  run $ lift (action 0 "foo" 0.1) *> (lift (action 1 "bar" 0.3) *> lift (action 2 "baz" 0.2))

  putStrLn "  Left Error:"
  try (run $ lift (fail "Fail") *> lift (action 0 "success" 0.1)) >>= print'
  putStrLn "  Right Error:"
  try (run $ lift (action 0 "success" 0.1) *> lift (fail "Fail")) >>= print'
  where
    print' :: Either SomeException () -> IO ()
    print' = putStrLn . ("    "++) . show

main :: IO ()
main = do
  putStrLn "oath timeout:"
  Oath.evalOath $ Oath.oath (action 0 "delay" 1.0) <|> Oath.delay 200000
  threadDelay 10000

  putStrLn "oath: "
  tester Oath.evalOath Oath.oath
  putStrLn "async: "
  tester Async.runConcurrently Async.Concurrently
  putStrLn "futures:"
  tester ((>>=Futures.block) . getCompose) (Compose . Futures.fork)

  putStrLn "streamly:"
  tester (S.drain . S.fromZipAsync . S.fromAhead) S.fromEffect

  putStrLn "promise:"
  tester Promise.runPromise Promise.liftIO

  -- random
  putStrLn "unsafe-promises:"
  try (tester id UP.promise) >>= (print :: Either SomeException () -> IO ())