monoidmap-internal-0.0.0.1: components/monoidmap-test/Test/Common.hs
{-# LANGUAGE ExistentialQuantification #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{- HLINT ignore "Redundant bracket" -}
{- HLINT ignore "Use camelCase" -}
{- HLINT ignore "Use null" -}
-- |
-- Copyright: © 2022–2025 Jonathan Knowles
-- License: Apache-2.0
--
module Test.Common
( Key
, Test
, TestKey
, TestValueType (..)
, testValueTypesAll
, testValueTypesGroup
, testValueTypesMonus
, testValueTypesLeftReductive
, testValueTypesRightReductive
, testValueTypesReductive
, testValueTypesLeftGCDMonoid
, testValueTypesRightGCDMonoid
, testValueTypesOverlappingGCDMonoid
, testValueTypesGCDMonoid
, testValueTypesLCMMonoid
, TestValue
, makeSpec
, property
) where
import Prelude
import Data.Group
( Group )
import Data.Kind
( Constraint, Type )
import Data.Monoid
( Dual, Product, Sum )
import Data.Monoid.GCD
( GCDMonoid, LeftGCDMonoid, OverlappingGCDMonoid, RightGCDMonoid )
import Data.Monoid.LCM
( LCMMonoid )
import Data.Monoid.Monus
( Monus )
import Data.Monoid.Null
( MonoidNull )
import Data.MonoidMap.Internal
( MonoidMap )
import Data.Proxy
( Proxy (Proxy) )
import Data.Semigroup.Cancellative
( LeftReductive, Reductive, RightReductive )
import Data.Set
( Set )
import Data.Text
( Text )
import Data.Typeable
( Typeable, typeRep )
import GHC.Exts
( IsList (..) )
import Numeric.Natural
( Natural )
import Test.Hspec
( Spec, describe )
import Test.Key
( Key2, Key4 )
import Test.QuickCheck
( Arbitrary (..)
, CoArbitrary (..)
, Function (..)
, Property
, Testable
, arbitrarySizedNatural
, checkCoverage
, coarbitraryIntegral
, coarbitraryShow
, frequency
, functionIntegral
, functionMap
, functionShow
, listOf
, scale
, shrinkIntegral
, shrinkMapBy
)
import qualified Data.MonoidMap.Internal as MonoidMap
import qualified Data.Text as Text
import qualified Test.QuickCheck as QC
--------------------------------------------------------------------------------
-- Arbitrary instances
--------------------------------------------------------------------------------
instance (Arbitrary k, Ord k, Arbitrary v, MonoidNull v) =>
Arbitrary (MonoidMap k v)
where
arbitrary =
fromList <$> scale (`mod` 16) (listOf ((,) <$> arbitrary <*> arbitrary))
shrink =
shrinkMapBy MonoidMap.fromMap MonoidMap.toMap shrink
instance (CoArbitrary k, CoArbitrary v) =>
CoArbitrary (MonoidMap k v)
where
coarbitrary = coarbitrary . MonoidMap.toMap
instance (Function k, Function v, Ord k, MonoidNull v) =>
Function (MonoidMap k v)
where
function = functionMap MonoidMap.toMap MonoidMap.fromMap
instance Arbitrary Natural where
arbitrary = arbitrarySizedNatural
shrink = shrinkIntegral
instance CoArbitrary Natural where
coarbitrary = coarbitraryIntegral
instance Function Natural where
function = functionIntegral
instance Arbitrary Text where
arbitrary = Text.pack <$> listOf genChar
where
genChar = frequency
[ (64, pure 'a')
, (16, pure 'b')
, ( 4, pure 'c')
, ( 1, pure 'd')
]
instance CoArbitrary Text where
coarbitrary = coarbitraryShow
instance Function Text where
function = functionShow
--------------------------------------------------------------------------------
-- Test keys
--------------------------------------------------------------------------------
type SmallKey = Key2
type Key = Key4
--------------------------------------------------------------------------------
-- Test constraints
--------------------------------------------------------------------------------
type Test k v = (TestKey k, TestValue v)
type TestKey k =
( Arbitrary k
, CoArbitrary k
, Function k
, Ord k
, Show k
, Typeable k
)
type TestValue v =
( Arbitrary v
, CoArbitrary v
, Eq v
, Function v
, MonoidNull v
, Show v
, Typeable v
)
--------------------------------------------------------------------------------
-- Test value types (for different type class constraints)
--------------------------------------------------------------------------------
data TestValueType (c :: Type -> Constraint) =
forall v. (TestValue v, c v) => TestValueType (Proxy v)
testValueTypesAll :: [TestValueType MonoidNull]
testValueTypesAll =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Dual [Int]))
, TestValueType (Proxy @(Dual [Natural]))
, TestValueType (Proxy @(Product Int))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Int))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @[Int])
, TestValueType (Proxy @[Natural])
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Int)))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesGroup :: [TestValueType Group]
testValueTypesGroup =
[ TestValueType (Proxy @(Sum Int))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Int)))
]
testValueTypesMonus :: [TestValueType Monus]
testValueTypesMonus =
[ TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesLeftReductive :: [TestValueType LeftReductive]
testValueTypesLeftReductive =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Dual [Int]))
, TestValueType (Proxy @(Dual [Natural]))
, TestValueType (Proxy @(Product Int))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Int))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @[Int])
, TestValueType (Proxy @[Natural])
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesRightReductive :: [TestValueType RightReductive]
testValueTypesRightReductive =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Dual [Int]))
, TestValueType (Proxy @(Dual [Natural]))
, TestValueType (Proxy @(Product Int))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Int))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @[Int])
, TestValueType (Proxy @[Natural])
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesReductive :: [TestValueType Reductive]
testValueTypesReductive =
[ TestValueType (Proxy @(Product Int))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Int))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesLeftGCDMonoid :: [TestValueType LeftGCDMonoid]
testValueTypesLeftGCDMonoid =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesRightGCDMonoid :: [TestValueType RightGCDMonoid]
testValueTypesRightGCDMonoid =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesOverlappingGCDMonoid :: [TestValueType OverlappingGCDMonoid]
testValueTypesOverlappingGCDMonoid =
[ TestValueType (Proxy @(Dual Text))
, TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(Text))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesGCDMonoid :: [TestValueType GCDMonoid]
testValueTypesGCDMonoid =
[ TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
testValueTypesLCMMonoid :: [TestValueType LCMMonoid]
testValueTypesLCMMonoid =
[ TestValueType (Proxy @(Product Natural))
, TestValueType (Proxy @(Set Int))
, TestValueType (Proxy @(Set Natural))
, TestValueType (Proxy @(Sum Natural))
, TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))
]
--------------------------------------------------------------------------------
-- Utilities
--------------------------------------------------------------------------------
makeSpec :: forall k v. Test k v => Spec -> Proxy k -> Proxy v -> Spec
makeSpec spec _k _v = describe (show $ typeRep (Proxy @(MonoidMap k v))) spec
property :: Testable t => t -> Property
property = checkCoverage . QC.property