@@ -0,0 +1,81 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE TypeOperators #-}
4+module Servant.ClientSpec where
6+import Control.Concurrent
7+import Control.Exception
8+import Control.Monad.Trans.Either
13+import Network.Wai.Handler.Warp
17+import Servant.API.Sub
18+import Servant.API.Get
21+import Servant.ServerSpec
33+getA :: URIAuth -> EitherT String IO Person
38+ it "Servant.API.Get" $ withWaiDaemon (return server) $ \ port -> do
39+ runEitherT (getA (mkHost "localhost" port)) `shouldReturn` Right alice
44+withWaiDaemon :: IO Application -> (Port -> IO a) -> IO a
45+withWaiDaemon mkApplication action = do
46+ application <- mkApplication
47+ bracket (acquire application) free (\ (_, _, port) -> action port)
49+ acquire application = do
50+ (notifyStart, waitForStart) <- lvar
51+ (notifyKilled, waitForKilled) <- lvar
52+ thread <- forkIO $ (do
53+ (krakenPort, socket) <- openTestSocket
55+ setPort krakenPort $ -- set here just for consistency, shouldn't be
56+ -- used (it's set in the socket)
57+ setBeforeMainLoop (notifyStart krakenPort)
59+ runSettingsSocket settings socket application)
60+ `finally` notifyKilled ()
61+ krakenPort <- waitForStart
62+ return (thread, waitForKilled, krakenPort)
63+ free (thread, waitForKilled, _) = do
67+ lvar :: IO (a -> IO (), IO a)
70+ let put = putMVar mvar
74+openTestSocket :: IO (Port, Socket)
76+ s <- socket AF_INET Stream defaultProtocol
77+ localhost <- inet_addr "127.0.0.1"
78+ bind s (SockAddrInet aNY_PORT localhost)
81+ return (fromIntegral port, s)