packages feed

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

{- |
    Module      :  Test.SDP.Indexed
    Copyright   :  (c) Andrey Mulik 2019
    License     :  BSD-style
    Maintainer  :  work.a.mulik@gmail.com
    Portability :  non-portable (requires non-portable modules)
    
    @Test.SDP.Indexed@ provides simple set of test for 'Indexed' class.
-}
module Test.SDP.Indexed
(
  -- * Indexed test
  TestIndexed, TestIndexed1, TestIndexed2, indexedTest,
  
  -- ** Particular tests
  basicIndexedTest, assocIndexedTest, readIndexedTest
)
where

import Prelude ()
import SDP.SafePrelude
import SDP.Indexed

import Data.Maybe

default ()

--------------------------------------------------------------------------------

-- | TestIndexed  is service type synonym for more comfortable quickCheck using.
type TestIndexed  l i = i -> l -> Bool

-- | TestIndexed1 is service type synonym for more comfortable quickCheck using.
type TestIndexed1 l i e = i -> l e -> Bool

-- | TestIndexed2 is service type synonym for more comfortable quickCheck using.
type TestIndexed2 l i e = i -> l i e -> Bool

--------------------------------------------------------------------------------

-- | 'basicIndexedTest' checks relations of 'isNull', 'safeElem' and 'inRange'.
basicIndexedTest :: (Bordered l i, Indexed l i e) => i -> l -> Bool
basicIndexedTest i es = let bnds = bounds es in isNull es || inRange bnds (safeElem bnds i)

{- |
  'assocIndexedTest' checks relations of 'assoc', 'assocs', ('.$'), ('*$') and
  ('//').
-}
assocIndexedTest :: (Bordered l i, Indexed l i e, Eq e, Eq l) => i -> l -> Bool
assocIndexedTest i es = and
  [
    assoc (bounds es) (assocs es) == es,
    
    es // (assocs es) == es,
    Z  // (assocs es) == es,
    es //     []      == es,
    
    -- if structure contain dublicates, (.$) may find earlier match.
    isNull es || i' >= fromJust ((== es ! i') .$ es),
    isNull es || elem i' ((== es!safeElem bnds i) *$ es)
  ]
  where
    i'   = safeElem bnds i
    bnds = bounds es

-- | 'readIndexedTest' checks relations of 'listL', ('.!'), ('!') and ('!?').
readIndexedTest :: (Bordered l i, Indexed l i e, Eq e) => i -> l -> Bool
readIndexedTest i es = and
    [
      -- just check (.!) on all range
      fmap (es .!) (indices es) == listL es,
      isNull es || (es ! i' == es .! i'),
      
      inRange bnds i || isNothing (es !? i),
      isNull es || isJust (es !? i')
    ]
  where
    i'   = safeElem bnds i
    bnds = bounds es

-- | 'indexedTest' is complex test, that includes all other tests.
indexedTest :: (Bordered l i, Indexed l i e, Eq e, Eq l) => i -> l -> Bool
indexedTest i es = and
  [
    basicIndexedTest i es,
    assocIndexedTest i es,
    readIndexedTest  i es
  ]