{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{- |
Module : Test.SDP.Gen
Copyright : (c) Andrey Mulik 2019
License : BSD-style
Maintainer : work.a.mulik@gmail.com
Portability : non-portable (requires non-portable modules)
@Test.SDP.Gen@ provides newtypes for QuickCheck.
-}
module Test.SDP.Gen
(
-- * Common newtypes for QuickCheck
Short (..), Medium (..), Long (..),
-- ** Related functions
linearLargeA, linearA, orderA
)
where
import Prelude ()
import SDP.SafePrelude
import SDP.Linear
import Test.QuickCheck
import Data.Coerce
default ()
--------------------------------------------------------------------------------
{- |
Short is newtype of short data structures [0, 100) in QuickCheck properties.
Short is the equivalent of the standard Arbitrary definition:
@arbitrary = fromList \<$\> arbitrary@.
-}
newtype Short a = Short a deriving ( Eq, Ord, Read, Show )
{- |
Medium is newtype of medium data structures in QuickCheck properties. The
Arbitrary Medium instance must create a random-sized structure from the range
[100, 1024).
Medium is useful in testing as a compromise between speed and reliability:
structures are too short for stress tests, but still human readable and enough
fast for auto-testing.
-}
newtype Medium a = Medium a deriving ( Eq, Ord, Read, Show )
{- |
Long is newtype of large data structures (>= 1024) in QuickCheck properties.
Since Large can generate really huge numbers, the maximum length is limited by
16384 - [1024, 16384).
Long is primarily intended for benchmarks, although a large range of lengths
makes them not very convenient for a pure comparison of several algorithms
(but for this can be used vector[Of] and generate). Long works well with
Unrolled and ByteList, since only the shortest of the allowed structures may
fit in one standard chunk (1024 elements).
-}
newtype Long a = Long a deriving ( Eq, Ord, Read, Show )
--------------------------------------------------------------------------------
instance (Linear l e, Arbitrary e) => Arbitrary (Short l)
where
arbitrary = arbitrary >>= \ n -> (Short . fromList) <$> vector n
instance (Linear l e, Arbitrary e) => Arbitrary (Medium l)
where
arbitrary = arbitrary >>= \ (Large n) -> (Medium . fromList) <$> vector (100 + n `mod` 914)
instance (Linear l e, Arbitrary e) => Arbitrary (Long l)
where
arbitrary = arbitrary >>= \ (Large n) -> (Long . fromList) <$> vector (1024 + n `mod` 15360)
--------------------------------------------------------------------------------
-- | 'linearA' is overloaded 'vector'.
linearA :: (Linear l e, Arbitrary e) => Int -> Gen l
linearA = fmap fromList . vector
-- | 'linearLargeA' is version of 'linearA', which generates 'Large' 'Int's.
linearLargeA :: (Linear l Int) => Int -> Gen l
linearLargeA =
let fromLarge = coerce :: [Large Int] -> [Int]
in fmap (fromList . fromLarge) . vector
{- |
'orderA' returns a simple comparator that can be used to test the behavior of
higher-order functions (for example, when comparing the results of @takeWhile@
for different structures).
-}
orderA :: (Ord e) => Gen (e -> e -> Bool)
orderA = elements [(>), (<), (>=), (<=), (==), (/=)]