module Foundation.Check.Print
( propertyToResult
, PropertyResult(..)
, diffBlame
) where
import Foundation.Check.Property
import Foundation.Check.Types
import Foundation.Primitive.Imports
import Foundation.Collection
import Foundation.Class.Bifunctor (bimap)
import Foundation.Numerical
propertyToResult :: PropertyTestArg -> (PropertyResult, Bool)
propertyToResult propertyTestArg =
let args = propertyGetArgs propertyTestArg
checks = getChecks propertyTestArg
in if checkHasFailed checks
then printError args checks
else (PropertySuccess, length args > 0)
where
printError args checks = (PropertyFailed (mconcat $ loop 1 args), False)
where
loop :: Word -> [String] -> [String]
loop _ [] = printChecks checks
loop !i (a:as) = "parameter " <> show i <> " : " <> a <> "\n" : loop (i+1) as
printChecks (PropertyBinaryOp True _ _ _) = []
printChecks (PropertyBinaryOp False n a b) =
[ "Property `a " <> n <> " b' failed where:\n"
, " a = " <> a <> "\n"
, " " <> bl1 <> "\n"
, " b = " <> b <> "\n"
, " " <> bl2 <> "\n"
]
where
(bl1, bl2) = diffBlame a b
printChecks (PropertyNamed True _) = []
printChecks (PropertyNamed False e) = ["Property " <> e <> " failed"]
printChecks (PropertyBoolean True) = []
printChecks (PropertyBoolean False) = ["Property failed"]
printChecks (PropertyFail _ e) = ["Property failed: " <> e]
printChecks (PropertyAnd True _ _) = []
printChecks (PropertyAnd False a1 a2) =
[ "Property `cond1 && cond2' failed where:\n"
, " cond1 = " <> h1 <> "\n"
]
<> ((<>) " " <$> hs1)
<>
[ " cond2 = " <> h2 <> "\n"
]
<> ((<>) " " <$> hs2)
where
(h1, hs1) = f a1
(h2, hs2) = f a2
f a = case printChecks a of
[] -> ("Succeed", [])
(x:xs) -> (x, xs)
propertyGetArgs (PropertyArg a p) = a : propertyGetArgs p
propertyGetArgs (PropertyEOA _) = []
getChecks (PropertyArg _ p) = getChecks p
getChecks (PropertyEOA c ) = c
diffBlame :: String -> String -> (String, String)
diffBlame a b = bimap fromList fromList $ go ([], []) (toList a) (toList b)
where
go (acc1, acc2) [] [] = (acc1, acc2)
go (acc1, acc2) l1 [] = (acc1 <> blaming (length l1), acc2)
go (acc1, acc2) [] l2 = (acc1 , acc2 <> blaming (length l2))
go (acc1, acc2) (x:xs) (y:ys)
| x == y = go (acc1 <> " ", acc2 <> " ") xs ys
| otherwise = go (acc1 <> "^", acc2 <> "^") xs ys
blaming n = replicate n '^'