mealstrom-0.0.1.0: test/CounterFSM.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-|
Module : CounterFSM
Description : Show how to "compress" multiple events into one.
Copyright : (c) Max Amanshauser, 2016
License : MIT
Maintainer : max@lambdalifting.org
After this test has run the DB table should show a "Count" entry
instead of ten individual Desu events.
-}
module CounterFSM (runCounterTests) where
import Test.Tasty
import Test.Tasty.HUnit
import Control.Concurrent
import Control.Monad
import Data.Aeson
import Data.Text
import Data.Typeable
import GHC.Generics
import Data.UUID
import Data.UUID.V4
import Mealstrom
import Mealstrom.PostgresJSONStore as PGJSON
import Mealstrom.MemoryStore as MemStore
type CounterKey = UUID
data CounterState = Desu
deriving (Eq,Show,Typeable)
instance ToJSON CounterState where
toJSON _ = "Desu"
instance FromJSON CounterState where
parseJSON "Desu" = return Desu
data CounterEvent = DesuEvent
deriving (Eq,Show,Typeable)
instance ToJSON CounterEvent where
toJSON _ = "DesuEvent"
instance FromJSON CounterEvent where
parseJSON "DesuEvent" = return DesuEvent
-- NOP
data CounterAction = DesuDummyAction
deriving (Eq,Show,Typeable,Generic)
instance ToJSON CounterAction where
toJSON _ = "DesuDummyAction"
instance FromJSON CounterAction where
parseJSON "DesuDummyAction" = return DesuDummyAction
instance MealyInstance CounterKey CounterState CounterEvent CounterAction
counterTransition :: (CounterState, CounterEvent) -> (CounterState,[CounterAction])
counterTransition =
\case (Desu, DesuEvent) -> (Desu,[DesuDummyAction])
counterEffects :: MVar () -> Msg CounterAction -> IO Bool
counterEffects mvar _ =
putMVar mvar () >> return True
runCounterTests :: String -> TestTree
runCounterTests c = testGroup "CounterFSM" [
testCase "CounterPG" (runTest $ PGJSON.mkStore c),
testCase "CounterMem" (runTest (MemStore.mkStore :: Text -> IO (MemoryStore CounterKey CounterState CounterEvent CounterAction)))
]
runTest c = do
sync <- newEmptyMVar
st <- c "CounterTest"
let t = FSMTable counterTransition (counterEffects sync)
let fsm = FSMHandle st st t 900 3
i <- nextRandom
post fsm i Desu
replicateM_ 10 (do
m <- mkMsgs [DesuEvent]
_ <- patch fsm i m
takeMVar sync)
s <- get fsm i
s @?= Just Desu