symbiote-0.0.2: test/Spec/Protocol.hs
{-# LANGUAGE
MultiParamTypeClasses
, TypeFamilies
, FlexibleInstances
, FlexibleContexts
, OverloadedStrings
#-}
module Spec.Protocol where
import qualified Data.Aeson as Json
import qualified Data.Aeson.Types as Json
import qualified Data.Serialize as Cereal
import qualified Data.Serialize.Get as Cereal
import qualified Data.Serialize.Put as Cereal
import qualified Data.ByteString as BS
import Data.Proxy
import Control.Monad.IO.Class (liftIO)
import Test.Serialization.Symbiote
(SymbioteOperation (..), Generating, Operating, First, Second, Topic, SymbioteT, register)
import Test.Serialization.Symbiote.Debug (Debug (..))
import Test.Serialization.Symbiote.WebSocket (firstPeerWebSocketJson, firstPeerWebSocketByteString)
import Test.Serialization.Symbiote.ZeroMQ (firstPeerZeroMQ)
import Test.Serialization.Symbiote.Aeson ()
import Test.Serialization.Symbiote.Cereal ()
import Test.QuickCheck (Arbitrary (..))
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (testCase)
import Network.WebSockets.Connection (defaultConnectionOptions)
import Network.WebSockets.Simple (accept)
import Network.WebSockets.Trans (runServerAppT)
import Network.Wai (responseLBS)
import Network.Wai.Handler.WebSockets (websocketsOr)
import Network.Wai.Handler.Warp (run)
import Network.Wai.Middleware.RequestLogger (logStdoutDev)
import Network.HTTP.Types (status400)
protocolTests :: [TestTree]
protocolTests =
[ testGroup "WebSocket Server"
[ testCase "Json" $
let tests :: SymbioteT Json.Value IO ()
tests = do
register "Generating Topic" 100 (Proxy :: Proxy (Generating Topic))
register "Operating Topic" 100 (Proxy :: Proxy (Operating Topic))
register "First Topic" 100 (Proxy :: Proxy (First Topic))
register "Second Topic" 100 (Proxy :: Proxy (Second Topic))
register "Topic" 100 (Proxy :: Proxy Topic)
runClient client = do
-- runServer "localhost" 3000 server'
let server = accept client
server' <- runServerAppT server
liftIO $ run 3000 $ logStdoutDev $ websocketsOr defaultConnectionOptions server' $ \_ respond ->
respond $ responseLBS status400 [] "Not a websocket"
in firstPeerWebSocketJson runClient NoDebug tests
, testCase "ByteString" $
let tests :: SymbioteT BS.ByteString IO ()
tests = do
register "Generating ByteString" 50 (Proxy :: Proxy (Generating BS.ByteString))
register "Operating ByteString" 50 (Proxy :: Proxy (Operating BS.ByteString))
register "First ByteString" 50 (Proxy :: Proxy (First BS.ByteString))
register "Second ByteString" 50 (Proxy :: Proxy (Second BS.ByteString))
register "Topic" 50 (Proxy :: Proxy Topic)
runClient client = do
-- runServer "localhost" 3000 server'
let server = accept client
server' <- runServerAppT server
liftIO $ run 3001 $ logStdoutDev $ websocketsOr defaultConnectionOptions server' $ \_ respond ->
respond $ responseLBS status400 [] "Not a websocket"
in firstPeerWebSocketByteString runClient NoDebug tests
]
, testGroup "ZeroMQ Server"
[ testCase "ByteString" $
let tests :: SymbioteT BS.ByteString IO ()
tests = do
register "Generating ByteString" 50 (Proxy :: Proxy (Generating BS.ByteString))
register "Operating ByteString" 50 (Proxy :: Proxy (Operating BS.ByteString))
register "First ByteString" 50 (Proxy :: Proxy (First BS.ByteString))
register "Second ByteString" 50 (Proxy :: Proxy (Second BS.ByteString))
register "Topic" 50 (Proxy :: Proxy Topic)
in firstPeerZeroMQ "tcp://*:3002" NoDebug tests
]
]
-- Internal instances
instance SymbioteOperation (Generating s) (Generating s) where
data Operation (Generating s) = GeneratingId
perform GeneratingId x = x
instance Arbitrary (Operation (Generating s)) where
arbitrary = pure GeneratingId
instance Json.ToJSON (Operation (Generating s)) where
toJSON GeneratingId = Json.String "id"
instance Json.FromJSON (Operation (Generating s)) where
parseJSON (Json.String s)
| s == "id" = pure GeneratingId
parseJSON json = Json.typeMismatch "Operation (Generating s)" json
instance Cereal.Serialize (Operation (Generating s)) where
put GeneratingId = Cereal.putWord8 0
get = do
x <- Cereal.getWord8
case x of
0 -> pure GeneratingId
_ -> fail "Operation (Generating s)"
instance SymbioteOperation (Operating s) (Operating s) where
data Operation (Operating s) = OperatingId
perform OperatingId x = x
instance Arbitrary (Operation (Operating s)) where
arbitrary = pure OperatingId
instance Json.ToJSON (Operation (Operating s)) where
toJSON OperatingId = Json.String "id"
instance Json.FromJSON (Operation (Operating s)) where
parseJSON (Json.String s)
| s == "id" = pure OperatingId
parseJSON json = Json.typeMismatch "Operation (Operating S)" json
instance Cereal.Serialize (Operation (Operating s)) where
put OperatingId = Cereal.putWord8 0
get = do
x <- Cereal.getWord8
case x of
0 -> pure OperatingId
_ -> fail "Operation (Operating s)"
instance SymbioteOperation (First s) (First s) where
data Operation (First s) = FirstId
perform FirstId x = x
instance Arbitrary (Operation (First s)) where
arbitrary = pure FirstId
instance Json.ToJSON (Operation (First s)) where
toJSON FirstId = Json.String "id"
instance Json.FromJSON (Operation (First s)) where
parseJSON (Json.String s)
| s == "id" = pure FirstId
parseJSON json = Json.typeMismatch "Operation (First S)" json
instance Cereal.Serialize (Operation (First s)) where
put FirstId = Cereal.putWord8 0
get = do
x <- Cereal.getWord8
case x of
0 -> pure FirstId
_ -> fail "Operation (First s)"
instance SymbioteOperation (Second s) (Second s) where
data Operation (Second s) = SecondId
perform SecondId x = x
instance Arbitrary (Operation (Second s)) where
arbitrary = pure SecondId
instance Json.ToJSON (Operation (Second s)) where
toJSON SecondId = Json.String "id"
instance Json.FromJSON (Operation (Second s)) where
parseJSON (Json.String s)
| s == "id" = pure SecondId
parseJSON json = Json.typeMismatch "Operation (Second S)" json
instance Cereal.Serialize (Operation (Second s)) where
put SecondId = Cereal.putWord8 0
get = do
x <- Cereal.getWord8
case x of
0 -> pure SecondId
_ -> fail "Operation (Second s)"
instance SymbioteOperation Topic Topic where
data Operation Topic = TopicId
perform TopicId x = x
instance Arbitrary (Operation Topic) where
arbitrary = pure TopicId
instance Json.ToJSON (Operation Topic) where
toJSON TopicId = Json.String "id"
instance Json.FromJSON (Operation Topic) where
parseJSON (Json.String s)
| s == "id" = pure TopicId
parseJSON json = Json.typeMismatch "Operation Topic" json
instance Cereal.Serialize (Operation Topic) where
put TopicId = Cereal.putWord8 0
get = do
x <- Cereal.getWord8
case x of
0 -> pure TopicId
_ -> fail "Operation Topic"