Skip to content

Commit 1b1fb6c

Browse files
committed
Cloud Haskell tests for QUIC
1 parent adbcba1 commit 1b1fb6c

File tree

8 files changed

+325
-117
lines changed

8 files changed

+325
-117
lines changed

.github/workflows/cabal.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,16 @@ jobs:
4848
id: setup-haskell
4949
with:
5050
ghc-version: ${{ matrix.ghc-version }}
51-
cabal-version: '3.12.1.0'
52-
51+
cabal-version: '3.16.0.0'
52+
5353
- name: Generate freeze file
5454
run: |
55-
cabal configure --enable-tests --test-show-details=direct
55+
# Note that the 'ci' flag is important to skip some tests
56+
# which are known to be failing in CI
57+
cabal configure --enable-tests --test-show-details=direct --flags ci
5658
cabal freeze ${{matrix.cabal-flags}} --minimize-conflict-set
5759
cat cabal.project.freeze
58-
60+
5961
- name: Cache cabal work
6062
uses: actions/cache@v4
6163
with:
@@ -68,12 +70,14 @@ jobs:
6870

6971
- name: Build dependencies only
7072
run: cabal build all --only-dependencies ${{matrix.cabal-flags}}
71-
73+
7274
- name: Build all packages
7375
run: cabal build all ${{matrix.cabal-flags}}
74-
76+
7577
- name: Run all tests
7678
# We have seen in the past some tests hang for hours, wasting resources.
7779
# The timeout below should be plenty
7880
timeout-minutes: 10
79-
run: cabal test all ${{matrix.cabal-flags}}
81+
# We run each test suite one-by-one to better observe problems.
82+
run: cabal test all -j1 ${{matrix.cabal-flags}}
83+

