packages feed

riak-1.1.2.0: tests/Utils.hs

{-# 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))