{- |
    Module      :  Test.SDP.Split
    Copyright   :  (c) Andrey Mulik 2021
    License     :  BSD-style
    Maintainer  :  work.a.mulik@gmail.com
    Portability :  portable
    
    @Test.SDP.Split@ is service module that provides 'Split' tests.
-}
module Test.SDP.Split
(
  -- * Split test
  TestSplit, TestSplit1, TestSplit2, splitTest,
  
  -- ** Particular tests
  basicSplitTest, whileSplitTest
)
where

import Prelude ()
import SDP.SafePrelude
import SDP.Linear

default ()

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

-- | 'TestSplit' is service type synonym for more comfortable quickCheck using.
type TestSplit s = Int -> s -> Bool

-- | 'TestSplit1' is service type synonym for more comfortable quickCheck using.
type TestSplit1 s e = Int -> s e -> Bool

-- | 'TestSplit2' is service type synonym for more comfortable quickCheck using.
type TestSplit2 s i e = Int -> s i e -> Bool

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

{- |
  @'splitTest' f n xs@ is default 'Split' test, where @f@ is arbitrary predicate
  (e.g. "Test.SDP.Gen.orderA").
-}
splitTest :: (Split s e, Eq e, Eq s, Bordered s i) => (e -> Bool) -> TestSplit s
splitTest :: (e -> Bool) -> TestSplit s
splitTest e -> Bool
f Int
n s
xs = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
  [
    TestSplit s
forall s e i. (Split s e, Eq e, Eq s, Bordered s i) => TestSplit s
basicSplitTest Int
n s
xs,
    (e -> Bool) -> s -> Bool
forall s e i.
(Split s e, Eq e, Eq s, Bordered s i) =>
(e -> Bool) -> s -> Bool
whileSplitTest e -> Bool
f s
xs
  ]

{- |
  'basicSplitTest' checks 'take', 'drop', 'sans', 'keep', 'split' and 'divide'
  correctness and relations.
-}
basicSplitTest :: (Split s e, Eq e, Eq s, Bordered s i) => TestSplit s
basicSplitTest :: TestSplit s
basicSplitTest Int
n s
xs = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
    [
      Int -> s -> (s, s)
forall s e. Split s e => Int -> s -> (s, s)
split  Int
n s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
tx, s
dx),
      Int -> s -> (s, s)
forall s e. Split s e => Int -> s -> (s, s)
divide Int
n s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
sx, s
kx),
      
      s -> [e]
forall l e. Linear l e => l -> [e]
listL s
tx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
ty, s -> [e]
forall l e. Linear l e => l -> [e]
listL s
dx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
dy,
      s -> [e]
forall l e. Linear l e => l -> [e]
listL s
sx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
sy, s -> [e]
forall l e. Linear l e => l -> [e]
listL s
kx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
ky,
      
      -- additional tests
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
tx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
dx,
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
sx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
kx
    ]
  where
    lx :: Int
lx = s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
xs
    ys :: [e]
ys = s -> [e]
forall l e. Linear l e => l -> [e]
listL  s
xs
    
    tx :: s
tx = Int -> s -> s
forall s e. Split s e => Int -> s -> s
take Int
n s
xs; ty :: [e]
ty = Int -> [e] -> [e]
forall s e. Split s e => Int -> s -> s
take Int
n [e]
ys
    dx :: s
dx = Int -> s -> s
forall s e. Split s e => Int -> s -> s
drop Int
n s
xs; dy :: [e]
dy = Int -> [e] -> [e]
forall s e. Split s e => Int -> s -> s
drop Int
n [e]
ys
    sx :: s
sx = Int -> s -> s
forall s e. Split s e => Int -> s -> s
sans Int
n s
xs; sy :: [e]
sy = Int -> [e] -> [e]
forall s e. Split s e => Int -> s -> s
sans Int
n [e]
ys
    kx :: s
kx = Int -> s -> s
forall s e. Split s e => Int -> s -> s
keep Int
n s
xs; ky :: [e]
ky = Int -> [e] -> [e]
forall s e. Split s e => Int -> s -> s
keep Int
n [e]
ys

