packages feed

sdp-quickcheck-0.2: src/Test/SDP/Set.hs

{- |
    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