module Lib where
import Text.Regex.PCRE.Heavy
import Data.ByteString (ByteString)
import Data.String.Interpolate
import System.Exit
data Threshold = Threshold
{ thresholdName :: String
, thresholdRegex :: ByteString
, thresholdValue :: Double
} deriving (Read, Show)
type Coverage = Double
type ThresholdEvaluationResult = (Threshold, Coverage, Bool)
extractCoverage :: String -> ByteString -> Double
extractCoverage src regexStr =
case compileM regexStr [] of
Left e ->
error e
Right regex ->
case scan regex src of
(_, coverage:_):_ ->
read coverage
_ ->
0
evaluate :: String -> [Threshold] -> [ThresholdEvaluationResult]
evaluate src thresholds = do
threshold <- thresholds
let
coverage =
extractCoverage src (thresholdRegex threshold)
isPass =
coverage >= thresholdValue threshold
return (threshold, coverage, isPass)
reportThreshold :: ThresholdEvaluationResult -> String
reportThreshold (Threshold tName _ tValue, coverage, isPass) =
let
remark = if isPass then "✓" else "·"
sign = if isPass then "≥" else "<"
in
[i|#{remark} #{tName}: #{coverage}% (#{sign} #{tValue}%)|]
evaluateAndReport :: String -> [Threshold] -> (String, Bool)
evaluateAndReport src thresholds =
let
evalResults = evaluate src thresholds
isAllThresholdPass = all (\(_, _, isPass) -> isPass) evalResults
reportSummary =
if isAllThresholdPass
then "Code coverage threshold check: PASS"
else "Code coverage threshold check: FAIL"
report = unlines $ reportSummary : map reportThreshold evalResults
in
(report, isAllThresholdPass)
evaluateAndReport' :: IO ()
evaluateAndReport' = do
thresholds <- readFile ".hpc-threshold" >>= return . read
src <- getContents
let (report, isPass) = evaluateAndReport src thresholds
putStrLn report
if isPass
then exitWith ExitSuccess
else exitWith $ ExitFailure 1