module Main where import Control.Concurrent (forkIO) import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) import Control.Exception (bracket) import Control.Monad (when) import Network.Socket hiding (recv) import System.Exit (exitFailure) import Test.HUnit (Counts(..), Test(..), (@=?), runTestTT) import qualified Data.ByteString.Char8 as C import Network.Socket.ByteString port :: PortNumber port = fromIntegral (3000 :: Int) ------------------------------------------------------------------------ -- Tests testSendAll :: Test testSendAll = TestCase $ mytest client server where server serverSock = do (sock, _) <- accept serverSock bytes <- recv sock 1024 testData @=? bytes sClose sock client sock = do addr <- inet_addr "127.0.0.1" connect sock $ SockAddrInet port addr sendAll sock testData testData = C.pack "test" ------------------------------------------------------------------------ -- Test helpers -- | Run a client/server pair and synchronize them so that the server -- is started before the client and the specified server action is -- finished before the client closes the connection. mytest :: (Socket -> IO a) -> (Socket -> IO b) -> IO () mytest clientAct serverAct = do barrier <- newEmptyMVar forkIO $ server barrier client barrier where server barrier = do addr <- inet_addr "127.0.0.1" bracket (socket AF_INET Stream defaultProtocol) sClose (\sock -> do setSocketOption sock ReuseAddr 1 bindSocket sock (SockAddrInet port addr) listen sock maxListenQueue putMVar barrier () serverAct sock putMVar barrier ()) client barrier = do takeMVar barrier bracket (socket AF_INET Stream defaultProtocol) sClose (\sock -> clientAct sock >> takeMVar barrier) main :: IO () main = withSocketsDo $ do counts <- runTestTT $ TestList [TestLabel "testSendAll" testSendAll] when (errors counts + failures counts > 0) exitFailure