strongweak-0.5.0: test/Strongweak/StrengthenSpec.hs
module Strongweak.StrengthenSpec ( spec ) where
import Strongweak.Util.Typeable
import Strongweak.Util.Text
import Strongweak
import Strongweak.Strengthen
import Common
import Data.Either.Validation
import Test.Hspec
import Numeric.Natural ( Natural )
import Data.Word
import Data.Foldable qualified as Foldable
import Data.Typeable ( TypeRep )
spec :: Spec
spec = do
it "returns a precise error for failed generic strengthening (named field)" $ do
let w = fromIntegral (maxBound @Word32) + 1
d = DP w 43 1 2 3 :: DP 'Weak
e = sfGenericSW1Show
"DP" "DP" 0 (Just "dp1f0")
(typeRep' @Natural) (typeRep' @Word32) w
strengthen @(DP 'Strong) d `shouldSatisfy` svEqFail e
it "returns a precise error for failed generic strengthening (unnamed field)" $ do
let w = fromIntegral (maxBound @Word8) + 1
d = DS0 0 1 2 3 w :: DS 'Weak
e = sfGenericSW1Show
"DS" "DS0" 4 Nothing
(typeRep' @Natural) (typeRep' @Word8) w
strengthen @(DS 'Strong) d `shouldSatisfy` svEqFail e
-- build strengthen failure
-- one failure, generic with SW, one wrapped failure (detailed)
sfGenericSW1Show
:: Show w
=> String -> String -> Natural -> Maybe String
-> TypeRep -> TypeRep -> w
-> Fail
sfGenericSW1Show d c i f tw ts w =
FailField d d c c i f i f (pure e)
where
e = FailShow tw ts (Just (tshow w)) detail
detail = error "tried to check failure descriptions in tests (bad idea)"
-- only test field and show, and ignore message in latter
sfEq :: Fail -> Fail -> Bool
sfEq s1 s2 = case s1 of
FailField dw ds cw cs iw fw is fs es -> case s2 of
FailField dw' ds' cw' cs' iw' fw' is' fs' es' ->
dw == dw' && ds == ds'
&& cw == cw' && cs == cs'
&& iw == iw' && is == is'
&& fw == fw' && fs == fs'
&& and (zipWith sfEq (Foldable.toList es) (Foldable.toList es'))
_ -> False
FailShow wt st wv _ -> case s2 of
FailShow wt' st' wv' _ ->
wt == wt' && st == st'
&& wv == wv'
_ -> False
_ -> error "unexpected strengthen fail"
svEqFail :: Fail -> Result s -> Bool
svEqFail e = \case
Success{} -> False
Failure es ->
case Foldable.toList es of
[e'] -> sfEq e e'
_ -> False