{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.Cardano.Data.SimpleOMap.StrictSpec where

import Data.Map.Strict qualified as Map
import Data.Proxy (Proxy (Proxy))
import Data.Sequence.Strict qualified as SSeq
import Data.Set qualified as Set
import Data.SimpleOMap.Strict
import Test.Cardano.Data.Arbitrary ()
import Test.Cardano.Ledger.Binary.RoundTrip (roundTripCborSpec)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck.Classes
import Prelude hiding (elem, filter, lookup, null)

spec :: Spec
spec :: Spec
spec =
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"SimpleOMap.Strict" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"membership checks work" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> (OMap Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"unconsed" ((OMap Int Int -> IO ()) -> Spec)
-> (OMap Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(OMap Int Int
m :: OMap Int Int) -> case OMap Int Int
m of
          OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          (Int
k, Int
_) :<|: OMap Int Int
_kv -> Int
k Int -> (Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` (Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
m)
      String -> (OMap Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"unsnoced" ((OMap Int Int -> IO ()) -> Spec)
-> (OMap Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(OMap Int Int
m :: OMap Int Int) -> case OMap Int Int
m of
          OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          OMap Int Int
_kv :|>: (Int
k, Int
_) -> Int
k Int -> (Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` (Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
m)
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when cons-ing" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> (OMap Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"adding a duplicate results in a no-op" ((OMap Int Int -> IO ()) -> Spec)
-> (OMap Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(OMap Int Int
m :: OMap Int Int) -> do
          case OMap Int Int
m of
            OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            (Int, Int)
kv :<|: OMap Int Int
_kv -> OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
m
          case OMap Int Int
m of
            OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            OMap Int Int
_kv :|>: (Int, Int)
kv -> OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
m
      String -> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"new values get added" (((OMap Int Int, (Int, Int)) -> IO ()) -> Spec)
-> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
m, kv :: (Int, Int)
kv@(Int
k, Int
_)) :: (OMap Int Int, (Int, Int))) ->
          if Int
k Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
m
            then (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
m
            else (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
:<|: OMap Int Int
m
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when snoc-ing" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> (OMap Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"adding a duplicate results in a no-op" ((OMap Int Int -> IO ()) -> Spec)
-> (OMap Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(OMap Int Int
m :: OMap Int Int) -> do
          case OMap Int Int
m of
            OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            (Int, Int)
kv :<|: OMap Int Int
_kv -> OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
m OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
kv
          case OMap Int Int
m of
            OMap Int Int
Empty -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            OMap Int Int
_kv :|>: (Int, Int)
kv -> OMap Int Int
m OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
m OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
kv
      String -> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"new values get added" (((OMap Int Int, (Int, Int)) -> IO ()) -> Spec)
-> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
m, kv :: (Int, Int)
kv@(Int
k, Int
_)) :: (OMap Int Int, (Int, Int))) ->
          if Int
k Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
m
            then OMap Int Int
m OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
kv OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
m
            else OMap Int Int
m OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
kv OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
m OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
:|>: (Int, Int)
kv
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"mappend preserves uniqueness" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> (OMap Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"mappending with itself should be a no-op" ((OMap Int Int -> IO ()) -> Spec)
-> (OMap Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(OMap Int Int
i :: OMap Int Int) -> do
          let il :: OMap Int Int
il = OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
|>< OMap Int Int
i
              ir :: OMap Int Int
ir = OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
><| OMap Int Int
i
          OMap Int Int
il OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
i
          OMap Int Int
ir OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
i
          OMap Int Int
il OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
          OMap Int Int
ir OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
      String -> ((OMap Int Int, OMap Int Int) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"mappending with duplicates: left-preserving" (((OMap Int Int, OMap Int Int) -> IO ()) -> Spec)
-> ((OMap Int Int, OMap Int Int) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
i, OMap Int Int
j) :: (OMap Int Int, OMap Int Int)) ->
          case OMap Int Int
j of
            OMap Int Int
Empty -> OMap Int Int
i OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
|>< OMap Int Int
j
            (Int, Int)
j' :<|: OMap Int Int
_js -> do
              let result :: OMap Int Int
result = OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
|>< OMap Int Int
j
              OMap Int Int
result OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (OMap Int Int
i OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
j') OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
|>< OMap Int Int
j
              OMap Int Int
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
      String -> ((OMap Int Int, OMap Int Int) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"mappending with duplicates: right-preserving" (((OMap Int Int, OMap Int Int) -> IO ()) -> Spec)
-> ((OMap Int Int, OMap Int Int) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
i, OMap Int Int
j) :: (OMap Int Int, OMap Int Int)) ->
          case OMap Int Int
i of
            OMap Int Int
Empty -> OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
><| OMap Int Int
j OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
j
            OMap Int Int
_is :|>: (Int, Int)
i' -> do
              let result :: OMap Int Int
result = OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
><| OMap Int Int
j
              OMap Int Int
result OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
i OMap Int Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
><| ((Int, Int)
i' (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
j)
              OMap Int Int
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
    String -> ((OMap Int Int, Set Int) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"extractKeys should satisfy membership" (((OMap Int Int, Set Int) -> IO ()) -> Spec)
-> ((OMap Int Int, Set Int) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
      \((OMap Int Int
omap, Set Int
set) :: (OMap Int Int, Set.Set Int)) -> do
        let result :: (OMap Int Int, Map Int Int)
result = Set Int -> OMap Int Int -> (OMap Int Int, Map Int Int)
forall k v. Ord k => Set k -> OMap k v -> (OMap k v, Map k v)
extractKeys Set Int
set OMap Int Int
omap
        (OMap Int Int, Map Int Int)
result (OMap Int Int, Map Int Int)
-> ((OMap Int Int, Map Int Int) -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` ((Int -> Bool) -> StrictSeq Int -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> Set Int -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` Set Int
set) (StrictSeq Int -> Bool)
-> ((OMap Int Int, Map Int Int) -> StrictSeq Int)
-> (OMap Int Int, Map Int Int)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OMap Int Int -> StrictSeq Int
forall k v. OMap k v -> StrictSeq k
toStrictSeqOKeys (OMap Int Int -> StrictSeq Int)
-> ((OMap Int Int, Map Int Int) -> OMap Int Int)
-> (OMap Int Int, Map Int Int)
-> StrictSeq Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OMap Int Int, Map Int Int) -> OMap Int Int
forall a b. (a, b) -> a
fst)
        (OMap Int Int, Map Int Int)
result (OMap Int Int, Map Int Int)
-> ((OMap Int Int, Map Int Int) -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` ((Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> Set Int -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set Int
set) ([Int] -> Bool)
-> ((OMap Int Int, Map Int Int) -> [Int])
-> (OMap Int Int, Map Int Int)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Int Int -> [Int]
forall k a. Map k a -> [k]
Map.keys (Map Int Int -> [Int])
-> ((OMap Int Int, Map Int Int) -> Map Int Int)
-> (OMap Int Int, Map Int Int)
-> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OMap Int Int, Map Int Int) -> Map Int Int
forall a b. (a, b) -> b
snd)
        (OMap Int Int, Map Int Int)
result (OMap Int Int, Map Int Int)
-> ((OMap Int Int, Map Int Int) -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds' (OMap Int Int -> Bool)
-> ((OMap Int Int, Map Int Int) -> OMap Int Int)
-> (OMap Int Int, Map Int Int)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OMap Int Int, Map Int Int) -> OMap Int Int
forall a b. (a, b) -> a
fst
    String -> ((OMap Int Int, Int) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"filter" (((OMap Int Int, Int) -> IO ()) -> Spec)
-> ((OMap Int Int, Int) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
      \((OMap Int Int
omap, Int
i) :: (OMap Int Int, Int)) -> do
        let result :: OMap Int Int
result = (Int -> Bool) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (v -> Bool) -> OMap k v -> OMap k v
filter (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i) OMap Int Int
omap
        OMap Int Int
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` (Int -> Bool) -> OMap Int Int -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i)
        OMap Int Int
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
    String -> ((OMap Int Int, Int) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"adjust" (((OMap Int Int, Int) -> IO ()) -> Spec)
-> ((OMap Int Int, Int) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
      \((OMap Int Int
omap, Int
i) :: (OMap Int Int, Int)) ->
        (Int -> Int) -> Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (v -> v) -> k -> OMap k v -> OMap k v
adjust (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
i OMap Int Int
omap OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"overwriting" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"cons' - (<||)" (((OMap Int Int, (Int, Int)) -> IO ()) -> Spec)
-> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
omap, kv :: (Int, Int)
kv@(Int
k, Int
v)) :: (OMap Int Int, (Int, Int))) -> do
          let consed :: OMap Int Int
consed = (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<|| OMap Int Int
omap
          if Int
k Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
omap
            then OMap Int Int
consed OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Int) -> Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (v -> v) -> k -> OMap k v -> OMap k v
adjust (Int -> Int -> Int
forall a b. a -> b -> a
const Int
v) Int
k OMap Int Int
omap
            else OMap Int Int
consed OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int, Int)
kv (Int, Int) -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
<| OMap Int Int
omap
      String -> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"snoc' - (||>)" (((OMap Int Int, (Int, Int)) -> IO ()) -> Spec)
-> ((OMap Int Int, (Int, Int)) -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \((OMap Int Int
omap, kv :: (Int, Int)
kv@(Int
k, Int
v)) :: (OMap Int Int, (Int, Int))) -> do
          let snoced :: OMap Int Int
snoced = OMap Int Int
omap OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
||> (Int, Int)
kv
          if Int
k Int -> OMap Int Int -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
`member` OMap Int Int
omap
            then OMap Int Int
snoced OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Int) -> Int -> OMap Int Int -> OMap Int Int
forall k v. Ord k => (v -> v) -> k -> OMap k v -> OMap k v
adjust (Int -> Int -> Int
forall a b. a -> b -> a
const Int
v) Int
k OMap Int Int
omap
            else OMap Int Int
snoced OMap Int Int -> OMap Int Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` OMap Int Int
omap OMap Int Int -> (Int, Int) -> OMap Int Int
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
|> (Int, Int)
kv
    String -> (Map Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"fromFoldable preserves order" ((Map Int Int -> IO ()) -> Spec) -> (Map Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
      \(Map Int Int
m :: Map.Map Int Int) -> do
        let sseq :: StrictSeq (Int, Int)
sseq = [(Int, Int)] -> StrictSeq (Int, Int)
forall a. [a] -> StrictSeq a
SSeq.fromList ([(Int, Int)] -> StrictSeq (Int, Int))
-> [(Int, Int)] -> StrictSeq (Int, Int)
forall a b. (a -> b) -> a -> b
$ Map Int Int -> [(Int, Int)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Int Int
m
            omap :: OMap Int Int
omap = StrictSeq (Int, Int) -> OMap Int Int
forall (f :: * -> *) k v.
(Foldable f, Ord k) =>
f (k, v) -> OMap k v
fromFoldable StrictSeq (Int, Int)
sseq
        OMap Int Int -> StrictSeq (Int, Int)
forall k v. Ord k => OMap k v -> StrictSeq (k, v)
toStrictSeqOfPairs OMap Int Int
omap StrictSeq (Int, Int) -> StrictSeq (Int, Int) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` StrictSeq (Int, Int)
sseq
        OMap Int Int
omap OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"fromFoldableDuplicates preserves order" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> (Map Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"with duplicates" ((Map Int Int -> IO ()) -> Spec) -> (Map Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(Map Int Int
m :: Map.Map Int Int) -> do
          let sseq :: StrictSeq (Int, Int)
sseq = [(Int, Int)] -> StrictSeq (Int, Int)
forall a. [a] -> StrictSeq a
SSeq.fromList ([(Int, Int)] -> StrictSeq (Int, Int))
-> [(Int, Int)] -> StrictSeq (Int, Int)
forall a b. (a -> b) -> a -> b
$ Map Int Int -> [(Int, Int)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Int Int
m
              omap :: OMap Int Int
omap = StrictSeq (Int, Int) -> OMap Int Int
forall (f :: * -> *) k v.
(Foldable f, Ord k) =>
f (k, v) -> OMap k v
fromFoldable StrictSeq (Int, Int)
sseq
              result :: (Set (Int, Int), OMap Int Int)
result = StrictSeq (Int, Int) -> (Set (Int, Int), OMap Int Int)
forall (f :: * -> *) k v.
(Foldable f, Ord k, Ord v) =>
f (k, v) -> (Set (k, v), OMap k v)
fromFoldableDuplicates (StrictSeq (Int, Int)
sseq StrictSeq (Int, Int)
-> StrictSeq (Int, Int) -> StrictSeq (Int, Int)
forall a. StrictSeq a -> StrictSeq a -> StrictSeq a
SSeq.>< StrictSeq (Int, Int)
sseq)
          OMap Int Int -> StrictSeq (Int, Int)
forall k v. Ord k => OMap k v -> StrictSeq (k, v)
toStrictSeqOfPairs ((Set (Int, Int), OMap Int Int) -> OMap Int Int
forall a b. (a, b) -> b
snd (Set (Int, Int), OMap Int Int)
result) StrictSeq (Int, Int) -> StrictSeq (Int, Int) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` StrictSeq (Int, Int)
sseq
          (Set (Int, Int), OMap Int Int)
result (Set (Int, Int), OMap Int Int)
-> (Set (Int, Int), OMap Int Int) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` ([(Int, Int)] -> Set (Int, Int)
forall a. Ord a => [a] -> Set a
Set.fromList (Map Int Int -> [(Int, Int)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Int Int
m), OMap Int Int
omap)
          (Set (Int, Int), OMap Int Int) -> OMap Int Int
forall a b. (a, b) -> b
snd (Set (Int, Int), OMap Int Int)
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
      String -> (Map Int Int -> IO ()) -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop String
"without duplicates" ((Map Int Int -> IO ()) -> Spec) -> (Map Int Int -> IO ()) -> Spec
forall a b. (a -> b) -> a -> b
$
        \(Map Int Int
m :: Map.Map Int Int) -> do
          let sseq :: StrictSeq (Int, Int)
sseq = [(Int, Int)] -> StrictSeq (Int, Int)
forall a. [a] -> StrictSeq a
SSeq.fromList ([(Int, Int)] -> StrictSeq (Int, Int))
-> [(Int, Int)] -> StrictSeq (Int, Int)
forall a b. (a -> b) -> a -> b
$ Map Int Int -> [(Int, Int)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Int Int
m
              omap :: OMap Int Int
omap = StrictSeq (Int, Int) -> OMap Int Int
forall (f :: * -> *) k v.
(Foldable f, Ord k) =>
f (k, v) -> OMap k v
fromFoldable StrictSeq (Int, Int)
sseq
              result :: (Set (Int, Int), OMap Int Int)
result = StrictSeq (Int, Int) -> (Set (Int, Int), OMap Int Int)
forall (f :: * -> *) k v.
(Foldable f, Ord k, Ord v) =>
f (k, v) -> (Set (k, v), OMap k v)
fromFoldableDuplicates StrictSeq (Int, Int)
sseq
          OMap Int Int -> StrictSeq (Int, Int)
forall k v. Ord k => OMap k v -> StrictSeq (k, v)
toStrictSeqOfPairs ((Set (Int, Int), OMap Int Int) -> OMap Int Int
forall a b. (a, b) -> b
snd (Set (Int, Int), OMap Int Int)
result) StrictSeq (Int, Int) -> StrictSeq (Int, Int) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` StrictSeq (Int, Int)
sseq
          (Set (Int, Int), OMap Int Int)
result (Set (Int, Int), OMap Int Int)
-> (Set (Int, Int), OMap Int Int) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Set (Int, Int)
forall a. Set a
Set.empty, OMap Int Int
omap)
          (Set (Int, Int), OMap Int Int) -> OMap Int Int
forall a b. (a, b) -> b
snd (Set (Int, Int), OMap Int Int)
result OMap Int Int -> (OMap Int Int -> Bool) -> IO ()
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
`shouldSatisfy` OMap Int Int -> Bool
forall k v. Ord k => OMap k v -> Bool
invariantHolds'
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"CBOR round-trip" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      forall t. (Show t, Eq t, Arbitrary t, EncCBOR t, DecCBOR t) => Spec
roundTripCborSpec @(OMap Int Int)
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"Typeclass laws" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      String -> IO () -> SpecM (Arg (IO ())) ()
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"Type" (IO () -> SpecM (Arg (IO ())) ())
-> IO () -> SpecM (Arg (IO ())) ()
forall a b. (a -> b) -> a -> b
$
        Proxy (OMap Int Int) -> [Proxy (OMap Int Int) -> Laws] -> IO ()
forall a. Proxy a -> [Proxy a -> Laws] -> IO ()
lawsCheckOne
          (Proxy (OMap Int Int)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (OMap Int Int))
          [ Proxy (OMap Int Int) -> Laws
forall a. (Eq a, Arbitrary a, Show a) => Proxy a -> Laws
eqLaws
          , Proxy (OMap Int Int) -> Laws
forall a.
(IsList a, Show a, Show (Item a), Arbitrary a, Arbitrary (Item a),
 Eq a) =>
Proxy a -> Laws
isListLaws
          , Proxy (OMap Int Int) -> Laws
forall a.
(Semigroup a, Eq a, Arbitrary a, Show a) =>
Proxy a -> Laws
semigroupLaws
          , Proxy (OMap Int Int) -> Laws
forall a. (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
monoidLaws
          , Proxy (OMap Int Int) -> Laws
forall a.
(Semigroup a, Monoid a, Eq a, Arbitrary a, Show a) =>
Proxy a -> Laws
semigroupMonoidLaws
          ]