packages feed

socket-0.1.0.0: tests/Basic.hs

{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, TypeFamilies #-}
module Main where

import Data.Monoid
import Data.ByteString (pack)
import Control.Monad
import Control.Exception
import Control.Concurrent.Async
import Foreign.C.Error
import System.Socket
import System.Exit

main :: IO ()
main = do 
  test "test0001.01" $ test0001 (undefined :: Socket SockAddrIn  STREAM TCP) localhost
  test "test0001.02" $ test0001 (undefined :: Socket SockAddrIn6 STREAM TCP) localhost6
  test "test0001.03" $ test0001 (undefined :: Socket SockAddrIn  STREAM SCTP) localhost
  test "test0001.04" $ test0001 (undefined :: Socket SockAddrIn6 STREAM SCTP) localhost6
  test "test0002.01" $ test0002 (undefined :: Socket SockAddrIn  DGRAM  UDP) localhost
  test "test0002.02" $ test0002 (undefined :: Socket SockAddrIn6 DGRAM  UDP) localhost6

-- Test connection oriented sockets (i.e. TCP).
test0001 :: (Address a, Type t, Protocol p) => Socket a t p -> a -> IO (Either String String)
test0001 dummy addr = do
  eServer <- try (socket `asTypeOf` return dummy)
  case eServer of
    Left e@(SocketException er) -> if er == ePROTONOSUPPORT
                                     then return (Right "Protocol not supported. System dependant.")
                                     else throwIO e
    Right server -> do
      bind server addr
      listen server 5
      serverRecv <- async $ do
        (peerSock, peerAddr) <- accept server
        recv peerSock 4096 mempty
      client <- socket `asTypeOf` return server
      connect client addr
      send client helloWorld mempty
      msg <- wait serverRecv
      close server
      close client
      if (msg /= helloWorld)
        then return (Left  "Received message was bogus.")
        else return (Right "")
      where
        helloWorld = "Hello world!"

-- Test stateless sockets (i.e. UDP).
test0002 :: (Address a, Type t, Protocol p) => Socket a t p -> a -> IO (Either String String)
test0002 dummy addr = do
  server <- socket `asTypeOf` return dummy
  bind server addr
  serverRecv <- async $ do
    recvFrom server 4096 mempty
  client <- socket `asTypeOf` return server
  sendTo client helloWorld mempty addr
  (msg,peerAddr) <- wait serverRecv
  close server
  close client
  if (msg /= helloWorld)
    then return (Left  "Received message was bogus.")
    else return (Right "")
  where
    helloWorld = "Hello world!"

localhost :: SockAddrIn
localhost =
  SockAddrIn
  { sinPort      = 7777
  , sinAddr      = pack [127,0,0,1]
  }

localhost6 :: SockAddrIn6
localhost6 =
  SockAddrIn6
  { sin6Port     = 7777
  , sin6Addr     = pack [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1]
  , sin6Flowinfo = 0
  , sin6ScopeId  = 0
  }

test :: String -> IO (Either String String) -> IO ()
test n t = do
  putStr ("Test " ++ show n ++ ": ")
  catch
    ( do  r <- t
          case r of
            Left  x -> putStr "FAIL " >> putStrLn x >> exitFailure
            Right x -> putStr "OK   " >> putStrLn x
    )
    (\e-> putStr "EXCP " >> putStrLn (show (e :: SomeException)) >> exitFailure)