{-# LANGUAGE CPP, FlexibleInstances #-}

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
import System.Exit (ExitCode(..), exitWith)
import System.Process.Run (Chunk(ProcessHandle, Result, Stdout, Stderr), CreateProcess,
                           collectOutput, dots, echoStart, echoEnd, indent, lazy, output,
                           proc, run, runT, shell, silent, vlevel)
import System.Process.ByteString ()
import System.Process.ByteString.Lazy ()
import System.Process.Text ()
import System.Process.Text.Lazy ()
import Test.HUnit

main :: IO ()
main = runTestTT (TestList [test0]) >>= \cts ->
       exitWith $ if errors cts + failures cts > 0
                  then ExitFailure 1
                  else ExitSuccess

instance Eq (Chunk String) where
    (Stdout a) == (Stdout b) = a == b
    (Stderr a) == (Stderr b) = a == b
    (Result a) == (Result b) = a == b
    _ == _ = False

-- Every fourth run these will say:
-- *System.Process.Run> _test4
-- -> ls
-- <interactive>: fd:12: hGetBuffering: illegal operation (handle is closed)
-- <interactive>: fd:14: hGetBuffering: illegal operation (handle is closed)
-- *** Exception: thread blocked indefinitely in an MVar operation

-- Oldest file in /usr/share/doc
file :: FilePath
file = "/usr/share/doc/cron/THANKS"
dir :: FilePath
dir = "/usr/share/doc/cron"

cmd :: CreateProcess
cmd = shell "echo a; echo b 1>&2; printf c"

omitProcessHandle :: [Chunk a] -> [Chunk a]
omitProcessHandle [] = []
omitProcessHandle (ProcessHandle _ : more) = omitProcessHandle more
omitProcessHandle (x : xs) = x : omitProcessHandle xs

test0 :: Test
test0 = TestCase $ do
          let expected = (ExitSuccess, "a\nc", "b\n") :: (ExitCode, String, String)
          actual <- collectOutput <$> runT (output >> run cmd "")
          assertEqual "test1" expected actual

-- | What we want to test with these is what gets written to the console,
-- and I haven't yet invested the thought required to do that.  Divert the
-- console output somehow I guess...
_test1 :: IO [Chunk String]
_test1 = runT (output >> run (proc "ls" []) "")
_test2 :: IO [Chunk String]
_test2 = runT (vlevel 0 >> run (proc "ls" []) "")
_test2a :: IO (ExitCode, String, String)
_test2a = runT (silent >> run (proc "ls" []) "")
_test3 :: IO [Chunk String]
_test3 = runT (dots 10 >> run (proc "ls" []) "")
_test4 :: IO [Chunk String]
_test4 = runT (lazy >> indent (const "1> ") (const "2> ") >> run (proc "ls" []) "")
_test5 :: IO [Chunk String]
_test5 = runT (echoStart >> echoEnd >> run (proc "ls" []) "")
_test6 :: IO [Chunk String]
_test6 = (runT (silent >> echoStart >> echoEnd >> run (proc "yes" []) "") :: IO [Chunk String]) >>= return . take 2
