{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving, TypeFamilies, TypeOperators, TypeSynonymInstances, UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} import Test.Hspec.Expectations import Test.Hspec.HUnit () import Test.Hspec.QuickCheck (prop) import Test.Hspec import Test.HUnit import Test.QuickCheck (Arbitrary, arbitrary, shrink, listOf) import Control.Monad (liftM, liftM2) import qualified Data.List as List import Data.SafeCopy import Data.Serialize.Get (runGet) import Data.Serialize.Put (runPut) import Data.Typeable import Data.EnumMapSet (EnumMapSet, (:&)(..), S(..)) import qualified Data.EnumMapSet as EMS newtype ID1 = ID1 Int deriving (Show, Enum, Arbitrary, Eq, Num, Typeable) newtype ID2 = ID2 Int deriving (Show, Enum, Arbitrary, Eq, Num, Typeable) type TestKey1 = S ID1 type TestEms1 = EnumMapSet TestKey1 type TestKey2 = ID2 :& S ID1 type TestEms2 = EnumMapSet TestKey2 instance (Arbitrary a, Arbitrary b) => Arbitrary (a :& b) where arbitrary = liftM2 (:&) arbitrary arbitrary shrink (x :& y) = [ x' :& y | x' <- shrink x ] ++ [ x :& y' | y' <- shrink y ] instance (Arbitrary s) => Arbitrary (S s) where arbitrary = liftM S arbitrary instance (Arbitrary k, EMS.Result k k () ~ (), EMS.IsKey k, EMS.SubKey k k ()) => Arbitrary (EnumMapSet k) where arbitrary = fmap EMS.fromList $ listOf arbitrary tens :: [Int] tens = [1, 10, 100, 1000, 10000, 100000, 1000000] l1IDtens :: TestEms1 l1IDtens = EMS.fromList $ map (\k -> S $ ID1 k) tens l1tens :: EnumMapSet (S Int) l1tens = EMS.fromList $ map (\k -> S k) tens l2tens :: TestEms2 l2tens = EMS.fromList $ do k1 <- [1, 5, 10] k2 <- tens return $ (ID2 k2) :& (S $ ID1 k1) main :: IO () main = hspec $ do describe "all" $ do let f :: S Int -> Bool f (S s) = s > 0 it "returns True for an empty EnumMapSet" $ EMS.all (const False) (EMS.empty :: EnumMapSet (Int :& S Int)) `shouldBe` True it "returns False when given all False" $ EMS.all (const False) (EMS.fromList [S 1, S (2 :: Int)]) `shouldBe` False it "returns False when given one False" $ EMS.all f (EMS.fromList [S 5, S 2, S (-1),S 1000]) `shouldBe` False let prop_list :: [Int] -> Bool prop_list list = let list' = map S list in EMS.all f (EMS.fromList list') == List.all f list' prop "is equivalent to List.all" prop_list describe "toList and fromList" $ do let testEq :: TestEms2 -> Bool testEq emm = op == emm where op = EMS.fromList $ EMS.toList emm prop "Leaves data intact" testEq describe "Typeable Instance" $ do it "TypeOf is unique when ID types differ" $ ((typeOf l1IDtens) == (typeOf l1tens)) @?= False it "TypeOf is unique when different levels" $ ((typeOf l2tens) == (typeOf l1tens)) @?= False describe "SafeCopy Instance" $ do let testEq :: TestEms2 -> Bool testEq ems = op == Right ems where op = runGet safeGet $ runPut $ safePut ems prop "Leaves data intact" testEq