caliper-0.1.0.0: test/Main.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ViewPatterns #-}
module Main where
import Data.TreeDiff
import Data.TreeDiff.Golden
import Data.TreeDiff.Instances.Caliper ()
import Data.Void
import System.FilePath
import Test.Tasty
import Test.Tasty.Golden.Advanced
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
import Data.Time.LocalTime
import Text.Megaparsec
import Caliper.Cli
import Caliper.Syntax
main :: IO ()
main = defaultMain tests
type ParseResult = Either (ParseErrorBundle T.Text Void)
tests :: TestTree
tests =
testGroup
"Tests"
[ parserTests
, resolutionTests
, queryTests
, histogramTests
]
parserTests :: TestTree
parserTests =
testGroup
"Parser"
[ parserTestOk "ok_001" "ok_001.clp"
, parserTestOk "ok_002" "ok_002.clp"
, parserTestOk "ok_003" "ok_003.clp"
, parserTestOk "ok_004" "ok_004.clp"
, parserTestOk "ok_005" "ok_005.clp"
, parserTestOk "ok_006" "ok_006.clp"
, parserTestOk "ok_007" "ok_007.clp"
, parserTestOk "ok_008" "ok_008.clp"
, parserTestOk "ok_009" "ok_009.clp"
, parserTestOk "ok_010" "ok_010.clp"
, parserTestOk "ok_012" "ok_012.clp"
, rawParserTestErr "err_003" "err_003.clp"
, rawParserTestErr "err_005" "err_005.clp"
, parserTestOk "ok_013" "ok_013.clp"
, parserTestOk "ok_014" "ok_014.clp"
, rawParserTestOk "ok_014_raw" "ok_014.clp"
, parserTestOk "ok_015" "ok_015.clp"
]
-- Doesn't resolve
rawParserTestOk :: String -> FilePath -> TestTree
rawParserTestOk name fp = mkGoldenTestOk (\_src -> pure) name ("parser" </> fp)
rawParserTestErr :: String -> FilePath -> TestTree
rawParserTestErr name fp = mkGoldenTestErr name ("parser" </> fp)
-- Resolves
parserTestOk :: String -> FilePath -> TestTree
parserTestOk name fp = mkGoldenTestOk (\_src -> pure . resolve) name ("parser" </> fp)
resolutionTests :: TestTree
resolutionTests =
testGroup
"Resolution"
[ resolveTestErr "err_001" "err_001.clp"
, resolveTestErr "err_002" "err_002.clp"
, resolveTestErr "err_004" "err_004.clp"
]
-- Parses but shouldn't resolve because of semantic errors
resolveTestErr :: String -> FilePath -> TestTree
resolveTestErr name fp = mkGoldenTestOk resolveShouldError name ("parser" </> fp)
where
resolveShouldError :: T.Text -> RawAst -> IO T.Text
resolveShouldError src (resolve -> (errs, _)) = pure $ mconcat $ map (resolutionErrorPretty src) errs
histogramTests :: TestTree
histogramTests =
testGroup
"histogram"
[ histogramTest groupEntriesByDay "001_groupByDay" "001.clp"
, histogramTest (fmap histogramLine . groupEntriesByDay) "001_groupByDay_cli" "001.clp"
]
histogramTest
:: ToExpr expr
=> ([ResolvedEntry] -> expr)
-> String
-> FilePath
-> TestTree
histogramTest f name fp = mkGoldenTestOk (\_src -> pure . fmap f . resolve) name ("histogram" </> fp)
queryTests :: TestTree
queryTests =
testGroup
"Query"
[ queryTest [HasKeyValue "foo" "bar"] "001_foobar" "001.clp"
, queryTest [Negate $ HasKeyValue "foo" "bar"] "001_notfoobar" "001.clp"
, beforeFilterTest (read "2025-10-02 22:59:06") "001_before_complete" "001.clp"
, beforeFilterTest (read "2025-10-02 22:59:55") "001_before_truncate" "001.clp"
, afterFilterTest (read "2025-10-02 22:59:06") "001_after_complete" "001.clp"
, afterFilterTest (read "2025-10-02 22:59:55") "001_after_truncate" "001.clp"
, beforeFilterTest (read "2025-10-02 22:59:06") "002_before_complete" "002.clp"
, beforeFilterTest (read "2025-10-02 22:59:55") "002_before_truncate" "002.clp"
, afterFilterTest (read "2025-10-02 22:59:06") "002_after_complete" "002.clp"
, afterFilterTest (read "2025-10-02 22:59:55") "002_after_truncate" "002.clp"
]
queryTest :: [TagPredicate] -> String -> FilePath -> TestTree
queryTest filters name fp =
mkGoldenTestOk
(\_src -> pure . fmap (filterByTags filters) . resolve)
name
("query" </> fp)
beforeFilterTest :: LocalTime -> String -> FilePath -> TestTree
beforeFilterTest thres name fp =
mkGoldenTestOk
(\_src -> pure . fmap (entriesBefore thres) . resolve)
name
("query" </> fp)
afterFilterTest :: LocalTime -> String -> FilePath -> TestTree
afterFilterTest thres name fp =
mkGoldenTestOk
(\_src -> pure . fmap (entriesAfter thres) . resolve)
name
("query" </> fp)
parsedRight :: IO (ParseResult a) -> IO a
parsedRight x =
x >>= \case
Left err -> fail $ errorBundlePretty err
Right ok -> pure ok
mkGoldenTestOk
:: ToExpr expr
=> (T.Text -> RawAst -> IO expr)
-> String
-> FilePath
-> TestTree
mkGoldenTestOk f = mkGoldenTest $ \src -> \case
Right output -> do
output' <- f src output
pure $ toExpr output'
Left err -> fail $ errorBundlePretty err
mkGoldenTestErr :: String -> FilePath -> TestTree
mkGoldenTestErr = mkGoldenTest $ \_src -> \case
Right output -> fail $ "Unexpected success:\n" <> show output
Left err -> pure $ errorBundlePretty err
mkGoldenTest
:: (Eq expr, ToExpr expr)
=> ( forall s e
. (VisualStream s, TraversableStream s, ShowErrorComponent e)
=> T.Text
-> Either (ParseErrorBundle s e) RawAst
-> IO expr
)
-- ^ handle the parse result
-> String
-> FilePath
-> TestTree
mkGoldenTest f name fname =
ediffGolden goldenTest name outFilePath $ do
content <- TIO.readFile inFilePath
f content $ runParser caliperAst inFilePath content
where
inFilePath = "test" </> "data" </> fname
outFilePath = inFilePath `replaceFileName` name `addExtension` ".expr"