waargonaut-0.6.0.0: test/Decoder/Laws.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Decoder.Laws (decoderLaws) where
import Control.Applicative (Applicative, pure)
import Control.Monad.Except (throwError)
import Data.Functor.Alt (Alt ((<!>)))
import Data.Functor.Identity (Identity)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.Hedgehog (testProperty)
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Waargonaut.Attoparsec as WA
import qualified Waargonaut.Decode as D
import Waargonaut.Decode.Error (DecodeError (ConversionFailure))
import Waargonaut.Decode.Types (Decoder)
import qualified Laws
runD :: Decoder Identity a -> Either (DecodeError, D.CursorHistory) a
runD d = WA.pureDecodeAttoparsecText d "true"
newtype ShowDecoder a = SD (Decoder Identity a)
deriving (Functor, Monad, Applicative)
instance Alt ShowDecoder where
(SD a) <!> (SD b) = SD (a <!> b)
instance Eq a => Eq (ShowDecoder a) where
(SD a) == (SD b) = runD a == runD b
instance Show a => Show (ShowDecoder a) where
show (SD d) = show $ runD d
genShowDecoder :: Gen a -> Gen (ShowDecoder a)
genShowDecoder genA = Gen.choice
[ SD . pure <$> genA
, SD <$> Gen.constant (throwError $ ConversionFailure "Intentional DecodeError (TEST)")
]
decoderLaws :: TestTree
decoderLaws = testGroup "Decoder Laws"
[ testGroup "Applicative"
[ testProperty "identity" $ Laws.applicative_id genShowDecoder Gen.bool
, testProperty "composition" $ Laws.applicative_composition genShowDecoder Gen.bool Gen.bool Gen.bool
, testProperty "homomorphism" $ Laws.applicative_homomorphism sdPure Gen.bool Gen.bool
, testProperty "interchange" $ Laws.applicative_interchange sdPure Gen.bool Gen.bool
]
, testGroup "Alt"
[ testProperty "associativity" $ Laws.alt_associativity genShowDecoder Gen.bool
, testProperty "left distributes" $ Laws.alt_left_distributes genShowDecoder Gen.bool Gen.bool
]
, testGroup "Monad"
[ testProperty "return a >>= k = k a" $ Laws.monad_return_bind genShowDecoder Gen.bool Gen.bool
, testProperty "m >>= return = m" $ Laws.monad_bind_return_id genShowDecoder Gen.bool
, testProperty "associativity" $ Laws.monad_associativity genShowDecoder Gen.bool Gen.bool Gen.bool
]
, testGroup "Functor"
[ testProperty "'fmap compose'" $ Laws.fmap_compose genShowDecoder Gen.bool Gen.bool Gen.bool
]
]
where
sdPure = (pure :: a -> ShowDecoder a)