{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-} module Utils ( globalAdmin , globalHost , globalHttpPort , shell , withGlobalConn , ShellFailure(..) ) where import Control.Applicative import Control.Exception import Control.Monad import Data.Typeable import Data.Yaml.TH (decodeFile) import Internal import System.Exit import System.IO.Unsafe (unsafePerformIO) import System.Timeout import Control.Applicative import qualified Network.Riak as Riak import qualified Network.Riak.Basic as B import Network.Riak.Connection.Pool (Pool, create, withConnection) import Network.Riak.Connection (defaultClient) import qualified System.Process as Process config :: Config config = $$(decodeFile "tests/test.yaml") -- | The global riak-admin string, configured in test.yaml. globalAdmin :: String globalAdmin = configAdmin config globalHost :: String globalHost = configHost config globalHttpPort :: Int globalHttpPort = configHttpPort config -- | Run action in some Riak connection withGlobalConn :: (B.Connection -> IO a) -> IO a withGlobalConn = withConnection pool -- | The global riak pool that all tests share. pool :: Pool pool = unsafePerformIO (create client 1 1 1) where client = Riak.defaultClient { Riak.host = globalHost , Riak.port = show (configProtoPort config) } {-# NOINLINE pool #-} data ShellFailure = ShellFailure Int String | ShellTimeout String deriving (Show, Typeable) instance Exception ShellFailure -- | Run a shell command (inheriting stdin, stdout, and stderr), and throw an -- exception if it fails. Time out after 30 seconds. shell :: String -> IO () shell s = timeout (30*1000*1000) act >>= \case Nothing -> throw (ShellTimeout s) _ -> pure () where act :: IO () act = bracketOnError (do (_, _, _, h) <- Process.createProcess (Process.shell s) pure h) Process.terminateProcess (Process.waitForProcess >=> \case ExitSuccess -> pure () ExitFailure n -> throw (ShellFailure n s))