packages feed

proctest 0.1.0.1 → 0.1.2.0

raw patch · 3 files changed

+76/−10 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Test.Proctest: CommandNotFound :: String -> RunException
+ Test.Proctest: ExitedTooEarly :: String -> RunException
+ Test.Proctest: data RunException
+ Test.Proctest: instance Exception RunException
+ Test.Proctest: instance Show RunException
+ Test.Proctest: instance Typeable RunException
+ Test.Proctest: isRunning :: ProcessHandle -> IO Bool
+ Test.Proctest.Assertions: runAssert :: Timeout -> FilePath -> [String] -> IO (Handle, Handle, Handle, ProcessHandle)

Files

Test/Proctest.hs view
@@ -65,6 +65,8 @@   -- * Running and stopping programs , run+, RunException (..)+, isRunning , terminateProcesses , closeHandles @@ -116,13 +118,34 @@ -- -- Directly runs the process, does not use a shell. ----- Sets the 'BufferMode to 'LineBuffering'.+-- Sets the 'BufferMode to 'LineBuffering' if successful.+--+-- Throws 'CommandNotFound' if the command doesn't exist.+-- Due to 'createProcess' not throwing an exception+-- (<http://www.haskell.org/pipermail/haskell-cafe/2012-August/102824.html>),+-- this is currently implemented by checking if the program+-- returns early with error code 127. run :: FilePath -> [String] -> IO (Handle, Handle, Handle, ProcessHandle) run cmd args = do-  r@(i, o, e, _) <- runInteractiveProcess cmd args Nothing Nothing-  setBuffering LineBuffering [i, o, e]-  return r+  r@(i, o, e, p) <- runInteractiveProcess cmd args Nothing Nothing+  getProcessExitCode p >>= \me -> case me of+    -- TODO see if we can make runInteractiveProcess throw the exception instead+    Just (ExitFailure 127) -> throwIO $ CommandNotFound cmd+    _                      -> do+      setBuffering LineBuffering [i, o, e]+      return r +-- | Exception to be thrown when a program could not be started.+data RunException = CommandNotFound String+                  | ExitedTooEarly String+                    deriving (Show, Typeable)++instance Exception RunException++-- | Tells whether the given process is still running.+isRunning :: ProcessHandle -> IO Bool+isRunning p = do x <- getProcessExitCode p; return (x == Nothing)+ -- | Terminates all processes in the list. terminateProcesses :: [ProcessHandle] -> IO () terminateProcesses = mapM_ terminateProcess@@ -132,7 +155,7 @@ closeHandles = mapM_ hClose  --- | A microsecnd timeout, or 'NoTimeout'.+-- | A microsecond timeout, or 'NoTimeout'. data Timeout = NoTimeout | Micros Int  -- | An error to be thrown if something is to be converted into timeout@@ -141,7 +164,7 @@  instance Exception InvalidTimeoutError --- | Turns the given number of microsecnds into a 'Timeout'.+-- | Turns the given number of microseconds into a 'Timeout'. -- -- Throws an exception on 'Int' overflow. mkTimeoutUs :: Integer -> Timeout@@ -173,7 +196,7 @@ -- -- Example: @(seconds 0.2)@ are roughly @Micros 200000@. seconds :: Float -> Timeout-seconds s = mkTimeoutUs (round $ s * 10000000)+seconds s = mkTimeoutUs (round $ s * 1000000)   -- | Suspends execution for the given timeout; uses 'threadDelay' internally.
+ Test/Proctest/Assertions.hs view
@@ -0,0 +1,42 @@+{- | Helpers for asserting certain things for programs, using HUnit.++All of the assertions in this module throw HUnit exceptions on failure+using `assertFailure`.+-}++module Test.Proctest.Assertions (+  -- * Starting programs+    runAssert++) where+++import Test.Proctest+import Test.HUnit+++-- | Performs the monadic action on the contents of the `Just`, if any.+onJust :: (Monad m) => (a -> m ()) -> Maybe a -> m ()+onJust = maybe (return ())++-- | Runs the given program with `run` and asserts that it is still running+-- after the given timeout.+--+-- Don't choose the timeout too high as this function will block for it.+--+-- If the timeout is exceeded, a HUnit `assertFailure` exception is thrown,+-- showing the command line to be invoked, the exit code, and the standard+-- error output of the program.+runAssert :: Timeout -> FilePath -> [String] -> IO (Handle, Handle, Handle, ProcessHandle)+runAssert timeout cmd args = do+  r@(_, _, hErr, p) <- run cmd args+  sleep timeout+  getProcessExitCode p >>= (onJust $ \ec -> do+    -- The lazy IO here is OK, as we immediately show the String afterwards.+    err <- hGetContents hErr+    assertFailure $ "The program '" ++ program ++ "' after being started immediately "+                    ++ "exited with exit code " ++ show ec ++ ".\n"+                    ++ "--- stderr: ---\n" ++ err ++ "\n--- End of stderr ---")+  return r+  where+    program = cmd ++ concatMap (" " ++) args
proctest.cabal view
@@ -1,5 +1,5 @@ name:          proctest-version:       0.1.0.1+version:       0.1.2.0 license:       MIT license-file:  LICENSE author:        Niklas Hambüchen@@ -29,12 +29,14 @@ library   default-language: Haskell2010   exposed-modules:-    Test.Proctest+      Test.Proctest+    , Test.Proctest.Assertions   build-depends:       base >= 4 && <= 5     , process >= 1.1.0.1     , bytestring     , text+    , HUnit   ghc-options:     -Wall @@ -55,4 +57,3 @@     , QuickCheck >= 2.4.2   ghc-options:     -threaded -fwarn-unused-imports-