{-# LANGUAGE TemplateHaskell #-} module Main where import Control.DeepSeq (NFData, force) import Control.Exception (Exception(..), SomeException(..), bracket_, evaluate, try) import GHC.IO.Handle (hDuplicate, hDuplicateTo) import Language.Haskell.TH (Q, runQ) import Language.Haskell.TH.Syntax.Compat (Splice, examineSplice) import System.IO (IOMode(WriteMode), stderr, hFlush, withFile) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertFailure, testCase) import Test.Tasty.Travis import ValidLiterals import Even import ByteString failingEven :: Splice Q Even failingEven = validInteger 39 failingByteString :: Splice Q ByteString failingByteString = valid "λ" evenVal :: Even evenVal = $$(validInteger 38) bytestringVal :: ByteString bytestringVal = $$(valid "HTTP/1.1 GET") checkExceptions :: NFData a => String -> a -> TestTree checkExceptions name expr = testCase name $ do result <- try . evaluate . force $ expr case result of Right _ -> return () Left (SomeException e) -> assertFailure (displayException e) withRedirectedStderr :: IO a -> IO a withRedirectedStderr act = withFile "/dev/null" WriteMode $ \nullHnd -> do hFlush stderr oldStderr <- hDuplicate stderr bracket_ (hDuplicateTo nullHnd stderr) (hDuplicateTo oldStderr stderr) act checkTHFails :: String -> Splice Q a -> TestTree checkTHFails name thExpr = testCase name $ do result <- try . withRedirectedStderr . runQ $ examineSplice thExpr case result of Right _ -> assertFailure "TH didn't fail!" Left e | Just ValidationFailure{} <- fromException e -> return () | otherwise -> assertFailure "Unexpected TH failure!" allTests :: TestTree allTests = testGroup "Tests" [ checkExceptions "Even" evenVal , checkExceptions "ByteString" bytestringVal , checkTHFails "Failing Even" $ failingEven , checkTHFails "Failing ByteString" $ failingByteString ] main :: IO () main = travisTestReporter travisConfig [] allTests where travisConfig = defaultConfig { travisFoldGroup = FoldMoreThan 1 , travisSummaryWhen = SummaryAlways }