module Pqi.Conformance.Operation.Notifies
( spec,
)
where
import Pqi (Notify (..))
import qualified Pqi
import Pqi.Conformance.Harness
import Pqi.Conformance.Prelude
import Test.Hspec
spec :: Pqi.Adapter -> SpecWith ByteString
spec :: Adapter -> SpecWith ByteString
spec Adapter
adapter =
String -> SpecWith ByteString -> SpecWith ByteString
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"notifies" do
String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"is empty with no pending notifications" \ByteString
conninfo ->
Adapter
-> ByteString
-> (Connection -> IO (Maybe (ByteString, ByteString)))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo \Connection
connection ->
(Notify -> (ByteString, ByteString))
-> Maybe Notify -> Maybe (ByteString, ByteString)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Notify -> (ByteString, ByteString)
channelAndPayload (Maybe Notify -> Maybe (ByteString, ByteString))
-> IO (Maybe Notify) -> IO (Maybe (ByteString, ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Connection -> IO (Maybe Notify)
Pqi.notifies Connection
connection
String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"delivers a listen/notify round-trip and then drains" \ByteString
conninfo ->
Adapter
-> ByteString
-> (Connection
-> IO
(Maybe (ByteString, ByteString), Maybe (ByteString, ByteString)))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo \Connection
connection -> do
_ <- Connection -> ByteString -> IO (Maybe Result)
Pqi.exec Connection
connection ByteString
"listen conformance_channel"
_ <- Pqi.exec connection "notify conformance_channel, 'payload-1'"
notification <- Pqi.notifies connection
pid <- Pqi.backendPID connection
for_ notification \Notify
n -> Notify -> Int32
Pqi.bePid Notify
n Int32 -> Int32 -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int32
pid
drained <- fmap channelAndPayload <$> Pqi.notifies connection
pure (fmap channelAndPayload notification, drained)
String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"queues notifications in order" \ByteString
conninfo ->
Adapter
-> ByteString
-> (Connection
-> IO
(Maybe (ByteString, ByteString), Maybe (ByteString, ByteString),
Maybe (ByteString, ByteString)))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo \Connection
connection -> do
_ <- Connection -> ByteString -> IO (Maybe Result)
Pqi.exec Connection
connection ByteString
"listen conformance_channel"
_ <- Pqi.exec connection "notify conformance_channel, 'first'"
_ <- Pqi.exec connection "notify conformance_channel, 'second'"
first <- Pqi.notifies connection
second <- Pqi.notifies connection
third <- Pqi.notifies connection
pid <- Pqi.backendPID connection
for_ first \Notify
n -> Notify -> Int32
Pqi.bePid Notify
n Int32 -> Int32 -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int32
pid
for_ second \Notify
n -> Notify -> Int32
Pqi.bePid Notify
n Int32 -> Int32 -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int32
pid
pure (fmap channelAndPayload first, fmap channelAndPayload second, fmap channelAndPayload third)
String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"stops delivery after unlisten" \ByteString
conninfo ->
Adapter
-> ByteString
-> (Connection -> IO (Maybe (ByteString, ByteString)))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo \Connection
connection -> do
_ <- Connection -> ByteString -> IO (Maybe Result)
Pqi.exec Connection
connection ByteString
"listen conformance_channel"
_ <- Pqi.exec connection "unlisten conformance_channel"
_ <- Pqi.exec connection "notify conformance_channel, 'lost'"
fmap channelAndPayload <$> Pqi.notifies connection
where
channelAndPayload :: Notify -> (ByteString, ByteString)
channelAndPayload Notify
notification = (Notify -> ByteString
Pqi.relname Notify
notification, Notify -> ByteString
Pqi.extra Notify
notification)