{-# OPTIONS_GHC -Wno-x-partial #-}
import Control.Exception (bracket)
import Fireplace
import GHC.IO.Handle (hDuplicate, hDuplicateTo)
import System.Environment (withArgs)
import System.IO
import System.Process (createPipe)
import Test.Tasty
import Test.Tasty.HUnit
import Text.Regex.TDFA ((=~))
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests = testGroup "Tests" [unitTests]
runWithMock :: [String] -> String -> IO () -> IO [String]
runWithMock mockArgs mockInput action = do
(readIn, writeIn) <- createPipe
(readOut, writeOut) <- createPipe
hPutStr writeIn mockInput
hClose writeIn
withArgs mockArgs $ do
bracket
( do
oldIn <- hDuplicate stdin
oldOut <- hDuplicate stdout
hDuplicateTo readIn stdin
hDuplicateTo writeOut stdout
return (oldIn, oldOut)
)
( \(oldIn, oldOut) -> do
hDuplicateTo oldIn stdin
hDuplicateTo oldOut stdout
hClose readIn
hClose writeOut
)
(const action)
lines <$> hGetContents readOut
assertTiming :: String -> Assertion
assertTiming timing = do
let match = "^RT [0-9]+ ns$"
isValid = timing =~ match :: Bool
assertBool ("Timing line '" ++ timing ++ "' didn't match regex") isValid
unitTests :: TestTree
unitTests =
testGroup
"v1Run Integration"
[ testCase "Selects Part One and shows timing" $ do
output@(ans : timing : _) <- runWithMock ["--part", "1"] "my input" (v1Run solvePt1 solvePt2)
length output @?= 2
ans @?= "25"
assertTiming timing
, testCase "Selects Part Two" $ do
output@(ans : timing : _) <- runWithMock ["--part", "2", "--args", "Reindeer"] "December" (v1Run solvePt1 solvePt2)
length output @?= 2
ans @?= "December Reindeer"
assertTiming timing
]
solvePt1 :: String -> [String] -> Int
solvePt1 _ _ = 25
solvePt2 :: String -> [String] -> String
solvePt2 input args = input ++ " " ++ concat args