seakale-tests-0.1.0.0: src/Database/Seakale/Tests/Request.hs
module Database.Seakale.Tests.Request
( RequestMock
, mockMatchingQuery
, mockMatchingExecute
, mockQuery
, mockExecute
, runRequestT
, runRequest
, runRequestT'
, runRequest'
, module Database.Seakale.Tests.Mock
) where
import Control.Monad.Identity
import Control.Monad.State
import Control.Monad.Trans.Free
import qualified Control.Monad.Except as E
import Data.Monoid
import qualified Data.ByteString.Lazy as BSL
import Database.Seakale.Request.Internal
hiding (runRequestT, runRequest)
import Database.Seakale.Types hiding (runQuery, runExecute)
import Database.Seakale.Tests.Mock
data RequestMock backend
= MockQuery QueryPredicate ([ColumnInfo backend], [Row backend])
| MockExecute QueryPredicate Integer
mockMatchingQuery :: (BSL.ByteString -> Bool)
-> ([ColumnInfo backend], [Row backend])
-> Mock (RequestMock backend) ()
mockMatchingQuery f dat = Action $ MockQuery (QPredFunction f) dat
mockMatchingExecute :: (BSL.ByteString -> Bool) -> Integer
-> Mock (RequestMock backend) ()
mockMatchingExecute f i = Action $ MockExecute (QPredFunction f) i
mockQuery :: BSL.ByteString -> ([ColumnInfo backend], [Row backend])
-> Mock (RequestMock backend) ()
mockQuery req dat = Action $ MockQuery (QPredPlain req) dat
mockExecute :: BSL.ByteString -> Integer -> Mock (RequestMock backend) ()
mockExecute req i = Action $ MockExecute (QPredPlain req) i
runQuery :: BSL.ByteString -> Mock (RequestMock backend) a
-> Maybe ( ([ColumnInfo backend], [Row backend])
, Mock (RequestMock backend) a )
runQuery req = consumeMock $ \case
MockQuery p cr | runQueryPredicate p req -> Just cr
_ -> Nothing
runExecute :: BSL.ByteString -> Mock (RequestMock backend) a
-> Maybe (Integer, Mock (RequestMock backend) a)
runExecute req = consumeMock $ \case
MockExecute p i | runQueryPredicate p req -> Just i
_ -> Nothing
runRequestT :: Monad m => backend -> Mock (RequestMock backend) b
-> RequestT backend m a -> m (Either SeakaleError a)
runRequestT b m = fmap fst . runRequestT' b m
runRequest :: backend -> Mock (RequestMock backend) b -> Request backend a
-> Either SeakaleError a
runRequest b m = fst . runRequest' b m
runRequestT' :: Monad m => backend -> Mock (RequestMock backend) b
-> RequestT backend m a
-> m (Either SeakaleError a, Mock (RequestMock backend) b)
runRequestT' b m =
flip runStateT m . E.runExceptT . iterT (interpreter b)
. hoistFreeT (lift . lift)
where
interpreter :: Monad m => backend
-> RequestF backend
(E.ExceptT SeakaleError
(StateT (Mock (RequestMock backend) b) m) a)
-> E.ExceptT SeakaleError
(StateT (Mock (RequestMock backend) b) m) a
interpreter backend = \case
Query req f -> do
mock <- get
case runQuery req mock of
Nothing -> E.throwError $ BackendError $
"no mock found for Query on " <> BSL.toStrict req
Just (res, mock') -> put mock' >> f res
Execute req f -> do
mock <- get
case runExecute req mock of
Nothing -> E.throwError $ BackendError $
"no mock found for Execute on " <> BSL.toStrict req
Just (res, mock') -> put mock' >> f res
GetBackend f -> f backend
ThrowError err -> E.throwError err
CatchError action handler -> E.catchError action handler
runRequest' :: backend -> Mock (RequestMock backend) b -> Request backend a
-> (Either SeakaleError a, Mock (RequestMock backend) b)
runRequest' backend mock = runIdentity . runRequestT' backend mock