|
1 | 1 | {-# LANGUAGE CPP #-} |
| 2 | +{-# LANGUAGE GeneralizedNewtypeDeriving #-} |
2 | 3 | import qualified Data.IntSet as IntSet |
3 | 4 | import Data.List (nub, sort, sortBy) |
4 | 5 | import qualified Data.List as List |
5 | 6 | import Data.Maybe (isJust, fromJust) |
6 | 7 | import qualified Data.Maybe as Maybe |
7 | 8 | import Data.Set |
8 | | -import Data.Set.Internal (link, merge) |
| 9 | +import Data.Set.Internal (link, link2) |
| 10 | +import Data.Set.Merge |
9 | 11 | import Prelude hiding (lookup, null, map, filter, foldr, foldl, foldl', all, take, drop, splitAt) |
10 | 12 | import Test.Tasty |
11 | 13 | import Test.Tasty.HUnit |
@@ -51,7 +53,7 @@ main = defaultMain $ testGroup "set-properties" |
51 | 53 | , testProperty "alterF/four" prop_alterF_four |
52 | 54 | , testProperty "alterF/valid" prop_alterF_valid |
53 | 55 | , testProperty "prop_Link" prop_Link |
54 | | - , testProperty "prop_Merge" prop_Merge |
| 56 | + , testProperty "prop_link2" prop_link2 |
55 | 57 | , testProperty "prop_UnionValid" prop_UnionValid |
56 | 58 | , testProperty "prop_UnionInsert" prop_UnionInsert |
57 | 59 | , testProperty "prop_UnionAssoc" prop_UnionAssoc |
@@ -122,6 +124,8 @@ main = defaultMain $ testGroup "set-properties" |
122 | 124 | , testProperty "lookupIndex" prop_lookupIndex |
123 | 125 | , testProperty "elemAt" prop_elemAt |
124 | 126 | , testProperty "deleteAt" prop_deleteAt |
| 127 | + , testProperty "merge" prop_merge |
| 128 | + , testProperty "mergeA" prop_mergeA |
125 | 129 | ] |
126 | 130 |
|
127 | 131 | -- A type with a peculiar Eq instance designed to make sure keys |
@@ -391,10 +395,10 @@ prop_Link x = forValidUnitTree $ \t -> |
391 | 395 | let (l,r) = split x t |
392 | 396 | in valid (link x l r) |
393 | 397 |
|
394 | | -prop_Merge :: Int -> Property |
395 | | -prop_Merge x = forValidUnitTree $ \t -> |
| 398 | +prop_link2 :: Int -> Property |
| 399 | +prop_link2 x = forValidUnitTree $ \t -> |
396 | 400 | let (l,r) = split x t |
397 | | - in valid (merge l r) |
| 401 | + in valid (link2 l r) |
398 | 402 |
|
399 | 403 | {-------------------------------------------------------------------- |
400 | 404 | Union |
@@ -752,3 +756,85 @@ prop_deleteAt i s = 0 <= i && i < size s ==> |
752 | 756 | toList s' === [x | (j, x) <- zip [0..] (toList s), i /= j] |
753 | 757 | where |
754 | 758 | s' = deleteAt i s |
| 759 | + |
| 760 | +prop_merge |
| 761 | + :: WhenMissingSpec Int |
| 762 | + -> WhenMissingSpec Int |
| 763 | + -> WhenMatchedSpec Int |
| 764 | + -> Set Int |
| 765 | + -> Set Int |
| 766 | + -> Property |
| 767 | +prop_merge miss1 miss2 match s1 s2 = |
| 768 | + valid s .&&. |
| 769 | + s === (filter (runIdentity . runWhenMissing miss1') s1Only `union` |
| 770 | + filter (runIdentity . runWhenMissing miss2') s2Only `union` |
| 771 | + filter (runIdentity . runWhenMatched match') s12Both) |
| 772 | + where |
| 773 | + miss1' = toSimpleWhenMissing miss1 |
| 774 | + miss2' = toSimpleWhenMissing miss2 |
| 775 | + match' = toSimpleWhenMatched match |
| 776 | + s = merge miss1' miss2' match' s1 s2 |
| 777 | + |
| 778 | + s1Only = difference s1 s2 |
| 779 | + s2Only = difference s2 s1 |
| 780 | + s12Both = intersection s1 s2 |
| 781 | + |
| 782 | + toSimpleWhenMissing s = case s of |
| 783 | + DropMissing -> dropMissing |
| 784 | + PreserveMissing -> preserveMissing |
| 785 | + FilterMissing f -> filterMissing (applyFun f) |
| 786 | + |
| 787 | + toSimpleWhenMatched (FilterMatched f) = filterMatched (applyFun f) |
| 788 | + |
| 789 | +prop_mergeA |
| 790 | + :: WhenMissingSpec Int |
| 791 | + -> WhenMissingSpec Int |
| 792 | + -> WhenMatchedSpec Int |
| 793 | + -> Set Int |
| 794 | + -> Set Int |
| 795 | + -> Property |
| 796 | +prop_mergeA miss1 miss2 match s1 s2 = |
| 797 | + valid s .&&. |
| 798 | + s === (filter (snd . runWhenMissing miss1') s1Only `union` |
| 799 | + filter (snd . runWhenMissing miss2') s2Only `union` |
| 800 | + filter (snd . runWhenMatched match') s12Both) .&&. |
| 801 | + xs === sort (concat (fmap (fst . runWhenMissing miss1') (toList s1Only) ++ |
| 802 | + fmap (fst . runWhenMissing miss2') (toList s2Only) ++ |
| 803 | + fmap (fst . runWhenMatched match') (toList s12Both))) |
| 804 | + where |
| 805 | + miss1' = toWhenMissing miss1 |
| 806 | + miss2' = toWhenMissing miss2 |
| 807 | + match' = toWhenMatched match |
| 808 | + (xs, s) = mergeA miss1' miss2' match' s1 s2 |
| 809 | + |
| 810 | + s1Only = difference s1 s2 |
| 811 | + s2Only = difference s2 s1 |
| 812 | + s12Both = intersection s1 s2 |
| 813 | + |
| 814 | + toWhenMissing s = case s of |
| 815 | + DropMissing -> dropMissing |
| 816 | + PreserveMissing -> preserveMissing |
| 817 | + FilterMissing f -> filterAMissing (\x -> ([x], applyFun f x)) |
| 818 | + |
| 819 | + toWhenMatched (FilterMatched f) = filterAMatched (\x -> ([x], applyFun f x)) |
| 820 | + |
| 821 | +data WhenMissingSpec a |
| 822 | + = DropMissing |
| 823 | + | PreserveMissing |
| 824 | + | FilterMissing (Fun a Bool) |
| 825 | + deriving Show |
| 826 | + |
| 827 | +instance (Arbitrary a, CoArbitrary a, Function a) |
| 828 | + => Arbitrary (WhenMissingSpec a) where |
| 829 | + arbitrary = oneof |
| 830 | + [ pure DropMissing |
| 831 | + , pure PreserveMissing |
| 832 | + , FilterMissing <$> arbitrary |
| 833 | + ] |
| 834 | + shrink s = case s of |
| 835 | + DropMissing -> [] |
| 836 | + PreserveMissing -> [] |
| 837 | + FilterMissing f -> FilterMissing <$> shrink f |
| 838 | + |
| 839 | +newtype WhenMatchedSpec a = FilterMatched (Fun a Bool) |
| 840 | + deriving (Show, Arbitrary) |
0 commit comments