gigaparsec-0.2.2.2: test/Text/Gigaparsec/DebugTests.hs
{-# LANGUAGE OverloadedStrings #-}
module Text.Gigaparsec.DebugTests where
import Test.Tasty
import Test.Tasty.HUnit
import Text.Gigaparsec
import Text.Gigaparsec.Char
import Text.Gigaparsec.Debug
import Text.Gigaparsec.Internal qualified as Internal
import Text.Gigaparsec.Internal.Errors qualified as Internal
import Text.Gigaparsec.Internal.RT qualified as Internal
import System.IO
import Data.Knob
import Data.Knob qualified as Knob (getContents)
import Data.ByteString.Char8 (unpack)
import Data.List (isInfixOf, isPrefixOf)
{-
This is quite interesting, because testing the debug combinator is a bit
odd. We need to redirect the standard IO channels to point to our own
implementations, and then analyse the input to look for key indicators
its working without testing the exact formats (which is not useful).
-}
tests :: TestTree
tests = testGroup "Debug" [
debugTests
]
debugTests :: TestTree
debugTests = testGroup "debug should"
[ testCase "have correct depth when nested" do
output <- mockDebug "a\r\n \t" $ \config ->
debugWith config "outer" (debugWith config "inner" item)
-- a line containing inner should have more leading spaces than
-- one containing outer
let ls = lines output
let outers = filter (isInfixOf "outer") ls
let inners = filter (isInfixOf "inners") ls
assertBool "all outer lines should have no leading spaces" $
not (any (isPrefixOf " ") outers)
assertBool "all inner lines should have leading spaces" $
all (isPrefixOf " ") inners
, testCase "don't have line breaks in the input string" do
output <- mockDebug "\n\n\n\n\n\n" $ \config ->
debugWith config "letter" letter
let ls = lines output
length ls @?= 4
-- TODO: watched registers never boil
]
ioParse :: Parsec a -> String -> IO ()
ioParse (Internal.Parsec p) inp = Internal.rtToIO $ p (Internal.emptyState inp) good bad
where good :: a -> Internal.State -> Internal.RT ()
good _ _ = return ()
bad :: Internal.Error -> Internal.State -> Internal.RT ()
bad _ _ = return ()
mockDebug :: String -> (DebugConfig -> Parsec a) -> IO String
mockDebug input f =
do mock <- newKnob ""
hMock <- newFileHandle mock "mock" WriteMode
let config = debugConfig { handle = hMock }
ioParse (f config) input
hClose hMock
unpack <$> Knob.getContents mock