{-# LANGUAGE CPP #-}
module Data.Conduit.ProcessSpec (spec, main) where

import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Data.Conduit
import qualified Data.Conduit.List as CL
import Data.Conduit.Process
import Control.Concurrent.Async (concurrently)
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as S
import System.Exit
import Control.Concurrent (threadDelay)

main :: IO ()
main = hspec spec

spec :: Spec
spec = describe "Data.Conduit.Process" $ do
#ifndef WINDOWS
    prop "cat" $ \wss -> do
        let lbs = L.fromChunks $ map S.pack wss
        ((sink, closeStdin), source, Inherited, cph) <- streamingProcess (shell "cat")
        ((), bss) <- concurrently
            (do
                mapM_ yield (L.toChunks lbs) $$ sink
                closeStdin)
            (source $$ CL.consume)
        L.fromChunks bss `shouldBe` lbs
        ec <- waitForStreamingProcess cph
        ec `shouldBe` ExitSuccess

    it "closed stream" $ do
        (ClosedStream, source, Inherited, cph) <- streamingProcess (shell "cat")
        bss <- source $$ CL.consume
        bss `shouldBe` []

        ec <- waitForStreamingProcess cph
        ec `shouldBe` ExitSuccess

    it "handles sub-process exit code" $ do
        (sourceCmdWithConsumer "exit 0" CL.sinkNull)
                `shouldReturn` (ExitSuccess, ())
        (sourceCmdWithConsumer "exit 11" CL.sinkNull)
                `shouldReturn` (ExitFailure 11, ())
        (sourceCmdWithConsumer "exit 12" CL.sinkNull)
                `shouldReturn` (ExitFailure 12, ())
#endif
    it "blocking vs non-blocking" $ do
        (ClosedStream, ClosedStream, ClosedStream, cph) <- streamingProcess (shell "sleep 1")

        mec1 <- getStreamingProcessExitCode cph
        mec1 `shouldBe` Nothing

        threadDelay 1500000

        -- For slow systems where sleep may take longer than 1.5 seconds, do
        -- this in a loop.
        let loop 0 = error "Took too long for sleep to exit, your system is acting funny"
            loop i = do
                mec2 <- getStreamingProcessExitCode cph
                case mec2 of
                    Nothing -> do
                        threadDelay 500000
                        loop (pred i)
                    Just _ -> mec2 `shouldBe` Just ExitSuccess
        loop 5

        ec <- waitForStreamingProcess cph
        ec `shouldBe` ExitSuccess
