{-# LANGUAGE UndecidableInstances #-}
module TestSuite (
-- * Changes
AtomicAChange (DoubleAndAdd),
AtomicBChange (TripleAndAdd),
-- * Test functions and transformations
testTrans,
testFun,
testPrdTrans,
testPrdFun,
testCompare,
-- * Test pattern
transTest
) where
-- Prelude
import Prelude hiding (id, (.))
-- Control
import Control.Category
import Control.Applicative
-- Data
import Data.Foldable (toList)
import Data.MultiChange (MultiChange)
import qualified Data.MultiChange as MultiChange
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.Incremental
import qualified Data.Incremental.Tuple as Tuple
import qualified Data.Incremental.Sequence as Seq
-- Test
import Test.QuickCheck
import Test.QuickCheck.Poly
-- Distribution
import Distribution.TestSuite
import Distribution.TestSuite.QuickCheck
-- Utilities
import Utilities
-- * Changes
-- ** Common changes
instance Arbitrary a => Arbitrary (PrimitiveChange a) where
arbitrary = frequency [(1, keepGen), (5, replaceGen)] where
keepGen = return Keep
replaceGen = fmap ReplaceBy arbitrary
shrink Keep = []
shrink (ReplaceBy val) = Keep : map ReplaceBy (shrink val)
instance Arbitrary p => Arbitrary (MultiChange p) where
arbitrary = fmap MultiChange.fromList arbitrary
shrink change = map MultiChange.fromList (shrink (toList change))
-- ** Pair changes
deriving instance (Show (DefaultChange a), Show (DefaultChange b)) =>
Show (Tuple.AtomicChange a b)
instance (Arbitrary (DefaultChange a), Arbitrary (DefaultChange b)) =>
Arbitrary (Tuple.AtomicChange a b) where
arbitrary = oneof [firstGen, secondGen] where
firstGen = fmap Tuple.First arbitrary
secondGen = fmap Tuple.Second arbitrary
shrink (Tuple.First change) = map Tuple.First (shrink change)
shrink (Tuple.Second change) = map Tuple.Second (shrink change)
-- ** Sequence changes
deriving instance (Show a, Show (DefaultChange a)) => Show (Seq.AtomicChange a)
instance (Arbitrary a, Arbitrary (DefaultChange a)) =>
Arbitrary (Seq.AtomicChange a) where
arbitrary = oneof [insertGen, deleteGen, shiftGen, changeAtGen] where
insertGen = liftA2 Seq.Insert arbitrary arbitrary
deleteGen = liftA2 Seq.Delete arbitrary arbitrary
shiftGen = liftA3 Seq.Shift arbitrary arbitrary arbitrary
changeAtGen = liftA2 Seq.ChangeAt arbitrary arbitrary
shrink (Seq.Insert ix seq)
= [Seq.Insert ix' seq'
| (ix', seq') <- shrink (ix, seq)]
shrink (Seq.Delete ix len)
= [Seq.Delete ix' len'
| (ix', len') <- shrink (ix, len)]
shrink (Seq.Shift src len tgt)
= [Seq.Shift src' len' tgt'
| (src', len', tgt') <- shrink (src, len, tgt)]
shrink (Seq.ChangeAt ix change)
= [Seq.ChangeAt ix' change'
| (ix', change') <- shrink (ix, change)]
-- ** Element changes
newtype AtomicAChange = DoubleAndAdd Integer deriving (Show, Arbitrary)
instance Change AtomicAChange where
type Value AtomicAChange = A
DoubleAndAdd diff $$ A integer = A (2 * integer + diff)
instance Changeable A where
type DefaultChange A = MultiChange AtomicAChange
deriving instance Ord A
newtype AtomicBChange = TripleAndAdd Integer deriving (Show, Arbitrary)
instance Change AtomicBChange where
type Value AtomicBChange = B
TripleAndAdd diff $$ B integer = B (3 * integer + diff)
instance Changeable B where
type DefaultChange B = MultiChange AtomicBChange
instance Changeable C
-- * Test functions and transformations
testTrans :: A ->> B
testTrans = MultiChange.map $ stateTrans init prop where
init (A integer) = (B integer, integer)
prop (DoubleAndAdd diff) state = (change', state') where
change' = TripleAndAdd (diff - state)
state' = 2 * state + diff
testFun :: C -> C
testFun = id
testPrdTrans :: A ->> Bool
testPrdTrans = MultiChange.composeMap $ stateTrans init prop where
init (A integer) = (testPrd integer, integer)
prop (DoubleAndAdd diff) state = (change', state') where
change' = ReplaceBy (testPrd state')
state' = 2 * state + diff
testPrdFun :: C -> Bool
testPrdFun = testPrd . unC
testPrd :: Integer -> Bool
testPrd = (>= 0)
testCompare :: A -> A -> Ordering
testCompare (A integer1) (A integer2) = compare (integer1 `div` 3)
(integer2 `div` 3)
-- * Test pattern
transTest :: (Show a, Arbitrary a, Changeable a,
Show (DefaultChange a), Arbitrary (DefaultChange a),
Eq b, Changeable b) =>
String -> (a ->> b) -> (a -> b) -> Test
transTest name trans fun = testProperty name prop where
prop src = recompute fun src == adapt trans src