@@ -20,7 +20,8 @@ import Test.Hspec (Arg, Expectation, Spec, SpecWith, describe, it)
20import Test.Hspec.Hedgehog (hedgehog)
20import Test.Hspec.Hedgehog (hedgehog)
22import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), delete, insert, invariantCheck,
22import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), delete, insert, invariantCheck,
23− lookup, member, generateOrderMapping, fromSortedList)
23+ lookup, member, generateOrderMapping, fromSortedList, alter,
25import qualified Hedgehog.Gen as Gen
26import qualified Hedgehog.Gen as Gen
26import qualified Hedgehog.Range as Range
27import qualified Hedgehog.Range as Range
@@ -34,6 +35,10 @@ typeRepMapPropertySpec = describe "TypeRepMap Property tests" $ do
34 deleteMemberSpec
35 deleteMemberSpec
35 insertInvariantSpec
36 insertInvariantSpec
36 deleteInvariantSpec
37 deleteInvariantSpec
37 describe "Internal helpers" $ do
42 describe "Internal helpers" $ do
38 generateOrderMappingInvariantSpec
43 generateOrderMappingInvariantSpec
39 describe "Instance Laws" $ do
44 describe "Instance Laws" $ do
@@ -82,11 +87,42 @@ deleteInvariantSpec = it "invariantCheck (delete k b) == True" $ hedgehog $ do
82 WrapTypeable (_ :: IntProxy n) <- forAll genTF
87 WrapTypeable (_ :: IntProxy n) <- forAll genTF
83 assert $ invariantCheck (delete @n m)
88 assert $ invariantCheck (delete @n m)
90+alterInsertSpec :: Property
91+alterInsertSpec = it "insert proxy m === alter (const (Just proxy)) m" $ hedgehog $ do
93+ WrapTypeable (proxy :: IntProxy n) <- forAll genTF
94+ insert proxy m === alter (const (Just proxy)) m
96+alterDeleteSpec :: Property
97+alterDeleteSpec = it "delete proxy m === alter (const Nothing) m" $ hedgehog $ do
98+ WrapTypeable (proxy :: IntProxy n) <- forAll genTF
99+ m <- insert proxy <$> forAll genMap
100+ delete @n @IntProxy m === alter @n @IntProxy (const Nothing) m
102+alterAdjustSpec :: Property
103+alterAdjustSpec = it "adjust f m == alter (fmap f) m" $ hedgehog $ do
105+ WrapTypeable (_ :: IntProxy n) <- forAll genTF
106+ let f (IntProxy p n) = IntProxy p (n * 10)
107+ adjust @n @IntProxy f m === alter @n @IntProxy (fmap f) m
109+alterModifySpec :: Property
110+alterModifySpec = it "lookup k (alter f) == f (lookup k m)" $ hedgehog $ do
112+ WrapTypeable (_ :: IntProxy n) <- forAll genTF
113+ randInt <- forAll (Gen.int Range.constantBounded)
114+ -- Function with some interesting behaviour, which inserts, seletes and modifies
115+ let f Nothing = Just (IntProxy Proxy randInt)
116+ f (Just (IntProxy p n))
118+ | otherwise = Just $ IntProxy p (n * 10)
119+ lookup @n @IntProxy (alter @n f m) === f (lookup @n @IntProxy m)
85----------------------------------------------------------------------------
121----------------------------------------------------------------------------
86-- Internal helpers
122-- Internal helpers
87----------------------------------------------------------------------------
123----------------------------------------------------------------------------
88generateOrderMappingInvariantSpec :: Property
124generateOrderMappingInvariantSpec :: Property
89−generateOrderMappingInvariantSpec =
125+generateOrderMappingInvariantSpec =
90 it "fmap (fromSortedList [1 .. n] !!) (generateOrderMapping n) == [1 .. n]" $ hedgehog $ do
126 it "fmap (fromSortedList [1 .. n] !!) (generateOrderMapping n) == [1 .. n]" $ hedgehog $ do
91 n <- forAll $ Gen.int (Range.linear 0 100)
127 n <- forAll $ Gen.int (Range.linear 0 100)
92 fmap (fromSortedList [1 .. n] !!) (generateOrderMapping n) === [1 .. n]
128 fmap (fromSortedList [1 .. n] !!) (generateOrderMapping n) === [1 .. n]
@@ -95,41 +131,16 @@ generateOrderMappingInvariantSpec =
95-- Semigroup and Monoid laws
131-- Semigroup and Monoid laws
96----------------------------------------------------------------------------
132----------------------------------------------------------------------------
98−#if __GLASGOW_HASKELL__ < 806
99−{- | This newtype is used to compare 'TypeRepMap's using only 'Fingerprint's.
100−It's not a good idea to write such 'Eq' instance for 'TypeRepMap' itself because
101−it doesn't compare values so it's not true equality. But this should be enough
104−newtype FpMap f = FpMap (TypeRepMap f)
105− deriving newtype (Show, Semigroup, Monoid)
107−instance Eq (FpMap f) where
108− FpMap (TypeRepMap as1 bs1 _ _) == FpMap (TypeRepMap as2 bs2 _ _) =
109− as1 == as2 && bs1 == bs2
112semigroupAssocSpec :: Property
134semigroupAssocSpec :: Property
113semigroupAssocSpec = it "x <> (y <> z) == (x <> y) <> z" $ hedgehog $ do
135semigroupAssocSpec = it "x <> (y <> z) == (x <> y) <> z" $ hedgehog $ do
114−#if __GLASGOW_HASKELL__ >= 806
115 x <- forAll genMap
136 x <- forAll genMap
116 y <- forAll genMap
137 y <- forAll genMap
117 z <- forAll genMap
138 z <- forAll genMap
119− x <- FpMap <$> forAll genMap
120− y <- FpMap <$> forAll genMap
121− z <- FpMap <$> forAll genMap
123 (x <> (y <> z)) === ((x <> y) <> z)
139 (x <> (y <> z)) === ((x <> y) <> z)
125monoidIdentitySpec :: Property
141monoidIdentitySpec :: Property
126monoidIdentitySpec = it "x <> mempty == mempty <> x == x" $ hedgehog $ do
142monoidIdentitySpec = it "x <> mempty == mempty <> x == x" $ hedgehog $ do
127−#if __GLASGOW_HASKELL__ >= 806
128 x <- forAll genMap
143 x <- forAll genMap
130− x <- FpMap <$> forAll genMap
133 x <> mempty === x
144 x <> mempty === x
134 mempty <> x === x
145 mempty <> x === x
@@ -150,3 +161,17 @@ genTF = do
150 case someNatVal randNat of
161 case someNatVal randNat of
151 Just (SomeNat proxyNat) -> pure $ WrapTypeable $ IntProxy proxyNat randInt
162 Just (SomeNat proxyNat) -> pure $ WrapTypeable $ IntProxy proxyNat randInt
152 Nothing -> error "Invalid test generator"
163 Nothing -> error "Invalid test generator"
165+----------------------------------------------------------------------------
167+----------------------------------------------------------------------------
168+#if __GLASGOW_HASKELL__ < 806
169+{- | We add an orphan Eq instance for old GHC versions just to make testing easier.
170+It's not a good idea to write such 'Eq' instance for 'TypeRepMap' itself because
171+it doesn't compare values so it's not true equality. But this should be enough
174+instance Eq (TypeRepMap f) where
175+ TypeRepMap as1 bs1 _ _ == TypeRepMap as2 bs2 _ _ =
176+ as1 == as2 && bs1 == bs2