packages feed

hegel-0.1.0: src/Hegel/Conformance.hs

-- | Helpers for writing Hegel conformance test binaries.
--
-- Each conformance binary reads parameters from @argv[1]@ (JSON), runs a
-- property test that draws values and writes metrics, then exits.
module Hegel.Conformance
  ( getTestCases,
    writeMetrics,
    formatMetrics,
  )
where

import System.Environment (lookupEnv)
import System.IO (IOMode (..), hFlush, hPutStr, withFile)

-- | Read the number of test cases from the @CONFORMANCE_TEST_CASES@
-- environment variable. Defaults to 50.
getTestCases :: IO Int
getTestCases = do
  val <- lookupEnv "CONFORMANCE_TEST_CASES"
  pure $ maybe 50 read val

-- | Format a list of key-value pairs as a JSON object string (one line).
-- Values are already pre-formatted as JSON (e.g. numbers without quotes,
-- strings with quotes, @\"null\"@ for null).
formatMetrics :: [(String, String)] -> String
formatMetrics pairs =
  "{" ++ intercalate ", " (map fmt pairs) ++ "}\n"
  where
    fmt (k, v) = "\"" ++ k ++ "\": " ++ v
    intercalate _ [] = ""
    intercalate sep (x : xs) = x ++ concatMap (sep ++) xs

-- | Write metrics to the file specified by @CONFORMANCE_METRICS_FILE@.
-- If the variable is not set, does nothing.
writeMetrics :: [(String, String)] -> IO ()
writeMetrics pairs = do
  mPath <- lookupEnv "CONFORMANCE_METRICS_FILE"
  case mPath of
    Nothing -> pure ()
    Just path ->
      withFile path AppendMode $ \h -> do
        hPutStr h (formatMetrics pairs)
        hFlush h