cabal.project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
packages: packages/*/**.cabal
22

33
package distributed-process-tests
4-
flags: +tcp
4+
flags: +tcp +quic

packages/distributed-process-tests/distributed-process-tests.cabal

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ copyright: Well-Typed LLP
1212
category: Control, Cloud Haskell
1313
build-type: Simple
1414
tested-with: GHC==8.10.7 GHC==9.0.2 GHC==9.2.8 GHC==9.4.8 GHC==9.6.7 GHC==9.8.4 GHC==9.10.3 GHC==9.12.2
15+
extra-source-files: tests/credentials/*
1516

1617
source-repository head
1718
Type: git
@@ -22,6 +23,14 @@ flag tcp
2223
Description: build and run TCP tests
2324
Default: False
2425

26+
flag quic
27+
Description: build and run QUIC tests
28+
Default: False
29+
30+
flag ci
31+
Description: Flag which is turned on when running in CI
32+
Default: False
33+
2534
common warnings
2635
ghc-options: -Wall
2736
-Wcompat
@@ -100,6 +109,26 @@ Test-Suite TestCHInTCP
100109
ghc-options: -threaded -rtsopts -with-rtsopts=-N -fno-warn-unused-do-bind
101110
HS-Source-Dirs: tests
102111

112+
Test-Suite TestCHInQUIC
113+
import: warnings
114+
Type: exitcode-stdio-1.0
115+
Main-Is: runQUIC.hs
116+
if flag(quic)
117+
Build-Depends: base >= 4.14 && < 5,
118+
distributed-process-tests,
119+
filepath,
120+
network-transport,
121+
network-transport-quic,
122+
tasty >= 1.5 && <1.6,
123+
else
124+
Buildable: False
125+
default-language: Haskell2010
126+
ghc-options: -threaded -rtsopts -with-rtsopts=-N
127+
HS-Source-Dirs: tests
128+
-- Some of the tests are not working in CI environments
129+
-- for some reason that I have not been able to figure out
130+
if flag(ci)
131+
cpp-options: -DCI
103132

104133
Test-Suite TestClosure
105134
import: warnings

packages/distributed-process-tests/src/Control/Distributed/Process/Tests/CH.hs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE NumericUnderscores #-}
12
module Control.Distributed.Process.Tests.CH (tests) where
23

34

@@ -42,8 +43,9 @@ import Control.Distributed.Process.Node
4243
import Control.Distributed.Process.Tests.Internal.Utils (pause)
4344
import Control.Distributed.Process.Serializable (Serializable)
4445
import Data.Maybe (isNothing, isJust)
46+
import System.Timeout (timeout)
4547
import Test.Tasty (TestTree, testGroup)
46-
import Test.Tasty.HUnit (Assertion, assertBool, assertEqual, testCase)
48+
import Test.Tasty.HUnit (Assertion, assertBool, assertEqual, testCase, assertFailure)
4749

4850
newtype Ping = Ping ProcessId
4951
deriving (Typeable, Binary, Show)
@@ -70,7 +72,12 @@ ping = do
7072
ping
7173

7274
verifyClient :: String -> MVar Bool -> IO ()
73-
verifyClient s b = takeMVar b >>= assertBool s
75+
verifyClient s b =
76+
-- The timeout below must be generous enough to support
77+
-- running tests in the Github Actions CI environment, which is quite slow.
78+
timeout 60_000_000
79+
(takeMVar b >>= assertBool s)
80+
>>= maybe (assertFailure $ "verifyClient timeout: " <> s) (\_ -> pure ())
7481

7582
expectPing :: MVar Bool -> Process ()
7683
expectPing mv = expect >>= liftIO . putMVar mv . checkPing
@@ -175,14 +182,14 @@ monitorTestProcess theirAddr mOrL un reason monitorSetup done =
175182
unmonitor ref
176183
liftIO $ putMVar done ()
177184
(False, ref) -> do
178-
receiveWait [
185+
receiveTimeout 1_000_000 [
179186
match (\(ProcessMonitorNotification ref' pid reason') -> do
180187
liftIO $ do
181188
assertBool "Bad Monitor Signal"
182189
(Just ref' == ref && pid == theirAddr &&
183190
mOrL && reason == reason')
184191
putMVar done ())
185-
]
192+
] >>= maybe (liftIO $ assertFailure "No ProcessMonitorNotification received within timeout window") pure
186193
)
187194
(\(ProcessLinkException pid reason') -> do
188195
(liftIO $ assertBool "link exception unmatched" $
@@ -220,11 +227,11 @@ testPing TestTransport{..} = do
220227
p <- expectTimeout 3000000
221228
case p of
222229
Just (Ping _) -> return ()
223-
Nothing -> die "Failed to receive Ping"
230+
Nothing -> let msg = "Failed to receive Ping" in liftIO (putMVar clientDone (Left msg)) >> die msg
224231

225-
putMVar clientDone ()
232+
putMVar clientDone (Right ())
226233

227-
takeMVar clientDone
234+
takeMVar clientDone >>= either assertFailure pure
228235

229236
-- | Monitor a process on an unreachable node
230237
testMonitorUnreachable :: TestTransport -> Bool -> Bool -> Assertion
@@ -348,6 +355,7 @@ testMonitorDisconnect TestTransport{..} mOrL un = do
348355
putMVar processAddr addr
349356
readMVar monitorSetup
350357
NT.closeEndPoint (localEndPoint localNode)
358+
threadDelay 100_000
351359
putMVar processAddr2 addr2
352360

353361
forkIO $ do
@@ -430,7 +438,7 @@ testTimeout TestTransport{..} = do
430438
done <- newEmptyMVar
431439

432440
runProcess localNode $ do
433-
res <- receiveTimeout 1000000 [match (\Add{} -> return ())]
441+
res <- receiveTimeout 1_000_000 [match (\Add{} -> return ())]
434442
liftIO $ putMVar done $ res == Nothing
435443

436444
verifyClient "Expected receiveTimeout to timeout..." done
@@ -447,7 +455,7 @@ testTimeout0 TestTransport{..} = do
447455
-- Variation on the venerable ping server which uses a zero timeout
448456
partner <- fix $ \loop ->
449457
receiveTimeout 0 [match (\(Pong partner) -> return partner)]
450-
>>= maybe (liftIO (threadDelay 100000) >> loop) return
458+
>>= maybe (liftIO (threadDelay 100_000) >> loop) return
451459
self <- getSelfPid
452460
send partner (Ping self)
453461
putMVar serverAddr addr
@@ -459,7 +467,7 @@ testTimeout0 TestTransport{..} = do
459467
pid <- getSelfPid
460468
-- Send a bunch of messages. A large number of messages that the server
461469
-- is not interested in, and then a single message that it wants
462-
replicateM_ 10000 $ send server "Irrelevant message"
470+
replicateM_ 10_000 $ send server "Irrelevant message"
463471
send server (Pong pid)
464472
expectPing clientDone
465473

@@ -582,7 +590,7 @@ testMergeChannels TestTransport{..} = do
582590
charChannel c = do
583591
(sport, rport) <- newChan
584592
replicateM_ 3 $ sendChan sport c
585-
liftIO $ threadDelay 10000 -- Make sure messages have been sent
593+
liftIO $ threadDelay 10_000 -- Make sure messages have been sent
586594
return rport
587595

588596
testTerminate :: TestTransport -> Assertion
@@ -621,15 +629,19 @@ testMonitorLiveNode TestTransport{..} = do
621629
forkProcess node2 $ do
622630
ref <- monitorNode (localNodeId node1)
623631
liftIO $ putMVar ready ()
632+
-- node1 gets closed
624633
liftIO $ takeMVar readyr
625634
send p ()
626-
receiveWait [
635+
receiveTimeout 10_000_000 [
627636
match (\(NodeMonitorNotification ref' nid _) ->
628637
(return $ ref == ref' && nid == localNodeId node1))
629-
] >>= liftIO . putMVar done
638+
] >>= maybe
639+
(liftIO $ assertFailure "Did not receive NodeMonitorNotification message within timeout window")
640+
(liftIO . putMVar done)
630641

631642
takeMVar ready
632643
closeLocalNode node1
644+
threadDelay 1_000_000
633645
putMVar readyr ()
634646

635647
verifyClient "Expected NodeMonitorNotification for LIVE node" done
@@ -638,22 +650,27 @@ testMonitorChannel :: TestTransport -> Assertion
638650
testMonitorChannel TestTransport{..} = do
639651
[node1, node2] <- replicateM 2 $ newLocalNode testTransport initRemoteTable
640652
gotNotification <- newEmptyMVar
653+
ready <- newEmptyMVar
641654

642655
pid <- forkProcess node1 $ do
656+
liftIO $ putMVar ready ()
643657
sport <- expect :: Process (SendPort ())
644658
ref <- monitorPort sport
645-
receiveWait [
659+
receiveTimeout 10_000_000 [
646660
-- reason might be DiedUnknownId if the receive port is GCed before the
647661
-- monitor is established (TODO: not sure that this is reasonable)
648662
match (\(PortMonitorNotification ref' port' reason) ->
649663
return $ ref' == ref && port' == sendPortId sport &&
650664
(reason == DiedNormal || reason == DiedUnknownId))
651-
] >>= liftIO . putMVar gotNotification
665+
] >>= maybe
666+
(liftIO $ assertFailure "Did not receive PortMonitorNotification message within timeout window")
667+
(liftIO . putMVar gotNotification)
652668

653669
runProcess node2 $ do
654670
(sport, _) <- newChan :: Process (SendPort (), ReceivePort ())
671+
liftIO $ takeMVar ready
655672
send pid sport
656-
liftIO $ threadDelay 100000
673+
liftIO $ threadDelay 100_000
657674

658675
verifyClient "Expected PortMonitorNotification" gotNotification
659676

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDoTCCAomgAwIBAgIUVp3lTRQWZSOwolWHNaghO6gR68owDQYJKoZIhvcNAQEL
3+
BQAwRTESMBAGA1UEAwwJMTI3LjAuMC4xMQswCQYDVQQGEwJDQTEPMA0GA1UECAwG
4+
UXVlYmVjMREwDwYDVQQHDAhNb250cmVhbDAgFw0yNTA4MTgwMDU1MDRaGA8yMTI1
5+
MDcyNTAwNTUwNFowRTESMBAGA1UEAwwJMTI3LjAuMC4xMQswCQYDVQQGEwJDQTEP
6+
MA0GA1UECAwGUXVlYmVjMREwDwYDVQQHDAhNb250cmVhbDCCASIwDQYJKoZIhvcN
7+
AQEBBQADggEPADCCAQoCggEBAORALZlg9Qmu+A2HT4MUjF1iGUdWF6tlRgF6+zLZ
8+
uvuSM+eR0yH+EJZB2xqanzkXHVAkAnHPWRZ2HWqTS7TLOMyRdPEkiCg+WmW2f0t0
9+
hNCjZVMviahQgOwHkbTZbfsUHTv65cEk4XCgvQXFteMC+Q3lCeXWGoeMOt7AZ3ld
10+
vf7jgmPTQXOQFhqa9q5Qcxn+b1+2NBgQXqEQTVARBLPbCB4M0SKLZ4fWK4VHZsbe
11+
k8fUJBGgz/gTDNNClUiVBhBiv/9uvunZRpU1QBN5tZYXAPc0hX608L33R+LFsoDM
12+
cO5+j+XIjvxWNk94cmM/cb4PLlZBeNBlXxWxY1lKAxjja58CAwEAAaOBhjCBgzAd
13+
BgNVHQ4EFgQUGj/6Vt/0fjbTGBHPZNRIxJywRnkwHwYDVR0jBBgwFoAUGj/6Vt/0
14+
fjbTGBHPZNRIxJywRnkwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsG
15+
AQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
16+
A4IBAQA+AuoFBODpWaWrVSjdGZPHP4DtlhB9jDy0WmUBJ8BxeB8SooJoyTsBXVhq
17+
7ACKp11rxJPk9Tv9JOsRrWi+YLzgs+QsKpUKb6RK5nszz17K1md8BavGzE4n/e0F
18+
tzYvWAeyIazHW551GMB1MkpSVcsJNqe91z35qmykmwIo8h+BgqTFzUFiln6bLnqP
19+
KxrWKdlVh2BGEVbH5APClQii0bX1qEn0A8CkAMbldC1GNFbfhyxk1v+8CVK1M6Nx
20+
BrTe15/CVTw/ceCfFZra4DinsflyCP+CcitGOUhWKgrUSiyN8xtr+Wopq4+ntm/Z
21+
ku6j3frrSJnT9A+nZyyGvZlSPrxf
22+
-----END CERTIFICATE-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDkQC2ZYPUJrvgN
3+
h0+DFIxdYhlHVherZUYBevsy2br7kjPnkdMh/hCWQdsamp85Fx1QJAJxz1kWdh1q
4+
k0u0yzjMkXTxJIgoPlpltn9LdITQo2VTL4moUIDsB5G02W37FB07+uXBJOFwoL0F
5+
xbXjAvkN5Qnl1hqHjDrewGd5Xb3+44Jj00FzkBYamvauUHMZ/m9ftjQYEF6hEE1Q
6+
EQSz2wgeDNEii2eH1iuFR2bG3pPH1CQRoM/4EwzTQpVIlQYQYr//br7p2UaVNUAT
7+
ebWWFwD3NIV+tPC990fixbKAzHDufo/lyI78VjZPeHJjP3G+Dy5WQXjQZV8VsWNZ
8+
SgMY42ufAgMBAAECggEAGfwodM6x9tFBkiC2b6DWPgdeA14Mwcl8x8xdbrOU8vD5
9+
EcLrO3J2JvUGYaf6uoAkKSyATr6hUMpPnQN52fJM3BUvMAjNq2810WCOa2OvfyUq
10+
8uZ1kIDhvH08HE+okq3+igaNQ4jUVYMnIdIZW+fJvMg3cUAHsyjGxvc2kH2YlLzQ
11+
3zxEFacnTb2K/Sxa/rFC7O3r2M6casTVsqfLyeShnSLEwLLk8tzCZZc6Sap9rVgh
12+
CIcUhZFGxLYWMBJwRs68rmgT7rvQvh8NxzDMGM9Z/AQzeeHAvjAkb4gZBu+W69vD
13+
CYjMi3cchdG/2ouYqijdv9DcqRDfz6BDwf8fT96dyQKBgQD0rGreqY7E8Wnt3EjF
14+
TYwi6Hj7r6gMw3kdIIJ49st2lTvOmeZpvJX7DOh43NNidx9q2Ai1XCCEDQlpPS7i
15+
UnqOLwX0gGYZjYkI8QSdNbJ9T4wepfSeox7dte/xnglEkfipHV3tLqhurgw+wvGW
16+
52hBB6DVSumzjcG/hrvkDth31QKBgQDu0SMH5mg4L4KaT9+qZm3IW+Xey3vwPFES
17+
w4bGsmAddzxXRIw6+ut2+AX/WSccUnZmgtiKKzS1yrBXGa98dqzjGRcDnbchkm+6
18+
Ka1s3ZSx7cjgya43jLIZ9ycwva8+OPPfzrOB6zLgIauwi5B7JsB1Qt81AXeo5/jb
19+
S64FRXkjowKBgChebj+QoEK0RjL9nnAXTGDSFGwKXmLEua3pmD1XEtjc5IJA+DhH
20+
6kMCrTSL0sCzQNbDECTEL4U6FWxssNicnSXqckQWD0J2DL8R7R33JxzvzAGehg7K
21+
gSQ5iX5HAeZzYyCb/MxOX3Hre4+7YFrykUvxc0Ld2lNKt0XfeA63uFWFAoGAOMfk
22+
ylYP5Xv2U3Y2Oa+M3pxq9SPwXdgZdpqiis+SZq8Y267ioItUPL8PvfyWffdlS05E
23+
6eUH7Uk50Bu9S5xz0rL+c8+l4QeOJPcP0tiEKCHfJwMMtwxutBm9aatP5T1pToc4
24+
yuT+/adDyQAF5CH8lGTH6TRmHPS6iHlf8MTp3n0CgYEAwUWjiimBoPQV3X2mHYp5
25+
yXBKGrsEItOmZUKYpl9UGVdGHHuZqzKi5ckOUK+vfd2uH9toUBMFK5aBM3VmFWPb
26+
3IpTrYe/Zu545dZszESjpl9JeiiSOVvPllCh0BrOAK1TwRapWUTsS8ut5pt5zLuo
27+
VbKNvUzMHtq6vp511AD0zCY=
28+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)