{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_HADDOCK prune not-home #-}

{- |
Module      : Test.KeyedVals.CheckHandle
Copyright   : (c) 2022 Tim Emiola
Maintainer  : Tim Emiola <adetcorrectlyunbo@emio.la>
SPDX-License-Identifier: BSD3
-}
module Test.KeyedVals.CheckTypedHandle (
  -- * a test fixture
  spec,

  -- * setup/teardown hspec tests
  setupFixture,
  closeFixture,
) where

import qualified Data.Map.Strict as Map
import KeyedVals.Handle.Typed
import Test.KeyedVals.Prelude


spec :: SpecWith (Handle IO)
spec :: SpecWith (Handle IO)
spec = do
  SpecWith (Handle IO)
checkFixedPathed
  SpecWith (Handle IO)
checkVarPathed


checkFixedPathed :: SpecWith (Handle IO)
checkFixedPathed :: SpecWith (Handle IO)
checkFixedPathed = do
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"with typed key-values stored in fixed paths" forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should load correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      forall (m :: * -> *) a.
(Monad m, DecodeKV a, DecodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> m (Either HandleErr (TypedKVs a))
loadKVs Handle IO
h forall v. PathOf v => TypedPath v
Fixed forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` Map (KeyType FixedDemo) FixedDemo
fixedKVs

    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength @FixedDemo forall v. PathOf v => TypedPath v
Fixed Natural
2

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should update an indexed value correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let k :: TypedKey FixedDemo
k = forall v. PathOf v => KeyType v -> TypedKey v
key FixedDemoKey
fixedK1
          want :: FixedDemo
want = (Int, Text) -> FixedDemo
FixedDemo (Int
1, Text
"changed")
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, PathOf a) =>
Handle m -> TypedKey a -> a -> m (Either HandleErr ())
saveTo Handle IO
h TypedKey FixedDemo
k FixedDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a) =>
Handle m -> TypedKey a -> m (Either HandleErr a)
loadFrom Handle IO
h TypedKey FixedDemo
k forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` FixedDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey FixedDemo
k forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just FixedDemo
want

    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength @FixedDemo forall v. PathOf v => TypedPath v
Fixed Natural
2

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should add an indexed value correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let added :: TypedKey FixedDemo
added = forall v. PathOf v => KeyType v -> TypedKey v
key FixedDemoKey
fixedK3
          want :: FixedDemo
want = (Int, Text) -> FixedDemo
FixedDemo (Int
3, Text
"added")
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey FixedDemo
added forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. Maybe a
Nothing
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, PathOf a) =>
Handle m -> TypedKey a -> a -> m (Either HandleErr ())
saveTo Handle IO
h TypedKey FixedDemo
added FixedDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey FixedDemo
added forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just FixedDemo
want

    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength @FixedDemo forall v. PathOf v => TypedPath v
Fixed Natural
3

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should update the key-values correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, EncodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> TypedKVs a -> m (Either HandleErr ())
updateKVs Handle IO
h forall v. PathOf v => TypedPath v
Fixed Map (KeyType FixedDemo) FixedDemo
moreFixedKVs
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h (forall v. PathOf v => KeyType v -> TypedKey v
key FixedDemoKey
fixedK1) forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just FixedDemo
fixedV3
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h (forall v. PathOf v => KeyType v -> TypedKey v
key FixedDemoKey
fixedK4) forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just FixedDemo
fixedV4

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should fetch a subset of the key-values as a dict correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let selection :: NonEmpty FixedDemoKey
selection = FixedDemoKey
fixedK1 forall a. a -> [a] -> NonEmpty a
:| [FixedDemoKey
fixedK4]
      forall (m :: * -> *) a.
(Monad m, DecodeKV a, PathOf a, DecodeKV (KeyType a),
 Ord (KeyType a)) =>
Handle m
-> TypedPath a
-> NonEmpty (KeyType a)
-> m (Either HandleErr (TypedKVs a))
loadSlice Handle IO
h forall v. PathOf v => TypedPath v
Fixed NonEmpty FixedDemoKey
selection forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` Map (KeyType FixedDemo) FixedDemo
moreFixedKVs


checkVarPathed :: SpecWith (Handle IO)
checkVarPathed :: SpecWith (Handle IO)
checkVarPathed = do
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"with typed key-values stored in variable paths" forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should load correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      forall (m :: * -> *) a.
(Monad m, DecodeKV a, DecodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> m (Either HandleErr (TypedKVs a))
loadKVs Handle IO
h TypedPath VarDemo
path1 forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` TypedKVs VarDemo
varKVs
      forall (m :: * -> *) a.
(Monad m, DecodeKV a, DecodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> m (Either HandleErr (TypedKVs a))
loadKVs Handle IO
h TypedPath VarDemo
path2 forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` TypedKVs VarDemo
varKVs

    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength TypedPath VarDemo
path1 Natural
2
    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength TypedPath VarDemo
path2 Natural
2

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should update an indexed value correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let k :: TypedKey VarDemo
k = VarDemoID
id1 forall v. VaryingPathOf v => PathVar v -> KeyType v -> TypedKey v
// VarDemoKey
varK1
          want :: VarDemo
want = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right Bool
False
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, PathOf a) =>
Handle m -> TypedKey a -> a -> m (Either HandleErr ())
saveTo Handle IO
h TypedKey VarDemo
k VarDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a) =>
Handle m -> TypedKey a -> m (Either HandleErr a)
loadFrom Handle IO
h TypedKey VarDemo
k forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` VarDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey VarDemo
k forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just VarDemo
want

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should add an indexed value correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let added :: TypedKey VarDemo
added = VarDemoID
id2 forall v. VaryingPathOf v => PathVar v -> KeyType v -> TypedKey v
// VarDemoKey
varK3
          want :: VarDemo
want = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left Text
"added"
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey VarDemo
added forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. Maybe a
Nothing
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, PathOf a) =>
Handle m -> TypedKey a -> a -> m (Either HandleErr ())
saveTo Handle IO
h TypedKey VarDemo
added VarDemo
want
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h TypedKey VarDemo
added forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just VarDemo
want

    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength TypedPath VarDemo
path1 Natural
2
    forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength TypedPath VarDemo
path2 Natural
3

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should update the key-values correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      forall a b. (Show a, Show b) => IO (Either a b) -> IO ()
endsRight_ forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, EncodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> TypedKVs a -> m (Either HandleErr ())
updateKVs Handle IO
h TypedPath VarDemo
path1 TypedKVs VarDemo
moreVarKVs
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h (VarDemoID
id1 forall v. VaryingPathOf v => PathVar v -> KeyType v -> TypedKey v
// VarDemoKey
varK1) forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just VarDemo
varV3
      forall a (m :: * -> *).
(Monad m, DecodeKV a, PathOf a) =>
Handle m -> TypedKey a -> m (Either HandleErr (Maybe a))
mayLoadFrom Handle IO
h (VarDemoID
id1 forall v. VaryingPathOf v => PathVar v -> KeyType v -> TypedKey v
// VarDemoKey
varK4) forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` forall a. a -> Maybe a
Just VarDemo
varV4

    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should fetch a subset of the key-values correctly" forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
      let selection :: NonEmpty VarDemoKey
selection = VarDemoKey
varK1 forall a. a -> [a] -> NonEmpty a
:| [VarDemoKey
varK4]
      forall (m :: * -> *) a.
(Monad m, DecodeKV a, PathOf a, DecodeKV (KeyType a),
 Ord (KeyType a)) =>
Handle m
-> TypedPath a
-> NonEmpty (KeyType a)
-> m (Either HandleErr (TypedKVs a))
loadSlice Handle IO
h TypedPath VarDemo
path1 NonEmpty VarDemoKey
selection forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` TypedKVs VarDemo
moreVarKVs


setupFixture :: Handle IO -> IO (Handle IO)
setupFixture :: Handle IO -> IO (Handle IO)
setupFixture Handle IO
h = do
  IO (Either HandleErr ()) -> IO ()
orThrowHandleErr forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, EncodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> TypedKVs a -> m (Either HandleErr ())
saveKVs Handle IO
h forall v. PathOf v => TypedPath v
Fixed Map (KeyType FixedDemo) FixedDemo
fixedKVs
  IO (Either HandleErr ()) -> IO ()
orThrowHandleErr forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, EncodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> TypedKVs a -> m (Either HandleErr ())
saveKVs Handle IO
h TypedPath VarDemo
path1 TypedKVs VarDemo
varKVs
  IO (Either HandleErr ()) -> IO ()
orThrowHandleErr forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, EncodeKV a, EncodeKV (KeyType a), Ord (KeyType a)) =>
Handle m -> TypedPath a -> TypedKVs a -> m (Either HandleErr ())
saveKVs Handle IO
h TypedPath VarDemo
path2 TypedKVs VarDemo
varKVs
  forall (f :: * -> *) a. Applicative f => a -> f a
