@@ -1,7 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE ScopedTypeVariables #-}
4−module RunSpec (main, spec, withApp, MySocket, msWrite, msRead, withMySocket) where
4+module RunSpec (main, spec, withApp, connectTo, MySocket, msWrite, msRead, msClose) where
6import Control.Concurrent (forkIO, killThread, threadDelay)
6import Control.Concurrent (forkIO, killThread, threadDelay)
7import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
7import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -37,7 +37,7 @@ type CounterApplication = Counter -> Application
38data MySocket = MySocket
38data MySocket = MySocket
39 { msSocket :: !Socket
39 { msSocket :: !Socket
40− , msBuffer :: !(I.IORef ByteString)
40+ , _msBuffer :: !(I.IORef ByteString)
43msWrite :: MySocket -> ByteString -> IO ()
43msWrite :: MySocket -> ByteString -> IO ()
@@ -70,16 +70,9 @@ msClose :: MySocket -> IO ()
70msClose = Network.Socket.close . msSocket
70msClose = Network.Socket.close . msSocket
72connectTo :: Int -> IO MySocket
72connectTo :: Int -> IO MySocket
73−connectTo port = do
73+connectTo port = MySocket
74− s <- fst <$> getSocketTCP "127.0.0.1" port
74+ <$> (fst <$> getSocketTCP "127.0.0.1" port)
75− ref <- I.newIORef mempty
75+ <*> I.newIORef mempty
81−withMySocket :: (MySocket -> IO a) -> Int -> IO a
82−withMySocket body port = bracket (connectTo port) msClose body
84incr :: MonadIO m => Counter -> m ()
77incr :: MonadIO m => Counter -> m ()
85incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
78incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
@@ -157,7 +150,8 @@ runTest :: Int -- ^ expected number of requests
158runTest expected app chunks = do
151runTest expected app chunks = do
159 ref <- I.newIORef (Right 0)
152 ref <- I.newIORef (Right 0)
160− withApp defaultSettings (app ref) $ withMySocket $ \ms -> do
153+ withApp defaultSettings (app ref) $ \port -> do
154+ ms <- connectTo port
161 forM_ chunks $ \chunk -> msWrite ms chunk
155 forM_ chunks $ \chunk -> msWrite ms chunk
162 _ <- timeout 100000 $ replicateM_ expected $ msRead ms 4096
156 _ <- timeout 100000 $ replicateM_ expected $ msRead ms 4096
163 res <- I.readIORef ref
157 res <- I.readIORef ref
@@ -174,9 +168,10 @@ runTerminateTest :: InvalidRequest
174runTerminateTest expected input = do
168runTerminateTest expected input = do
175 ref <- I.newIORef Nothing
169 ref <- I.newIORef Nothing
176 let onExc _ = I.writeIORef ref . Just
170 let onExc _ = I.writeIORef ref . Just
177− withApp (setOnException onExc defaultSettings) dummyApp $ withMySocket $ \ms -> do
171+ withApp (setOnException onExc defaultSettings) dummyApp $ \port -> do
172+ handle <- connectTo port
178− msWrite ms input
173+ msWrite handle input
179− msClose ms -- explicitly
174+ msClose handle
180 threadDelay 1000
175 threadDelay 1000
181 res <- I.readIORef ref
176 res <- I.readIORef ref
182 show res `shouldBe` show (Just expected)
177 show res `shouldBe` show (Just expected)
@@ -247,11 +242,13 @@ spec = do
247 let app req f = do
242 let app req f = do
248 liftIO $ I.writeIORef iheaders $ requestHeaders req
243 liftIO $ I.writeIORef iheaders $ requestHeaders req
249 f $ responseLBS status200 [] ""
244 f $ responseLBS status200 [] ""
250− withApp defaultSettings app $ withMySocket $ \ms -> do
245+ withApp defaultSettings app $ \port -> do
246+ handle <- connectTo port
251 let input = S.concat
247 let input = S.concat
252 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
248 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
254− msWrite ms input
250+ msWrite handle input
255 threadDelay 1000
252 threadDelay 1000
256 headers <- I.readIORef iheaders
253 headers <- I.readIORef iheaders
257 headers `shouldBe`
254 headers `shouldBe`
@@ -262,11 +259,13 @@ spec = do
262 let app req f = do
259 let app req f = do
263 liftIO $ I.writeIORef iheaders $ requestHeaders req
260 liftIO $ I.writeIORef iheaders $ requestHeaders req
264 f $ responseLBS status200 [] ""
261 f $ responseLBS status200 [] ""
265− withApp defaultSettings app $ withMySocket $ \ms -> do
262+ withApp defaultSettings app $ \port -> do
263+ handle <- connectTo port
266 let input = S.concat
264 let input = S.concat
267 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
265 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
269− msWrite ms input
267+ msWrite handle input
270 threadDelay 1000
269 threadDelay 1000
271 headers <- I.readIORef iheaders
270 headers <- I.readIORef iheaders
272 headers `shouldBe`
271 headers `shouldBe`
@@ -282,14 +281,16 @@ spec = do
282 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
281 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
283 atomically $ modifyTVar countVar (+ 1)
282 atomically $ modifyTVar countVar (+ 1)
284 f $ responseLBS status200 [] ""
283 f $ responseLBS status200 [] ""
285− withApp defaultSettings app $ withMySocket $ \ms -> do
284+ withApp defaultSettings app $ \port -> do
285+ handle <- connectTo port
286 let input = S.concat
286 let input = S.concat
287 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
287 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
288 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
288 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
289 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
289 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
290 , "b\r\nHello World\r\n0\r\n\r\n"
290 , "b\r\nHello World\r\n0\r\n\r\n"
292− msWrite ms input
292+ msWrite handle input
293 atomically $ do
294 atomically $ do
294 count <- readTVar countVar
295 count <- readTVar countVar
295 check $ count == 2
296 check $ count == 2
@@ -306,12 +307,14 @@ spec = do
306 I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
307 I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
307 atomically $ modifyTVar countVar (+ 1)
308 atomically $ modifyTVar countVar (+ 1)
308 f $ responseLBS status200 [] ""
309 f $ responseLBS status200 [] ""
309− withApp defaultSettings app $ withMySocket $ \ms -> do
310+ withApp defaultSettings app $ \port -> do
311+ handle <- connectTo port
310 let input = concat $ replicate 2 $
312 let input = concat $ replicate 2 $
311 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
313 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
312 (replicate 50 "5\r\n12345\r\n") ++
314 (replicate 50 "5\r\n12345\r\n") ++
313 ["0\r\n\r\n"]
315 ["0\r\n\r\n"]
314− mapM_ (msWrite ms) input
316+ mapM_ (msWrite handle) input
315 atomically $ do
318 atomically $ do
316 count <- readTVar countVar
319 count <- readTVar countVar
317 check $ count == 2
320 check $ count == 2
@@ -327,14 +330,16 @@ spec = do
327 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
330 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
328 atomically $ modifyTVar countVar (+ 1)
331 atomically $ modifyTVar countVar (+ 1)
329 f $ responseLBS status200 [] ""
332 f $ responseLBS status200 [] ""
330− withApp defaultSettings app $ withMySocket $ \ms -> do
333+ withApp defaultSettings app $ \port -> do
334+ handle <- connectTo port
331 let input = S.concat
335 let input = S.concat
332 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
336 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
333 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
337 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
334 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
338 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
335 , "b\r\nHello World\r\n0\r\n\r\n"
339 , "b\r\nHello World\r\n0\r\n\r\n"
337− mapM_ (msWrite ms) $ map S.singleton $ S.unpack input
341+ mapM_ (msWrite handle) $ map S.singleton $ S.unpack input
338 atomically $ do
343 atomically $ do
339 count <- readTVar countVar
344 count <- readTVar countVar
340 check $ count == 2
345 check $ count == 2
@@ -355,18 +360,20 @@ spec = do
355 E.throwIO (e :: E.SomeException)
360 E.throwIO (e :: E.SomeException)
356 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
361 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
357 f $ responseLBS status200 [] ""
362 f $ responseLBS status200 [] ""
358− withApp (setTimeout 1 defaultSettings) app $ withMySocket $ \ms -> do
363+ withApp (setTimeout 1 defaultSettings) app $ \port -> do
359 let bs1 = S.replicate 2048 88
364 let bs1 = S.replicate 2048 88
360 bs2 = "This is short"
365 bs2 = "This is short"
361 bs = S.append bs1 bs2
366 bs = S.append bs1 bs2
367+ handle <- connectTo port
362− msWrite ms "POST / HTTP/1.1\r\n"
368+ msWrite handle "POST / HTTP/1.1\r\n"
363− msWrite ms "content-length: "
369+ msWrite handle "content-length: "
364− msWrite ms $ S8.pack $ show $ S.length bs
370+ msWrite handle $ S8.pack $ show $ S.length bs
365− msWrite ms "\r\n\r\n"
371+ msWrite handle "\r\n\r\n"
366 threadDelay 100000
372 threadDelay 100000
367− msWrite ms bs1
373+ msWrite handle bs1
368 threadDelay 100000
374 threadDelay 100000
369− msWrite ms bs2
375+ msWrite handle bs2
370 threadDelay 5000000
377 threadDelay 5000000
371 front <- I.readIORef ifront
378 front <- I.readIORef ifront
372 S.concat (front []) `shouldBe` bs
379 S.concat (front []) `shouldBe` bs
@@ -382,7 +389,8 @@ spec = do
384 doubleBS = S.concatMap $ \w -> S.pack [w, w]
391 doubleBS = S.concatMap $ \w -> S.pack [w, w]
385− withApp defaultSettings app $ withMySocket $ \ms -> do
392+ withApp defaultSettings app $ \port -> do
393+ ms <- connectTo port
386 msWrite ms "POST / HTTP/1.1\r\n\r\n12345"
394 msWrite ms "POST / HTTP/1.1\r\n\r\n12345"
387 timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "1122334455")
395 timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "1122334455")
388 msWrite ms "67890"
396 msWrite ms "67890"
@@ -410,14 +418,15 @@ spec = do
410 atomically $ modifyTVar countVar (+ 1)
418 atomically $ modifyTVar countVar (+ 1)
413− withApp defaultSettings app $ withMySocket $ \ms -> do
421+ withApp defaultSettings app $ \port -> do
422+ (sock, _addr) <- getSocketTCP "127.0.0.1" port
414− msWrite ms "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
423+ sendAll sock "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
415 threadDelay 10000
424 threadDelay 10000
416− msWrite ms "5\r\nhello\r\n0\r\n\r\n"
425+ sendAll sock "5\r\nhello\r\n0\r\n\r\n"
417 atomically $ do
426 atomically $ do
418 count <- readTVar countVar
427 count <- readTVar countVar
419 check $ count >= 1
428 check $ count >= 1
420− bs <- safeRecv (msSocket ms) 4096 -- must not use msRead
429+ bs <- safeRecv sock 4096
421 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
430 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
423 it "streaming response with length" $ do
432 it "streaming response with length" $ do