@@ -1,7 +1,7 @@
11{-# LANGUAGE OverloadedStrings #-}
22{-# LANGUAGE ScopedTypeVariables #-}
33
4−module RunSpec (main, spec, withApp, connectTo, MySocket, msWrite, msRead, msClose) where
4+module RunSpec (main, spec, withApp, MySocket, msWrite, msRead, withMySocket) where
55
66import Control.Concurrent (forkIO, killThread, threadDelay)
77import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -37,7 +37,7 @@ type CounterApplication = Counter -> Application
3737
3838data MySocket = MySocket
3939 { msSocket :: !Socket
40− , _msBuffer :: !(I.IORef ByteString)
40+ , msBuffer :: !(I.IORef ByteString)
4141 }
4242
4343msWrite :: MySocket -> ByteString -> IO ()
@@ -70,9 +70,16 @@ msClose :: MySocket -> IO ()
7070msClose = Network.Socket.close . msSocket
7171
7272connectTo :: Int -> IO MySocket
73−connectTo port = MySocket
74− <$> (fst <$> getSocketTCP "127.0.0.1" port)
75− <*> I.newIORef mempty
73+connectTo port = do
74+ s <- fst <$> getSocketTCP "127.0.0.1" port
75+ ref <- I.newIORef mempty
76+ return MySocket {
77+ msSocket = s
78+ , msBuffer = ref
79+ }
80+
81+withMySocket :: (MySocket -> IO a) -> Int -> IO a
82+withMySocket body port = bracket (connectTo port) msClose body
7683
7784incr :: MonadIO m => Counter -> m ()
7885incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
@@ -150,8 +157,7 @@ runTest :: Int -- ^ expected number of requests
150157 -> IO ()
151158runTest expected app chunks = do
152159 ref <- I.newIORef (Right 0)
153− withApp defaultSettings (app ref) $ \port -> do
154− ms <- connectTo port
160+ withApp defaultSettings (app ref) $ withMySocket $ \ms -> do
155161 forM_ chunks $ \chunk -> msWrite ms chunk
156162 _ <- timeout 100000 $ replicateM_ expected $ msRead ms 4096
157163 res <- I.readIORef ref
@@ -168,10 +174,9 @@ runTerminateTest :: InvalidRequest
168174runTerminateTest expected input = do
169175 ref <- I.newIORef Nothing
170176 let onExc _ = I.writeIORef ref . Just
171− withApp (setOnException onExc defaultSettings) dummyApp $ \port -> do
172− handle <- connectTo port
173− msWrite handle input
174− msClose handle
177+ withApp (setOnException onExc defaultSettings) dummyApp $ withMySocket $ \ms -> do
178+ msWrite ms input
179+ msClose ms -- explicitly
175180 threadDelay 1000
176181 res <- I.readIORef ref
177182 show res `shouldBe` show (Just expected)
@@ -242,13 +247,11 @@ spec = do
242247 let app req f = do
243248 liftIO $ I.writeIORef iheaders $ requestHeaders req
244249 f $ responseLBS status200 [] ""
245− withApp defaultSettings app $ \port -> do
246− handle <- connectTo port
250+ withApp defaultSettings app $ withMySocket $ \ms -> do
247251 let input = S.concat
248252 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
249253 ]
250− msWrite handle input
251− msClose handle
254+ msWrite ms input
252255 threadDelay 1000
253256 headers <- I.readIORef iheaders
254257 headers `shouldBe`
@@ -259,13 +262,11 @@ spec = do
259262 let app req f = do
260263 liftIO $ I.writeIORef iheaders $ requestHeaders req
261264 f $ responseLBS status200 [] ""
262− withApp defaultSettings app $ \port -> do
263− handle <- connectTo port
265+ withApp defaultSettings app $ withMySocket $ \ms -> do
264266 let input = S.concat
265267 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
266268 ]
267− msWrite handle input
268− msClose handle
269+ msWrite ms input
269270 threadDelay 1000
270271 headers <- I.readIORef iheaders
271272 headers `shouldBe`
@@ -281,16 +282,14 @@ spec = do
281282 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
282283 atomically $ modifyTVar countVar (+ 1)
283284 f $ responseLBS status200 [] ""
284− withApp defaultSettings app $ \port -> do
285− handle <- connectTo port
285+ withApp defaultSettings app $ withMySocket $ \ms -> do
286286 let input = S.concat
287287 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
288288 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
289289 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
290290 , "b\r\nHello World\r\n0\r\n\r\n"
291291 ]
292− msWrite handle input
293− msClose handle
292+ msWrite ms input
294293 atomically $ do
295294 count <- readTVar countVar
296295 check $ count == 2
@@ -307,14 +306,12 @@ spec = do
307306 I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
308307 atomically $ modifyTVar countVar (+ 1)
309308 f $ responseLBS status200 [] ""
310− withApp defaultSettings app $ \port -> do
311− handle <- connectTo port
309+ withApp defaultSettings app $ withMySocket $ \ms -> do
312310 let input = concat $ replicate 2 $
313311 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
314312 (replicate 50 "5\r\n12345\r\n") ++
315313 ["0\r\n\r\n"]
316− mapM_ (msWrite handle) input
317− msClose handle
314+ mapM_ (msWrite ms) input
318315 atomically $ do
319316 count <- readTVar countVar
320317 check $ count == 2
@@ -330,16 +327,14 @@ spec = do
330327 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
331328 atomically $ modifyTVar countVar (+ 1)
332329 f $ responseLBS status200 [] ""
333− withApp defaultSettings app $ \port -> do
334− handle <- connectTo port
330+ withApp defaultSettings app $ withMySocket $ \ms -> do
335331 let input = S.concat
336332 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
337333 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
338334 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
339335 , "b\r\nHello World\r\n0\r\n\r\n"
340336 ]
341− mapM_ (msWrite handle) $ map S.singleton $ S.unpack input
342− msClose handle
337+ mapM_ (msWrite ms) $ map S.singleton $ S.unpack input
343338 atomically $ do
344339 count <- readTVar countVar
345340 check $ count == 2
@@ -360,20 +355,18 @@ spec = do
360355 E.throwIO (e :: E.SomeException)
361356 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
362357 f $ responseLBS status200 [] ""
363− withApp (setTimeout 1 defaultSettings) app $ \port -> do
358+ withApp (setTimeout 1 defaultSettings) app $ withMySocket $ \ms -> do
364359 let bs1 = S.replicate 2048 88
365360 bs2 = "This is short"
366361 bs = S.append bs1 bs2
367− handle <- connectTo port
368− msWrite handle "POST / HTTP/1.1\r\n"
369− msWrite handle "content-length: "
370− msWrite handle $ S8.pack $ show $ S.length bs
371− msWrite handle "\r\n\r\n"
362+ msWrite ms "POST / HTTP/1.1\r\n"
363+ msWrite ms "content-length: "
364+ msWrite ms $ S8.pack $ show $ S.length bs
365+ msWrite ms "\r\n\r\n"
372366 threadDelay 100000
373− msWrite handle bs1
367+ msWrite ms bs1
374368 threadDelay 100000
375− msWrite handle bs2
376− msClose handle
369+ msWrite ms bs2
377370 threadDelay 5000000
378371 front <- I.readIORef ifront
379372 S.concat (front []) `shouldBe` bs
@@ -389,8 +382,7 @@ spec = do
389382 loop
390383 loop
391384 doubleBS = S.concatMap $ \w -> S.pack [w, w]
392− withApp defaultSettings app $ \port -> do
393− ms <- connectTo port
385+ withApp defaultSettings app $ withMySocket $ \ms -> do
394386 msWrite ms "POST / HTTP/1.1\r\n\r\n12345"
395387 timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "1122334455")
396388 msWrite ms "67890"
@@ -418,15 +410,14 @@ spec = do
418410 atomically $ modifyTVar countVar (+ 1)
419411 loop
420412 loop
421− withApp defaultSettings app $ \port -> do
422− (sock, _addr) <- getSocketTCP "127.0.0.1" port
423− sendAll sock "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
413+ withApp defaultSettings app $ withMySocket $ \ms -> do
414+ msWrite ms "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
424415 threadDelay 10000
425− sendAll sock "5\r\nhello\r\n0\r\n\r\n"
416+ msWrite ms "5\r\nhello\r\n0\r\n\r\n"
426417 atomically $ do
427418 count <- readTVar countVar
428419 check $ count >= 1
429− bs <- safeRecv sock 4096
420+ bs <- safeRecv (msSocket ms) 4096 -- must not use msRead
430421 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
431422
432423 it "streaming response with length" $ do