pure Handle IO
h


closeFixture :: Handle IO -> IO ()
closeFixture :: Handle IO -> IO ()
closeFixture = forall (m :: * -> *). Handle m -> m ()
close


fixedK1, fixedK2, fixedK3, fixedK4 :: FixedDemoKey
fixedK1 :: FixedDemoKey
fixedK1 = FixedDemoKey
25
fixedK2 :: FixedDemoKey
fixedK2 = FixedDemoKey
49
fixedK3 :: FixedDemoKey
fixedK3 = FixedDemoKey
81
fixedK4 :: FixedDemoKey
fixedK4 = FixedDemoKey
121


fixedV1, fixedV2, fixedV3, fixedV4 :: FixedDemo
fixedV1 :: FixedDemo
fixedV1 = (Int, Text) -> FixedDemo
FixedDemo (Int
1, Text
"one")
fixedV2 :: FixedDemo
fixedV2 = (Int, Text) -> FixedDemo
FixedDemo (Int
2, Text
"two")
fixedV3 :: FixedDemo
fixedV3 = (Int, Text) -> FixedDemo
FixedDemo (Int
1, Text
"un")
fixedV4 :: FixedDemo
fixedV4 = (Int, Text) -> FixedDemo
FixedDemo (Int
4, Text
"quatre")


