{- | Module : Test.SDP.Set Copyright : (c) Andrey Mulik 2019 License : BSD-style Maintainer : work.a.mulik@gmail.com Portability : non-portable (requires non-portable modules) @Test.SDP.Set@ provides basic test quite for 'Set' class. -} module Test.SDP.Set ( -- * Set test TestSet, TestSet1, setTest, -- * Particular tests basicSetTest, insdelSetTest, lookupSetTest, unintSetTest, diffSetTest, elemSetTest ) where import Prelude () import SDP.SafePrelude import SDP.Linear import SDP.Set default () -------------------------------------------------------------------------------- -- | TestSet is service type synonym for more comfortable quickCheck using. type TestSet s o = o -> s -> s -> Bool -- | TestSet1 is service type synonym for more comfortable quickCheck using. type TestSet1 s o = o -> s o -> s o -> Bool -------------------------------------------------------------------------------- {- | 'basicSetTest' checks relations of 'set', ('/?\') and ('\?/'). Note that basicSetTest requires any @('Set' s o) => s@, not necessarily a set (may contain any data). -} basicSetTest :: (Set s o, Nullable s, Eq s, Ord o) => s -> Bool basicSetTest sx = and [ isNull sx == isNull sx', set sx' == sx', (sx' \?/ sx') /= (sx' /?\ sx') ] where sx' = set sx {- | 'insdelSetTest' checks rules of 'insert' and 'delete'. Note that 'insdelSetTest' requires a set, not any @('Set' s o) => s@. -} insdelSetTest :: (Set s o, Eq s, Ord o) => o -> s -> Bool insdelSetTest e sx' = and [ (insert e sx' == sx') || not (member e sx'), (delete e sx' == sx') || (member e sx') ] {- | 'unintSetTest' checks the laws of union ('\/') and intersection ('/\'). Note that unintSetTest requires any @('Set' s o) => s@, not necessarily a set (may contain any data). -} unintSetTest :: (Set s o, Linear s o, Ord o) => s -> s -> Bool unintSetTest sx' sy' = and [ (is `isSubseqOf` sx') && (is `isSubseqOf` sy') && (is `isSubseqOf` un), (sx' `isSubseqOf` un) && (sy' `isSubseqOf` un) ] where is = sx' /\ sy' un = sx' \/ sy' {- | 'diffSetTest' checks laws of difference ('\\') and symmetric difference ('\^/'). Note that diffSetTest requires a set, not any @('Set' s o) => s@ -} diffSetTest :: (Set s o, Linear s o, Ord o) => s -> s -> Bool diffSetTest sx' sy' = and [ (cp `isSubseqOf` sx') && (isNull cp || not (cp `isSubseqOf` sy')) && (cp `isSubseqOf` un), (isNull sd && isNull is || sd /?\ is) && (sd `isSubseqOf` un) ] where is = sx' /\ sy' un = sx' \/ sy' cp = sx' \\ sy' sd = sx' \^/ sy' {- | 'elemSetTest' checks relations of 'member' and 'isSubseqOf'. Note that elemSetTest requires any @('Set' s o) => s@, not necessarily a set (may contain any data). -} elemSetTest :: (Set s o, Linear s o, Ord o) => o -> s -> Bool elemSetTest e sx = and [ (e' `isSubseqOf` sx) == member e sx', (e' `isSubseqOf` sx) == member e sx' ] where sx' = set sx; e' = single e {- | 'lookupSetTest' checks relations of 'lookupLT', 'lookupGT', 'lookupLE' and 'lookupGE'. Note that lookupSetTest requires a set, not any @('Set' s o) => s@. -} lookupSetTest :: (Set s o, Linear s o, Ord o) => o -> s -> Bool lookupSetTest e sx = and [ lookupLT e sx == lookupLT e (listL sx), lookupGT e sx == lookupGT e (listL sx), lookupLE e sx == lookupLE e (listL sx), lookupGE e sx == lookupGE e (listL sx), case lookupLT e sx of {Nothing -> True; Just x -> x < e}, case lookupGT e sx of {Nothing -> True; Just x -> x > e}, case lookupLE e sx of {Nothing -> True; Just x -> x <= e}, case lookupGE e sx of {Nothing -> True; Just x -> x >= e} ] {- | 'setTest' is complex test, that includes all other tests. Note that setTest requires any @('Set' s o) => s@, not necessarily a set (may contain any data). -} setTest :: (Set s o, Linear s o, Ord s, Ord o) => o -> s -> s -> Bool setTest e xs ys = and [ unintSetTest sx sy, diffSetTest sx sy, basicSetTest xs, insdelSetTest e sx, lookupSetTest e sx, elemSetTest e xs ] where sx = set xs sy = set ys