diff --git a/services/federator/default.nix b/services/federator/default.nix index fa8eac96bda..e0d3e9d7235 100644 --- a/services/federator/default.nix +++ b/services/federator/default.nix @@ -168,6 +168,7 @@ mkDerivation { ]; testHaskellDepends = [ aeson + async base bytestring bytestring-conversion diff --git a/services/federator/federator.cabal b/services/federator/federator.cabal index 872f9911236..2a8181f5f18 100644 --- a/services/federator/federator.cabal +++ b/services/federator/federator.cabal @@ -380,6 +380,7 @@ test-suite federator-tests build-depends: aeson + , async , base , bytestring , bytestring-conversion diff --git a/services/federator/src/Federator/MockServer.hs b/services/federator/src/Federator/MockServer.hs index 828a87bcb1a..31094692c8f 100644 --- a/services/federator/src/Federator/MockServer.hs +++ b/services/federator/src/Federator/MockServer.hs @@ -151,7 +151,7 @@ mockInternalRequest remoteCalls mock targetDomain component (RPC path) req cont if path == "api-version" then pure $ MockResponse Wai.status200 "application/json" (Aeson.encode (VersionInfo mock.versions)) else do - modifyIORef remoteCalls (<> [fedRequest]) + atomicModifyIORef' remoteCalls (\xs -> (xs <> [fedRequest], ())) fromException @MockException . handle (throw . handleException) $ mock.handler fedRequest diff --git a/services/federator/test/unit/Test/Federator/Client.hs b/services/federator/test/unit/Test/Federator/Client.hs index 8bc976fe6a9..0660390b393 100644 --- a/services/federator/test/unit/Test/Federator/Client.hs +++ b/services/federator/test/unit/Test/Federator/Client.hs @@ -35,6 +35,7 @@ module Test.Federator.Client (tests) where +import Control.Concurrent.Async (replicateConcurrently_) import Control.Exception hiding (handle) import Control.Monad.Codensity import Control.Monad.Except @@ -92,6 +93,7 @@ tests = testGroup "HTTP2 client" [ testCase "testResponseHeaders" testResponseHeaders, + testCase "testConcurrentRequestsAllRecorded" testConcurrentRequestsAllRecorded, testCase "testStreaming" testStreaming ] ] @@ -248,6 +250,20 @@ testResponseHeaders = do responseStatusCode resp @?= HTTP.status200 lookup "X-Foo" (toList (responseHeaders resp)) @?= Just "bar" +testConcurrentRequestsAllRecorded :: IO () +testConcurrentRequestsAllRecorded = do + (_, sentRequests) <- + withTempMockFederator def $ \port -> do + let req = + HTTP2.requestBuilder + HTTP.methodPost + "/rpc/target.example.com/brig/test" + [("Wire-Origin-Domain", "origin.example.com"), (federationRequestIdHeaderName, "rid")] + "body" + mgr <- defaultHttp2Manager + replicateConcurrently_ 50 (performHTTP2Request mgr (False, "127.0.0.1", port) req) + length sentRequests @?= 50 + testStreaming :: IO () testStreaming = withInfiniteMockServer $ \port -> do let req = HTTP2.requestBuilder HTTP.methodPost "test" [] mempty