{- |
  'whileSplitTest' checks 'takeWhile', 'dropWhile', 'takeEnd', 'dropEnd',
  'spanl', 'spanr', 'breakl' and 'breakr' correctness and relations.
-}
whileSplitTest :: (Split s e, Eq e, Eq s, Bordered s i) => (e -> Bool) -> s -> Bool
whileSplitTest :: (e -> Bool) -> s -> Bool
whileSplitTest e -> Bool
f s
xs = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
    [
      (e -> Bool) -> s -> (s, s)
forall s e. Split s e => (e -> Bool) -> s -> (s, s)
spanl e -> Bool
f s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
tx, s
dx), (e -> Bool) -> s -> (s, s)
forall s e. Split s e => (e -> Bool) -> s -> (s, s)
breakl e -> Bool
f s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
ntx, s
ndx),
      (e -> Bool) -> s -> (s, s)
forall s e. Split s e => (e -> Bool) -> s -> (s, s)
spanr e -> Bool
f s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
sx, s
kx), (e -> Bool) -> s -> (s, s)
forall s e. Split s e => (e -> Bool) -> s -> (s, s)
breakr e -> Bool
f s
xs (s, s) -> (s, s) -> Bool
forall a. Eq a => a -> a -> Bool
== (s
nsx, s
nkx),
      
      s -> [e]
forall l e. Linear l e => l -> [e]
listL s
tx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
ty, s -> [e]
forall l e. Linear l e => l -> [e]
listL s
dx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
dy,
      s -> [e]
forall l e. Linear l e => l -> [e]
listL s
sx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
sy, s -> [e]
forall l e. Linear l e => l -> [e]
listL s
kx [e] -> [e] -> Bool
forall a. Eq a => a -> a -> Bool
== [e]
ky,
      
      -- additional tests
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf  s
tx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf  s
dx,
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf  s
sx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf  s
kx,
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
ntx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
ndx,
      Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
nsx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
nkx
    ]
  where
    lx :: Int
lx = s -> Int
forall b i. Bordered b i => b -> Int
sizeOf s
xs
    ys :: [e]
ys = s -> [e]
forall l e. Linear l e => l -> [e]
listL  s
xs
    
    tx :: s
tx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
takeWhile e -> Bool
f s
xs; ty :: [e]
ty = (e -> Bool) -> [e] -> [e]
forall s e. Split s e => (e -> Bool) -> s -> s
takeWhile e -> Bool
f [e]
ys; ntx :: s
ntx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
takeWhile (Bool -> Bool
not (Bool -> Bool) -> (e -> Bool) -> e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Bool
f) s
xs
    dx :: s
dx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
dropWhile e -> Bool
f s
xs; dy :: [e]
dy = (e -> Bool) -> [e] -> [e]
forall s e. Split s e => (e -> Bool) -> s -> s
dropWhile e -> Bool
f [e]
ys; ndx :: s
ndx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
dropWhile (Bool -> Bool
not (Bool -> Bool) -> (e -> Bool) -> e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Bool
f) s
xs
    sx :: s
sx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
dropEnd   e -> Bool
f s
xs; sy :: [e]
sy = (e -> Bool) -> [e] -> [e]
forall s e. Split s e => (e -> Bool) -> s -> s
dropEnd   e -> Bool
f [e]
ys; nsx :: s
nsx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
dropEnd   (Bool -> Bool
not (Bool -> Bool) -> (e -> Bool) -> e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Bool
f) s
xs
    kx :: s
kx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
takeEnd   e -> Bool
f s
xs; ky :: [e]
ky = (e -> Bool) -> [e] -> [e]
forall s e. Split s e => (e -> Bool) -> s -> s
takeEnd   e -> Bool
f [e]
ys; nkx :: s
nkx = (e -> Bool) -> s -> s
forall s e. Split s e => (e -> Bool) -> s -> s
takeEnd   (Bool -> Bool
not (Bool -> Bool) -> (e -> Bool) -> e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Bool
f) s
xs