fixedKVs, moreFixedKVs :: TypedKVs FixedDemo
fixedKVs :: Map (KeyType FixedDemo) FixedDemo
fixedKVs =
  forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
    [ (FixedDemoKey
fixedK1, FixedDemo
fixedV1)
    , (FixedDemoKey
fixedK2, FixedDemo
fixedV2)
    ]
moreFixedKVs :: Map (KeyType FixedDemo) FixedDemo
moreFixedKVs =
  forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
    [ (FixedDemoKey
fixedK1, FixedDemo
fixedV3)
    , (FixedDemoKey
fixedK4, FixedDemo
fixedV4)
    ]


varK1, varK2, varK3, varK4 :: VarDemoKey
varK1 :: VarDemoKey
varK1 = VarDemoKey
36
varK2 :: VarDemoKey
varK2 = VarDemoKey
64
varK3 :: VarDemoKey
varK3 = VarDemoKey
100
varK4 :: VarDemoKey
varK4 = VarDemoKey
144


path1, path2 :: TypedPath VarDemo
path1 :: TypedPath VarDemo
path1 = forall v. VaryingPathOf v => PathVar v -> TypedPath v
Variable VarDemoID
id1
path2 :: TypedPath VarDemo
path2 = forall v. VaryingPathOf v => PathVar v -> TypedPath v
Variable VarDemoID
id2


id1, id2 :: VarDemoID
id1 :: VarDemoID
id1 = VarDemoID
"id1"
id2 :: VarDemoID
id2 = VarDemoID
"id2"


varV1, varV2, varV3, varV4 :: VarDemo
varV1 :: VarDemo
varV1 = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left Text
"one"
varV2 :: VarDemo
varV2 = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right Bool
False
varV3 :: VarDemo
varV3 = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left Text
"three"
varV4 :: VarDemo
varV4 = Either Text Bool -> VarDemo
VarDemo forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left Text
"four"


varKVs, moreVarKVs :: TypedKVs VarDemo
varKVs :: TypedKVs VarDemo
varKVs =
  forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
    [ (VarDemoKey
varK1, VarDemo
varV1)
    , (VarDemoKey
varK2, VarDemo
varV2)
    ]
moreVarKVs :: TypedKVs VarDemo
moreVarKVs =
  forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
    [ (VarDemoKey
varK1, VarDemo
varV3)
    , (VarDemoKey
varK4, VarDemo
varV4)
    ]


checkLength ::
  (Ord (KeyType v)) =>
  TypedPath v ->
  Natural ->
  SpecWith (Handle IO)
checkLength :: forall v.
Ord (KeyType v) =>
TypedPath v -> Natural -> SpecWith (Handle IO)
checkLength TypedPath v
path Natural
n = forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"and the reported size" forall a b. (a -> b) -> a -> b
$ do
  forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be correct " forall a b. (a -> b) -> a -> b
$ \Handle IO
h -> do
    forall a (m :: * -> *).
(Monad m, Ord (KeyType a)) =>
Handle m -> TypedPath a -> m (Either HandleErr Natural)
countKVs Handle IO
h TypedPath v
path forall a b.
(HasCallStack, Show a, Eq a, Show b, Eq b) =>
IO (Either a b) -> b -> IO ()
`endsRight` Natural
n