{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Data.GenValidity.Appendful.Collection where

import Control.Monad
import Data.Appendful
import Data.GenValidity
import Data.GenValidity.Containers ()
import Data.GenValidity.Time ()
import Data.Map (Map)
import qualified Data.Map as M
import Data.Set (Set)
import qualified Data.Set as S
import Test.QuickCheck

instance GenValid ClientId where
  genValid :: Gen ClientId
genValid = Gen ClientId
forall a. (Generic a, GGenValid (Rep a)) => Gen a
genValidStructurallyWithoutExtraChecking
  shrinkValid :: ClientId -> [ClientId]
shrinkValid = ClientId -> [ClientId]
forall a.
(Generic a, GValidRecursivelyShrink (Rep a),
 GValidSubterms (Rep a) a) =>
a -> [a]
shrinkValidStructurallyWithoutExtraFiltering

instance (GenValid ci, GenValid si, GenValid a, Show ci, Show si, Show a, Ord ci, Ord si, Ord a) => GenValid (ClientStore ci si a) where
  genValid :: Gen (ClientStore ci si a)
genValid =
    (Int -> Gen (ClientStore ci si a)) -> Gen (ClientStore ci si a)
forall a. (Int -> Gen a) -> Gen a
sized ((Int -> Gen (ClientStore ci si a)) -> Gen (ClientStore ci si a))
-> (Int -> Gen (ClientStore ci si a)) -> Gen (ClientStore ci si a)
forall a b. (a -> b) -> a -> b
$ \Int
n -> do
      (Int
a, Int
b) <- Int -> Gen (Int, Int)
genSplit Int
n
      Set si
s <- Int -> Gen (Set si) -> Gen (Set si)
forall a. Int -> Gen a -> Gen a
resize Int
a Gen (Set si)
forall a. GenValid a => Gen a
genValid
      Map ci a
clientStoreAdded <- Int -> Gen (Map ci a) -> Gen (Map ci a)
forall a. Int -> Gen a -> Gen a
resize Int
b Gen (Map ci a)
forall a. GenValid a => Gen a
genValid
      Map si a
clientStoreSynced <- Set si -> Gen (Map si a)
forall i a. (Ord i, GenValid a) => Set i -> Gen (Map i a)
mapWithIds Set si
s
      ClientStore ci si a -> Gen (ClientStore ci si a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ClientStore :: forall ci si a. Map ci a -> Map si a -> ClientStore ci si a
ClientStore {Map ci a
Map si a
clientStoreAdded :: Map ci a
clientStoreSynced :: Map si a
clientStoreSynced :: Map si a
clientStoreAdded :: Map ci a
..}
  shrinkValid :: ClientStore ci si a -> [ClientStore ci si a]
shrinkValid = ClientStore ci si a -> [ClientStore ci si a]
forall a.
(Validity a, Generic a, GValidRecursivelyShrink (Rep a),
 GValidSubterms (Rep a) a) =>
a -> [a]
shrinkValidStructurally

instance (GenValid ci, GenValid si, GenValid a, Show ci, Show si, Show a, Ord ci, Ord si, Ord a) => GenValid (SyncRequest ci si a) where
  genValid :: Gen (SyncRequest ci si a)
genValid = do
    Map ci a
syncRequestAdded <- Gen (Map ci a)
forall a. GenValid a => Gen a
genValid
    Maybe si
syncRequestMaximumSynced <- Gen (Maybe si)
forall a. GenValid a => Gen a
genValid
    SyncRequest ci si a -> Gen (SyncRequest ci si a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure SyncRequest :: forall ci si a. Map ci a -> Maybe si -> SyncRequest ci si a
SyncRequest {Maybe si
Map ci a
syncRequestAdded :: Map ci a
syncRequestMaximumSynced :: Maybe si
syncRequestMaximumSynced :: Maybe si
syncRequestAdded :: Map ci a
..}
  shrinkValid :: SyncRequest ci si a -> [SyncRequest ci si a]
shrinkValid = SyncRequest ci si a -> [SyncRequest ci si a]
forall a.
(Validity a, Generic a, GValidRecursivelyShrink (Rep a),
 GValidSubterms (Rep a) a) =>
a -> [a]
shrinkValidStructurally

instance (GenValid ci, GenValid si, GenValid a, Show ci, Show si, Show a, Ord ci, Ord si, Ord a) => GenValid (SyncResponse ci si a) where
  genValid :: Gen (SyncResponse ci si a)
genValid = do
    (Set si
s1, Set si
s2) <- Gen (Set si)
forall a. GenValid a => Gen a
genValid Gen (Set si)
-> (Set si -> Gen (Set si, Set si)) -> Gen (Set si, Set si)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Set si -> Gen (Set si, Set si)
forall i. Ord i => Set i -> Gen (Set i, Set i)
splitSet
    Map ci si
syncResponseClientAdded <-
      ([(ci, si)] -> Map ci si) -> Gen [(ci, si)] -> Gen (Map ci si)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [(ci, si)] -> Map ci si
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList (Gen [(ci, si)] -> Gen (Map ci si))
-> Gen [(ci, si)] -> Gen (Map ci si)
forall a b. (a -> b) -> a -> b
$
        [si] -> (si -> Gen (ci, si)) -> Gen [(ci, si)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (Set si -> [si]
forall a. Set a -> [a]
S.toList Set si
s1) ((si -> Gen (ci, si)) -> Gen [(ci, si)])
-> (si -> Gen (ci, si)) -> Gen [(ci, si)]
forall a b. (a -> b) -> a -> b
$
          \si
i -> do
            ci
cid <- Gen ci
forall a. GenValid a => Gen a
genValid -- TODO maybe we can find a way to not generate duplicate client ids and speed up this generator, but it's fine for now.
            (ci, si) -> Gen (ci, si)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ci
cid, si
i)
    Map si a
syncResponseServerAdded <- Set si -> Gen (Map si a)
forall i a. (Ord i, GenValid a) => Set i -> Gen (Map i a)
mapWithIds Set si
s2
    SyncResponse ci si a -> Gen (SyncResponse ci si a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure SyncResponse :: forall ci si a. Map ci si -> Map si a -> SyncResponse ci si a
SyncResponse {Map ci si
Map si a
syncResponseClientAdded :: Map ci si
syncResponseServerAdded :: Map si a
syncResponseServerAdded :: Map si a
syncResponseClientAdded :: Map ci si
..}
  shrinkValid :: SyncResponse ci si a -> [SyncResponse ci si a]
shrinkValid = SyncResponse ci si a -> [SyncResponse ci si a]
forall a.
(Validity a, Generic a, GValidRecursivelyShrink (Rep a),
 GValidSubterms (Rep a) a) =>
a -> [a]
shrinkValidStructurally

splitSet :: Ord i => Set i -> Gen (Set i, Set i)
splitSet :: Set i -> Gen (Set i, Set i)
splitSet Set i
s =
  if Set i -> Bool
forall a. Set a -> Bool
S.null Set i
s
    then (Set i, Set i) -> Gen (Set i, Set i)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Set i
forall a. Set a
S.empty, Set i
forall a. Set a
S.empty)
    else do
      i
a <- [i] -> Gen i
forall a. [a] -> Gen a
elements ([i] -> Gen i) -> [i] -> Gen i
forall a b. (a -> b) -> a -> b
$ Set i -> [i]
forall a. Set a -> [a]
S.toList Set i
s
      (Set i, Set i) -> Gen (Set i, Set i)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Set i, Set i) -> Gen (Set i, Set i))
-> (Set i, Set i) -> Gen (Set i, Set i)
forall a b. (a -> b) -> a -> b
$ i -> Set i -> (Set i, Set i)
forall a. Ord a => a -> Set a -> (Set a, Set a)
S.split i
a Set i
s

mapWithIds :: (Ord i, GenValid a) => Set i -> Gen (Map i a)
mapWithIds :: Set i -> Gen (Map i a)
mapWithIds = Map i (Gen a) -> Gen (Map i a)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA (Map i (Gen a) -> Gen (Map i a))
-> (Set i -> Map i (Gen a)) -> Set i -> Gen (Map i a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (i -> Gen a) -> Set i -> Map i (Gen a)
forall k a. (k -> a) -> Set k -> Map k a
M.fromSet (Gen a -> i -> Gen a
forall a b. a -> b -> a
const Gen a
forall a. GenValid a => Gen a
genValid)

instance (GenValid si, GenValid a, Show si, Show a, Ord si, Ord a) => GenValid (ServerStore si a) where
  genValid :: Gen (ServerStore si a)
genValid = Gen (ServerStore si a)
forall a. (Generic a, GGenValid (Rep a)) => Gen a
genValidStructurallyWithoutExtraChecking
  shrinkValid :: ServerStore si a -> [ServerStore si a]
shrinkValid = ServerStore si a -> [ServerStore si a]
forall a.
(Generic a, GValidRecursivelyShrink (Rep a),
 GValidSubterms (Rep a) a) =>
a -> [a]
shrinkValidStructurallyWithoutExtraFiltering

genServerStoreFromSet :: (Ord si, GenValid v) => Set si -> Gen (ServerStore si v)
genServerStoreFromSet :: Set si -> Gen (ServerStore si v)
genServerStoreFromSet Set si
s = Map si v -> ServerStore si v
forall si a. Map si a -> ServerStore si a
ServerStore (Map si v -> ServerStore si v)
-> Gen (Map si v) -> Gen (ServerStore si v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set si -> Gen (Map si v)
forall i a. (Ord i, GenValid a) => Set i -> Gen (Map i a)
mapWithIds Set si
s

genUnsyncedStore ::
  forall ci si a.
  (Show ci, Ord ci, Ord si, Ord a, GenValid ci, GenValid si, GenValid a) =>
  Gen (ClientStore ci si a)
genUnsyncedStore :: Gen (ClientStore ci si a)
genUnsyncedStore = do
  Map ci a
as <- Gen (Map ci a)
forall a. GenValid a => Gen a
genValid
  ClientStore ci si a -> Gen (ClientStore ci si a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ClientStore ci si a -> Gen (ClientStore ci si a))
-> ClientStore ci si a -> Gen (ClientStore ci si a)
forall a b. (a -> b) -> a -> b
$ ClientStore Any si a
forall ci si a. ClientStore ci si a
emptyClientStore {clientStoreAdded :: Map ci a
clientStoreAdded = Map ci a
as}

genClientStoreFromSet :: (Show ci, Ord ci, Ord si, GenValid ci, GenValid v) => Set si -> Gen (ClientStore ci si v)
genClientStoreFromSet :: Set si -> Gen (ClientStore ci si v)
genClientStoreFromSet Set si
s = do
  Map ci v
clientStoreAdded <- Gen (Map ci v)
forall a. GenValid a => Gen a
genValid
  Map si v
clientStoreSynced <- Set si -> Gen (Map si v)
forall i a. (Ord i, GenValid a) => Set i -> Gen (Map i a)
mapWithIds Set si
s
  ClientStore ci si v -> Gen (ClientStore ci si v)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ClientStore :: forall ci si a. Map ci a -> Map si a -> ClientStore ci si a
ClientStore {Map ci v
Map si v
clientStoreSynced :: Map si v
clientStoreAdded :: Map ci v
clientStoreAdded :: Map ci v
clientStoreSynced :: Map si v
..}