{-# LANGUAGE ScopedTypeVariables #-}

module Test.Cardano.Data.MapExtrasSpec (mapExtrasSpec) where

import Control.Monad
import Data.Map (Map)
import qualified Data.Map.Strict as Map
import Data.MapExtras
import Test.Cardano.Data
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck

mapExtrasSpec :: Spec
mapExtrasSpec :: Spec
mapExtrasSpec =
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"MapExtras" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> (Map Int Float -> Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"extract k m === (lookup k m, delete k m)" ((Map Int Float -> Int -> IO ()) -> Spec)
-> (Map Int Float -> Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$ \(Map Int Float
m :: Map Int Float) Int
k -> do
      let (Maybe Float
v, Map Int Float
ma) = Int -> Map Int Float -> (Maybe Float, Map Int Float)
forall k b. Ord k => k -> Map k b -> (Maybe b, Map k b)
extract Int
k Map Int Float
m
      Map Int Float -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Float
ma
      Map Int Float
ma Map Int Float -> Map Int Float -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Map Int Float -> Map Int Float
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete Int
k Map Int Float
m
      Maybe Float
v Maybe Float -> Maybe Float -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Map Int Float -> Maybe Float
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Int
k Map Int Float
m
    String -> (Map Int Float -> Set Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"extractKeys m s === (withoutKeys m s, restrictKeys m s)" ((Map Int Float -> Set Int -> IO ()) -> Spec)
-> (Map Int Float -> Set Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$ \(Map Int Float
m :: Map Int Float) Set Int
s -> do
      let (Map Int Float
wk, Map Int Float
rk) = Map Int Float -> Set Int -> (Map Int Float, Map Int Float)
forall k a. Ord k => Map k a -> Set k -> (Map k a, Map k a)
extractKeys Map Int Float
m Set Int
s
      Map Int Float -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Float
wk
      Map Int Float -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Float
rk
      Map Int Float
wk Map Int Float -> Map Int Float -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Map Int Float -> Set Int -> Map Int Float
forall k a. Ord k => Map k a -> Set k -> Map k a
Map.withoutKeys Map Int Float
m Set Int
s
      Map Int Float
rk Map Int Float -> Map Int Float -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Map Int Float -> Set Int -> Map Int Float
forall k a. Ord k => Map k a -> Set k -> Map k a
Map.restrictKeys Map Int Float
m Set Int
s
    String -> (Map Int Float -> Map Int Char -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"noKeys == withoutKeys" ((Map Int Float -> Map Int Char -> IO ()) -> Spec)
-> (Map Int Float -> Map Int Char -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$ \(Map Int Float
m1 :: Map Int Float) (Map Int Char
m2 :: Map Int Char) -> do
      let nk :: Map Int Float
nk = Map Int Float -> Map Int Char -> Map Int Float
forall k a b. Ord k => Map k a -> Map k b -> Map k a
noKeys Map Int Float
m1 Map Int Char
m2
      Map Int Float -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Float
nk
      Map Int Float
nk Map Int Float -> Map Int Float -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Map Int Float -> Set Int -> Map Int Float
forall k a. Ord k => Map k a -> Set k -> Map k a
Map.withoutKeys Map Int Float
m1 (Map Int Char -> Set Int
forall k a. Map k a -> Set k
Map.keysSet Map Int Char
m2)
    String
-> (Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
-> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"intersectDomP" ((Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
 -> Spec)
-> (Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
-> Spec
forall a b. (a -> b) -> a -> b
$ \Fun (Int, Word) Bool
fun (Map Int Char
m1 :: Map Int Char) (Map Int Word
m2 :: Map Int Word) -> do
      let f :: Int -> Word -> Bool
f = Fun (Int, Word) Bool -> Int -> Word -> Bool
forall a b c. Fun (a, b) c -> a -> b -> c
applyFun2 Fun (Int, Word) Bool
fun :: Int -> Word -> Bool
          ma :: Map Int Word
ma = (Int -> Word -> Bool)
-> Map Int Char -> Map Int Word -> Map Int Word
forall k v2 v1.
Ord k =>
(k -> v2 -> Bool) -> Map k v1 -> Map k v2 -> Map k v2
intersectDomP Int -> Word -> Bool
f Map Int Char
m1 Map Int Word
m2
      Map Int Word -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Word
ma
      Map Int Word
ma Map Int Word -> Map Int Word -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Word -> Bool) -> Map Int Word -> Map Int Word
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
Map.filterWithKey Int -> Word -> Bool
f (Map Int Word -> Map Int Char -> Map Int Word
forall k a b. Ord k => Map k a -> Map k b -> Map k a
Map.intersection Map Int Word
m2 Map Int Char
m1)
    String
-> (Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
-> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"intersectDomPLeft" ((Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
 -> Spec)
-> (Fun (Int, Word) Bool -> Map Int Char -> Map Int Word -> IO ())
-> Spec
forall a b. (a -> b) -> a -> b
$ \Fun (Int, Word) Bool
fun (Map Int Char
m1 :: Map Int Char) (Map Int Word
m2 :: Map Int Word) -> do
      let f :: Int -> Word -> Bool
f = Fun (Int, Word) Bool -> Int -> Word -> Bool
forall a b c. Fun (a, b) c -> a -> b -> c
applyFun2 Fun (Int, Word) Bool
fun :: Int -> Word -> Bool
          ma :: Map Int Char
ma = (Int -> Word -> Bool)
-> Map Int Char -> Map Int Word -> Map Int Char
forall k v2 v1.
Ord k =>
(k -> v2 -> Bool) -> Map k v1 -> Map k v2 -> Map k v1
intersectDomPLeft Int -> Word -> Bool
f Map Int Char
m1 Map Int Word
m2
      Map Int Char -> IO ()
forall k a.
(HasCallStack, Ord k, Show k, Show a) =>
Map k a -> IO ()
expectValidMap Map Int Char
ma
      Map Int Char
ma Map Int Char -> Map Int Char -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Char -> Maybe Char) -> Map Int Char -> Map Int Char
forall k a b. (k -> a -> Maybe b) -> Map k a -> Map k b
Map.mapMaybeWithKey (\Int
k Char
v -> Char
v Char -> Maybe () -> Maybe Char
forall a b. a -> Maybe b -> Maybe a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> (Word -> Bool) -> Word -> Maybe ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word -> Bool
f Int
k (Word -> Maybe ()) -> Maybe Word -> Maybe ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Int -> Map Int Word -> Maybe Word
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Int
k Map Int Word
m2)) Map Int Char
m1