{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
import Data.Map.Word8 (Map)
import Data.Proxy (Proxy (..))
import Data.Semigroup (Sum)
import Data.Word (Word8)
import Test.Tasty (TestTree, defaultMain, testGroup)
import Test.Tasty.QuickCheck (Arbitrary, Discard (Discard), property, testProperty, (===))
import qualified Data.List as List
import qualified Data.Map.Word8 as Map
import qualified Test.QuickCheck.Classes as QCC
import qualified Test.Tasty.QuickCheck as TQC
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests =
testGroup
"byte-containers"
[ testGroup
"append"
[ testProperty "doubleton" $ \ka (va :: Word) kb vb ->
Map.toList
(Map.union (Map.singleton ka va) (Map.singleton kb vb))
=== ( case compare ka kb of
EQ -> [(ka, va)]
LT -> [(ka, va), (kb, vb)]
GT -> [(kb, vb), (ka, va)]
)
, testProperty "lookup" lookupProp
, testProperty "associative" $ \alist blist clist ->
let a = Map.fromList alist :: Map Word
b = Map.fromList blist
c = Map.fromList clist
in Map.union a (Map.union b c)
=== Map.union (Map.union a b) c
, lawsToTest (QCC.semigroupLaws (Proxy :: Proxy (Map [Integer])))
, lawsToTest (QCC.monoidLaws (Proxy :: Proxy (Map [Integer])))
, lawsToTest (QCC.commutativeMonoidLaws (Proxy :: Proxy (Map (Sum Integer))))
, lawsToTest (QCC.functorLaws (Proxy :: Proxy Map))
]
, testGroup
"insert"
[ testProperty "replaces" $ \k v v' alist ->
let a = Map.insert k v (Map.fromList alist) :: Map Word
a' = Map.insert k v' a
in if
| v /= v' ->
Map.lookup k a' === Just v'
| otherwise -> property Discard
]
]
instance (Arbitrary a) => Arbitrary (Map a) where
arbitrary = Map.fromList <$> TQC.arbitrary
lookupProp :: TQC.Property
lookupProp = TQC.property $ \(xs :: [(Word8, Integer)]) ->
let ys = Map.fromList xs
in foldr
( \x r -> case List.lookup x xs == Map.lookup x ys of
True -> r
False -> TQC.counterexample ("key " ++ show x) False
)
(TQC.property True)
[0 .. 255 :: Word8]
lawsToTest :: QCC.Laws -> TestTree
lawsToTest (QCC.Laws name pairs) = testGroup name (map (uncurry TQC.testProperty) pairs)