monoidmap-0.0.1.7: src/test/Data/MonoidMap/ConversionSpec.hs
{- HLINT ignore "Redundant bracket" -}
{- HLINT ignore "Use camelCase" -}
{- HLINT ignore "Use null" -}
-- |
-- Copyright: © 2022–2025 Jonathan Knowles
-- License: Apache-2.0
--
module Data.MonoidMap.ConversionSpec
( spec
) where
import Prelude
import Control.Monad
( forM_ )
import Data.Function
( (&) )
import Data.Map.Strict
( Map )
import Data.MonoidMap
( MonoidMap, nonNullCount )
import Data.Proxy
( Proxy (..) )
import Test.Common
( Key, Test, TestType (TestType), makeSpec, property, testTypesMonoidNull )
import Test.Hspec
( Spec, describe, it )
import Test.QuickCheck
( Fun (..), Property, applyFun2, cover, (===) )
import qualified Data.Foldable as F
import qualified Data.List as List
import qualified Data.List.NonEmpty as NE
import qualified Data.Map.Strict as Map
import qualified Data.MonoidMap as MonoidMap
spec :: Spec
spec = describe "Conversions" $ do
forM_ testTypesMonoidNull $ \(TestType p) -> specFor (Proxy @Key) p
specFor :: forall k v. Test k v => Proxy k -> Proxy v -> Spec
specFor = makeSpec $ do
describe "Conversion to and from lists" $ do
it "prop_fromList_get" $
prop_fromList_get
@k @v & property
it "prop_fromList_toMap" $
prop_fromList_toMap
@k @v & property
it "prop_fromList_toList" $
prop_fromList_toList
@k @v & property
it "prop_toList_fromList" $
prop_toList_fromList
@k @v & property
it "prop_toList_sort" $
prop_toList_sort
@k @v & property
it "prop_fromListWith_get" $
prop_fromListWith_get
@k @v & property
describe "Conversion to and from ordinary maps" $ do
it "prop_fromMap_toMap" $
prop_fromMap_toMap
@k @v & property
it "prop_toMap_fromMap" $
prop_toMap_fromMap
@k @v & property
--------------------------------------------------------------------------------
-- Conversion to and from lists
--------------------------------------------------------------------------------
prop_fromList_get
:: Test k v => [(k, v)] -> k -> Property
prop_fromList_get kvs k =
MonoidMap.get k (MonoidMap.fromList kvs)
===
F.foldMap snd (filter ((== k) . fst) kvs)
& cover 2
(matchingKeyCount == 0)
"matchingKeyCount == 0"
& cover 2
(matchingKeyCount == 1)
"matchingKeyCount == 1"
& cover 2
(matchingKeyCount == 2)
"matchingKeyCount == 2"
& cover 2
(matchingKeyCount >= 3)
"matchingKeyCount >= 3"
where
matchingKeyCount =
length $ filter ((== k) . fst) kvs
prop_fromList_toMap
:: Test k v => [(k, v)] -> Property
prop_fromList_toMap kvs =
MonoidMap.toMap m === Map.filter (/= mempty) o
& cover 2
(MonoidMap.nonNull m && nonNullCount m /= Map.size o)
"MonoidMap.nonNull m && nonNullCount m /= Map.size o"
& cover 2
(MonoidMap.nonNull m && nonNullCount m == Map.size o)
"MonoidMap.nonNull m && nonNullCount m == Map.size o"
where
m = MonoidMap.fromList kvs
o = Map.fromListWith (flip (<>)) kvs
prop_fromList_toList
:: Test k v => [(k, v)] -> Property
prop_fromList_toList kvs =
MonoidMap.toList m === Map.toList (Map.filter (/= mempty) o)
& cover 2
(MonoidMap.nonNull m && nonNullCount m /= Map.size o)
"MonoidMap.nonNull m && nonNullCount m /= Map.size o"
& cover 2
(MonoidMap.nonNull m && nonNullCount m == Map.size o)
"MonoidMap.nonNull m && nonNullCount m == Map.size o"
where
m = MonoidMap.fromList kvs
o = Map.fromListWith (flip (<>)) kvs
prop_toList_fromList
:: Test k v => MonoidMap k v -> Property
prop_toList_fromList m =
MonoidMap.fromList (MonoidMap.toList m) === m
& cover 2
(MonoidMap.nonNull m)
"MonoidMap.nonNull m"
prop_toList_sort
:: Test k v => MonoidMap k v -> Property
prop_toList_sort m =
List.sortOn fst (MonoidMap.toList m) === MonoidMap.toList m
& cover 2
(MonoidMap.nonNull m)
"MonoidMap.nonNull m"
prop_fromListWith_get
:: Test k v => Fun (v, v) v -> [(k, v)] -> k -> Property
prop_fromListWith_get (applyFun2 -> f) kvs k =
MonoidMap.get k (MonoidMap.fromListWith f kvs)
===
maybe mempty
(F.foldl1 f)
(NE.nonEmpty (snd <$> filter ((== k) . fst) kvs))
& cover 2
(matchingKeyCount == 0)
"matchingKeyCount == 0"
& cover 2
(matchingKeyCount == 1)
"matchingKeyCount == 1"
& cover 2
(matchingKeyCount == 2)
"matchingKeyCount == 2"
& cover 2
(matchingKeyCount >= 3)
"matchingKeyCount >= 3"
where
matchingKeyCount =
length $ filter ((== k) . fst) kvs
--------------------------------------------------------------------------------
-- Conversion to and from ordinary maps
--------------------------------------------------------------------------------
prop_fromMap_toMap
:: Test k v => Map k v -> Property
prop_fromMap_toMap o =
MonoidMap.toMap m === Map.filter (/= mempty) o
& cover 2
(MonoidMap.nonNull m && nonNullCount m /= Map.size o)
"MonoidMap.nonNull m && nonNullCount m /= Map.size o"
& cover 2
(MonoidMap.nonNull m && nonNullCount m == Map.size o)
"MonoidMap.nonNull m && nonNullCount m == Map.size o"
where
m = MonoidMap.fromMap o
prop_toMap_fromMap
:: Test k v => MonoidMap k v -> Property
prop_toMap_fromMap m =
MonoidMap.fromMap (MonoidMap.toMap m) === m