18
18
module ServerTests where
19
19
20
20
import Control.Concurrent (ThreadId , killThread , threadDelay )
21
+ import Control.Concurrent.Async (concurrently_ )
21
22
import Control.Concurrent.STM
22
23
import Control.Exception (SomeException , throwIO , try )
23
24
import Control.Monad
@@ -29,6 +30,7 @@ import Data.ByteString.Char8 (ByteString)
29
30
import qualified Data.ByteString.Char8 as B
30
31
import Data.Hashable (hash )
31
32
import qualified Data.IntSet as IS
33
+ import Data.List.NonEmpty (NonEmpty )
32
34
import Data.String (IsString (.. ))
33
35
import Data.Type.Equality
34
36
import qualified Data.X509.Validation as XV
@@ -75,6 +77,7 @@ serverTests = do
75
77
describe " GET command" testGetCommand
76
78
describe " GET & SUB commands" testGetSubCommands
77
79
describe " Exceeding queue quota" testExceedQueueQuota
80
+ describe " Concurrent sending and delivery" testConcurrentSendDelivery
78
81
describe " Store log" testWithStoreLog
79
82
describe " Restore messages" testRestoreMessages
80
83
describe " Restore messages (old / v2)" testRestoreExpireMessages
@@ -111,16 +114,25 @@ sendRecv h@THandle {params} (sgn, corrId, qId, cmd) = do
111
114
tGet1 h
112
115
113
116
signSendRecv :: forall c p . (Transport c , PartyI p ) => THandleSMP c 'TClient -> C. APrivateAuthKey -> (ByteString , EntityId , Command p ) -> IO (Transmission (Either ErrorType BrokerMsg ))
114
- signSendRecv h pk = signSendRecv_ h pk Nothing
117
+ signSendRecv h pk t = do
118
+ [r] <- signSendRecv_ h pk Nothing t
119
+ pure r
120
+
121
+ signSendRecv2 :: forall c p . (Transport c , PartyI p ) => THandleSMP c 'TClient -> C. APrivateAuthKey -> (ByteString , EntityId , Command p ) -> IO (Transmission (Either ErrorType BrokerMsg ), Transmission (Either ErrorType BrokerMsg ))
122
+ signSendRecv2 h pk t = do
123
+ [r1, r2] <- signSendRecv_ h pk Nothing t
124
+ pure (r1, r2)
115
125
116
126
serviceSignSendRecv :: forall c p . (Transport c , PartyI p ) => THandleSMP c 'TClient -> C. APrivateAuthKey -> C. PrivateKeyEd25519 -> (ByteString , EntityId , Command p ) -> IO (Transmission (Either ErrorType BrokerMsg ))
117
- serviceSignSendRecv h pk = signSendRecv_ h pk . Just
127
+ serviceSignSendRecv h pk serviceKey t = do
128
+ [r] <- signSendRecv_ h pk (Just serviceKey) t
129
+ pure r
118
130
119
- signSendRecv_ :: forall c p . (Transport c , PartyI p ) => THandleSMP c 'TClient -> C. APrivateAuthKey -> Maybe C. PrivateKeyEd25519 -> (ByteString , EntityId , Command p ) -> IO (Transmission (Either ErrorType BrokerMsg ))
131
+ signSendRecv_ :: forall c p . (Transport c , PartyI p ) => THandleSMP c 'TClient -> C. APrivateAuthKey -> Maybe C. PrivateKeyEd25519 -> (ByteString , EntityId , Command p ) -> IO (NonEmpty ( Transmission (Either ErrorType BrokerMsg ) ))
120
132
signSendRecv_ h@ THandle {params} (C. APrivateAuthKey a pk) serviceKey_ (corrId, qId, cmd) = do
121
133
let TransmissionForAuth {tForAuth, tToSend} = encodeTransmissionForAuth params (CorrId corrId, qId, cmd)
122
134
Right () <- tPut1 h (authorize tForAuth, tToSend)
123
- tGet1 h
135
+ liftIO $ tGetClient h
124
136
where
125
137
authorize t = (,(`C.sign'` t) <$> serviceKey_) <$> case a of
126
138
C. SEd25519 -> Just . TASignature . C. ASignature C. SEd25519 $ C. sign' pk t'
@@ -365,7 +377,7 @@ testCreateDelete =
365
377
Resp " bcda" _ ok4 <- signSendRecv rh rKey (" bcda" , rId, OFF )
366
378
(ok4, OK ) #== " accepts OFF when suspended"
367
379
368
- Resp " cdab" _ (Msg mId2 msg2) <- signSendRecv rh rKey (" cdab" , rId, SUB )
380
+ ( Resp " cdab" _ (SOK Nothing ), Resp " " _ ( Msg mId2 msg2)) <- signSendRecv2 rh rKey (" cdab" , rId, SUB )
369
381
(dec mId2 msg2, Right " hello" ) #== " accepts SUB when suspended and delivers the message again (because was not ACKed)"
370
382
371
383
Resp " dabc" _ err5 <- sendRecv rh (sampleSig, " dabc" , rId, DEL )
@@ -404,7 +416,7 @@ stressTest =
404
416
Resp " " NoEntity (Ids rId _ _) <- signSendRecv h1 rKey (" " , NoEntity , New rPub dhPub)
405
417
pure rId
406
418
let subscribeQueues h = forM_ rIds $ \ rId -> do
407
- Resp " " rId' OK <- signSendRecv h rKey (" " , rId, SUB )
419
+ Resp " " rId' ( SOK Nothing ) <- signSendRecv h rKey (" " , rId, SUB )
408
420
rId' `shouldBe` rId
409
421
closeConnection $ connection h1
410
422
subscribeQueues h2
@@ -497,7 +509,7 @@ testSwitchSub =
497
509
Resp " abcd" _ (Msg mId2 msg2) <- signSendRecv rh1 rKey (" abcd" , rId, ACK mId1)
498
510
(dec mId2 msg2, Right " test2, no ACK" ) #== " test message 2 delivered, no ACK"
499
511
500
- Resp " bcda" _ (Msg mId2' msg2') <- signSendRecv rh2 rKey (" bcda" , rId, SUB )
512
+ ( Resp " bcda" _ (SOK Nothing ), Resp " " _ ( Msg mId2' msg2')) <- signSendRecv2 rh2 rKey (" bcda" , rId, SUB )
501
513
(dec mId2' msg2', Right " test2, no ACK" ) #== " same simplex queue via another TCP connection, tes2 delivered again (no ACK in 1st queue)"
502
514
Resp " cdab" _ OK <- signSendRecv rh2 rKey (" cdab" , rId, ACK mId2')
503
515
@@ -620,6 +632,27 @@ testExceedQueueQuota =
620
632
Resp " 10" _ OK <- signSendRecv rh rKey (" 10" , rId, ACK mId4)
621
633
pure ()
622
634
635
+ testConcurrentSendDelivery :: SpecWith (ASrvTransport , AStoreType )
636
+ testConcurrentSendDelivery =
637
+ it " should continue delivering messages if message is sent before it is acknowledged" $ \ (ATransport t, msType) -> do
638
+ g <- C. newRandom
639
+ smpTest3 t msType $ \ rh sh1 sh2 -> do
640
+ (sPub, sKey) <- atomically $ C. generateAuthKeyPair C. SEd25519 g
641
+ (sId, rId, rKey, dhShared) <- createAndSecureQueue rh sPub
642
+ let dec = decryptMsgV3 dhShared
643
+ sndMsg sh n = do
644
+ Resp (CorrId n') _ OK <- signSendRecv sh sKey (n, sId, _SEND (" msg " <> n))
645
+ n' `shouldBe` n
646
+ isMsg1or2 mId msg = dec mId msg == Right " msg 1" || dec mId msg == Right " msg 2" `shouldBe` True
647
+ replicateM_ 50 $ do
648
+ concurrently_ (sndMsg sh1 " 1" ) (sndMsg sh2 " 2" )
649
+ Resp " " _ (Msg mId1 msg1) <- tGet1 rh
650
+ isMsg1or2 mId1 msg1
651
+ Resp " 3" _ (Msg mId2 msg2) <- signSendRecv rh rKey (" 3" , rId, ACK mId1)
652
+ isMsg1or2 mId2 msg2
653
+ Resp " 4" _ OK <- signSendRecv rh rKey (" 4" , rId, ACK mId2)
654
+ pure ()
655
+
623
656
testWithStoreLog :: SpecWith (ASrvTransport , AStoreType )
624
657
testWithStoreLog =
625
658
it " should store simplex queues to log and restore them after server restart" $ \ (at@ (ATransport t), msType) -> do
@@ -684,7 +717,7 @@ testWithStoreLog =
684
717
nId <- readTVarIO notifierId
685
718
Resp " dabc" _ (SOK Nothing ) <- signSendRecv h1 nKey (" dabc" , nId, NSUB )
686
719
Resp " bcda" _ OK <- signSendRecv h sKey1 (" bcda" , sId1, _SEND' " hello" )
687
- Resp " cdab" _ (Msg mId3 msg3) <- signSendRecv h rKey1 (" cdab" , rId1, SUB )
720
+ ( Resp " cdab" _ (SOK Nothing ), Resp " " _ ( Msg mId3 msg3)) <- signSendRecv2 h rKey1 (" cdab" , rId1, SUB )
688
721
(decryptMsgV3 dh1 mId3 msg3, Right " hello" ) #== " delivered from restored queue"
689
722
Resp " " _ (NMSG _ _) <- tGet1 h1
690
723
-- this queue is removed - not restored
@@ -769,7 +802,7 @@ testRestoreMessages =
769
802
Just rKey <- readTVarIO recipientKey
770
803
Just dh <- readTVarIO dhShared
771
804
let dec = decryptMsgV3 dh
772
- Resp " 2" _ (Msg mId2 msg2) <- signSendRecv h rKey (" 2" , rId, SUB )
805
+ ( Resp " 2" _ (SOK Nothing ), Resp " " _ ( Msg mId2 msg2)) <- signSendRecv2 h rKey (" 2" , rId, SUB )
773
806
(dec mId2 msg2, Right " hello 2" ) #== " restored message delivered"
774
807
Resp " 3" _ (Msg mId3 msg3) <- signSendRecv h rKey (" 3" , rId, ACK mId2)
775
808
(dec mId3 msg3, Right " hello 3" ) #== " restored message delivered"
@@ -786,7 +819,7 @@ testRestoreMessages =
786
819
Just rKey <- readTVarIO recipientKey
787
820
Just dh <- readTVarIO dhShared
788
821
let dec = decryptMsgV3 dh
789
- Resp " 4" _ (Msg mId4 msg4) <- signSendRecv h rKey (" 4" , rId, SUB )
822
+ ( Resp " 4" _ (SOK Nothing ), Resp " " _ ( Msg mId4 msg4)) <- signSendRecv2 h rKey (" 4" , rId, SUB )
790
823
(dec mId4 msg4, Right " hello 4" ) #== " restored message delivered"
791
824
Resp " 5" _ (Msg mId5 msg5) <- signSendRecv h rKey (" 5" , rId, ACK mId4)
792
825
(dec mId5 msg5, Right " hello 5" ) #== " restored message delivered"
@@ -1131,16 +1164,15 @@ testMsgExpireOnSend =
1131
1164
threadDelay 2500000
1132
1165
Resp " 2" _ OK <- signSendRecv sh sKey (" 2" , sId, _SEND " hello (should NOT expire)" )
1133
1166
testSMPClient @ c $ \ rh -> do
1134
- Resp " 3" _ (Msg mId msg) <- signSendRecv rh rKey (" 3" , rId, SUB )
1167
+ ( Resp " 3" _ (SOK Nothing ), Resp " " _ ( Msg mId msg)) <- signSendRecv2 rh rKey (" 3" , rId, SUB )
1135
1168
(dec mId msg, Right " hello (should NOT expire)" ) #== " delivered"
1136
1169
1000 `timeout` tGetClient @ SMPVersion @ ErrorType @ BrokerMsg rh >>= \ case
1137
1170
Nothing -> return ()
1138
1171
Just _ -> error " nothing else should be delivered"
1139
1172
1140
1173
testMsgExpireOnInterval :: SpecWith (ASrvTransport , AStoreType )
1141
1174
testMsgExpireOnInterval =
1142
- -- fails on ubuntu
1143
- xit' " should expire messages that are not received before messageTTL after expiry interval" $ \ (ATransport (t :: TProxy c 'TServer), msType) -> do
1175
+ it " should expire messages that are not received before messageTTL after expiry interval" $ \ (ATransport (t :: TProxy c 'TServer), msType) -> do
1144
1176
g <- C. newRandom
1145
1177
(sPub, sKey) <- atomically $ C. generateAuthKeyPair C. SEd25519 g
1146
1178
let cfg' = updateCfg (cfgMS msType) $ \ cfg_ -> cfg_ {messageExpiration = Just ExpirationConfig {ttl = 1 , checkInterval = 1 }, idleQueueInterval = 1 }
@@ -1151,7 +1183,7 @@ testMsgExpireOnInterval =
1151
1183
threadDelay 3000000
1152
1184
testSMPClient @ c $ \ rh -> do
1153
1185
signSendRecv rh rKey (" 2" , rId, SUB ) >>= \ case
1154
- Resp " 2" _ OK -> pure ()
1186
+ Resp " 2" _ ( SOK Nothing ) -> pure ()
1155
1187
r -> unexpected r
1156
1188
1000 `timeout` tGetClient @ SMPVersion @ ErrorType @ BrokerMsg rh >>= \ case
1157
1189
Nothing -> return ()
@@ -1170,7 +1202,7 @@ testMsgNOTExpireOnInterval =
1170
1202
Resp " 1" _ OK <- signSendRecv sh sKey (" 1" , sId, _SEND " hello (should NOT expire)" )
1171
1203
threadDelay 2500000
1172
1204
testSMPClient @ c $ \ rh -> do
1173
- Resp " 2" _ (Msg mId msg) <- signSendRecv rh rKey (" 2" , rId, SUB )
1205
+ ( Resp " 2" _ (SOK Nothing ), Resp " " _ ( Msg mId msg)) <- signSendRecv2 rh rKey (" 2" , rId, SUB )
1174
1206
(dec mId msg, Right " hello (should NOT expire)" ) #== " delivered"
1175
1207
1000 `timeout` tGetClient @ SMPVersion @ ErrorType @ BrokerMsg rh >>= \ case
1176
1208
Nothing -> return ()
0 commit comments