{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
module Test (tests) where
import Data.Maybe
import Control.Concurrent
import Control.Monad
import Data.ByteString
import Distribution.TestSuite
import Network.DNS.MDNSResponder.Client
handle_err :: MVar (Maybe String) -> AsyncConnectionErrorHandler
handle_err var err = putMVar var . Just $
"connect async: " ++ (show err)
register_req :: Request NTDResponse
register_req = ServiceRegister
mempty
kDNSServiceInterfaceIndexLocalOnly
empty
"_test._tcp"
empty
empty
80
empty
browse_req :: Request NTDResponse
browse_req = ServiceBrowse
kDNSServiceInterfaceIndexLocalOnly
"_test._tcp"
empty
resolve_req :: NullFreeByteString
-> NullFreeByteString
-> NullFreeByteString
-> Request ResolveResponse
resolve_req = ServiceResolve
mempty
kDNSServiceInterfaceIndexLocalOnly
handle_register_res :: MVar (Maybe String) -> AsyncResponseHandler a
handle_register_res var (Left err) = putMVar var . Just $
"register async: " ++ (show err)
handle_register_res var (Right _) = putMVar var Nothing
handle_browse_res :: MVar (Either String (Response a))
-> AsyncResponseHandler a
handle_browse_res var (Left err) = putMVar var . Left $
"browse async: " ++ (show err)
handle_browse_res var (Right res) = putMVar var $ Right res
handle_resolve_res :: MVar (Maybe String) -> AsyncResponseHandler a
handle_resolve_res var (Left err) = putMVar var . Just $
"resolve async: " ++ (show err)
handle_resolve_res var (Right _) = putMVar var Nothing
resolve :: IO ()
-> Connection
-> Response NTDResponse
-> MVar (Either String a)
-> IO Progress
resolve cleanup' con (Response _ (NTDResponse {..})) var' = do
var <- newEmptyMVar
tid <- forkIO $ do
Left str <- takeMVar var'
putMVar var $ Just str
let cleanup = do
killThread tid
cleanup'
req = resolve_req ntd_name ntd_regtype ntd_domain
err <- request con req (handle_resolve_res var)
when (err /= kDNSServiceErr_NoError) $
putMVar var . Just $ "resolve sync: " ++ (show err)
res <- takeMVar var
case res of
Just msg -> do
cleanup
return . Finished $ Fail msg
Nothing -> return $ Finished Pass
browseThen :: IO ()
-> Connection
-> MVar (Maybe String)
-> IO Progress
browseThen cleanup' con var' = do
var <- newEmptyMVar
tid <- forkIO $ takeMVar var' >>= putMVar var . Left . fromJust
let cleanup = do
killThread tid
cleanup'
err <- request con browse_req (handle_browse_res var)
when (err /= kDNSServiceErr_NoError) $
putMVar var . Left $ "browse sync: " ++ (show err)
res <- takeMVar var
case res of
Left msg -> do
cleanup
return . Finished $ Fail msg
Right res' -> return $
Progress "browse" (resolve cleanup con res' var)
registerThen :: IO ()
-> Connection
-> MVar (Maybe String)
-> IO Progress
registerThen cleanup con var = do
err <- request con register_req (handle_register_res var)
when (err /= kDNSServiceErr_NoError) $
putMVar var . Just $ "register sync: " ++ (show err)
res <- takeMVar var
case res of
Just msg -> do
cleanup
return . Finished $ Fail msg
Nothing -> return $
Progress "register" (browseThen cleanup con var)
connectThen :: IO Progress
connectThen = do
var <- newEmptyMVar
addr <- defaultAddr
e_con <- connect addr (handle_err var)
return $ case e_con of
Left err -> Finished . Fail $ "connect: " ++ (show err)
Right con ->
Progress "connect" (registerThen (disconnect con) con var)
tests :: IO [Test]
tests = return [ (Test registerAndResolve) ]
where
registerAndResolve = TestInstance
{ run = connectThen
, name = "Register and resolve a service"
, tags = []
, options = []
, setOption = \_ _ -> Right registerAndResolve
}