packages feed

angel-0.6.1: test/Angel/JobSpec.hs

{-# LANGUAGE CPP #-}
module Angel.JobSpec (spec) where

import Angel.Job (killProcess)
import Angel.Process ( getProcessHandleStatus
                     , hardKillProcessHandle )
import Angel.Data hiding (Spec, spec)
import Angel.Util (sleepSecs)

import Control.Monad.IO.Class
import System.Exit (ExitCode(..))
import System.Posix.Directory (getWorkingDirectory)
import System.Posix.Signals (sigKILL)
import System.Posix.Process (ProcessStatus(..))
import System.Process ( createProcess
                      , proc
                      , ProcessHandle )

import SpecHelper

spec :: Spec
spec =
  describe "killProcess" $ do
    describe "using SoftKill" $ do
      it "cleanly kills well-behaved processes" $ runAngelM dummyOptions $ do
        ph <- liftIO launchCompliantJob
        killProcess $ SoftKill "thing" ph Nothing
        liftIO $
          patientlyGetProcessExitCode ph `shouldReturn` (Just $ Exited ExitSuccess)

      it "does not forcefully kill stubborn processes" $ runAngelM dummyOptions $ do
        ph <- liftIO launchStubbornJob
        killProcess $ SoftKill "thing" ph Nothing
        -- stubborn job gets marked as [defunct] here. no idea why. it should be able to survive a SIGTERM
        liftIO $ do
          patientlyGetProcessExitCode ph `shouldReturn` Nothing
          hardKillProcessHandle ph -- cleanup

    describe "using HardKill" $ do
      it "cleanly kills well-behaved processes" $ runAngelM dummyOptions $ do
        ph <- liftIO launchCompliantJob
        killProcess $ HardKill "thing" ph Nothing 1
        -- Can't geth the exiit status because the life check in Job "uses up" the waitpid
        liftIO $
          patientlyGetProcessExitCode ph `shouldReturn` Nothing
      it "forcefully kills stubborn processes" $ runAngelM dummyOptions $ do
        ph <- liftIO launchStubbornJob
        killProcess $ HardKill "thing" ph Nothing 1
        liftIO $
#if MIN_VERSION_unix(2,7,0)
          patientlyGetProcessExitCode ph `shouldReturn` (Just $ Terminated sigKILL False)
#else
          patientlyGetProcessExitCode ph `shouldReturn` (Just $ Terminated sigKILL)
#endif
    describe "with a logger" $
      it "cleanly kills well-behaved loggers" $ runAngelM dummyOptions $ do
        ph <- liftIO launchCompliantJob
        lph <- liftIO launchCompliantJob
        killProcess $ SoftKill "thing" ph (Just lph)
        liftIO $
          patientlyGetProcessExitCode lph `shouldReturn` (Just $ Exited ExitSuccess)

launchCompliantJob :: IO ProcessHandle
launchCompliantJob = launchJob "CompliantJob"

launchStubbornJob :: IO ProcessHandle
launchStubbornJob = launchJob "StubbornJob"

launchJob :: FilePath -> IO ProcessHandle
launchJob n = do wd <- getWorkingDirectory
                 let path = wd ++ "/test/test_jobs/" ++ n
                 (_, _, _, ph) <- createProcess $ proc path []
                 sleepSecs 1
                 return ph

patientlyGetProcessExitCode :: ProcessHandle -> IO (Maybe ProcessStatus)
patientlyGetProcessExitCode ph = sleepSecs 1 >> getProcessHandleStatus ph

dummyOptions :: Options
dummyOptions = Options {
      configFile = ""
    , verbosity  = V0
    }