{-# LANGUAGE UndecidableInstances #-}
module GenServerTests
( test_genServer,
)
where
import Common
import Control.Eff.Concurrent.Protocol.Broker as Broker
import qualified Control.Eff.Concurrent.Protocol.EffectfulServer as E
import qualified Control.Eff.Concurrent.Protocol.StatefulServer as S
import Data.Coerce (coerce)
-- ------------------------------
data Small deriving (Typeable)
instance HasPdu Small where
data Pdu Small r where
SmallCall :: Bool -> Pdu Small ('Synchronous Bool)
SmallCast :: String -> Pdu Small 'Asynchronous
deriving (Typeable)
instance NFData (Pdu Small r) where
rnf (SmallCall x) = rnf x
rnf (SmallCast x) = rnf x
instance ToLogMsg (Pdu Small r) where
toLogMsg (SmallCall x) = "SmallCall " <> toLogMsg x
toLogMsg (SmallCast x) = "SmallCast " <> toLogMsg x
-- ----------------------------------------------------------------------------
instance ToTypeLogMsg Small where
toTypeLogMsg _ = "Small"
instance IoLogging e => S.Server Small (Processes e) where
data StartArgument Small = MkSmall deriving (Show)
newtype Model Small = SmallModel String deriving (Default)
update _me MkSmall x =
case x of
E.OnCall rt (SmallCall f) ->
do
S.modifyModel (\(SmallModel y) -> SmallModel (y ++ ", " ++ show f))
sendReply rt f
E.OnCast msg ->
logInfo msg
other ->
interrupt (ErrorInterrupt (toLogMsg other))
instance ToLogMsg (S.StartArgument Small)
-- ----------------------------------------------------------------------------
data Big deriving (Typeable)
instance ToTypeLogMsg Big where
toTypeLogMsg _ = "Big"
instance HasPdu Big where
type EmbeddedPduList Big = '[Small]
data Pdu Big r where
BigCall :: Bool -> Pdu Big ('Synchronous Bool)
BigCast :: String -> Pdu Big 'Asynchronous
BigSmall :: Pdu Small r -> Pdu Big r
deriving (Typeable)
instance NFData (Pdu Big r) where
rnf (BigCall x) = rnf x
rnf (BigCast x) = rnf x
rnf (BigSmall x) = rnf x
instance ToLogMsg (Pdu Big r) where
toLogMsg (BigCall x) = "SmallCall " <> toLogMsg x
toLogMsg (BigCast x) = "SmallCast " <> toLogMsg x
toLogMsg (BigSmall x) = "BigSmall " <> toLogMsg x
instance HasPduPrism Big Small where
embedPdu = BigSmall
fromPdu (BigSmall x) = Just x
fromPdu _ = Nothing
-- ----------------------------------------------------------------------------
instance IoLogging e => S.Server Big (Processes e) where
data StartArgument Big = MkBig deriving (Show)
newtype Model Big = BigModel String deriving (Default)
update me MkBig = \case
E.OnCall rt req ->
case req of
BigCall o -> do
logNotice (LABEL "BigCall" o)
sendReply rt o
BigSmall x ->
S.coerceEffects
( S.update
(coerce me)
MkSmall
(S.OnCall (toEmbeddedReplyTarget rt) x)
)
E.OnCast req ->
case req of
BigCast o -> S.putModel (BigModel o)
BigSmall x -> S.coerceEffects (S.update (coerce me) MkSmall (S.OnCast x))
other ->
interrupt (ErrorInterrupt (toLogMsg other))
instance ToLogMsg (StartArgument Big)
-- ----------------------------------------------------------------------------
test_genServer :: HasCallStack => TestTree
test_genServer =
setTravisTestOptions $
testGroup
"Server"
[ runTestCase "When a server is started it handles call Pdus without dieing" $ do
big <- S.startLink MkBig
call big (BigCall True) >>= lift . assertBool "invalid result 1"
isProcessAlive (_fromEndpoint big) >>= lift . assertBool "process dead"
call big (BigCall False) >>= lift . assertBool "invalid result 2" . not
isProcessAlive (_fromEndpoint big) >>= lift . assertBool "process dead"
cast big (BigCast "rezo")
isProcessAlive (_fromEndpoint big) >>= lift . assertBool "process dead"
cast big (BigSmall (SmallCast "yo diggi"))
isProcessAlive (_fromEndpoint big) >>= lift . assertBool "process dead"
call big (BigSmall (SmallCall False)) >>= lift . assertBool "invalid result 3" . not
isProcessAlive (_fromEndpoint big) >>= lift . assertBool "process dead"
]