content: --   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)
  --
  --   Licensed under the Apache License, Version 2.0 (the "License");
  --   you may not use this file except in compliance with the License.
  --   You may obtain a copy of the License at
  --
  --       http://www.apache.org/licenses/LICENSE-2.0
  --
  --   Unless required by applicable law or agreed to in writing, software
  --   distributed under the License is distributed on an "AS IS" BASIS,
  --   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  --   See the License for the specific language governing permissions and
  --   limitations under the License.
  
  {-# LANGUAGE OverloadedStrings #-}
  module System.Console.Hawk.Test where
  
  import System.Directory
  import System.IO
  import Test.Hspec
  import Test.HUnit
  import GHC.IO.Handle
  
  import System.Console.Hawk
  
  
  run :: IO ()
  run = withContextHSpec $ \itEval itApply itMap ->
          describe "Hawk" $ do
            itEval "1" `into` "1\n"
            itEval "1+1" `into` "2\n"
            itEval "[1]" `into` "1\n"
            itEval "[1,2]" `into` "1\n2\n"
            itEval "(1,2)" `into` "1\n2\n"
            itEval "[[1]]" `into` "1\n"
            itEval "[[1,2]]" `into` "1 2\n"
            itEval "[[1,2],[3,4]]" `into` "1 2\n3 4\n"
            
            itApply "id" `onInput` "foo" `into` "foo\n"
            itApply "L.transpose" `onInput` "1 2\n3 4" `into` "1 3\n2 4\n"
            itApply "L.map (!! 1)" `onInput` "1 2\n3 4" `into` "2\n4\n"
  
            itMap "(!! 1)" `onInput` "1 2\n3 4" `into` "2\n4\n"
    where onInput f x = f x
          into f x = f x
  
  withContextHSpec :: ((String -> String -> Spec)
                      -> (String -> String -> String -> Spec)
                      -> (String -> String -> String -> Spec)
                      -> Spec)
                   -> IO ()
  withContextHSpec body = do
    let it' flags expr input expected =
          let descr = "evals " ++ show expr ++
                      " on input " ++ show input ++
                      " equals to " ++ show expected
          in it descr $ do
               tmpd <- getTemporaryDirectory
               (tmpf, tmph) <- openTempFile tmpd "hawk_input"
               hPutStr tmph input
               hClose tmph
               out <- catchOutput $ do
                 processArgs $ concat [ ["-c", "tests/preludes/default"]
                                      , flags
                                      , [expr, tmpf]
                                      ]
               removeFile tmpf
               assertEqual descr expected out
    let [itApply,itMap] = map it' [["-a"],["-m"]]
    let itEval expr expected = it' [] expr "" expected
    hspec $ body itEval itApply itMap
  
  
  -- from http://stackoverflow.com/a/9664017/3286185
  catchOutput :: IO () -> IO String
  catchOutput f = do
      tmpd <- getTemporaryDirectory
      (tmpf, tmph) <- openTempFile tmpd "haskell_stdout"
      stdout_dup <- hDuplicate stdout
      hDuplicateTo tmph stdout
      hClose tmph
      f
      hDuplicateTo stdout_dup stdout
      str <- readFile tmpf
      length str `seq` removeFile tmpf
      return str
  