content: {-# LANGUAGE ExtendedDefaultRules #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE CPP #-}
  
  import Test.Hspec
  import Data.Conduit.Shell hiding (ignore) -- https://github.com/fpco/stackage/issues/2355#issue-212177275
  import Data.Conduit.Shell.PATH (true, false)
  import Data.Conduit.Shell.Segments (strings, ignore)
  import qualified Data.Conduit.List as CL
  import qualified Data.Conduit.Binary as CB
  import qualified Data.ByteString.Char8 as S8
  import Control.Applicative
  import Data.ByteString
  import Data.Char (toUpper)
  import Data.Either (isRight, isLeft)
  import Control.Exception (try)
  
  main :: IO ()
  main =
    hspec $
    do describe "SHELL path functions" $
         do it "false" $
              do val <- run $ strings (false <|> echo "failed")
                 val `shouldBe` ["failed"]
            it "true" $
              do val <- run $ strings (true <|> echo "passed")
                 val `shouldBe` []
       describe "ls" $
         do it "home directory check" $
              do val <- run $ strings (ls "/")
                 val `shouldContain` ["home"]
            it "long option" $
              do val <- run $ strings (ls "-a" ["/"])
                 val `shouldContain` ["home"]
       describe "multiple string usage" $
         do it "make two directory" $
              do val <-
                   run $
                   do ignore $ mkdir "-p" "mtest1" "mtest2" "mtest3"
                      strings $ ls "."
                 run $ rmdir ["mtest1", "mtest2", "mtest3"]
                 val `shouldContain` ["mtest1", "mtest2", "mtest3"]
       describe "list usage in variadic" $
         do it "two directory" $
              do val <-
                   run $
                   do ignore $ mkdir "-p" ["test1", "test2"]
                      strings $ ls "."
                 run $ rmdir ["test1", "test2"]
                 val `shouldContain` ["test1", "test2"]
       describe "shell calls" $
         do it "shell ls" $
              do val <- run $ do strings $ shell "ls /"
                 val `shouldContain` ["home"]
       describe "ordering of arguments" $
         do it "echo -e" $
              do val <- run $ do strings $ echo "-e" "hello\n" "haskell"
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell"]
  #else
                 val `shouldBe` ["hello", " haskell"]
  #endif
            it "mixed variant" $
              do val <- run $ strings $ echo "-e" ["hello\n", "haskell"]
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell"]
  #else
                 val `shouldBe` ["hello", " haskell"]
  #endif
            it "list variant" $
              do val <- run $ strings $ echo ["-e", "hello\n", "haskell"]
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell"]
  #else
                 val `shouldBe` ["hello", " haskell"]
  #endif
            it "list mixed variant - 1" $
              do val <- run $ strings $ echo "-e" ["hello\n", "haskell"]
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell"]
  #else
                 val `shouldBe` ["hello", " haskell"]
  #endif
            it "list mixed variant - 2" $
              do val <- run $ strings $ echo "-e" ["hello\n", "haskell\n"] "world"
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell", " world"]
  #else
                 val `shouldBe` ["hello", " haskell", " world"]
  #endif
            it "list mixed variant - 3" $
              do val <- run $ strings $ echo "-e" ["hello\n", "haskell\n"] "world\n" ["planet"]
  #ifdef darwin_HOST_OS
                 val `shouldBe` ["-e hello", " haskell", " world", " planet"]
  #else
                 val `shouldBe` ["hello", " haskell", " world", " planet"]
  #endif
       describe "cd" $
         do it "cd /" $
              do val <-
                   run $
                   do ignore $ cd "/"
                      strings pwd
                 val `shouldBe` ["/"]
            it "cd /home" $
              do val <-
                   run $
                   do ignore $ cd ["/home", undefined]
                      strings pwd
                 val `shouldBe` ["/home"]
       describe "Piping" $
         do it "basic piping" $
              do (val :: [String]) <-
                   run $ strings (echo "hello" $| conduit (CL.map (S8.map toUpper)))
                 val `shouldBe` ["HELLO"]
            it "piping of commands - example 1" $
               do val <- run $ strings (ls "/" $| grep "etc")
                  val `shouldBe` ["etc"]
            it "piping of commands - example 2" $
               do val <- run $ strings (echo "hello" $| tr "[a-z]" "[A-Z]")
                  val `shouldBe` ["HELLO"]
       describe "Exception" $
         do it "Basic exception handling - success" $
              do (val :: Either ProcessException () ) <- try $ run (ls "/bin")
                 val `shouldSatisfy` isRight
            it "Basic exception handling - failure" $
              do (val :: Either ProcessException () ) <- try $ run (ls "/non_existent_directory")
                 val `shouldSatisfy` isLeft
            it "Basic exception handling with <|> - success" $
              do (val :: Either ProcessException () ) <- try $ run (ls "/non_existent_directory" <|> ls "/bin")
                 val `shouldSatisfy` isRight
            it "Basic exception handling with <|> - failure" $
              do (val :: Either ProcessException () ) <- try $ run (ls "/non_existent_directory" <|> ls "/non_existent_directory")
                 val `shouldSatisfy` isLeft
            it "Basic exception handling with <|> - first success" $
              do (val :: Either ProcessException () ) <- try $ run (ls "/bin" <|> ls "/non_existent_directory")
                 val `shouldSatisfy` isRight
  