{- |
    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 -> l -> Bool
basicIndexedTest i
i l
es = let bnds :: (i, i)
bnds = l -> (i, i)
forall b i. Bordered b i => b -> (i, i)
bounds l
es in l -> Bool
forall e. Nullable e => e -> Bool
isNull l
es Bool -> Bool -> Bool
|| (i, i) -> i -> Bool
forall i. Index i => (i, i) -> i -> Bool
inRange (i, i)
bnds ((i, i) -> i -> i
forall i. Index i => (i, i) -> i -> i
safeElem (i, i)
bnds i
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 -> l -> Bool
assocIndexedTest i
i l
es = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
  [
    (i, i) -> [(i, e)] -> l
forall v i e. Indexed v i e => (i, i) -> [(i, e)] -> v
assoc (l -> (i, i)
forall b i. Bordered b i => b -> (i, i)
bounds l
es) (l -> [(i, e)]
forall map key e. Map map key e => map -> [(key, e)]
assocs l
es) l -> l -> Bool
forall a. Eq a => a -> a -> Bool
== l
es,
    
    l
es l -> [(i, e)] -> l
forall map key e. Map map key e => map -> [(key, e)] -> map
// (l -> [(i, e)]
forall map key e. Map map key e => map -> [(key, e)]
assocs l
es) l -> l -> Bool
forall a. Eq a => a -> a -> Bool
== l
es,
    l
forall e. Nullable e => e
Z  l -> [(i, e)] -> l
forall map key e. Map map key e => map -> [(key, e)] -> map
// (l -> [(i, e)]
forall map key e. Map map key e => map -> [(key, e)]
assocs l
es) l -> l -> Bool
forall a. Eq a => a -> a -> Bool
== l
es,
    l
es l -> [(i, e)] -> l
forall map key e. Map map key e => map -> [(key, e)] -> map
//     []      l -> l -> Bool
forall a. Eq a => a -> a -> Bool
== l
es,
    
    -- if structure contain dublicates, (.$) may find earlier match.
    l -> Bool
forall e. Nullable e => e -> Bool
isNull l
es Bool -> Bool -> Bool
|| i
i' i -> i -> Bool
forall a. Ord a => a -> a -> Bool
>= Maybe i -> i
forall a. HasCallStack => Maybe a -> a
fromJust ((e -> e -> Bool
forall a. Eq a => a -> a -> Bool
== l
es l -> i -> e
forall map key e. Map map key e => map -> key -> e
! i
i') (e -> Bool) -> l -> Maybe i
forall map key e. Map map key e => (e -> Bool) -> map -> Maybe key
.$ l
es),
    l -> Bool
forall e. Nullable e => e -> Bool
isNull l
es Bool -> Bool -> Bool
|| i -> [i] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem i
i' ((e -> e -> Bool
forall a. Eq a => a -> a -> Bool
== l
esl -> i -> e
forall map key e. Map map key e => map -> key -> e
!(i, i) -> i -> i
forall i. Index i => (i, i) -> i -> i
safeElem (i, i)
bnds i
i) (e -> Bool) -> l -> [i]
forall map key e. Map map key e => (e -> Bool) -> map -> [key]
*$ l
es)
  ]
  where
    i' :: i
i'   = (i, i) -> i -> i
forall i. Index i => (i, i) -> i -> i
safeElem (i, i)
bnds i
i
    bnds :: (i, i)
bnds = l -> (i, i)
forall b i. Bordered b i => b -> (i, i)
bounds l
es

-- | 'readIndexedTest' checks relations of 'listL', ('.!'), ('!') and ('!?').
readIndexedTest :: (Bordered l i, Indexed l i e, Eq e) => i -> l -> Bool
readIndexedTest :: i -> l -> Bool
readIndexedTest i
i l
es = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
    [
      -- just check (.!) on all range
      (i -> e) -> [i] -> [e]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (l
es l -> i -> e
forall map key e. Map map key e => map -> key -> e
.!) (l -> [i]
forall b i. Bordered b i => b -> [i]
indices l
es) [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== l -> [e]
forall l e. Linear l e => l -> [e]
listL l
es,
      l -> Bool
forall e. Nullable e => e -> Bool
isNull l
es Bool -> Bool -> Bool
|| (l
es l -> i -> e
forall map key e. Map map key e => map -> key -> e
! i
i' e -> e -> Bool
forall a. Eq a => a -> a -> Bool
== l
es l -> i -> e
forall map key e. Map map key e => map -> key -> e
.! i
i'),
      
      (i, i) -> i -> Bool
forall i. Index i => (i, i) -> i -> Bool
inRange (i, i)
bnds i
i Bool -> Bool -> Bool
|| Maybe e -> Bool
forall a. Maybe a -> Bool
isNothing (l
es l -> i -> Maybe e
forall map key e. Map map key e => map -> key -> Maybe e
!? i
i),
      l -> Bool
forall e. Nullable e => e -> Bool
isNull l
es Bool -> Bool -> Bool
|| Maybe e -> Bool
forall a. Maybe a -> Bool
isJust (l
es l -> i -> Maybe e
forall map key e. Map map key e => map -> key -> Maybe e
!? i
i')
    ]
  where
    i' :: i
i'   = (i, i) -> i -> i
forall i. Index i => (i, i) -> i -> i
safeElem (i, i)
bnds i
i
    bnds :: (i, i)
bnds = l -> (i, i)
forall b i. Bordered b i => b -> (i, i)
bounds l
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 -> l -> Bool
indexedTest i
i l
es = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
  [
    i -> l -> Bool
forall l i e. (Bordered l i, Indexed l i e) => i -> l -> Bool
basicIndexedTest i
i l
es,
    i -> l -> Bool
forall l i e.
(Bordered l i, Indexed l i e, Eq e, Eq l) =>
i -> l -> Bool
assocIndexedTest i
i l
es,
    i -> l -> Bool
forall l i e. (Bordered l i, Indexed l i e, Eq e) => i -> l -> Bool
readIndexedTest  i
i l
es
  ]