module Ribosome.Test.Await where import Hedgehog (TestT) import Control.Exception (throw) import Control.Monad.Error.Class (MonadError (throwError), catchError) import Hedgehog.Internal.Property (mkTestT, runTestT, Failure, Journal) import Ribosome.Control.Concurrent.Wait (WaitError(Thrown, ConditionUnmet, NotStarted), waitIODef) await :: ∀ e a b m . MonadError e m => MonadIO m => MonadBaseControl IO m => (a -> TestT m b) -> m a -> TestT m b await :: (a -> TestT m b) -> m a -> TestT m b await a -> TestT m b assertion m a acquire = do m (Either (WaitError (Either (Failure, Journal) e)) b) -> TestT m (Either (WaitError (Either (Failure, Journal) e)) b) forall (t :: (* -> *) -> * -> *) (m :: * -> *) a. (MonadTrans t, Monad m) => m a -> t m a lift (m (Either e a) -> (Either e a -> m (Either (Either (Failure, Journal) e) b)) -> m (Either (WaitError (Either (Failure, Journal) e)) b) forall (m :: * -> *) a e b. (MonadIO m, MonadBaseControl IO m) => m a -> (a -> m (Either e b)) -> m (Either (WaitError e) b) waitIODef m (Either e a) acquire' Either e a -> m (Either (Either (Failure, Journal) e) b) check') TestT m (Either (WaitError (Either (Failure, Journal) e)) b) -> (Either (WaitError (Either (Failure, Journal) e)) b -> TestT m b) -> TestT m b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Right b a -> b -> TestT m b forall (f :: * -> *) a. Applicative f => a -> f a pure b a Left (ConditionUnmet (Left (Failure err, Journal journal))) -> m (Either Failure b, Journal) -> TestT m b forall (m :: * -> *) a. m (Either Failure a, Journal) -> TestT m a mkTestT ((Either Failure b, Journal) -> m (Either Failure b, Journal) forall (f :: * -> *) a. Applicative f => a -> f a pure (Failure -> Either Failure b forall a b. a -> Either a b Left Failure err, Journal journal)) Left (ConditionUnmet (Right e e)) -> e -> TestT m b forall e (m :: * -> *) a. MonadError e m => e -> m a throwError e e Left (Thrown excp e) -> excp -> TestT m b forall a e. Exception e => e -> a throw excp e Left WaitError (Either (Failure, Journal) e) NotStarted -> String -> TestT m b forall (m :: * -> *) a. MonadFail m => String -> m a fail String "await was not started" where acquire' :: m (Either e a) acquire' :: m (Either e a) acquire' = m (Either e a) -> (e -> m (Either e a)) -> m (Either e a) forall e (m :: * -> *) a. MonadError e m => m a -> (e -> m a) -> m a catchError (a -> Either e a forall a b. b -> Either a b Right (a -> Either e a) -> m a -> m (Either e a) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> m a acquire) (Either e a -> m (Either e a) forall (f :: * -> *) a. Applicative f => a -> f a pure (Either e a -> m (Either e a)) -> (e -> Either e a) -> e -> m (Either e a) forall b c a. (b -> c) -> (a -> b) -> a -> c . e -> Either e a forall a b. a -> Either a b Left) check' :: Either e a -> m (Either (Either (Failure, Journal) e) b) check' :: Either e a -> m (Either (Either (Failure, Journal) e) b) check' (Right a a) = do (Either Failure b result, Journal journal) <- TestT m b -> m (Either Failure b, Journal) forall (m :: * -> *) a. TestT m a -> m (Either Failure a, Journal) runTestT (a -> TestT m b assertion a a) Either (Either (Failure, Journal) e) b -> m (Either (Either (Failure, Journal) e) b) forall (f :: * -> *) a. Applicative f => a -> f a pure ((Failure -> Either (Failure, Journal) e) -> Either Failure b -> Either (Either (Failure, Journal) e) b forall a c b. (a -> c) -> Either a b -> Either c b mapLeft ((Failure, Journal) -> Either (Failure, Journal) e forall a b. a -> Either a b Left ((Failure, Journal) -> Either (Failure, Journal) e) -> (Failure -> (Failure, Journal)) -> Failure -> Either (Failure, Journal) e forall b c a. (b -> c) -> (a -> b) -> a -> c . (,Journal journal)) Either Failure b result) check' (Left e e) = do Either (Either (Failure, Journal) e) b -> m (Either (Either (Failure, Journal) e) b) forall (f :: * -> *) a. Applicative f => a -> f a pure (Either (Failure, Journal) e -> Either (Either (Failure, Journal) e) b forall a b. a -> Either a b Left (e -> Either (Failure, Journal) e forall a b. b -> Either a b Right e e))