PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/Network/Socket/ByteStringSpec.hs

http://github.com/haskell/network
Haskell | 308 lines | 238 code | 57 blank | 13 comment | 2 complexity | 6e10e29d6ad8157ff585bed6643fcaec MD5 | raw file
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Network.Socket.ByteStringSpec (main, spec) where
  3. import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
  4. import Data.Bits
  5. import Data.Maybe
  6. import Control.Monad
  7. import qualified Data.ByteString as S
  8. import qualified Data.ByteString.Char8 as C
  9. import Network.Socket
  10. import Network.Socket.ByteString
  11. import Network.Test.Common
  12. import System.Environment
  13. import Test.Hspec
  14. main :: IO ()
  15. main = hspec spec
  16. spec :: Spec
  17. spec = do
  18. describe "send" $ do
  19. it "works well" $ do
  20. let server sock = recv sock 1024 `shouldReturn` testMsg
  21. client sock = send sock testMsg
  22. tcpTest client server
  23. it "throws when closed" $ do
  24. let server _ = return ()
  25. client sock = do
  26. close sock
  27. send sock testMsg `shouldThrow` anyException
  28. tcpTest client server
  29. it "checks -1 correctly on Windows" $ do
  30. sock <- socket AF_INET Stream defaultProtocol
  31. send sock "hello world" `shouldThrow` anyException
  32. describe "sendAll" $ do
  33. it "works well" $ do
  34. let server sock = recv sock 1024 `shouldReturn` testMsg
  35. client sock = sendAll sock testMsg
  36. tcpTest client server
  37. it "throws when closed" $ do
  38. let server _ = return ()
  39. client sock = do
  40. close sock
  41. sendAll sock testMsg `shouldThrow` anyException
  42. tcpTest client server
  43. describe "sendTo" $ do
  44. it "works well" $ do
  45. let server sock = recv sock 1024 `shouldReturn` testMsg
  46. client sock addr = sendTo sock testMsg addr
  47. udpTest client server
  48. it "throws when closed" $ do
  49. let server _ = return ()
  50. client sock addr = do
  51. close sock
  52. sendTo sock testMsg addr `shouldThrow` anyException
  53. udpTest client server
  54. describe "sendAllTo" $ do
  55. it "works well" $ do
  56. let server sock = recv sock 1024 `shouldReturn` testMsg
  57. client sock addr = sendAllTo sock testMsg addr
  58. udpTest client server
  59. it "throws when closed" $ do
  60. let server _ = return ()
  61. client sock addr = do
  62. close sock
  63. sendAllTo sock testMsg addr `shouldThrow` anyException
  64. udpTest client server
  65. describe "sendMany" $ do
  66. it "works well" $ do
  67. let server sock = recv sock 1024 `shouldReturn` S.append seg1 seg2
  68. client sock = sendMany sock [seg1, seg2]
  69. seg1 = C.pack "This is a "
  70. seg2 = C.pack "test message."
  71. tcpTest client server
  72. it "throws when closed" $ do
  73. let server _ = return ()
  74. client sock = do
  75. close sock
  76. sendMany sock [seg1, seg2] `shouldThrow` anyException
  77. seg1 = C.pack "This is a "
  78. seg2 = C.pack "test message."
  79. tcpTest client server
  80. describe "sendManyTo" $ do
  81. it "works well" $ do
  82. let server sock = recv sock 1024 `shouldReturn` S.append seg1 seg2
  83. client sock addr = sendManyTo sock [seg1, seg2] addr
  84. seg1 = C.pack "This is a "
  85. seg2 = C.pack "test message."
  86. udpTest client server
  87. it "throws when closed" $ do
  88. let server _ = return ()
  89. client sock addr = do
  90. close sock
  91. sendManyTo sock [seg1, seg2] addr `shouldThrow` anyException
  92. seg1 = C.pack "This is a "
  93. seg2 = C.pack "test message."
  94. udpTest client server
  95. describe "recv" $ do
  96. it "works well" $ do
  97. let server sock = recv sock 1024 `shouldReturn` testMsg
  98. client sock = send sock testMsg
  99. tcpTest client server
  100. it "throws when closed" $ do
  101. let server sock = do
  102. close sock
  103. recv sock 1024 `shouldThrow` anyException
  104. client sock = send sock testMsg
  105. tcpTest client server
  106. it "can treat overflow" $ do
  107. let server sock = do
  108. seg1 <- recv sock (S.length testMsg - 3)
  109. seg2 <- recv sock 1024
  110. let msg = S.append seg1 seg2
  111. msg `shouldBe` testMsg
  112. client sock = send sock testMsg
  113. tcpTest client server
  114. it "returns empty string at EOF" $ do
  115. let client s = recv s 4096 `shouldReturn` S.empty
  116. server s = shutdown s ShutdownSend
  117. tcpTest client server
  118. it "checks -1 correctly on Windows" $ do
  119. sock <- socket AF_INET Stream defaultProtocol
  120. recv sock 1024 `shouldThrow` anyException
  121. describe "recvFrom" $ do
  122. it "works well" $ do
  123. let server sock = do
  124. (msg, _) <- recvFrom sock 1024
  125. testMsg `shouldBe` msg
  126. client sock = do
  127. addr <- getPeerName sock
  128. sendTo sock testMsg addr
  129. tcpTest client server
  130. it "throws when closed" $ do
  131. let server sock = do
  132. close sock
  133. recvFrom sock 1024 `shouldThrow` anyException
  134. client sock = do
  135. addr <- getPeerName sock
  136. sendTo sock testMsg addr
  137. tcpTest client server
  138. it "can treat overflow" $ do
  139. let server sock = do
  140. (seg1, _) <- recvFrom sock (S.length testMsg - 3)
  141. (seg2, _) <- recvFrom sock 1024
  142. let msg = S.append seg1 seg2
  143. testMsg `shouldBe` msg
  144. client sock = send sock testMsg
  145. tcpTest client server
  146. it "returns empty string at EOF" $ do
  147. let server sock = do
  148. (seg1, _) <- recvFrom sock (S.length testMsg - 3)
  149. seg1 `shouldBe` S.empty
  150. client sock = shutdown sock ShutdownSend
  151. tcpTest client server
  152. describe "sendMsg" $ do
  153. it "works well" $ do
  154. let server sock = recv sock 1024 `shouldReturn` S.append seg1 seg2
  155. client sock addr = sendMsg sock addr [seg1, seg2] [] mempty
  156. seg1 = C.pack "This is a "
  157. seg2 = C.pack "test message."
  158. udpTest client server
  159. it "throws when closed" $ do
  160. let server _ = return ()
  161. client sock addr = do
  162. close sock
  163. sendMsg sock addr [seg1, seg2] [] mempty `shouldThrow` anyException
  164. seg1 = C.pack "This is a "
  165. seg2 = C.pack "test message."
  166. udpTest client server
  167. describe "recvMsg" $ do
  168. it "works well" $ do
  169. let server sock = do
  170. (_, msg, cmsgs, flags) <- recvMsg sock 1024 0 mempty
  171. msg `shouldBe` seg
  172. cmsgs `shouldBe` []
  173. flags `shouldBe` mempty
  174. client sock addr = sendTo sock seg addr
  175. seg = C.pack "This is a test message"
  176. udpTest client server
  177. it "receives truncated flag" $ do
  178. let server sock = do
  179. (_, _, _, flags) <- recvMsg sock (S.length seg - 2) 0 mempty
  180. flags .&. MSG_TRUNC `shouldBe` MSG_TRUNC
  181. client sock addr = sendTo sock seg addr
  182. seg = C.pack "This is a test message"
  183. udpTest client server
  184. it "peek" $ do
  185. let server sock = do
  186. (_, msgs, _, _flags) <- recvMsg sock 1024 0 MSG_PEEK
  187. -- flags .&. MSG_PEEK `shouldBe` MSG_PEEK -- Mac only
  188. (_, msgs', _, _) <- recvMsg sock 1024 0 mempty
  189. msgs `shouldBe` msgs'
  190. client sock addr = sendTo sock seg addr
  191. seg = C.pack "This is a test message"
  192. udpTest client server
  193. it "receives control messages for IPv4" $ do
  194. -- This test behaves strange on AppVeyor and I don't know why so skip
  195. -- TOS for now.
  196. isAppVeyor <- isJust <$> lookupEnv "APPVEYOR"
  197. -- Avoid race condition between the client sending the message and
  198. -- the server finishing its socket configuration. Otherwise the
  199. -- message may be received with default socket options!
  200. serverReady <- newEmptyMVar
  201. let server sock = do
  202. whenSupported RecvIPv4TTL $ setSocketOption sock RecvIPv4TTL 1
  203. whenSupported RecvIPv4PktInfo $ setSocketOption sock RecvIPv4PktInfo 1
  204. whenSupported RecvIPv4TOS $ setSocketOption sock RecvIPv4TOS 1
  205. putMVar serverReady ()
  206. (_, _, cmsgs, _) <- recvMsg sock 1024 128 mempty
  207. whenSupported RecvIPv4PktInfo $
  208. ((lookupCmsg CmsgIdIPv4PktInfo cmsgs >>= decodeCmsg) :: Maybe IPv4PktInfo) `shouldNotBe` Nothing
  209. when (not isAppVeyor) $ do
  210. whenSupported RecvIPv4TTL $
  211. ((lookupCmsg CmsgIdIPv4TTL cmsgs >>= decodeCmsg) :: Maybe IPv4TTL) `shouldNotBe` Nothing
  212. whenSupported RecvIPv4TOS $
  213. ((lookupCmsg CmsgIdIPv4TOS cmsgs >>= decodeCmsg) :: Maybe IPv4TOS) `shouldNotBe` Nothing
  214. client sock addr = takeMVar serverReady >> sendTo sock seg addr
  215. seg = C.pack "This is a test message"
  216. udpTest client server
  217. it "receives control messages for IPv6" $ do
  218. -- Avoid race condition between the client sending the message and
  219. -- the server finishing its socket configuration. Otherwise the
  220. -- message may be received with default socket options!
  221. serverReady <- newEmptyMVar
  222. let server sock = do
  223. whenSupported RecvIPv6HopLimit $ setSocketOption sock RecvIPv6HopLimit 1
  224. whenSupported RecvIPv6TClass $ setSocketOption sock RecvIPv6TClass 1
  225. whenSupported RecvIPv6PktInfo $ setSocketOption sock RecvIPv6PktInfo 1
  226. putMVar serverReady ()
  227. (_, _, cmsgs, _) <- recvMsg sock 1024 128 mempty
  228. whenSupported RecvIPv6HopLimit $
  229. ((lookupCmsg CmsgIdIPv6HopLimit cmsgs >>= decodeCmsg) :: Maybe IPv6HopLimit) `shouldNotBe` Nothing
  230. whenSupported RecvIPv6TClass $
  231. ((lookupCmsg CmsgIdIPv6TClass cmsgs >>= decodeCmsg) :: Maybe IPv6TClass) `shouldNotBe` Nothing
  232. whenSupported RecvIPv6PktInfo $
  233. ((lookupCmsg CmsgIdIPv6PktInfo cmsgs >>= decodeCmsg) :: Maybe IPv6PktInfo) `shouldNotBe` Nothing
  234. client sock addr = takeMVar serverReady >> sendTo sock seg addr
  235. seg = C.pack "This is a test message"
  236. udpTest6 client server
  237. it "receives truncated control messages" $ do
  238. -- Avoid race condition between the client sending the message and
  239. -- the server finishing its socket configuration. Otherwise the
  240. -- message may be received with default socket options!
  241. serverReady <- newEmptyMVar
  242. let server sock = do
  243. whenSupported RecvIPv4TTL $ setSocketOption sock RecvIPv4TTL 1
  244. whenSupported RecvIPv4TOS $ setSocketOption sock RecvIPv4TOS 1
  245. whenSupported RecvIPv4PktInfo $ setSocketOption sock RecvIPv4PktInfo 1
  246. putMVar serverReady ()
  247. (_, _, _, flags) <- recvMsg sock 1024 10 mempty
  248. flags .&. MSG_CTRUNC `shouldBe` MSG_CTRUNC
  249. client sock addr = takeMVar serverReady >> sendTo sock seg addr
  250. seg = C.pack "This is a test message"
  251. udpTest client server