packages feed

HMock 0.1.0.1 → 0.2.0.0

raw patch · 39 files changed

+4514/−4108 lines, 39 filesdep +stmPVP ok

version bump matches the API change (PVP)

Dependencies added: stm

API changes (from Hackage documentation)

- Test.HMock: (|->) :: (Monad m, Expectable cls name m r expectable) => expectable -> r -> Rule cls name m r
- Test.HMock: (|=>) :: Expectable cls name m r expectable => expectable -> (Action cls name m r -> MockT m r) -> Rule cls name m r
- Test.HMock: -- for each method.
- Test.HMock: -- replaced with predicates.
- Test.HMock: -- | A specification for matching actions. The actual arguments should be
- Test.HMock: Predicate :: String -> (a -> Bool) -> Predicate a
- Test.HMock: [Match] :: MatchResult
- Test.HMock: [NoMatch] :: Int -> MatchResult
- Test.HMock: [accept] :: Predicate a -> a -> Bool
- Test.HMock: [showPredicate] :: Predicate a -> String
- Test.HMock: andP :: Predicate a -> Predicate a -> Predicate a
- Test.HMock: anyMultiplicity :: Multiplicity
- Test.HMock: anyOf :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock: anything :: Predicate a
- Test.HMock: approxEq :: (RealFloat a, Show a) => a -> Predicate a
- Test.HMock: atLeast :: Multiplicity -> Multiplicity
- Test.HMock: atMost :: Multiplicity -> Multiplicity
- Test.HMock: between :: Multiplicity -> Multiplicity -> Multiplicity
- Test.HMock: byDefault :: forall cls name m r. (MonadIO m, MockableMethod cls name m r) => Rule cls name m r -> MockT m ()
- Test.HMock: caseInsensitive :: (MonoFunctor t, MonoFunctor a, Element t ~ Char, Element a ~ Char) => (t -> Predicate a) -> t -> Predicate a
- Test.HMock: class ExpectContext (t :: (Type -> Type) -> Type -> Type)
- Test.HMock: class Expectable cls name m r e | e -> cls name m r
- Test.HMock: class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint)
- Test.HMock: class (Typeable cls) => MockableBase (cls :: (Type -> Type) -> Constraint) where {
- Test.HMock: consecutiveTimes :: (MonadIO m, ExpectContext ctx) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
- Test.HMock: contains :: MonoFoldable t => Predicate (Element t) -> Predicate t
- Test.HMock: containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock: containsCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock: containsEntry :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t
- Test.HMock: containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t
- Test.HMock: containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock: containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock: data MatchResult
- Test.HMock: data MockT m a
- Test.HMock: data Multiplicity
- Test.HMock: data Predicate a
- Test.HMock: data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
- Test.HMock: data family Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type;
- Test.HMock: describeExpectations :: MonadIO m => MockT m String
- Test.HMock: each :: MonoFoldable t => Predicate (Element t) -> Predicate t
- Test.HMock: elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock: endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock: entriesAre :: (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t
- Test.HMock: eq :: (Show a, Eq a) => a -> Predicate a
- Test.HMock: expect :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => expectable -> ctx m ()
- Test.HMock: expectAny :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => expectable -> ctx m ()
- Test.HMock: expectN :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => Multiplicity -> expectable -> ctx m ()
- Test.HMock: finite :: RealFloat a => Predicate a
- Test.HMock: geq :: (Show a, Ord a) => a -> Predicate a
- Test.HMock: gt :: (Show a, Ord a) => a -> Predicate a
- Test.HMock: hasSubsequence :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock: hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock: inAnyOrder :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock: inSequence :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock: infinite :: RealFloat a => Predicate a
- Test.HMock: infixl 1 |->
- Test.HMock: is :: HasCallStack => (a -> Bool) -> Predicate a
- Test.HMock: isEmpty :: MonoFoldable t => Predicate t
- Test.HMock: just :: Predicate a -> Predicate (Maybe a)
- Test.HMock: keysAre :: (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t
- Test.HMock: left :: Predicate a -> Predicate (Either a b)
- Test.HMock: leq :: (Show a, Ord a) => a -> Predicate a
- Test.HMock: lt :: (Show a, Ord a) => a -> Predicate a
- Test.HMock: matchAction :: MockableBase cls => Matcher cls name m a -> Action cls name m a -> MatchResult
- Test.HMock: matchesCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock: matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock: meetsMultiplicity :: Multiplicity -> Int -> Bool
- Test.HMock: mockDefaultlessMethod :: forall cls name m r. (HasCallStack, MonadIO m, MockableMethod cls name m r) => Action cls name m r -> MockT m r
- Test.HMock: mockMethod :: forall cls name m r. (HasCallStack, MonadIO m, MockableMethod cls name m r, Default r) => Action cls name m r -> MockT m r
- Test.HMock: nAn :: RealFloat a => Predicate a
- Test.HMock: neq :: (Show a, Eq a) => a -> Predicate a
- Test.HMock: nonEmpty :: MonoFoldable t => Predicate t
- Test.HMock: notP :: Predicate a -> Predicate a
- Test.HMock: once :: Multiplicity
- Test.HMock: orP :: Predicate a -> Predicate a -> Predicate a
- Test.HMock: qIs :: HasCallStack => ExpQ -> ExpQ
- Test.HMock: qMatch :: PatQ -> ExpQ
- Test.HMock: qWith :: ExpQ -> ExpQ
- Test.HMock: right :: Predicate b -> Predicate (Either a b)
- Test.HMock: runMockT :: forall m a. MonadIO m => MockT m a -> m a
- Test.HMock: setupMockable :: (Mockable cls, MonadIO m, Typeable m) => proxy cls -> MockT m ()
- Test.HMock: showAction :: MockableBase cls => Action cls name m a -> String
- Test.HMock: showMatcher :: MockableBase cls => Maybe (Action cls name m a) -> Matcher cls name m b -> String
- Test.HMock: sizeIs :: MonoFoldable t => Predicate Int -> Predicate t
- Test.HMock: startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock: times :: (MonadIO m, ExpectContext ctx) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
- Test.HMock: toRule :: Expectable cls name m r e => e -> Rule cls name m r
- Test.HMock: type MockableMethod (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) = (Mockable cls, Typeable m, KnownSymbol name, Typeable r)
- Test.HMock: typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b
- Test.HMock: unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock: verifyExpectations :: MonadIO m => MockT m ()
- Test.HMock: with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a
- Test.HMock: withMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b
- Test.HMock: zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)
- Test.HMock: zip4P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate (a, b, c, d)
- Test.HMock: zip5P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate e -> Predicate (a, b, c, d, e)
- Test.HMock: zipP :: Predicate a -> Predicate b -> Predicate (a, b)
- Test.HMock: }
- Test.HMock.Internal.Expectable: (|->) :: (Monad m, Expectable cls name m r expectable) => expectable -> r -> Rule cls name m r
- Test.HMock.Internal.Expectable: (|=>) :: Expectable cls name m r expectable => expectable -> (Action cls name m r -> MockT m r) -> Rule cls name m r
- Test.HMock.Internal.Expectable: Expected :: ExpectSet (Step m) -> Expected m a
- Test.HMock.Internal.Expectable: [:->] :: Matcher cls name m r -> Maybe (Action cls name m r -> MockT m r) -> SingleRule cls name m r
- Test.HMock.Internal.Expectable: [:=>] :: Matcher cls name m r -> [Action cls name m r -> MockT m r] -> Rule cls name m r
- Test.HMock.Internal.Expectable: [Step] :: MockableMethod cls name m r => Located (SingleRule cls name m r) -> Step m
- Test.HMock.Internal.Expectable: [unwrapExpected] :: Expected m a -> ExpectSet (Step m)
- Test.HMock.Internal.Expectable: anyOf :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock.Internal.Expectable: class ExpectContext (t :: (Type -> Type) -> Type -> Type)
- Test.HMock.Internal.Expectable: class Expectable cls name m r e | e -> cls name m r
- Test.HMock.Internal.Expectable: consecutiveTimes :: (MonadIO m, ExpectContext ctx) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
- Test.HMock.Internal.Expectable: data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
- Test.HMock.Internal.Expectable: data SingleRule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
- Test.HMock.Internal.Expectable: data Step m
- Test.HMock.Internal.Expectable: expandRepeatRule :: MockableMethod cls name m r => Multiplicity -> CallStack -> Rule cls name m r -> ExpectSet (Step m)
- Test.HMock.Internal.Expectable: expandRule :: MockableMethod cls name m r => CallStack -> Rule cls name m r -> ExpectSet (Step m)
- Test.HMock.Internal.Expectable: expect :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => expectable -> ctx m ()
- Test.HMock.Internal.Expectable: expectAny :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => expectable -> ctx m ()
- Test.HMock.Internal.Expectable: expectN :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable, ExpectContext ctx) => Multiplicity -> expectable -> ctx m ()
- Test.HMock.Internal.Expectable: fromExpectSet :: (ExpectContext t, MonadIO m) => ExpectSet (Step m) -> t m ()
- Test.HMock.Internal.Expectable: inAnyOrder :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock.Internal.Expectable: inSequence :: (MonadIO m, ExpectContext ctx) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
- Test.HMock.Internal.Expectable: infixl 1 |->
- Test.HMock.Internal.Expectable: instance GHC.Show.Show (Test.HMock.Internal.Expectable.Step m)
- Test.HMock.Internal.Expectable: instance Test.HMock.Internal.Expectable.ExpectContext Test.HMock.Internal.Expectable.Expected
- Test.HMock.Internal.Expectable: instance Test.HMock.Internal.Expectable.Expectable cls name m r (Test.HMock.Internal.Expectable.Rule cls name m r)
- Test.HMock.Internal.Expectable: instance Test.HMock.Internal.Expectable.Expectable cls name m r (Test.HMock.Internal.Mockable.Matcher cls name m r)
- Test.HMock.Internal.Expectable: newtype Expected m a
- Test.HMock.Internal.Expectable: times :: (MonadIO m, ExpectContext ctx) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
- Test.HMock.Internal.Expectable: toRule :: Expectable cls name m r e => e -> Rule cls name m r
- Test.HMock.Internal.Expectable: type MockableMethod (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) = (Mockable cls, Typeable m, KnownSymbol name, Typeable r)
- Test.HMock.Internal.MockT: MockState :: ExpectSet (Step m) -> [Step m] -> Set TypeRep -> MockState m
- Test.HMock.Internal.MockT: [MockT] :: {unMockT :: ReaderT (MVar (MockState m)) m a} -> MockT m a
- Test.HMock.Internal.MockT: [mockClasses] :: MockState m -> Set TypeRep
- Test.HMock.Internal.MockT: [mockDefaults] :: MockState m -> [Step m]
- Test.HMock.Internal.MockT: [mockExpectSet] :: MockState m -> ExpectSet (Step m)
- Test.HMock.Internal.MockT: byDefault :: forall cls name m r. (MonadIO m, MockableMethod cls name m r) => Rule cls name m r -> MockT m ()
- Test.HMock.Internal.MockT: data MockState m
- Test.HMock.Internal.MockT: describeExpectations :: MonadIO m => MockT m String
- Test.HMock.Internal.MockT: initClassIfNeeded :: forall cls m proxy. (Mockable cls, Typeable m, MonadIO m) => proxy cls -> MockT m ()
- Test.HMock.Internal.MockT: initClassesAsNeeded :: MonadIO m => ExpectSet (Step m) -> MockT m ()
- Test.HMock.Internal.MockT: initMockState :: MockState m
- Test.HMock.Internal.MockT: instance (Control.Monad.Reader.Class.MonadReader r m, Control.Monad.Writer.Class.MonadWriter w m, Control.Monad.State.Class.MonadState s m) => Control.Monad.RWS.Class.MonadRWS r w s (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.IO.Unlift.MonadUnliftIO m => Control.Monad.IO.Unlift.MonadUnliftIO (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Control.Monad.Trans.Class.MonadTrans Test.HMock.Internal.MockT.MockT
- Test.HMock.Internal.MockT: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance GHC.Base.Applicative m => GHC.Base.Applicative (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance GHC.Base.Functor m => GHC.Base.Functor (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance GHC.Base.Monad m => GHC.Base.Monad (Test.HMock.Internal.MockT.MockT m)
- Test.HMock.Internal.MockT: instance Test.HMock.Internal.Expectable.ExpectContext Test.HMock.Internal.MockT.MockT
- Test.HMock.Internal.MockT: mapMockT :: (m a -> m b) -> MockT m a -> MockT m b
- Test.HMock.Internal.MockT: mockDefaultlessMethod :: forall cls name m r. (HasCallStack, MonadIO m, MockableMethod cls name m r) => Action cls name m r -> MockT m r
- Test.HMock.Internal.MockT: mockMethod :: forall cls name m r. (HasCallStack, MonadIO m, MockableMethod cls name m r, Default r) => Action cls name m r -> MockT m r
- Test.HMock.Internal.MockT: mockMethodImpl :: forall cls name m r. (HasCallStack, MonadIO m, MockableMethod cls name m r) => r -> Action cls name m r -> MockT m r
- Test.HMock.Internal.MockT: newtype MockT m a
- Test.HMock.Internal.MockT: noMatchError :: (HasCallStack, Mockable cls) => Action cls name m a -> String
- Test.HMock.Internal.MockT: partialMatchError :: (HasCallStack, Mockable cls) => Action cls name m a -> [String] -> String
- Test.HMock.Internal.MockT: runMockT :: forall m a. MonadIO m => MockT m a -> m a
- Test.HMock.Internal.MockT: verifyExpectations :: MonadIO m => MockT m ()
- Test.HMock.Internal.MockT: withMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b
- Test.HMock.Internal.Mockable: -- for each method.
- Test.HMock.Internal.Mockable: -- replaced with predicates.
- Test.HMock.Internal.Mockable: -- | A specification for matching actions. The actual arguments should be
- Test.HMock.Internal.Mockable: [Match] :: MatchResult
- Test.HMock.Internal.Mockable: [NoMatch] :: Int -> MatchResult
- Test.HMock.Internal.Mockable: class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint)
- Test.HMock.Internal.Mockable: class (Typeable cls) => MockableBase (cls :: (Type -> Type) -> Constraint) where {
- Test.HMock.Internal.Mockable: data MatchResult
- Test.HMock.Internal.Mockable: data family Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type;
- Test.HMock.Internal.Mockable: matchAction :: MockableBase cls => Matcher cls name m a -> Action cls name m a -> MatchResult
- Test.HMock.Internal.Mockable: setupMockable :: (Mockable cls, MonadIO m, Typeable m) => proxy cls -> MockT m ()
- Test.HMock.Internal.Mockable: showAction :: MockableBase cls => Action cls name m a -> String
- Test.HMock.Internal.Mockable: showMatcher :: MockableBase cls => Maybe (Action cls name m a) -> Matcher cls name m b -> String
- Test.HMock.Internal.Mockable: }
- Test.HMock.Internal.Multiplicity: Multiplicity :: Int -> Maybe Int -> Multiplicity
- Test.HMock.Internal.Multiplicity: anyMultiplicity :: Multiplicity
- Test.HMock.Internal.Multiplicity: atLeast :: Multiplicity -> Multiplicity
- Test.HMock.Internal.Multiplicity: atMost :: Multiplicity -> Multiplicity
- Test.HMock.Internal.Multiplicity: between :: Multiplicity -> Multiplicity -> Multiplicity
- Test.HMock.Internal.Multiplicity: data Multiplicity
- Test.HMock.Internal.Multiplicity: exhaustable :: Multiplicity -> Bool
- Test.HMock.Internal.Multiplicity: feasible :: Multiplicity -> Bool
- Test.HMock.Internal.Multiplicity: infeasible :: Multiplicity
- Test.HMock.Internal.Multiplicity: instance GHC.Classes.Eq Test.HMock.Internal.Multiplicity.Multiplicity
- Test.HMock.Internal.Multiplicity: instance GHC.Num.Num Test.HMock.Internal.Multiplicity.Multiplicity
- Test.HMock.Internal.Multiplicity: instance GHC.Show.Show Test.HMock.Internal.Multiplicity.Multiplicity
- Test.HMock.Internal.Multiplicity: meetsMultiplicity :: Multiplicity -> Int -> Bool
- Test.HMock.Internal.Multiplicity: normalize :: Multiplicity -> Multiplicity
- Test.HMock.Internal.Multiplicity: once :: Multiplicity
- Test.HMock.Internal.Predicates: Predicate :: String -> (a -> Bool) -> Predicate a
- Test.HMock.Internal.Predicates: [accept] :: Predicate a -> a -> Bool
- Test.HMock.Internal.Predicates: [showPredicate] :: Predicate a -> String
- Test.HMock.Internal.Predicates: andP :: Predicate a -> Predicate a -> Predicate a
- Test.HMock.Internal.Predicates: anything :: Predicate a
- Test.HMock.Internal.Predicates: approxEq :: (RealFloat a, Show a) => a -> Predicate a
- Test.HMock.Internal.Predicates: caseInsensitive :: (MonoFunctor t, MonoFunctor a, Element t ~ Char, Element a ~ Char) => (t -> Predicate a) -> t -> Predicate a
- Test.HMock.Internal.Predicates: contains :: MonoFoldable t => Predicate (Element t) -> Predicate t
- Test.HMock.Internal.Predicates: containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock.Internal.Predicates: containsCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock.Internal.Predicates: containsEntry :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t
- Test.HMock.Internal.Predicates: containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t
- Test.HMock.Internal.Predicates: containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock.Internal.Predicates: containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock.Internal.Predicates: data Predicate a
- Test.HMock.Internal.Predicates: each :: MonoFoldable t => Predicate (Element t) -> Predicate t
- Test.HMock.Internal.Predicates: elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock.Internal.Predicates: endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock.Internal.Predicates: entriesAre :: (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t
- Test.HMock.Internal.Predicates: eq :: (Show a, Eq a) => a -> Predicate a
- Test.HMock.Internal.Predicates: false :: Predicate Bool
- Test.HMock.Internal.Predicates: finite :: RealFloat a => Predicate a
- Test.HMock.Internal.Predicates: geq :: (Show a, Ord a) => a -> Predicate a
- Test.HMock.Internal.Predicates: gt :: (Show a, Ord a) => a -> Predicate a
- Test.HMock.Internal.Predicates: hasSubsequence :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock.Internal.Predicates: hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock.Internal.Predicates: infinite :: RealFloat a => Predicate a
- Test.HMock.Internal.Predicates: instance GHC.Show.Show (Test.HMock.Internal.Predicates.Predicate a)
- Test.HMock.Internal.Predicates: is :: HasCallStack => (a -> Bool) -> Predicate a
- Test.HMock.Internal.Predicates: isEmpty :: MonoFoldable t => Predicate t
- Test.HMock.Internal.Predicates: just :: Predicate a -> Predicate (Maybe a)
- Test.HMock.Internal.Predicates: keysAre :: (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t
- Test.HMock.Internal.Predicates: left :: Predicate a -> Predicate (Either a b)
- Test.HMock.Internal.Predicates: leq :: (Show a, Ord a) => a -> Predicate a
- Test.HMock.Internal.Predicates: lt :: (Show a, Ord a) => a -> Predicate a
- Test.HMock.Internal.Predicates: matchesCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock.Internal.Predicates: matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- Test.HMock.Internal.Predicates: nAn :: RealFloat a => Predicate a
- Test.HMock.Internal.Predicates: neq :: (Show a, Eq a) => a -> Predicate a
- Test.HMock.Internal.Predicates: nonEmpty :: MonoFoldable t => Predicate t
- Test.HMock.Internal.Predicates: notP :: Predicate a -> Predicate a
- Test.HMock.Internal.Predicates: orP :: Predicate a -> Predicate a -> Predicate a
- Test.HMock.Internal.Predicates: qIs :: HasCallStack => ExpQ -> ExpQ
- Test.HMock.Internal.Predicates: qMatch :: PatQ -> ExpQ
- Test.HMock.Internal.Predicates: qWith :: ExpQ -> ExpQ
- Test.HMock.Internal.Predicates: right :: Predicate b -> Predicate (Either a b)
- Test.HMock.Internal.Predicates: sizeIs :: MonoFoldable t => Predicate Int -> Predicate t
- Test.HMock.Internal.Predicates: startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- Test.HMock.Internal.Predicates: true :: Predicate Bool
- Test.HMock.Internal.Predicates: typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b
- Test.HMock.Internal.Predicates: unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- Test.HMock.Internal.Predicates: with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a
- Test.HMock.Internal.Predicates: zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)
- Test.HMock.Internal.Predicates: zip4P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate (a, b, c, d)
- Test.HMock.Internal.Predicates: zip5P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate e -> Predicate (a, b, c, d, e)
- Test.HMock.Internal.Predicates: zipP :: Predicate a -> Predicate b -> Predicate (a, b)
- Test.HMock.Internal.TH: MockableOptions :: String -> Bool -> MockableOptions
- Test.HMock.Internal.TH: [mockSuffix] :: MockableOptions -> String
- Test.HMock.Internal.TH: [mockVerbose] :: MockableOptions -> Bool
- Test.HMock.Internal.TH: data MockableOptions
- Test.HMock.Internal.TH: deriveForMockT :: Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveForMockTWithOptions :: MockableOptions -> Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockable :: Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableBase :: Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableBaseType :: Q Type -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableType :: Q Type -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]
- Test.HMock.Internal.TH: deriveMockableWithOptions :: MockableOptions -> Name -> Q [Dec]
- Test.HMock.Internal.TH: deriveTypeForMockT :: Q Type -> Q [Dec]
- Test.HMock.Internal.TH: deriveTypeForMockTWithOptions :: MockableOptions -> Q Type -> Q [Dec]
- Test.HMock.Internal.TH: instance Data.Default.Class.Default Test.HMock.Internal.TH.MockableOptions
- Test.HMock.Internal.TH: instance GHC.Show.Show Test.HMock.Internal.TH.Instance
- Test.HMock.Internal.TH: instance GHC.Show.Show Test.HMock.Internal.TH.Method
- Test.HMock.Internal.TH: makeMockable :: Name -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableBase :: Name -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableBaseType :: Q Type -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableType :: Q Type -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]
- Test.HMock.Internal.TH: makeMockableWithOptions :: MockableOptions -> Name -> Q [Dec]
- Test.HMock.Internal.TH.Util: bindVar :: Name -> TyVarBndr
- Test.HMock.Internal.TH.Util: constrainVars :: [TypeQ] -> [Name] -> CxtQ
- Test.HMock.Internal.TH.Util: freeTypeVars :: Type -> [Name]
- Test.HMock.Internal.TH.Util: hasNestedPolyType :: Type -> Bool
- Test.HMock.Internal.TH.Util: hasPolyType :: Type -> Bool
- Test.HMock.Internal.TH.Util: localizeMember :: Type -> Name -> Type -> Q Type
- Test.HMock.Internal.TH.Util: relevantContext :: Type -> ([Name], Cxt) -> ([Name], Cxt)
- Test.HMock.Internal.TH.Util: removeModNames :: Data a => a -> a
- Test.HMock.Internal.TH.Util: resolveInstance :: Name -> Type -> Q (Maybe Cxt)
- Test.HMock.Internal.TH.Util: simplifyContext :: Cxt -> Q (Maybe Cxt)
- Test.HMock.Internal.TH.Util: splitType :: Type -> ([Name], Cxt, [Type])
- Test.HMock.Internal.TH.Util: substTypeVar :: Name -> Type -> Type -> Type
- Test.HMock.Internal.TH.Util: substTypeVars :: [(Name, Type)] -> Type -> Type
- Test.HMock.Internal.TH.Util: tvName :: TyVarBndr -> Name
- Test.HMock.Internal.TH.Util: unappliedName :: Type -> Maybe Name
- Test.HMock.Internal.TH.Util: unifyTypes :: Type -> Type -> Q (Maybe [(Name, Type)])
+ Test.HMock.ExpectContext: anyOf :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
+ Test.HMock.ExpectContext: class ExpectContext (ctx :: (Type -> Type) -> Type -> Type)
+ Test.HMock.ExpectContext: consecutiveTimes :: (ExpectContext ctx, MonadIO m) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
+ Test.HMock.ExpectContext: expect :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => expectable -> ctx m ()
+ Test.HMock.ExpectContext: expectAny :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => expectable -> ctx m ()
+ Test.HMock.ExpectContext: expectN :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => Multiplicity -> expectable -> ctx m ()
+ Test.HMock.ExpectContext: inAnyOrder :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
+ Test.HMock.ExpectContext: inSequence :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()
+ Test.HMock.ExpectContext: times :: (ExpectContext ctx, MonadIO m) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m ()
+ Test.HMock.ExpectContext: type MockableMethod (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) = (Mockable cls, Typeable m, KnownSymbol name, Typeable r)
+ Test.HMock.Internal.Rule: [:=>] :: Matcher cls name m r -> [Action cls name m r -> MockT m r] -> Rule cls name m r
+ Test.HMock.Internal.Rule: data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
+ Test.HMock.Internal.State: MockState :: TVar (ExpectSet (Step m)) -> TVar [(Bool, Step m)] -> TVar Bool -> TVar (Set TypeRep) -> Maybe (MockState m) -> MockState m
+ Test.HMock.Internal.State: [MockSetup] :: {unMockSetup :: ReaderT (MockState m) STM a} -> MockSetup m a
+ Test.HMock.Internal.State: [MockT] :: {unMockT :: ReaderT (MockState m) m a} -> MockT m a
+ Test.HMock.Internal.State: [mockCheckAmbiguity] :: MockState m -> TVar Bool
+ Test.HMock.Internal.State: [mockClasses] :: MockState m -> TVar (Set TypeRep)
+ Test.HMock.Internal.State: [mockDefaults] :: MockState m -> TVar [(Bool, Step m)]
+ Test.HMock.Internal.State: [mockExpectSet] :: MockState m -> TVar (ExpectSet (Step m))
+ Test.HMock.Internal.State: [mockParent] :: MockState m -> Maybe (MockState m)
+ Test.HMock.Internal.State: allStates :: MockState m -> [MockState m]
+ Test.HMock.Internal.State: class MockContext ctx
+ Test.HMock.Internal.State: data MockState m
+ Test.HMock.Internal.State: expectThisSet :: MonadIO m => ExpectSet (Step m) -> MockT m ()
+ Test.HMock.Internal.State: fromMockSetup :: (MockContext ctx, MonadIO m) => MockSetup m a -> ctx m a
+ Test.HMock.Internal.State: initClassIfNeeded :: forall cls m proxy. (Mockable cls, Typeable m, MonadIO m) => proxy cls -> MockSetup m ()
+ Test.HMock.Internal.State: initClassesAsNeeded :: MonadIO m => ExpectSet (Step m) -> MockSetup m ()
+ Test.HMock.Internal.State: initMockState :: MonadIO m => Maybe (MockState m) -> m (MockState m)
+ Test.HMock.Internal.State: instance (Control.Monad.Reader.Class.MonadReader r m, Control.Monad.Writer.Class.MonadWriter w m, Control.Monad.State.Class.MonadState s m) => Control.Monad.RWS.Class.MonadRWS r w s (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.IO.Unlift.MonadUnliftIO m => Control.Monad.IO.Unlift.MonadUnliftIO (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Control.Monad.Trans.Class.MonadTrans Test.HMock.Internal.State.MockT
+ Test.HMock.Internal.State: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance GHC.Base.Applicative (Test.HMock.Internal.State.MockSetup m)
+ Test.HMock.Internal.State: instance GHC.Base.Applicative m => GHC.Base.Applicative (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance GHC.Base.Functor (Test.HMock.Internal.State.MockSetup m)
+ Test.HMock.Internal.State: instance GHC.Base.Functor m => GHC.Base.Functor (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance GHC.Base.Monad (Test.HMock.Internal.State.MockSetup m)
+ Test.HMock.Internal.State: instance GHC.Base.Monad m => GHC.Base.Monad (Test.HMock.Internal.State.MockT m)
+ Test.HMock.Internal.State: instance Test.HMock.ExpectContext.ExpectContext Test.HMock.Internal.State.MockT
+ Test.HMock.Internal.State: instance Test.HMock.Internal.State.MockContext Test.HMock.Internal.State.MockSetup
+ Test.HMock.Internal.State: instance Test.HMock.Internal.State.MockContext Test.HMock.Internal.State.MockT
+ Test.HMock.Internal.State: mapMockT :: (m a -> m b) -> MockT m a -> MockT m b
+ Test.HMock.Internal.State: mockSetupSTM :: STM a -> MockSetup m a
+ Test.HMock.Internal.State: newtype MockSetup m a
+ Test.HMock.Internal.State: newtype MockT m a
+ Test.HMock.Internal.State: rootState :: MockState m -> MockState m
+ Test.HMock.Internal.State: runInRootState :: MockSetup m a -> MockSetup m a
+ Test.HMock.Internal.Step: Expected :: ExpectSet (Step m) -> Expected m a
+ Test.HMock.Internal.Step: [:->] :: Matcher cls name m r -> Maybe (Action cls name m r -> MockT m r) -> SingleRule cls name m r
+ Test.HMock.Internal.Step: [Step] :: MockableMethod cls name m r => Located (SingleRule cls name m r) -> Step m
+ Test.HMock.Internal.Step: [unwrapExpected] :: Expected m a -> ExpectSet (Step m)
+ Test.HMock.Internal.Step: data SingleRule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
+ Test.HMock.Internal.Step: data Step m
+ Test.HMock.Internal.Step: expandRepeatRule :: MockableMethod cls name m r => Multiplicity -> CallStack -> Rule cls name m r -> ExpectSet (Step m)
+ Test.HMock.Internal.Step: expandRule :: MockableMethod cls name m r => CallStack -> Rule cls name m r -> ExpectSet (Step m)
+ Test.HMock.Internal.Step: instance GHC.Show.Show (Test.HMock.Internal.Step.Step m)
+ Test.HMock.Internal.Step: instance Test.HMock.ExpectContext.ExpectContext Test.HMock.Internal.Step.Expected
+ Test.HMock.Internal.Step: newtype Expected m a
+ Test.HMock.Internal.TH: bindVar :: Name -> TyVarBndr
+ Test.HMock.Internal.TH: constrainVars :: [TypeQ] -> [Name] -> CxtQ
+ Test.HMock.Internal.TH: freeTypeVars :: Type -> [Name]
+ Test.HMock.Internal.TH: hasNestedPolyType :: Type -> Bool
+ Test.HMock.Internal.TH: hasPolyType :: Type -> Bool
+ Test.HMock.Internal.TH: localizeMember :: Type -> Name -> Type -> Q Type
+ Test.HMock.Internal.TH: relevantContext :: Type -> ([Name], Cxt) -> ([Name], Cxt)
+ Test.HMock.Internal.TH: removeModNames :: Data a => a -> a
+ Test.HMock.Internal.TH: resolveInstance :: Name -> Type -> Q (Maybe Cxt)
+ Test.HMock.Internal.TH: simplifyContext :: Cxt -> Q (Maybe Cxt)
+ Test.HMock.Internal.TH: splitType :: Type -> ([Name], Cxt, [Type])
+ Test.HMock.Internal.TH: substTypeVar :: Name -> Type -> Type -> Type
+ Test.HMock.Internal.TH: substTypeVars :: [(Name, Type)] -> Type -> Type
+ Test.HMock.Internal.TH: tvName :: TyVarBndr -> Name
+ Test.HMock.Internal.TH: unappliedName :: Type -> Maybe Name
+ Test.HMock.Internal.TH: unifyTypes :: Type -> Type -> Q (Maybe [(Name, Type)])
+ Test.HMock.MockMethod: mockDefaultlessMethod :: (HasCallStack, MonadIO m, MockableMethod cls name m r) => Action cls name m r -> MockT m r
+ Test.HMock.MockMethod: mockMethod :: (HasCallStack, MonadIO m, MockableMethod cls name m r, Default r) => Action cls name m r -> MockT m r
+ Test.HMock.MockT: allowUnexpected :: forall cls name m r rule ctx. (MonadIO m, MockableMethod cls name m r, Expectable cls name m r rule, MockContext ctx) => rule -> ctx m ()
+ Test.HMock.MockT: byDefault :: forall cls name m r ctx. (MonadIO m, MockableMethod cls name m r, MockContext ctx) => Rule cls name m r -> ctx m ()
+ Test.HMock.MockT: class MockContext ctx
+ Test.HMock.MockT: data MockSetup m a
+ Test.HMock.MockT: data MockT m a
+ Test.HMock.MockT: describeExpectations :: MonadIO m => MockT m String
+ Test.HMock.MockT: nestMockT :: forall m a. MonadIO m => MockT m a -> MockT m a
+ Test.HMock.MockT: runMockT :: forall m a. MonadIO m => MockT m a -> m a
+ Test.HMock.MockT: setAmbiguityCheck :: MonadIO m => Bool -> MockT m ()
+ Test.HMock.MockT: verifyExpectations :: MonadIO m => MockT m ()
+ Test.HMock.MockT: withMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b
+ Test.HMock.MockT: withNestedMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> MockT m b
+ Test.HMock.Mockable: -- for each method.
+ Test.HMock.Mockable: -- replaced with predicates.
+ Test.HMock.Mockable: -- | A specification for matching actions. The actual arguments should be
+ Test.HMock.Mockable: [Match] :: MatchResult
+ Test.HMock.Mockable: [NoMatch] :: Int -> MatchResult
+ Test.HMock.Mockable: class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint)
+ Test.HMock.Mockable: class (Typeable cls) => MockableBase (cls :: (Type -> Type) -> Constraint) where {
+ Test.HMock.Mockable: data MatchResult
+ Test.HMock.Mockable: data family Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type;
+ Test.HMock.Mockable: matchAction :: MockableBase cls => Matcher cls name m a -> Action cls name m a -> MatchResult
+ Test.HMock.Mockable: setupMockable :: (Mockable cls, MonadIO m, Typeable m) => proxy cls -> MockSetup m ()
+ Test.HMock.Mockable: showAction :: MockableBase cls => Action cls name m a -> String
+ Test.HMock.Mockable: showMatcher :: MockableBase cls => Maybe (Action cls name m a) -> Matcher cls name m b -> String
+ Test.HMock.Mockable: }
+ Test.HMock.Multiplicity: anyMultiplicity :: Multiplicity
+ Test.HMock.Multiplicity: atLeast :: Multiplicity -> Multiplicity
+ Test.HMock.Multiplicity: atMost :: Multiplicity -> Multiplicity
+ Test.HMock.Multiplicity: between :: Multiplicity -> Multiplicity -> Multiplicity
+ Test.HMock.Multiplicity: data Multiplicity
+ Test.HMock.Multiplicity: feasible :: Multiplicity -> Bool
+ Test.HMock.Multiplicity: instance GHC.Classes.Eq Test.HMock.Multiplicity.Multiplicity
+ Test.HMock.Multiplicity: instance GHC.Num.Num Test.HMock.Multiplicity.Multiplicity
+ Test.HMock.Multiplicity: instance GHC.Show.Show Test.HMock.Multiplicity.Multiplicity
+ Test.HMock.Multiplicity: meetsMultiplicity :: Multiplicity -> Int -> Bool
+ Test.HMock.Multiplicity: once :: Multiplicity
+ Test.HMock.Predicates: Predicate :: String -> (a -> Bool) -> Predicate a
+ Test.HMock.Predicates: [accept] :: Predicate a -> a -> Bool
+ Test.HMock.Predicates: [showPredicate] :: Predicate a -> String
+ Test.HMock.Predicates: andP :: Predicate a -> Predicate a -> Predicate a
+ Test.HMock.Predicates: anything :: Predicate a
+ Test.HMock.Predicates: approxEq :: (RealFloat a, Show a) => a -> Predicate a
+ Test.HMock.Predicates: caseInsensitive :: (MonoFunctor t, MonoFunctor a, Element t ~ Char, Element a ~ Char) => (t -> Predicate a) -> t -> Predicate a
+ Test.HMock.Predicates: contains :: MonoFoldable t => Predicate (Element t) -> Predicate t
+ Test.HMock.Predicates: containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
+ Test.HMock.Predicates: containsCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
+ Test.HMock.Predicates: containsEntry :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t
+ Test.HMock.Predicates: containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t
+ Test.HMock.Predicates: containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
+ Test.HMock.Predicates: containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
+ Test.HMock.Predicates: data Predicate a
+ Test.HMock.Predicates: each :: MonoFoldable t => Predicate (Element t) -> Predicate t
+ Test.HMock.Predicates: elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
+ Test.HMock.Predicates: endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
+ Test.HMock.Predicates: entriesAre :: (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t
+ Test.HMock.Predicates: eq :: (Show a, Eq a) => a -> Predicate a
+ Test.HMock.Predicates: finite :: RealFloat a => Predicate a
+ Test.HMock.Predicates: geq :: (Show a, Ord a) => a -> Predicate a
+ Test.HMock.Predicates: gt :: (Show a, Ord a) => a -> Predicate a
+ Test.HMock.Predicates: hasSubsequence :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
+ Test.HMock.Predicates: hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
+ Test.HMock.Predicates: infinite :: RealFloat a => Predicate a
+ Test.HMock.Predicates: instance GHC.Show.Show (Test.HMock.Predicates.Predicate a)
+ Test.HMock.Predicates: is :: HasCallStack => (a -> Bool) -> Predicate a
+ Test.HMock.Predicates: isEmpty :: MonoFoldable t => Predicate t
+ Test.HMock.Predicates: just :: Predicate a -> Predicate (Maybe a)
+ Test.HMock.Predicates: keysAre :: (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t
+ Test.HMock.Predicates: left :: Predicate a -> Predicate (Either a b)
+ Test.HMock.Predicates: leq :: (Show a, Ord a) => a -> Predicate a
+ Test.HMock.Predicates: lt :: (Show a, Ord a) => a -> Predicate a
+ Test.HMock.Predicates: matchesCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
+ Test.HMock.Predicates: matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
+ Test.HMock.Predicates: nAn :: RealFloat a => Predicate a
+ Test.HMock.Predicates: neq :: (Show a, Eq a) => a -> Predicate a
+ Test.HMock.Predicates: nonEmpty :: MonoFoldable t => Predicate t
+ Test.HMock.Predicates: notP :: Predicate a -> Predicate a
+ Test.HMock.Predicates: orP :: Predicate a -> Predicate a -> Predicate a
+ Test.HMock.Predicates: qIs :: HasCallStack => ExpQ -> ExpQ
+ Test.HMock.Predicates: qMatch :: PatQ -> ExpQ
+ Test.HMock.Predicates: qWith :: ExpQ -> ExpQ
+ Test.HMock.Predicates: right :: Predicate b -> Predicate (Either a b)
+ Test.HMock.Predicates: sizeIs :: MonoFoldable t => Predicate Int -> Predicate t
+ Test.HMock.Predicates: startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
+ Test.HMock.Predicates: typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b
+ Test.HMock.Predicates: unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
+ Test.HMock.Predicates: with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a
+ Test.HMock.Predicates: zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)
+ Test.HMock.Predicates: zip4P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate (a, b, c, d)
+ Test.HMock.Predicates: zip5P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate e -> Predicate (a, b, c, d, e)
+ Test.HMock.Predicates: zipP :: Predicate a -> Predicate b -> Predicate (a, b)
+ Test.HMock.Rule: (|->) :: (Monad m, Expectable cls name m r ex) => ex -> r -> Rule cls name m r
+ Test.HMock.Rule: (|=>) :: Expectable cls name m r ex => ex -> (Action cls name m r -> MockT m r) -> Rule cls name m r
+ Test.HMock.Rule: class Expectable cls name m r ex | ex -> cls name m r
+ Test.HMock.Rule: data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type)
+ Test.HMock.Rule: infixl 1 |=>
+ Test.HMock.Rule: instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Internal.Rule.Rule cls name m r)
+ Test.HMock.Rule: instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Mockable.Matcher cls name m r)
+ Test.HMock.Rule: toRule :: Expectable cls name m r ex => ex -> Rule cls name m r
+ Test.HMock.TH: instance Data.Default.Class.Default Test.HMock.TH.MockableOptions
+ Test.HMock.TH: instance GHC.Show.Show Test.HMock.TH.Instance
+ Test.HMock.TH: instance GHC.Show.Show Test.HMock.TH.Method

Files

CHANGELOG.md view
@@ -1,5 +1,20 @@ # Revision history for hmock +## 0.2.0.0 -- 2021-06-24++* Added ambiguity checking.+  * This is an optional feature, which is off by default.+  * To make it easier to avoid ambiguity, there is now an `allowUnexpected` that+  * causes unexpected calls to be ignored and optionally provide a response, but+    doesn't comflict with expectations that override it.  Ambiuguous uses of+    `expectAny` can often be replaced with `allowUnexpected`.+* Restricted mockable setup to defaults to avoid race conditions.+  * Setup handlers now run in the `MockSetup` monad.+  * Adding expectations from setup is no longer allowed.  However, you can use+    `allowUnexpected` to allow unexpected calls.+* Added `nestMockT` and `withNestedMockT` to the API.+* Exported smaller modules to make selective imports easier.+ ## 0.1.0.1 -- 2021-06-20  * Fixed a bad dependency that broke some GHC versions.
HMock.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               HMock-version:            0.1.0.1+version:            0.2.0.0 synopsis:           A flexible mock framework for testing effectful code. description:        HMock is a flexible mock framework for testing effectful                     code in Haskell.  Tests can set up expectations about@@ -29,15 +29,19 @@  library     exposed-modules:  Test.HMock,+                      Test.HMock.ExpectContext,+                      Test.HMock.Mockable,+                      Test.HMock.MockMethod,+                      Test.HMock.MockT,+                      Test.HMock.Multiplicity,+                      Test.HMock.Predicates,+                      Test.HMock.Rule,                       Test.HMock.TH,-                      Test.HMock.Internal.Multiplicity,-                      Test.HMock.Internal.MockT,                       Test.HMock.Internal.ExpectSet,-                      Test.HMock.Internal.Expectable,-                      Test.HMock.Internal.Mockable,-                      Test.HMock.Internal.Predicates,+                      Test.HMock.Internal.Rule,+                      Test.HMock.Internal.State,+                      Test.HMock.Internal.Step,                       Test.HMock.Internal.TH,-                      Test.HMock.Internal.TH.Util,                       Test.HMock.Internal.Util     build-depends:    base >=4.11.0 && < 4.16,                       constraints >= 0.13 && < 0.14,@@ -49,6 +53,7 @@                       mono-traversable >= 1.0.15 && < 1.1,                       mtl >= 2.2.2 && < 2.3,                       regex-tdfa >= 1.3.1 && < 1.4,+                      stm >= 2.5.0 && < 2.6,                       syb >= 0.7.2 && < 0.8,                       template-haskell >= 2.13.0 && < 2.18,                       transformers-base >= 0.4.5 && < 0.5,@@ -64,14 +69,14 @@                       Core,                       Demo,                       DocTests.All,-                      DocTests.Test.HMock.Internal.Multiplicity,-                      DocTests.Test.HMock.Internal.Predicates,+                      DocTests.Test.HMock.Multiplicity,+                      DocTests.Test.HMock.Predicates,                       ExpectSet,                       Extras,                       QuasiMock,+                      QuasiMockBase,                       TH,-                      Util.DeriveRecursive,-                      Util.TH+                      Util.DeriveRecursive     build-depends:    HMock,                       QuickCheck,                       base,
src/Test/HMock.hs view
@@ -49,102 +49,77 @@ -- 'runMockT' to begin a test with mocks, 'expect' to set up your expected -- actions and responses, and finally execute your code. module Test.HMock-  ( -- * Running mocks-    MockT,-    runMockT,-    withMockT,-    describeExpectations,-    verifyExpectations,-    byDefault,+  ( +    -- * The 'Mockable' class -    -- * Setting expectations-    MockableMethod,-    Expectable (..),-    Rule,-    (|=>),-    (|->),-    ExpectContext,-    expect,-    expectN,-    expectAny,-    inSequence,-    inAnyOrder,-    anyOf,-    times,-    consecutiveTimes,+    -- | HMock starts with the 'Mockable' class (most of which is actually in+    -- its superclass, 'MockableBase').  This class is implemented for each+    -- interface you want to mock, and describes which actions are possible,+    -- and how to match and compare them.  It's a lot of boilerplate, so you'll+    -- usually derive it with Template Haskell, but the instance must exist.+    module Test.HMock.Mockable, +    -- * Running mocks++    -- | Tests with mocks run in the 'MockT' monad transformer, which wraps a+    -- base monad and adds the ability to delegate methods to HMock for+    -- matching.  'runMockT' is the entry point for 'MockT'.+    --+    -- This module also defines the more restricted 'MockSetup;' monad, which+    -- is used to set up defaults for a type.+    module Test.HMock.MockT,++    -- * Rules for actions and responses++    -- | The bread and butter of mocks is matching actions and specifying+    -- responses.  Matchers and corresponding responses are combined into a+    -- 'Rule'+    module Test.HMock.Rule,++    -- * Combinators for building test plans++    -- | A complete execution plans consists of a collection of individual rules+    -- combined in various ways.  HMock defines a set of composable combinators+    -- for the execution plan.+    module Test.HMock.ExpectContext,+     -- * Predicates-    Predicate (..),-    anything,-    eq,-    neq,-    gt,-    geq,-    lt,-    leq,-    just,-    left,-    right,-    zipP,-    zip3P,-    zip4P,-    zip5P,-    andP,-    orP,-    notP,-    startsWith,-    endsWith,-    hasSubstr,-    hasSubsequence,-    caseInsensitive,-    matchesRegex,-    matchesCaseInsensitiveRegex,-    containsRegex,-    containsCaseInsensitiveRegex,-    isEmpty,-    nonEmpty,-    sizeIs,-    elemsAre,-    unorderedElemsAre,-    each,-    contains,-    containsAll,-    containsOnly,-    containsKey,-    containsEntry,-    keysAre,-    entriesAre,-    approxEq,-    finite,-    infinite,-    nAn,-    is,-    qIs,-    with,-    qWith,-    qMatch,-    typed, +    -- | When matching methods, you can either match on exact parameter values,+    -- or using 'Predicate's.  The 'Predicate' type either accepts or rejects+    -- values of parameters, and HMock provides an extensive library of standard+    -- 'Predicate's to make it easier to match exactly what you want to.+    module Test.HMock.Predicates,+     -- * Multiplicity-    Multiplicity,-    meetsMultiplicity,-    once,-    anyMultiplicity,-    atLeast,-    atMost,-    between, -    -- * Implementing mocks-    MockableBase (..),-    Mockable (..),-    MatchResult (..),-    mockMethod,-    mockDefaultlessMethod,+    -- | For repeated actions in your execution plan, you often want to control+    -- the number of times somrthing is allowed to happen.  This is called a+    -- 'Multiplicity'.+    module Test.HMock.Multiplicity,++    -- * Delegating mocks++    -- | In order to run your test code with the 'MockT', you need instances of+    -- your effect classes for the 'MockT' type.  If you mock all methods of the+    -- class, this can be derived using Template Haskell.  For partial mocks,+    -- you'll need to write the instances yourself, using 'mockMethod' and its+    -- cousin 'mockDefaultlessMethod'.+    module Test.HMock.MockMethod,++    -- * Template Haskell generator++    -- | These are the Template Haskell splices which generate boilerplate for+    -- your classes to be used with HMock.+    module Test.HMock.TH,   ) where -import Test.HMock.Internal.Expectable-import Test.HMock.Internal.MockT-import Test.HMock.Internal.Mockable-import Test.HMock.Internal.Multiplicity-import Test.HMock.Internal.Predicates+import Test.HMock.ExpectContext+import Test.HMock.MockT+import Test.HMock.MockMethod+import Test.HMock.Mockable+import Test.HMock.Multiplicity+import Test.HMock.Predicates+import Test.HMock.Rule+import Test.HMock.TH
+ src/Test/HMock/ExpectContext.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE RankNTypes #-}++-- | This module defines the 'ExpectContext' class, whose members provide the+-- combinators for building the execution plan for your mocks.  Notably, there+-- is a 'Test.HMock.MockT.MockT' instance for 'ExpectContext', so you can use+-- these combinators to add expectations inside your tests that run in+-- 'Test.HMock.MockT.MockT', as well as nesting them in other combinators.+module Test.HMock.ExpectContext+  ( MockableMethod,+    ExpectContext (..),+  )+where++import Control.Monad.IO.Class (MonadIO)+import Data.Kind (Constraint, Type)+import Data.Typeable (Typeable)+import GHC.Stack (HasCallStack)+import GHC.TypeLits (KnownSymbol, Symbol)+import Test.HMock.Mockable (Mockable)+import Test.HMock.Multiplicity (Multiplicity)+import Test.HMock.Rule (Expectable)++-- | All constraints needed to mock a method with the given class, name, base+-- monad, and return type.+type MockableMethod+  (cls :: (Type -> Type) -> Constraint)+  (name :: Symbol)+  (m :: Type -> Type)+  (r :: Type) =+  (Mockable cls, Typeable m, KnownSymbol name, Typeable r)++-- | Type class for contexts in which one can build expectations.  Notably, this+-- includes `Test.HMock.MockT.MockT`, which expects actions to be performed+-- during a test.+--+-- The methods of this class represent the user-facing API for build your+-- execution plan for mocks.+class ExpectContext (ctx :: (Type -> Type) -> Type -> Type) where+  -- | Creates an expectation that an action is performed once per given+  -- response (or exactly once if there is no response).+  --+  -- @+  -- 'Test.HMock.MockT.runMockT' '$' do+  --   'expect' '$'+  --     ReadFile "foo.txt"+  --       'Test.HMock.Rule.|->' "lorem ipsum"+  --       'Test.HMock.Rule.|->' "oops, the file changed out from under me!"+  --   callCodeUnderTest+  -- @+  --+  -- In this example, `readFile` must be called exactly twice by the tested+  -- code, and will return "lorem ipsum" the first time, but something different the+  -- second time.+  expect ::+    ( HasCallStack,+      MonadIO m,+      MockableMethod cls name m r,+      Expectable cls name m r expectable+    ) =>+    expectable ->+    ctx m ()++  -- | Creates an expectation that an action is performed some number of times.+  --+  -- @+  --   'Test.HMock.MockT.runMockT' '$' do+  --     'expect' '$' MakeList+  --     'expectN' ('Test.HMock.atLeast' 2) '$'+  --       CheckList "Cindy Lou Who" 'Test.HMock.Rule.|->' "nice"+  --+  --     callCodeUnderTest+  -- @+  expectN ::+    ( HasCallStack,+      MonadIO m,+      MockableMethod cls name m r,+      Expectable cls name m r expectable+    ) =>+    -- | The number of times the action should be performed.+    Multiplicity ->+    -- | The action and its response.+    expectable ->+    ctx m ()++  -- | Specifies a response if a matching action is performed, but doesn't+  -- expect anything.  This is equivalent to @'expectN'+  -- 'Test.HMock.Multiplicity.anyMultiplicity'@, but shorter.+  --+  -- In this example, the later use of 'expectAny' overrides earlier uses, but+  -- only for calls that match its conditions.+  --+  -- @+  --   'Test.HMock.MockT.runMockT' '$' do+  --     'expectAny' '$' ReadFile_ anything 'Test.HMock.Rule.|->' "tlhIngan maH!"+  --     'expectAny' '$' ReadFile "config.txt" 'Test.HMock.Rule.|->' "lang: klingon"+  --+  --     callCodeUnderTest+  -- @+  expectAny ::+    ( HasCallStack,+      MonadIO m,+      MockableMethod cls name m r,+      Expectable cls name m r expectable+    ) =>+    expectable ->+    ctx m ()++  -- | Creates a sequential expectation.  Other actions can still happen during+  -- the sequence, but these specific expectations must be met in this order.+  --+  -- @+  --   'inSequence'+  --     [ 'expect' '$' MoveForward,+  --       'expect' '$' TurnRight,+  --       'expect' '$' MoveForward+  --     ]+  -- @+  --+  -- Beware of using 'inSequence' too often.  It is appropriate when the+  -- property you are testing is that the order of effects is correct.  If+  -- that's not the purpose of the test, consider adding several independent+  -- expectations, instead.  This avoids over-asserting, and keeps your tests+  -- less brittle.+  inSequence ::+    MonadIO m => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()++  -- | Combines multiple expectations, which can occur in any order.  Most of+  -- the time, you can achieve the same thing by expecting each separately, but+  -- this can be combined in complex expectations to describe more complex+  -- ordering constraints.+  --+  -- If ambiguity checking is disabled, the choice is left-biased, so earlier+  -- options are preferred over ambiguous later options.+  --+  -- @+  --   'inSequence'+  --     [ 'inAnyOrder'+  --         [ 'expect' '$' AdjustMirrors,+  --           'expect' '$' FastenSeatBelt+  --         ],+  --       'expect' '$' StartCar+  --     ]+  -- @+  inAnyOrder ::+    MonadIO m => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()++  -- | Combines multiple expectations, requiring exactly one of them to occur.+  -- If ambiguity checking is disabled, the choice is left-biased, so earlier+  -- options are preferred over ambiguous later options.+  --+  -- @+  --   'anyOf'+  --     [ 'expect' $ ApplyForJob,+  --       'expect' $ ApplyForUniversity+  --     ]+  -- @+  anyOf ::+    MonadIO m => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m ()++  -- | Creates a parent expectation that the child expectation will happen a+  -- certain number of times.  Unlike `expectN`, the child expectation can be+  -- arbitrarily complex and span multiple actions.  Also unlike 'expectN', each+  -- new execution will restart response sequences for rules with more than one+  -- response.+  --+  -- Different occurrences of the child can be interleaved.  If ambiguity+  -- checking is disabled, progressing on an existing occurrence is preferred+  -- over starting a new occurrence when it's ambiguous.+  times ::+    MonadIO m =>+    Multiplicity ->+    (forall ctx'. ExpectContext ctx' => ctx' m ()) ->+    ctx m ()++  -- | Creates a parent expectation that the child expectation will happen a+  -- certain number of times.  Unlike `expectN`, the child expectation can be+  -- arbitrarily complex and span multiple actions.  Also unlike 'expectN', each+  -- new execution will restart response sequences for rules with more than one+  -- response.+  --+  -- Different occurrences of the child must happen consecutively, with one+  -- finishing before the next begins.+  consecutiveTimes ::+    MonadIO m =>+    Multiplicity ->+    (forall ctx'. ExpectContext ctx' => ctx' m ()) ->+    ctx m ()
src/Test/HMock/Internal/ExpectSet.hs view
@@ -3,14 +3,13 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} +-- | The internal core language of expectations in HMock. module Test.HMock.Internal.ExpectSet where -import Test.HMock.Internal.Multiplicity+import Test.HMock.Multiplicity   ( Multiplicity,     between,-    exhaustable,-    feasible,-    normalize,+    feasible, meetsMultiplicity   )  -- | A set of expected steps and their responses.  This is the "core" language@@ -40,9 +39,9 @@ satisfied (ExpectInterleave e f) = satisfied e && satisfied f satisfied (ExpectEither e f) = satisfied e || satisfied f satisfied (ExpectMulti mult e) =-  feasible mult && (exhaustable mult || satisfied e)+  feasible mult && (meetsMultiplicity mult 0 || satisfied e) satisfied (ExpectConsecutive mult e) =-  feasible mult && (exhaustable mult || satisfied e)+  feasible mult && (meetsMultiplicity mult 0 || satisfied e)  -- | Computes the live steps of the ExpectSet.  In other words: which individual -- steps can be matched right now, and what are the remaining expectations in@@ -107,7 +106,7 @@   | ExpectNothing <- e' = ExpectNothing   | m == 0 = ExpectNothing   | m == 1 = e'-  | otherwise = ExpectMulti (normalize m) e'+  | otherwise = ExpectMulti m e'   where     e' = simplify e simplify (ExpectConsecutive m e)@@ -115,7 +114,7 @@   | ExpectNothing <- e' = ExpectNothing   | m == 0 = ExpectNothing   | m == 1 = e'-  | otherwise = ExpectConsecutive (normalize m) e'+  | otherwise = ExpectConsecutive m e'   where     e' = simplify e simplify other = other@@ -196,9 +195,9 @@       | satisfied e || satisfied f = ExpectNothing       | otherwise = ExpectEither (go e) (go f)     go (ExpectMulti m e)-      | exhaustable m = ExpectNothing+      | meetsMultiplicity m 0 = ExpectNothing       | otherwise = ExpectMulti m (go e)     go (ExpectConsecutive m e)-      | exhaustable m = ExpectNothing+      | meetsMultiplicity m 0 = ExpectNothing       | otherwise = ExpectConsecutive m (go e)     go other = other
− src/Test/HMock/Internal/Expectable.hs
@@ -1,342 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE StandaloneDeriving #-}--module Test.HMock.Internal.Expectable where--import Control.Monad.Trans (MonadIO)-import Data.Kind (Constraint, Type)-import Data.Maybe (listToMaybe)-import Data.Typeable-import GHC.Stack (CallStack, HasCallStack, callStack)-import GHC.TypeLits (KnownSymbol, Symbol)-import Test.HMock.Internal.ExpectSet-import {-# SOURCE #-} Test.HMock.Internal.MockT-import Test.HMock.Internal.Mockable-import Test.HMock.Internal.Multiplicity-import Test.HMock.Internal.Util (Located (Loc), locate, withLoc)---- | Something that can be expected.  This type class covers a number of cases:------   * Expecting an exact 'Action'.---   * Expecting anything that matches a 'Matcher'.---   * Adding a return value (with '|->') or response (with '|=>').-class Expectable cls name m r e | e -> cls name m r where-  toRule :: e -> Rule cls name m r---- | A rule for matching a method and responding to it when it matches.------ The method may be matched by providing either an 'Action' to match exactly,--- or a 'Matcher'.  Exact matching is only available when all method arguments--------- A 'Rule' may have zero or more responses, which are attached using '|->' and--- '|=>'.  If there are no responses for a 'Rule', then there must be a default--- response for that action, and it is used.  If more than one response is--- added, the rule will perform the responses in order, repeating the last--- response if there are additional matches.------ Example:------ @--- 'expect' $---   GetLine_ 'Test.HMock.anything'---     '|->' "hello"---     '|=>' \(GetLine prompt) -> "The prompt was " ++ prompt---     '|->' "quit"--- @-data-  Rule-    (cls :: (Type -> Type) -> Constraint)-    (name :: Symbol)-    (m :: Type -> Type)-    (r :: Type)-  where-  (:=>) ::-    Matcher cls name m r ->-    [Action cls name m r -> MockT m r] ->-    Rule cls name m r---- | Attaches a response to an expectation.  This is a very flexible response,--- which can look at arguments, do things in the base monad, set up more--- expectations, etc.  The matching 'Action' is passed to the response, and is--- guaranteed to be a match so it's fine to just pattern match on the correct--- method.-(|=>) ::-  Expectable cls name m r expectable =>-  expectable ->-  (Action cls name m r -> MockT m r) ->-  Rule cls name m r-e |=> r = m :=> (rs ++ [r]) where m :=> rs = toRule e--infixl 1 |=>---- | Attaches a return value to an expectation.  This is more convenient than--- '|=>' in the common case where you just want to return a known result.--- @e '|->' r@ means the same thing as @e '|=>' 'const' ('return' r)@.-(|->) ::-  (Monad m, Expectable cls name m r expectable) =>-  expectable ->-  r ->-  Rule cls name m r-m |-> r = m |=> const (return r)--infixl 1 |->--instance Expectable cls name m r (Rule cls name m r) where-  toRule = id--instance Expectable cls name m r (Matcher cls name m r) where-  toRule m = m :=> []---- | All constraints needed to mock a method with the given class, name, base--- monad, and return type.-type MockableMethod-  (cls :: (Type -> Type) -> Constraint)-  (name :: Symbol)-  (m :: Type -> Type)-  (r :: Type) =-  (Mockable cls, Typeable m, KnownSymbol name, Typeable r)---- | A Rule that contains only a single response.  This is the target for--- desugaring the multi-response rule format.-data-  SingleRule-    (cls :: (Type -> Type) -> Constraint)-    (name :: Symbol)-    (m :: Type -> Type)-    (r :: Type)-  where-  (:->) ::-    Matcher cls name m r ->-    Maybe (Action cls name m r -> MockT m r) ->-    SingleRule cls name m r---- | A single step of an expectation.-data Step m where-  Step ::-    MockableMethod cls name m r =>-    Located (SingleRule cls name m r) ->-    Step m--instance Show (Step m) where-  show (Step l@(Loc _ (m :-> _))) =-    withLoc (showMatcher Nothing m <$ l)---- | Expands a Rule into an expectation.  The expected multiplicity will be one--- if there are no responses; otherwise one call is expected per response.-expandRule ::-  MockableMethod cls name m r =>-  CallStack ->-  Rule cls name m r ->-  ExpectSet (Step m)-expandRule callstack (m :=> []) =-  ExpectStep (Step (locate callstack (m :-> Nothing)))-expandRule callstack (m :=> rs) =-  foldr1-    ExpectInterleave-    (map (ExpectStep . Step . locate callstack . (m :->) . Just) rs)---- | Expands a Rule into an expectation, given a target multiplicity.  It is an--- error if there are too many responses for the multiplicity.  If there are--- too few responses, the last response will be repeated.-expandRepeatRule ::-  MockableMethod cls name m r =>-  Multiplicity ->-  CallStack ->-  Rule cls name m r ->-  ExpectSet (Step m)-expandRepeatRule mult _ (_ :=> rs)-  | not (feasible (mult - fromIntegral (length rs))) =-    error $-      show (length rs)-        ++ " responses is too many for multiplicity "-        ++ show mult-expandRepeatRule mult callstack (m :=> (r1 : r2 : rs)) =-  ExpectSequence first (expandRepeatRule (mult - 1) callstack (m :=> (r2 : rs)))-  where-    first-      | exhaustable mult =-        ExpectMulti-          (atMost 1)-          (ExpectStep (Step (locate callstack (m :-> Just r1))))-      | otherwise = ExpectStep (Step (locate callstack (m :-> Just r1)))-expandRepeatRule mult callstack (m :=> rs) =-  ExpectMulti mult (ExpectStep (Step (locate callstack (m :-> listToMaybe rs))))---- | Type class for contexts in which it makes sense to express an expectation.--- Notably, this includes `MockT`, which expects actions to be performed during--- a test.-class ExpectContext (t :: (Type -> Type) -> Type -> Type) where-  fromExpectSet :: MonadIO m => ExpectSet (Step m) -> t m ()--newtype Expected m a = Expected {unwrapExpected :: ExpectSet (Step m)}--instance ExpectContext Expected where-  fromExpectSet = Expected---- | Creates an expectation that an action is performed once per given--- response (or exactly once if there is no response).------ @--- 'runMockT' '$' do---   'expect' '$'---     ReadFile "foo.txt"---       '|->' "lorem ipsum"---       '|->' "oops, the file changed out from under me!"---   callCodeUnderTest--- @------ In this example, `readFile` must be called exactly twice by the tested code,--- and will return "lorem ipsum" the first time, but something different the--- second time.-expect ::-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r,-    Expectable cls name m r expectable,-    ExpectContext ctx-  ) =>-  expectable ->-  ctx m ()-expect e = fromExpectSet (expandRule callStack (toRule e))---- | Creates an expectation that an action is performed some number of times.------ @---   'runMockT' '$' do---     'expect' '$' MakeList---     'expectN' ('Test.HMock.atLeast' 2) '$'---       CheckList "Cindy Lou Who" '|->' "nice"------     callCodeUnderTest--- @-expectN ::-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r,-    Expectable cls name m r expectable,-    ExpectContext ctx-  ) =>-  -- | The number of times the action should be performed.-  Multiplicity ->-  -- | The action and its response.-  expectable ->-  ctx m ()-expectN mult e = fromExpectSet (expandRepeatRule mult callStack (toRule e))---- | Specifies a response if a matching action is performed, but doesn't expect--- anything.  This is equivalent to @'expectN' 'anyMultiplicity'@, but shorter.------ In this example, the later use of 'whenever' overrides earlier uses, but only--- for calls that match its conditions.------ @---   'runMockT' '$' do---     'whenever' '$' ReadFile_ anything '|->' "tlhIngan maH!"---     'whenever' '$' ReadFile "config.txt" '|->' "lang: klingon"------     callCodeUnderTest--- @-expectAny ::-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r,-    Expectable cls name m r expectable,-    ExpectContext ctx-  ) =>-  expectable ->-  ctx m ()-expectAny e =-  fromExpectSet (expandRepeatRule anyMultiplicity callStack (toRule e))---- | Creates a sequential expectation.  Other actions can still happen during--- the sequence, but these specific expectations must be met in this order.------ @---   'inSequence'---     [ 'expect' '$' MoveForward,---       'expect' '$' TurnRight,---       'expect' '$' MoveForward---     ]--- @------ Beware of using 'inSequence' too often.  It is appropriate when the property--- you are testing is that the order of effects is correct.  If that's not the--- purpose of the test, consider adding several independent expectations,--- instead.  This avoids over-asserting, and keeps your tests less brittle.-inSequence ::-  (MonadIO m, ExpectContext ctx) =>-  (forall ctx'. ExpectContext ctx' => [ctx' m ()]) ->-  ctx m ()-inSequence es = fromExpectSet (foldr1 ExpectSequence (map unwrapExpected es))---- | Combines multiple expectations, which can occur in any order.  Most of the--- time, you can achieve the same thing by expecting each separately, but this--- can be combined in complex expectations to describe more complex ordering--- constraints.------ @---   'inSequence'---     [ 'inAnyOrder'---         [ 'expect' '$' AdjustMirrors,---           'expect' '$' FastenSeatBelt---         ],---       'expect' '$' StartCar---     ]--- @-inAnyOrder ::-  (MonadIO m, ExpectContext ctx) =>-  (forall ctx'. ExpectContext ctx' => [ctx' m ()]) ->-  ctx m ()-inAnyOrder es = fromExpectSet (foldr1 ExpectInterleave (map unwrapExpected es))---- | Combines multiple expectations, requiring exactly one of them to occur.------ @---   'anyOf'---     [ 'expect' $ ApplyForJob,---       'expect' $ ApplyForUniversity---     ]--- @-anyOf ::-  (MonadIO m, ExpectContext ctx) =>-  (forall ctx'. ExpectContext ctx' => [ctx' m ()]) ->-  ctx m ()-anyOf es = fromExpectSet (foldr1 ExpectEither (map unwrapExpected es))---- | Creates a parent expectation that the child expectation will happen a--- certain number of times.  Unlike `expectN`, the child expectation can be--- arbitrarily complex and span multiple actions.  Also unlike 'expectN', each--- new execution will restart response sequences for rules with more than one--- response.------ Different occurrences of the child can be interleaved.  In case of ambiguity,--- progressing on an existing occurrence is preferred over starting a new--- occurrence.-times :: (MonadIO m, ExpectContext ctx) =>-  Multiplicity ->-  (forall ctx'. ExpectContext ctx' => ctx' m ()) ->-  ctx m ()-times mult e = fromExpectSet (ExpectMulti mult (unwrapExpected e))---- | Creates a parent expectation that the child expectation will happen a--- certain number of times.  Unlike `expectN`, the child expectation can be--- arbitrarily complex and span multiple actions.  Also unlike 'expectN', each--- new execution will restart response sequences for rules with more than one--- response.------ Different occurrences of the child must happen consecutively, with one--- finishing before the next begins.-consecutiveTimes :: (MonadIO m, ExpectContext ctx) =>-  Multiplicity ->-  (forall ctx'. ExpectContext ctx' => ctx' m ()) ->-  ctx m ()-consecutiveTimes mult e =-  fromExpectSet (ExpectConsecutive mult (unwrapExpected e))
− src/Test/HMock/Internal/MockT.hs
@@ -1,301 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UndecidableInstances #-}--module Test.HMock.Internal.MockT where--import Control.Concurrent (MVar)-import Control.Monad (forM_, unless)-import Control.Monad.Base (MonadBase)-import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)-import Control.Monad.Cont (MonadCont)-import Control.Monad.Except (MonadError)-import Control.Monad.RWS (MonadRWS)-import Control.Monad.Reader-  ( MonadReader (ask, local, reader),-    ReaderT,-    mapReaderT,-    runReaderT,-  )-import Control.Monad.State (MonadState)-import Control.Monad.Trans (MonadIO, MonadTrans, lift)-import Control.Monad.Writer (MonadWriter)-import Data.Default (Default (def))-import Data.Either (partitionEithers)-import Data.Function (on)-import Data.List (intercalate, sortBy)-import Data.Maybe (catMaybes, fromMaybe)-import Data.Proxy (Proxy (Proxy))-import Data.Set (Set)-import qualified Data.Set as Set-import Data.Typeable (TypeRep, Typeable, cast, typeRep)-import GHC.Stack-import Test.HMock.Internal.ExpectSet-import Test.HMock.Internal.Expectable-import Test.HMock.Internal.Mockable-import Test.HMock.Internal.Util (Located (..), locate, withLoc)-import UnliftIO (MonadUnliftIO, newMVar, putMVar, readMVar, takeMVar)--#if !MIN_VERSION_base(4, 13, 0)-import Control.Monad.Fail (MonadFail)-#endif--data MockState m = MockState-  { mockExpectSet :: ExpectSet (Step m),-    mockDefaults :: [Step m],-    mockClasses :: Set TypeRep-  }--initMockState :: MockState m-initMockState =-  MockState-    { mockExpectSet = ExpectNothing,-      mockDefaults = [],-      mockClasses = Set.empty-    }---- | Monad transformer for running mocks.-newtype MockT m a where-  MockT :: {unMockT :: ReaderT (MVar (MockState m)) m a} -> MockT m a-  deriving-    ( Functor,-      Applicative,-      Monad,-      MonadFail,-      MonadIO,-      MonadState s,-      MonadWriter w,-      MonadRWS r w s,-      MonadError e,-      MonadCont,-      MonadBase b,-      MonadCatch,-      MonadMask,-      MonadThrow,-      MonadUnliftIO-    )--instance MonadTrans MockT where-  lift = MockT . lift--mapMockT :: (m a -> m b) -> MockT m a -> MockT m b-mapMockT f = MockT . mapReaderT f . unMockT--initClassIfNeeded ::-  forall cls m proxy.-  (Mockable cls, Typeable m, MonadIO m) =>-  proxy cls ->-  MockT m ()-initClassIfNeeded proxy =-  do-    stateVar <- MockT ask-    mockState <- takeMVar stateVar-    let newMockClasses = Set.insert t (mockClasses mockState)-    putMVar stateVar (mockState {mockClasses = newMockClasses})-    unless (t `Set.member` mockClasses mockState) $ do-      setupMockable (Proxy :: Proxy cls)-  where-    t = typeRep proxy--initClassesAsNeeded :: MonadIO m => ExpectSet (Step m) -> MockT m ()-initClassesAsNeeded es = forM_ (getSteps es) $-  \(Step (_ :: Located (SingleRule cls name m r))) ->-    initClassIfNeeded (Proxy :: Proxy cls)--instance MonadReader r m => MonadReader r (MockT m) where-  ask = lift ask-  local = mapMockT . local-  reader = lift . reader--instance ExpectContext MockT where-  fromExpectSet e = do-    initClassesAsNeeded e-    stateVar <- MockT ask-    mockState <- takeMVar stateVar-    let newExpectSet = e `ExpectInterleave` mockExpectSet mockState-    putMVar stateVar (mockState {mockExpectSet = newExpectSet})---- | Runs a test in the 'MockT' monad, handling all of the mocks.-runMockT :: forall m a. MonadIO m => MockT m a -> m a-runMockT test = withMockT constTest-  where-    constTest :: (forall b. MockT m b -> m b) -> MockT m a-    constTest _inMockT = test---- | Runs a test in the 'MockT' monad.  The test can unlift other MockT pieces--- to the base monad while still acting on the same set of expectations.  This--- can be useful for testing concurrency or similar mechanisms.------ @--- test = 'withMockT' '$' \inMockT -> do---    'expect' '$' ...------    'liftIO' '$' 'forkIO' '$' inMockT firstThread---    'liftIO' '$' 'forkIO' '$' inMockT secondThread--- @------ This is a low-level primitive.  Consider using the @unliftio@ package for--- higher level implementations of multithreading and other primitives.-withMockT ::-  forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b-withMockT test = do-  stateVar <- newMVar initMockState-  let inMockT :: forall a. MockT m a -> m a-      inMockT m = runReaderT (unMockT m) stateVar-  flip runReaderT stateVar $-    unMockT $ do-      a <- test inMockT-      verifyExpectations-      return a---- | Fetches a 'String' that describes the current set of outstanding--- expectations.  This is sometimes useful for debugging test code.  The exact--- format is not specified.-describeExpectations :: MonadIO m => MockT m String-describeExpectations =-  formatExpectSet <$> (MockT ask >>= fmap mockExpectSet . readMVar)---- | Verifies that all mock expectations are satisfied.  You normally don't need--- to do this, because it happens automatically at the end of your test in--- 'runMockT'.  However, it's occasionally useful to check expectations in the--- middle of a test, such as before going on to the next stage.------ Use of 'verifyExpectations' might signify that you are doing too much in a--- single test.  Consider splitting large tests into a separate test for each--- case.-verifyExpectations :: MonadIO m => MockT m ()-verifyExpectations = do-  expectSet <- MockT ask >>= fmap mockExpectSet . readMVar-  unless (satisfied expectSet) $ do-    case excess expectSet of-      ExpectNothing -> return ()-      missing -> error $ "Unmet expectations:\n" ++ formatExpectSet missing---- | Changes the default response for matching actions.------ Without 'byDefault', actions with no explicit response will return the--- 'Default' value for the type, or 'undefined' if the return type isn't an--- instance of 'Default'.  'byDefault' replaces that with a new default--- response, also overriding any previous defaults. The rule passed in must have--- exactly one response.-byDefault ::-  forall cls name m r.-  (MonadIO m, MockableMethod cls name m r) =>-  Rule cls name m r ->-  MockT m ()-byDefault (m :=> [r]) = do-  initClassIfNeeded (Proxy :: Proxy cls)-  stateVar <- MockT ask-  mockState <- takeMVar stateVar-  let newDefaults =-        Step (locate callStack (m :-> Just r)) : mockDefaults mockState-  putMVar stateVar (mockState {mockDefaults = newDefaults})-byDefault _ = error "Defaults must have exactly one response."--mockMethodImpl ::-  forall cls name m r.-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r-  ) =>-  r ->-  Action cls name m r ->-  MockT m r-mockMethodImpl surrogate action =-  do-    initClassIfNeeded (Proxy :: Proxy cls)-    stateVar <- MockT ask-    mockState <- takeMVar stateVar-    let (newExpectSet, response) =-          decideAction (mockExpectSet mockState) (mockDefaults mockState)-    putMVar stateVar mockState {mockExpectSet = newExpectSet}-    response-  where-    decideAction expectSet defaults =-      let (partial, full) = partitionEithers (tryMatch <$> liveSteps expectSet)-          orderedPartial = snd <$> sortBy (compare `on` fst) (catMaybes partial)-       in case (full, findDefault defaults, surrogate, orderedPartial) of-            ((e, Just response) : _, _, _, _) -> (e, response)-            ((e, Nothing) : _, d, s, _) -> (e, fromMaybe (return s) d)-            ([], _, _, []) -> error $ noMatchError action-            ([], _, _, _) -> error $ partialMatchError action orderedPartial-    tryMatch ::-      (Step m, ExpectSet (Step m)) ->-      Either (Maybe (Int, String)) (ExpectSet (Step m), Maybe (MockT m r))-    tryMatch (Step expected, e)-      | Just lrule@(Loc _ (m :-> impl)) <- cast expected =-        case matchAction m action of-          NoMatch n ->-            Left (Just (n, withLoc (showMatcher (Just action) m <$ lrule)))-          Match ->-            Right (e, ($ action) <$> impl)-      | otherwise = Left Nothing--    findDefault :: [Step m] -> Maybe (MockT m r)-    findDefault [] = Nothing-    findDefault (Step expected : _)-      | Just (Loc _ (m :-> Just r)) <- cast expected,-        Match <- matchAction m action =-        Just (r action)-    findDefault (_ : steps) = findDefault steps---- | Implements a method in a 'Mockable' monad by delegating to the mock--- framework.  If the method is called unexpectedly, an exception will be--- thrown.  However, an expected invocation without a specified response will--- return the default value.-mockMethod ::-  forall cls name m r.-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r,-    Default r-  ) =>-  Action cls name m r ->-  MockT m r-mockMethod action =-  withFrozenCallStack $ mockMethodImpl def action---- | Implements a method in a 'Mockable' monad by delegating to the mock--- framework.  If the method is called unexpectedly, an exception will be--- thrown.  However, an expected invocation without a specified response will--- return undefined.  This can be used in place of 'mockMethod' when the return--- type has no default.-mockDefaultlessMethod ::-  forall cls name m r.-  ( HasCallStack,-    MonadIO m,-    MockableMethod cls name m r-  ) =>-  Action cls name m r ->-  MockT m r-mockDefaultlessMethod action =-  withFrozenCallStack $ mockMethodImpl undefined action---- An error for an action that matches no expectations at all.-noMatchError ::-  (HasCallStack, Mockable cls) =>-  -- | The action that was received.-  Action cls name m a ->-  String-noMatchError a =-  "Unexpected action: " ++ showAction a---- An error for an action that doesn't match the argument predicates for any--- of the method's expectations.-partialMatchError ::-  (HasCallStack, Mockable cls) =>-  -- | The action that was received.-  Action cls name m a ->-  -- | Descriptions of the matchers that most closely matched, closest first.-  [String] ->-  String-partialMatchError a partials =-  "Wrong arguments: "-    ++ showAction a-    ++ "\n\nClosest matches:\n - "-    ++ intercalate "\n - " (take 5 partials)
− src/Test/HMock/Internal/MockT.hs-boot
@@ -1,12 +0,0 @@-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE RoleAnnotations #-}--module Test.HMock.Internal.MockT where--import Data.Kind (Type)--type role MockT nominal nominal--data MockT (m :: Type -> Type) (a :: Type)--instance Monad m => Monad (MockT m)
− src/Test/HMock/Internal/Mockable.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--module Test.HMock.Internal.Mockable where--import Control.Monad.Trans (MonadIO)-import Data.Kind (Constraint, Type)-import Data.Typeable (Typeable)-import GHC.TypeLits (Symbol)-import {-# SOURCE #-} Test.HMock.Internal.MockT (MockT)---- | The result of matching a @'Matcher' a@ with an @'Action' b@.  Because the--- types should already guarantee that the methods match, all that's left is to--- match arguments.-data MatchResult where-  -- | No match.  The int is the number of arguments that don't match.-  NoMatch :: Int -> MatchResult-  -- | Match. Stores a witness to the equality of return types.-  Match :: MatchResult---- | A base class for 'Monad' subclasses whose methods can be mocked.  You--- usually want to generate this instance using 'Test.HMock.TH.makeMockable',--- 'Test.HMock.TH.makeMockableBase', 'Test.HMock.TH.deriveMockable', or--- 'Test.HMock.TH.deriveMockableBase'.  It's just boilerplate.-class (Typeable cls) => MockableBase (cls :: (Type -> Type) -> Constraint) where-  -- | An action that is performed.  This data type will have one constructor-  -- for each method.-  data Action cls :: Symbol -> (Type -> Type) -> Type -> Type--  -- | A specification for matching actions.  The actual arguments should be-  -- replaced with predicates.-  data Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type--  -- | Gets a text description of an 'Action', for use in error messages.-  showAction :: Action cls name m a -> String--  -- | Gets a text description of a 'Matcher', for use in error messages.-  showMatcher :: Maybe (Action cls name m a) -> Matcher cls name m b -> String--  -- | Attempts to match an 'Action' with a 'Matcher'.-  matchAction :: Matcher cls name m a -> Action cls name m a -> MatchResult---- | A class for 'Monad' subclasses whose methods can be mocked.  This class--- augments 'MockableBase' with a setup method that is run before HMock touches--- the 'Monad' subclass for the first time.  The default implementation does--- nothing, but you can derive your own instances that add setup behavior.-class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint) where-  -- An action to run and set up defaults for this class.  The action will be-  -- run before HMock touches the class, either to add expectations or to-  -- delegate a method.-  setupMockable :: (MonadIO m, Typeable m) => proxy cls -> MockT m ()-  setupMockable _ = return ()
− src/Test/HMock/Internal/Multiplicity.hs
@@ -1,153 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}--module Test.HMock.Internal.Multiplicity where---- | An acceptable range of number of times for something to happen.------ A multiplicity can have a lower and an upper bound.-data Multiplicity = Multiplicity Int (Maybe Int) deriving (Eq)--instance Show Multiplicity where-  show m | not (feasible m) = "infeasible"-  show (Multiplicity 0 (Just 0)) = "never"-  show (Multiplicity 1 (Just 1)) = "once"-  show (Multiplicity 2 (Just 2)) = "twice"-  show (Multiplicity 0 Nothing) = "any number of times"-  show (Multiplicity 1 Nothing) = "at least once"-  show (Multiplicity 2 Nothing) = "at least twice"-  show (Multiplicity n Nothing) = "at least " ++ show n ++ " times"-  show (Multiplicity 0 (Just 1)) = "at most once"-  show (Multiplicity 0 (Just 2)) = "at most twice"-  show (Multiplicity 0 (Just n)) = "at most " ++ show n ++ " times"-  show (Multiplicity m (Just n))-    | m == n = show n ++ " times"-    | m == n - 1 = show m ++ " or " ++ show n ++ " times"-    | otherwise = show m ++ " to " ++ show n ++ " times"---- | A 'Multiplicity' value representing inconsistent expectations.-infeasible :: Multiplicity-infeasible = Multiplicity 0 (Just (-1))---- | This is an incomplete instance, provided for convenience.------ >>> meetsMultiplicity 5 4--- False--- >>> meetsMultiplicity 5 5--- True--- >>> between 4 6 - between 1 2--- 2 to 5 times-instance Num Multiplicity where-  fromInteger n-    | n < 0 = infeasible-    | otherwise =-      normalize $-        Multiplicity (fromInteger n) (Just (fromInteger n))--  m1@(Multiplicity a b) + m2@(Multiplicity c d)-    | feasible m1 && feasible m2 =-      normalize $ Multiplicity (a + c) ((+) <$> b <*> d)-    | otherwise = infeasible--  m1@(Multiplicity a b) - m2@(Multiplicity c d)-    | feasible m1 && feasible m2 =-      normalize $ Multiplicity (maybe 0 (a -) d) (subtract c <$> b)-    | otherwise = infeasible--  (*) = error "Multiplicities are not closed under multiplication"--  abs = id--  signum (Multiplicity 0 (Just 0)) = 0-  signum _ = 1--normalize :: Multiplicity -> Multiplicity-normalize (Multiplicity a b) = Multiplicity (max a 0) b---- | Checks whether a certain number satisfies the 'Multiplicity'.-meetsMultiplicity :: Multiplicity -> Int -> Bool-meetsMultiplicity (Multiplicity lo mbhi) n-  | n < lo = False-  | Just hi <- mbhi, n > hi = False-  | otherwise = True---- | A 'Multiplicity' that means exactly once.------ >>> meetsMultiplicity once 0--- False--- >>> meetsMultiplicity once 1--- True--- >>> meetsMultiplicity once 2--- False-once :: Multiplicity-once = 1---- | A 'Multiplicity' that means any number of times.--- >>> meetsMultiplicity anyMultiplicity 0--- True--- >>> meetsMultiplicity anyMultiplicity 1--- True--- >>> meetsMultiplicity anyMultiplicity 10--- True-anyMultiplicity :: Multiplicity-anyMultiplicity = atLeast 0---- | A 'Multiplicity' that means at least this many times.------ >>> meetsMultiplicity (atLeast 2) 1--- False--- >>> meetsMultiplicity (atLeast 2) 2--- True--- >>> meetsMultiplicity (atLeast 2) 3--- True-atLeast :: Multiplicity -> Multiplicity-atLeast (Multiplicity n _) = Multiplicity n Nothing---- | A 'Multiplicity' that means at most this many times.------ >>> meetsMultiplicity (atMost 2) 1--- True--- >>> meetsMultiplicity (atMost 2) 2--- True--- >>> meetsMultiplicity (atMost 2) 3--- False-atMost :: Multiplicity -> Multiplicity-atMost (Multiplicity _ n) = Multiplicity 0 n---- | A 'Multiplicity' that means any number in this interval, endpoints--- included.  For example, @'between' 2 3@ means 2 or 3 times, while--- @'between' n n@ is equivalent to @n@.------ >>> meetsMultiplicity (between 2 3) 1--- False--- >>> meetsMultiplicity (between 2 3) 2--- True--- >>> meetsMultiplicity (between 2 3) 3--- True--- >>> meetsMultiplicity (between 2 3) 4--- False-between :: Multiplicity -> Multiplicity -> Multiplicity-between (Multiplicity m _) (Multiplicity _ n) = Multiplicity m n---- | Checks whether a 'Multiplicity' includes zero in its range.------ >>> exhaustable anyMultiplicity--- True--- >>> exhaustable (atLeast 2)--- False--- >>> exhaustable (atMost 3)--- True--- >>> exhaustable (between 0 2)--- True-exhaustable :: Multiplicity -> Bool-exhaustable m@(Multiplicity lo _) = feasible m && lo == 0---- | Checks whether a 'Multiplicity' is capable of matching any number at all.------ >>> feasible once--- True--- >>> feasible 0--- True--- >>> feasible (once - 2)--- False-feasible :: Multiplicity -> Bool-feasible (Multiplicity a b) = maybe True (>= a) b
− src/Test/HMock/Internal/Predicates.hs
@@ -1,944 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}--module Test.HMock.Internal.Predicates where--import Data.Char (toUpper)-import Data.Maybe (isJust)-import Data.MonoTraversable-import qualified Data.Sequences as Seq-import Data.Typeable (Proxy (..), Typeable, cast, typeRep)-import GHC.Exts (IsList (Item, toList))-import GHC.Stack (HasCallStack, callStack)-import Language.Haskell.TH (ExpQ, PatQ, pprint)-import Language.Haskell.TH.Syntax (lift)-import Test.HMock.Internal.TH.Util (removeModNames)-import Test.HMock.Internal.Util (choices, locate, isSubsequenceOf, withLoc)-import Text.Regex.TDFA hiding (match)---- $setup--- >>> :set -XTemplateHaskell--- >>> :set -XTypeApplications--- >>> :set -Wno-type-defaults---- | A predicate, which tests values and either accepts or rejects them.  This--- is similar to @a -> 'Bool'@, but also has a 'Show' instance to describe what--- it is checking.------ Predicates are used to define which arguments a general matcher should--- accept.-data Predicate a = Predicate-  { showPredicate :: String,-    accept :: a -> Bool-  }--instance Show (Predicate a) where show = showPredicate---- | A 'Predicate' that accepts anything at all.------ >>> accept anything "foo"--- True--- >>> accept anything undefined--- True-anything :: Predicate a-anything =-  Predicate-    { showPredicate = "anything",-      accept = const True-    }---- | A 'Predicate' that accepts only the given value.------ >>> accept (eq "foo") "foo"--- True--- >>> accept (eq "foo") "bar"--- False-eq :: (Show a, Eq a) => a -> Predicate a-eq x =-  Predicate-    { showPredicate = show x,-      accept = (== x)-    }---- | A 'Predicate' that accepts anything but the given value.------ >>> accept (neq "foo") "foo"--- False--- >>> accept (neq "foo") "bar"--- True-neq :: (Show a, Eq a) => a -> Predicate a-neq x =-  Predicate-    { showPredicate = "≠ " ++ show x,-      accept = (/= x)-    }---- | A 'Predicate' that accepts anything greater than the given value.------ >>> accept (gt 5) 4--- False--- >>> accept (gt 5) 5--- False--- >>> accept (gt 5) 6--- True-gt :: (Show a, Ord a) => a -> Predicate a-gt x =-  Predicate-    { showPredicate = "> " ++ show x,-      accept = (> x)-    }---- | A 'Predicate' that accepts anything greater than or equal to the given--- value.------ >>> accept (geq 5) 4--- False--- >>> accept (geq 5) 5--- True--- >>> accept (geq 5) 6--- True-geq :: (Show a, Ord a) => a -> Predicate a-geq x =-  Predicate-    { showPredicate = "≥ " ++ show x,-      accept = (>= x)-    }---- | A 'Predicate' that accepts anything less than the given value.------ >>> accept (lt 5) 4--- True--- >>> accept (lt 5) 5--- False--- >>> accept (lt 5) 6--- False-lt :: (Show a, Ord a) => a -> Predicate a-lt x =-  Predicate-    { showPredicate = "< " ++ show x,-      accept = (< x)-    }---- | A 'Predicate' that accepts anything less than or equal to the given value.------ >>> accept (leq 5) 4--- True--- >>> accept (leq 5) 5--- True--- >>> accept (leq 5) 6--- False-leq :: (Show a, Ord a) => a -> Predicate a-leq x =-  Predicate-    { showPredicate = "≤ " ++ show x,-      accept = (<= x)-    }---- | A 'Predicate' that matches 'True' values.------ >>> accept true True--- True--- >>> accept true False--- False-true :: Predicate Bool-true = eq True---- | A 'Predicate' that matches 'False' values.------ >>> accept false True--- False--- >>> accept false False--- True-false :: Predicate Bool-false = eq False---- | A 'Predicate' that accepts 'Maybe' values of @'Just' x@, where @x@ matches--- the given child 'Predicate'.------ >>> accept (just (eq "value")) Nothing--- False--- >>> accept (just (eq "value")) (Just "value")--- True--- >>> accept (just (eq "value")) (Just "wrong value")--- False-just :: Predicate a -> Predicate (Maybe a)-just p =-  Predicate-    { showPredicate = "Just (" ++ showPredicate p ++ ")",-      accept = \case Just x -> accept p x; _ -> False-    }---- | A 'Predicate' that accepts an 'Either' value of @'Left' x@, where @x@--- matches the given child 'Predicate'.------ >>> accept (left (eq "value")) (Left "value")--- True--- >>> accept (left (eq "value")) (Right "value")--- False--- >>> accept (left (eq "value")) (Left "wrong value")--- False-left :: Predicate a -> Predicate (Either a b)-left p =-  Predicate-    { showPredicate = "Left (" ++ showPredicate p ++ ")",-      accept = \case Left x -> accept p x; _ -> False-    }---- | A 'Predicate' that accepts an 'Either' value of @'Right' x@, where @x@--- matches the given child 'Predicate'.------ >>> accept (right (eq "value")) (Right "value")--- True--- >>> accept (right (eq "value")) (Right "wrong value")--- False--- >>> accept (right (eq "value")) (Left "value")--- False-right :: Predicate b -> Predicate (Either a b)-right p =-  Predicate-    { showPredicate = "Right (" ++ showPredicate p ++ ")",-      accept = \case Right x -> accept p x; _ -> False-    }---- | A 'Predicate' that accepts pairs whose elements satisfy the corresponding--- child 'Predicates'.------ >>> accept (zipP (eq "foo") (eq "bar")) ("foo", "bar")--- True--- >>> accept (zipP (eq "foo") (eq "bar")) ("bar", "foo")--- False-zipP :: Predicate a -> Predicate b -> Predicate (a, b)-zipP p q =-  Predicate-    { showPredicate = show (p, q),-      accept = \(x, y) -> accept p x && accept q y-    }---- | A 'Predicate' that accepts 3-tuples whose elements satisfy the--- corresponding child 'Predicate's.------ >>> accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("foo", "bar", "qux")--- True--- >>> accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("qux", "bar", "foo")--- False-zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)-zip3P p1 p2 p3 =-  Predicate-    { showPredicate = show (p1, p2, p3),-      accept = \(x1, x2, x3) -> accept p1 x1 && accept p2 x2 && accept p3 x3-    }---- | A 'Predicate' that accepts 3-tuples whose elements satisfy the--- corresponding child 'Predicates'.------ >>> accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (1, 2, 3, 4)--- True--- >>> accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (4, 3, 2, 1)--- False-zip4P ::-  Predicate a ->-  Predicate b ->-  Predicate c ->-  Predicate d ->-  Predicate (a, b, c, d)-zip4P p1 p2 p3 p4 =-  Predicate-    { showPredicate = show (p1, p2, p3, p4),-      accept = \(x1, x2, x3, x4) ->-        accept p1 x1 && accept p2 x2 && accept p3 x3 && accept p4 x4-    }---- | A 'Predicate' that accepts 3-tuples whose elements satisfy the--- corresponding child 'Predicates'.------ >>> accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (1, 2, 3, 4, 5)--- True--- >>> accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (5, 4, 3, 2, 1)--- False-zip5P ::-  Predicate a ->-  Predicate b ->-  Predicate c ->-  Predicate d ->-  Predicate e ->-  Predicate (a, b, c, d, e)-zip5P p1 p2 p3 p4 p5 =-  Predicate-    { showPredicate = show (p1, p2, p3, p4, p5),-      accept = \(x1, x2, x3, x4, x5) ->-        accept p1 x1 && accept p2 x2 && accept p3 x3 && accept p4 x4-          && accept p5 x5-    }---- | A 'Predicate' that accepts anything accepted by both of its children.------ >>> accept (lt "foo" `andP` gt "bar") "eta"--- True--- >>> accept (lt "foo" `andP` gt "bar") "quz"--- False--- >>> accept (lt "foo" `andP` gt "bar") "alpha"--- False-andP :: Predicate a -> Predicate a -> Predicate a-p `andP` q =-  Predicate-    { showPredicate = showPredicate p ++ " and " ++ showPredicate q,-      accept = \x -> accept p x && accept q x-    }---- | A 'Predicate' that accepts anything accepted by either of its children.------ >>> accept (lt "bar" `orP` gt "foo") "eta"--- False--- >>> accept (lt "bar" `orP` gt "foo") "quz"--- True--- >>> accept (lt "bar" `orP` gt "foo") "alpha"--- True-orP :: Predicate a -> Predicate a -> Predicate a-p `orP` q =-  Predicate-    { showPredicate = showPredicate p ++ " or " ++ showPredicate q,-      accept = \x -> accept p x || accept q x-    }---- | A 'Predicate' that inverts another 'Predicate', accepting whatever its--- child rejects, and rejecting whatever its child accepts.------ >>> accept (notP (eq "negative")) "positive"--- True--- >>> accept (notP (eq "negative")) "negative"--- False-notP :: Predicate a -> Predicate a-notP p =-  Predicate-    { showPredicate = "not " ++ showPredicate p,-      accept = not . accept p-    }---- | A 'Predicate' that accepts sequences that start with the given prefix.------ >>> accept (startsWith "fun") "fungible"--- True--- >>> accept (startsWith "gib") "fungible"--- False-startsWith :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t-startsWith pfx =-  Predicate-    { showPredicate = "starts with " ++ show pfx,-      accept = (pfx `Seq.isPrefixOf`)-    }---- | A 'Predicate' that accepts sequences that end with the given suffix.------ >>> accept (endsWith "ow") "crossbow"--- True--- >>> accept (endsWith "ow") "trebuchet"--- False-endsWith :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t-endsWith sfx =-  Predicate-    { showPredicate = "ends with " ++ show sfx,-      accept = (sfx `Seq.isSuffixOf`)-    }---- | A 'Predicate' that accepts sequences that contain the given (consecutive)--- substring.------ >>> accept (hasSubstr "i") "team"--- False--- >>> accept (hasSubstr "i") "partnership"--- True-hasSubstr :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t-hasSubstr s =-  Predicate-    { showPredicate = "has substring " ++ show s,-      accept = (s `Seq.isInfixOf`)-    }---- | A 'Predicate' that accepts sequences that contain the given (not--- necessarily consecutive) subsequence.------ >>> accept (hasSubsequence [1..5]) [1, 2, 3, 4, 5]--- True--- >>> accept (hasSubsequence [1..5]) [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]--- True--- >>> accept (hasSubsequence [1..5]) [2, 3, 5, 7, 11]--- False-hasSubsequence :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t-hasSubsequence s =-  Predicate-    { showPredicate = "has subsequence " ++ show s,-      accept = (s `isSubsequenceOf`)-    }---- | Transforms a 'Predicate' on 'String's or string-like types to match without--- regard to case.------ >>> accept (caseInsensitive startsWith "foo") "FOOTBALL!"--- True--- >>> accept (caseInsensitive endsWith "ball") "soccer"--- False--- >>> accept (caseInsensitive eq "time") "TIME"--- True--- >>> accept (caseInsensitive gt "NOTHING") "everything"--- False-caseInsensitive ::-  ( MonoFunctor t,-    MonoFunctor a,-    Element t ~ Char,-    Element a ~ Char-  ) =>-  (t -> Predicate a) ->-  (t -> Predicate a)-caseInsensitive p s =-  Predicate-    { showPredicate = "(case insensitive) " ++ show (p s),-      accept = accept capP . omap toUpper-    }-  where-    capP = p (omap toUpper s)---- | A 'Predicate' that accepts 'String's or string-like values matching a--- regular expression.  The expression must match the entire argument.------ You should not use @'caseInsensitive' 'matchesRegex'@, because regular--- expression syntax itself is still case-sensitive even when the text you are--- matching is not.  Instead, use 'matchesCaseInsensitiveRegex'.------ >>> accept (matchesRegex "x{2,5}y?") "xxxy"--- True--- >>> accept (matchesRegex "x{2,5}y?") "xyy"--- False--- >>> accept (matchesRegex "x{2,5}y?") "wxxxyz"--- False-matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a-matchesRegex s =-  Predicate-    { showPredicate = "/" ++ init (tail $ show s) ++ "/",-      accept = \x -> case matchOnceText r x of-        Just (a, _, b) -> a == empty && b == empty-        Nothing -> False-    }-  where-    r = makeRegexOpts comp exec s :: Regex-    comp = defaultCompOpt {newSyntax = True, lastStarGreedy = True}-    exec = defaultExecOpt {captureGroups = False}---- | A 'Predicate' that accepts 'String's or string-like values matching a--- regular expression in a case-insensitive way.  The expression must match the--- entire argument.------ You should use this instead of @'caseInsensitive' 'matchesRegex'@, because--- regular expression syntax itself is still case-sensitive even when the text--- you are matching is not.------ >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XXXY"--- True--- >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XYY"--- False--- >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"--- False-matchesCaseInsensitiveRegex ::-  (RegexLike Regex a, Eq a) => String -> Predicate a-matchesCaseInsensitiveRegex s =-  Predicate-    { showPredicate = "/" ++ init (tail $ show s) ++ "/i",-      accept = \x -> case matchOnceText r x of-        Just (a, _, b) -> a == empty && b == empty-        Nothing -> False-    }-  where-    r = makeRegexOpts comp exec s :: Regex-    comp =-      defaultCompOpt-        { newSyntax = True,-          lastStarGreedy = True,-          caseSensitive = False-        }-    exec = defaultExecOpt {captureGroups = False}---- | A 'Predicate' that accepts 'String's or string-like values containing a--- match for a regular expression.  The expression need not match the entire--- argument.------ You should not use @'caseInsensitive' 'containsRegex'@, because regular--- expression syntax itself is still case-sensitive even when the text you are--- matching is not.  Instead, use 'containsCaseInsensitiveRegex'.------ >>> accept (containsRegex "x{2,5}y?") "xxxy"--- True--- >>> accept (containsRegex "x{2,5}y?") "xyy"--- False--- >>> accept (containsRegex "x{2,5}y?") "wxxxyz"--- True-containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a-containsRegex s =-  Predicate-    { showPredicate = "contains /" ++ init (tail $ show s) ++ "/",-      accept = isJust . matchOnce r-    }-  where-    r = makeRegexOpts comp exec s :: Regex-    comp = defaultCompOpt {newSyntax = True, lastStarGreedy = True}-    exec = defaultExecOpt {captureGroups = False}---- | A 'Predicate' that accepts 'String's or string-like values containing a--- match for a regular expression in a case-insensitive way.  The expression--- need match the entire argument.------ You should use this instead of @'caseInsensitive' 'containsRegex'@, because--- regular expression syntax itself is still case-sensitive even when the text--- you are matching is not.------ >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "XXXY"--- True--- >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "XYY"--- False--- >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"--- True-containsCaseInsensitiveRegex ::-  (RegexLike Regex a, Eq a) => String -> Predicate a-containsCaseInsensitiveRegex s =-  Predicate-    { showPredicate = "contains /" ++ init (tail $ show s) ++ "/i",-      accept = isJust . matchOnce r-    }-  where-    r = makeRegexOpts comp exec s :: Regex-    comp =-      defaultCompOpt-        { newSyntax = True,-          lastStarGreedy = True,-          caseSensitive = False-        }-    exec = defaultExecOpt {captureGroups = False}---- | A 'Predicate' that accepts empty data structures.------ >>> accept isEmpty []--- True--- >>> accept isEmpty [1, 2, 3]--- False--- >>> accept isEmpty ""--- True--- >>> accept isEmpty "gas tank"--- False-isEmpty :: MonoFoldable t => Predicate t-isEmpty =-  Predicate-    { showPredicate = "empty",-      accept = onull-    }---- | A 'Predicate' that accepts non-empty data structures.------ >>> accept nonEmpty []--- False--- >>> accept nonEmpty [1, 2, 3]--- True--- >>> accept nonEmpty ""--- False--- >>> accept nonEmpty "gas tank"--- True-nonEmpty :: MonoFoldable t => Predicate t-nonEmpty =-  Predicate-    { showPredicate = "nonempty",-      accept = not . onull-    }---- | A 'Predicate' that accepts data structures whose number of elements match--- the child 'Predicate'.------ >>> accept (sizeIs (lt 3)) ['a' .. 'f']--- False--- >>> accept (sizeIs (lt 3)) ['a' .. 'b']--- True-sizeIs :: MonoFoldable t => Predicate Int -> Predicate t-sizeIs p =-  Predicate-    { showPredicate = "size " ++ showPredicate p,-      accept = accept p . olength-    }---- | A 'Predicate' that accepts data structures whose contents each match the--- corresponding 'Predicate' in the given list, in the same order.------ >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4]--- True--- >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4, 5]--- False--- >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 10, 4]--- False-elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t-elemsAre ps =-  Predicate-    { showPredicate = show ps,-      accept = \xs ->-        olength xs == olength ps-          && and (zipWith accept ps (otoList xs))-    }---- | A 'Predicate' that accepts data structures whose contents each match the--- corresponding 'Predicate' in the given list, in any order.------ >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3]--- True--- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [2, 3, 1]--- True--- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3, 4]--- False--- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 3]--- False-unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t-unorderedElemsAre ps =-  Predicate-    { showPredicate =-        "(any order) " ++ show ps,-      accept = matches ps . otoList-    }-  where-    matches (q : qs) xs = or [matches qs ys | (y, ys) <- choices xs, accept q y]-    matches [] xs = null xs---- | A 'Predicate' that accepts data structures whose elements each match the--- child 'Predicate'.------ >>> accept (each (gt 5)) [4, 5, 6]--- False--- >>> accept (each (gt 5)) [6, 7, 8]--- True--- >>> accept (each (gt 5)) []--- True-each :: MonoFoldable t => Predicate (Element t) -> Predicate t-each p =-  Predicate-    { showPredicate = "each (" ++ showPredicate p ++ ")",-      accept = oall (accept p)-    }---- | A 'Predicate' that accepts data structures which contain at least one--- element matching the child 'Predicate'.------ >>> accept (contains (gt 5)) [3, 4, 5]--- False--- >>> accept (contains (gt 5)) [4, 5, 6]--- True--- >>> accept (contains (gt 5)) []--- False-contains :: MonoFoldable t => Predicate (Element t) -> Predicate t-contains p =-  Predicate-    { showPredicate = "contains (" ++ showPredicate p ++ ")",-      accept = oany (accept p)-    }---- | A 'Predicate' that accepts data structures which contain an element--- satisfying each of the child predicates.  @'containsAll' [p1, p2, ..., pn]@--- is equivalent to @'contains' p1 `'andP'` 'contains' p2 `'andP'` ... `'andP'`--- 'contains' pn@.------ >>> accept (containsAll [eq "foo", eq "bar"]) ["bar", "foo"]--- True--- >>> accept (containsAll [eq "foo", eq "bar"]) ["foo"]--- False--- >>> accept (containsAll [eq "foo", eq "bar"]) ["foo", "bar", "qux"]--- True-containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t-containsAll ps =-  Predicate-    { showPredicate = "contains all of " ++ show ps,-      accept = \xs -> all (flip oany xs . accept) ps-    }---- | A 'Predicate' that accepts data structures whose elements all satisfy at--- least one of the child predicates.  @'containsOnly' [p1, p2, ..., pn]@ is--- equivalent to @'each' (p1 `'orP'` p2 `'orP'` ... `'orP'` pn)@.------ >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "foo"]--- True--- >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "bar"]--- True--- >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "qux"]--- False-containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t-containsOnly ps =-  Predicate-    { showPredicate = "contains only " ++ show ps,-      accept = oall (\x -> any (`accept` x) ps)-    }---- | A 'Predicate' that accepts map-like structures which contain a key matching--- the child 'Predicate'.------ >>> accept (containsKey (eq "foo")) [("foo", 1), ("bar", 2)]--- True--- >>> accept (containsKey (eq "foo")) [("bar", 1), ("qux", 2)]--- False-containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t-containsKey p =-  Predicate-    { showPredicate = "contains key " ++ show p,-      accept = \m -> any (accept p) (fst <$> toList m)-    }---- | A 'Predicate' that accepts map-like structures which contain a key/value--- pair matched by the given child 'Predicate's (one for the key, and one for--- the value).------ >>> accept (containsEntry (eq "foo") (gt 10)) [("foo", 12), ("bar", 5)]--- True--- >>> accept (containsEntry (eq "foo") (gt 10)) [("foo", 5), ("bar", 12)]--- False--- >>> accept (containsEntry (eq "foo") (gt 10)) [("bar", 12)]--- False-containsEntry ::-  (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t-containsEntry p q =-  Predicate-    { showPredicate = "contains entry " ++ show (p, q),-      accept = any (\(x, y) -> accept p x && accept q y) . toList-    }---- | A 'Predicate' that accepts map-like structures whose keys are exactly those--- matched by the given list of 'Predicates', in any order.------ >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("b", 2), ("c", 3)]--- True--- >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("c", 1), ("b", 2), ("a", 3)]--- True--- >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("c", 3)]--- False--- >>> accept (keysAre [eq "a", eq "b"]) [("a", 1), ("b", 2), ("c", 3)]--- False-keysAre ::-  (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t-keysAre ps =-  Predicate-    { showPredicate = "keys are " ++ show ps,-      accept = matches ps . map fst . toList-    }-  where-    matches (q : qs) xs = or [matches qs ys | (y, ys) <- choices xs, accept q y]-    matches [] xs = null xs---- | A 'Predicate' that accepts map-like structures whose entries are exactly--- those matched by the given list of 'Predicate' pairs, in any order.------ >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4)]--- True--- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(3, 4), (1, 2)]--- True--- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 4), (3, 2)]--- False--- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4), (5, 6)]--- False-entriesAre ::-  (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t-entriesAre ps =-  Predicate-    { showPredicate = "entries are " ++ show ps,-      accept = matches ps . toList-    }-  where-    matches ((p, q) : pqs) xs =-      or [matches pqs ys | ((k, v), ys) <- choices xs, accept p k, accept q v]-    matches [] xs = null xs---- | A 'Predicate' that accepts values of 'RealFloat' types that are close to--- the given number.  The expected precision is scaled based on the target--- value, so that reasonable rounding error is accepted but grossly inaccurate--- results are not.------ The following naive use of 'eq' fails due to rounding:------ >>> accept (eq 1.0) (sum (replicate 100 0.01))--- False------ The solution is to use 'approxEq', which accounts for rounding error.--- However, 'approxEq' doesn't accept results that are far enough off that they--- likely arise from incorrect calculations instead of rounding error.------ >>> accept (approxEq 1.0) (sum (replicate 100 0.01))--- True--- >>> accept (approxEq 1.0) (sum (replicate 100 0.009999))--- False-approxEq :: (RealFloat a, Show a) => a -> Predicate a-approxEq x =-  Predicate-    { showPredicate = "≈ " ++ show x,-      accept = \y -> abs (x - y) < diff-    }-  where-    diff = encodeFloat 1 (snd (decodeFloat x) + floatDigits x `div` 2)---- | A 'Predicate' that accepts finite numbers of any 'RealFloat' type.------ >>> accept finite 1.0--- True--- >>> accept finite (0 / 0)--- False--- >>> accept finite (1 / 0)--- False-finite :: RealFloat a => Predicate a-finite =-  Predicate-    { showPredicate = "finite",-      accept = \x -> not (isInfinite x) && not (isNaN x)-    }---- | A 'Predicate' that accepts infinite numbers of any 'RealFloat' type.------ >>> accept infinite 1.0--- False--- >>> accept infinite (0 / 0)--- False--- >>> accept infinite (1 / 0)--- True-infinite :: RealFloat a => Predicate a-infinite =-  Predicate-    { showPredicate = "infinite",-      accept = isInfinite-    }---- | A 'Predicate' that accepts NaN values of any 'RealFloat' type.------ >>> accept nAn 1.0--- False--- >>> accept nAn (0 / 0)--- True--- >>> accept nAn (1 / 0)--- False-nAn :: RealFloat a => Predicate a-nAn =-  Predicate-    { showPredicate = "NaN",-      accept = isNaN-    }---- | A conversion from @a -> 'Bool'@ to 'Predicate'.  This is a fallback that--- can be used to build a 'Predicate' that checks anything at all.  However, its--- description will be less helpful than standard 'Predicate's.------ >>> accept (is even) 3--- False--- >>> accept (is even) 4--- True-is :: HasCallStack => (a -> Bool) -> Predicate a-is f =-  Predicate-    { showPredicate = withLoc (locate callStack "custom predicate"),-      accept = f-    }---- | A Template Haskell splice that acts like 'is', but receives a quoted--- expression at compile time and has a more helpful description for error--- messages.------ >>> accept $(qIs [| even |]) 3--- False--- >>> accept $(qIs [| even |]) 4--- True------ >>> show $(qIs [| even |])--- "even"-qIs :: HasCallStack => ExpQ -> ExpQ-qIs f =-  [|-    Predicate-      { showPredicate = $(lift . pprint . removeModNames =<< f),-        accept = $f-      }-    |]---- | A combinator to lift a 'Predicate' to work on a property or computed value--- of the original value.------ >>> accept (with abs (gt 5)) (-6)--- True--- >>> accept (with abs (gt 5)) (-5)--- False--- >>> accept (with reverse (eq "olleh")) "hello"--- True--- >>> accept (with reverse (eq "olleh")) "goodbye"--- False-with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a-with f p =-  Predicate-    { showPredicate =-        withLoc (locate callStack "property") ++ ": " ++ show p,-      accept = accept p . f-    }---- | A Template Haskell splice that acts like 'is', but receives a quoted typed--- expression at compile time and has a more helpful description for error--- messages.------ >>> accept ($(qWith [| abs |]) (gt 5)) (-6)--- True--- >>> accept ($(qWith [| abs |]) (gt 5)) (-5)--- False--- >>> accept ($(qWith [| reverse |]) (eq "olleh")) "hello"--- True--- >>> accept ($(qWith [| reverse |]) (eq "olleh")) "goodbye"--- False------ >>> show ($(qWith [| abs |]) (gt 5))--- "abs: > 5"-qWith :: ExpQ -> ExpQ-qWith f =-  [|-    \p ->-      Predicate-        { showPredicate =-            $(lift . pprint . removeModNames =<< f) ++ ": " ++ show p,-          accept = accept p . $f-        }-    |]---- | A Template Haskell splice that turns a quoted pattern into a predicate that--- accepts values that match the pattern.------ >>> accept $(qMatch [p| Just (Left _) |]) Nothing--- False--- >>> accept $(qMatch [p| Just (Left _) |]) (Just (Left 5))--- True--- >>> accept $(qMatch [p| Just (Left _) |]) (Just (Right 5))--- False------ >>> show $(qMatch [p| Just (Left _) |])--- "Just (Left _)"-qMatch :: PatQ -> ExpQ-qMatch qpat =-  [|-    Predicate-      { showPredicate = $(lift . pprint . removeModNames =<< qpat),-        accept = \case-          $(qpat) -> True-          _ -> False-      }-    |]---- | Converts a 'Predicate' to a new type.  Typically used with visible type--- application, as in the examples below.------ >>> accept (typed @String anything) "foo"--- True--- >>> accept (typed @String (sizeIs (gt 5))) "foo"--- False--- >>> accept (typed @String anything) (42 :: Int)--- False-typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b-typed p =-  Predicate-    { showPredicate =-        showPredicate p ++ " :: " ++ show (typeRep (Proxy :: Proxy a)),-      accept = \x -> case cast x of-        Nothing -> False-        Just y -> accept p y-    }
+ src/Test/HMock/Internal/Rule.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}++-- | Internal module to define 'Rule', so that its constructor can be visible+-- to other implementation code.+module Test.HMock.Internal.Rule where++import Data.Kind (Constraint, Type)+import GHC.TypeLits (Symbol)+import {-# SOURCE #-} Test.HMock.Internal.State (MockT)+import Test.HMock.Mockable (MockableBase (..))++-- | A rule for matching a method and responding to it when it matches.+--+-- The method may be matched by providing either an 'Action' to match exactly,+-- or a 'Matcher'.  Exact matching is only available when all method arguments+--+-- A 'Rule' may have zero or more responses, which are attached using+-- 'Test.HMock.Rule.|->' and 'Test.HMock.Rule.|=>'.  If there are no responses+-- for a 'Rule', then there must be a default response for that action, and it+-- is used.  If more than one response is added, the rule will perform the+-- responses in order, repeating the last response if there are additional+-- matches.+--+-- Example:+--+-- @+-- 'Test.HMock.ExpectContext.expect' $+--   GetLine_ 'Test.HMock.anything'+--     'Test.HMock.Rule.|->' "hello"+--     'Test.HMock.Rule.|=>' \(GetLine prompt) -> "The prompt was " ++ prompt+--     'Test.HMock.Rule.|->' "quit"+-- @+data+  Rule+    (cls :: (Type -> Type) -> Constraint)+    (name :: Symbol)+    (m :: Type -> Type)+    (r :: Type)+  where+  (:=>) ::+    Matcher cls name m r ->+    [Action cls name m r -> MockT m r] ->+    Rule cls name m r
+ src/Test/HMock/Internal/State.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This module contains MockT and SetupMockT state functions.+module Test.HMock.Internal.State where++import Control.Monad (forM_, unless, (<=<))+import Control.Monad.Base (MonadBase)+import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.Cont (MonadCont)+import Control.Monad.Except (MonadError)+import Control.Monad.Extra (maybeM)+import Control.Monad.RWS (MonadRWS)+import Control.Monad.Reader (MonadReader (..), ReaderT, mapReaderT, runReaderT)+import Control.Monad.State (MonadState)+import Control.Monad.Trans (MonadTrans, lift)+import Control.Monad.Writer (MonadWriter)+import Data.Proxy (Proxy (Proxy))+import Data.Set (Set)+import qualified Data.Set as Set+import Data.Typeable (TypeRep, Typeable, typeRep)+import GHC.Stack (withFrozenCallStack)+import Test.HMock.ExpectContext (ExpectContext (..))+import Test.HMock.Internal.ExpectSet (ExpectSet (..), getSteps)+import Test.HMock.Internal.Step (SingleRule, Step (..), unwrapExpected)+import Test.HMock.Internal.Util (Located)+import Test.HMock.Mockable (Mockable (..))+import UnliftIO+  ( MonadIO,+    MonadUnliftIO,+    STM,+    TVar,+    atomically,+    modifyTVar,+    newTVarIO,+    readTVar,+    readTVarIO,+  )++#if !MIN_VERSION_base(4, 13, 0)+import Control.Monad.Fail (MonadFail)+#endif++-- | Full state of a mock.+data MockState m = MockState+  { mockExpectSet :: TVar (ExpectSet (Step m)),+    mockDefaults :: TVar [(Bool, Step m)],+    mockCheckAmbiguity :: TVar Bool,+    mockClasses :: TVar (Set TypeRep),+    mockParent :: Maybe (MockState m)+  }++-- | Initializes a new 'MockState' with the given parent.  If the parent is+-- 'Nothing', then a new root state is made.+initMockState :: MonadIO m => Maybe (MockState m) -> m (MockState m)+initMockState parent =+  MockState+    <$> newTVarIO ExpectNothing+    <*> newTVarIO []+    <*> maybeM+      (newTVarIO False)+      (newTVarIO <=< readTVarIO . mockCheckAmbiguity)+      (return parent)+    <*> maybe (newTVarIO Set.empty) (return . mockClasses) parent+    <*> pure parent++-- | Gets a list of all states, starting with the innermost.+allStates :: MockState m -> [MockState m]+allStates s+  | Just s' <- mockParent s = s : allStates s'+  | otherwise = [s]++-- | Gets the root state.+rootState :: MockState m -> MockState m+rootState = last . allStates++-- | Monad for setting up a mockable class.  Note that even though the type+-- looks that way, this is *not* a monad transformer.  It's a very restricted+-- environment that can only be used to set up defaults for a class.+newtype MockSetup m a where+  MockSetup :: {unMockSetup :: ReaderT (MockState m) STM a} -> MockSetup m a+  deriving (Functor, Applicative, Monad)++-- | Runs a setup action with the root state, rather than the current one.+runInRootState :: MockSetup m a -> MockSetup m a+runInRootState = MockSetup . local rootState . unMockSetup++-- | Run an STM action in 'MockSetup'+mockSetupSTM :: STM a -> MockSetup m a+mockSetupSTM m = MockSetup (lift m)++-- | Runs class initialization for a 'Mockable' class, if it hasn't been run+-- yet.+initClassIfNeeded ::+  forall cls m proxy.+  (Mockable cls, Typeable m, MonadIO m) =>+  proxy cls ->+  MockSetup m ()+initClassIfNeeded proxy = runInRootState $ do+  state <- MockSetup ask+  classes <- mockSetupSTM $ readTVar (mockClasses state)+  unless (Set.member t classes) $ do+    mockSetupSTM $ modifyTVar (mockClasses state) (Set.insert t)+    setupMockable (Proxy :: Proxy cls)+  where+    t = typeRep proxy++-- | Runs class initialization for all uninitialized 'Mockable' classes in the+-- given 'ExpectSet'.+initClassesAsNeeded :: MonadIO m => ExpectSet (Step m) -> MockSetup m ()+initClassesAsNeeded es = runInRootState $+  forM_ (getSteps es) $+    \(Step (_ :: Located (SingleRule cls name m r))) ->+      initClassIfNeeded (Proxy :: Proxy cls)++-- | Monad transformer for running mocks.+newtype MockT m a where+  MockT :: {unMockT :: ReaderT (MockState m) m a} -> MockT m a+  deriving+    ( Functor,+      Applicative,+      Monad,+      MonadFail,+      MonadIO,+      MonadState s,+      MonadWriter w,+      MonadRWS r w s,+      MonadError e,+      MonadCont,+      MonadBase b,+      MonadCatch,+      MonadMask,+      MonadThrow,+      MonadUnliftIO+    )++instance MonadTrans MockT where+  lift = MockT . lift++-- | Applies a function to the base monad of 'MockT'.+mapMockT :: (m a -> m b) -> MockT m a -> MockT m b+mapMockT f = MockT . mapReaderT f . unMockT++instance MonadReader r m => MonadReader r (MockT m) where+  ask = lift ask+  local = mapMockT . local+  reader = lift . reader++-- | This type class defines a shared API between the 'MockT' and 'MockSetup'+-- monads.+class MockContext ctx where+  -- | Runs a 'MockSetup' action in this monad.+  fromMockSetup :: MonadIO m => MockSetup m a -> ctx m a++instance MockContext MockSetup where+  fromMockSetup = id++instance MockContext MockT where+  fromMockSetup m = do+    state <- MockT ask+    atomically $ runReaderT (unMockSetup m) state++-- | Adds an expectation to the 'MockState' for the given 'ExpectSet',+-- interleaved with any existing expectations.+expectThisSet :: MonadIO m => ExpectSet (Step m) -> MockT m ()+expectThisSet e = fromMockSetup $ do+  initClassesAsNeeded e+  state <- MockSetup ask+  mockSetupSTM $ modifyTVar (mockExpectSet state) (e `ExpectInterleave`)++instance ExpectContext MockT where+  expect e =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ expect e+  expectN mult e =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ expectN mult e+  expectAny e =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ expectAny e+  inSequence es =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ inSequence es+  inAnyOrder es =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ inAnyOrder es+  anyOf es =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ anyOf es+  times mult es =+    withFrozenCallStack $ expectThisSet $ unwrapExpected $ times mult es+  consecutiveTimes mult es =+    withFrozenCallStack $+      expectThisSet $ unwrapExpected $ consecutiveTimes mult es
+ src/Test/HMock/Internal/State.hs-boot view
@@ -0,0 +1,18 @@+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE RoleAnnotations #-}++module Test.HMock.Internal.State where++import Data.Kind (Type)++type role MockT nominal nominal++data MockT (m :: Type -> Type) (a :: Type)++instance Monad m => Monad (MockT m)++type role MockSetup nominal nominal++data MockSetup (m :: Type -> Type) (a :: Type)++instance Monad (MockSetup m)
+ src/Test/HMock/Internal/Step.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}++-- | This module defines the desugaring from multi-response 'Rule's into+-- multiple steps.+module Test.HMock.Internal.Step where++import Data.Kind (Constraint, Type)+import Data.Maybe (listToMaybe)+import GHC.Stack (CallStack, callStack)+import GHC.TypeLits (Symbol)+import Test.HMock.ExpectContext (ExpectContext (..), MockableMethod)+import Test.HMock.Internal.ExpectSet (ExpectSet (..))+import Test.HMock.Internal.Rule (Rule (..))+import {-# SOURCE #-} Test.HMock.Internal.State (MockT)+import Test.HMock.Internal.Util (Located (..), locate, withLoc)+import Test.HMock.Mockable (MockableBase (..))+import Test.HMock.Multiplicity+  ( Multiplicity,+    anyMultiplicity,+    feasible,+    meetsMultiplicity,+  )+import Test.HMock.Rule (Expectable (toRule))++-- | A Rule that contains only a single response.  This is the target for+-- desugaring the multi-response rule format.+data+  SingleRule+    (cls :: (Type -> Type) -> Constraint)+    (name :: Symbol)+    (m :: Type -> Type)+    (r :: Type)+  where+  (:->) ::+    Matcher cls name m r ->+    Maybe (Action cls name m r -> MockT m r) ->+    SingleRule cls name m r++-- | A single step of an expectation.+data Step m where+  Step ::+    MockableMethod cls name m r =>+    Located (SingleRule cls name m r) ->+    Step m++instance Show (Step m) where+  show (Step l@(Loc _ (m :-> _))) =+    withLoc (showMatcher Nothing m <$ l)++-- | Expands a Rule into an expectation.  The expected multiplicity will be one+-- if there are no responses; otherwise one call is expected per response.+expandRule ::+  MockableMethod cls name m r =>+  CallStack ->+  Rule cls name m r ->+  ExpectSet (Step m)+expandRule callstack (m :=> []) =+  ExpectStep (Step (locate callstack (m :-> Nothing)))+expandRule callstack (m :=> rs) =+  foldr1+    ExpectSequence+    (map (ExpectStep . Step . locate callstack . (m :->) . Just) rs)++-- | Expands a Rule into an expectation, given a target multiplicity.  It is an+-- error if there are too many responses for the multiplicity.  If there are+-- too few responses, the last response will be repeated.+expandRepeatRule ::+  MockableMethod cls name m r =>+  Multiplicity ->+  CallStack ->+  Rule cls name m r ->+  ExpectSet (Step m)+expandRepeatRule mult _ (_ :=> rs)+  | not (feasible (mult - fromIntegral (length rs))) =+    error $+      show (length rs)+        ++ " responses is too many for multiplicity "+        ++ show mult+expandRepeatRule mult callstack (m :=> (r1 : r2 : rs))+  | meetsMultiplicity mult 0 = ExpectEither ExpectNothing body+  | otherwise = body+  where+    body =+      ExpectSequence+        (ExpectStep (Step (locate callstack (m :-> Just r1))))+        (expandRepeatRule (mult - 1) callstack (m :=> (r2 : rs)))+expandRepeatRule mult callstack (m :=> rs) =+  ExpectConsecutive+    mult+    (ExpectStep (Step (locate callstack (m :-> listToMaybe rs))))++-- | Newtype wrapper to make the type of ExpectSet conform to the ExpectContext+-- class.  The "return type" a is a phantom.+newtype Expected m a = Expected {unwrapExpected :: ExpectSet (Step m)}++instance ExpectContext Expected where+  expect e = Expected (expandRule callStack (toRule e))+  expectN mult e = Expected (expandRepeatRule mult callStack (toRule e))+  expectAny e =+    Expected (expandRepeatRule anyMultiplicity callStack (toRule e))+  inSequence es = Expected (foldr1 ExpectSequence (map unwrapExpected es))+  inAnyOrder es = Expected (foldr1 ExpectInterleave (map unwrapExpected es))+  anyOf es = Expected (foldr1 ExpectEither (map unwrapExpected es))+  times mult e = Expected (ExpectMulti mult (unwrapExpected e))+  consecutiveTimes mult e =+    Expected (ExpectConsecutive mult (unwrapExpected e))
src/Test/HMock/Internal/TH.hs view
@@ -1,697 +1,235 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE ExplicitNamespaces #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} +-- | Template Haskell utilities used to implement HMock. module Test.HMock.Internal.TH-  ( MockableOptions (..),-    makeMockable,-    makeMockableType,-    makeMockableWithOptions,-    makeMockableTypeWithOptions,-    makeMockableBase,-    makeMockableBaseType,-    makeMockableBaseWithOptions,-    makeMockableBaseTypeWithOptions,-    deriveMockable,-    deriveMockableType,-    deriveMockableWithOptions,-    deriveMockableTypeWithOptions,-    deriveMockableBase,-    deriveMockableBaseType,-    deriveMockableBaseWithOptions,-    deriveMockableBaseTypeWithOptions,-    deriveForMockT,-    deriveTypeForMockT,-    deriveForMockTWithOptions,-    deriveTypeForMockTWithOptions,+  ( unappliedName,+    tvName,+    bindVar,+    substTypeVar,+    substTypeVars,+    splitType,+    freeTypeVars,+    relevantContext,+    constrainVars,+    unifyTypes,+    removeModNames,+    hasPolyType,+    hasNestedPolyType,+    resolveInstance,+    simplifyContext,+    localizeMember,   ) where -import Control.Monad (replicateM, unless, when, zipWithM)-import Control.Monad.Extra (concatMapM)-import Control.Monad.Trans (MonadIO)-import Data.Bool (bool)-import Data.Char (toUpper)-import Data.Default (Default (..))-import Data.Either (partitionEithers)-import qualified Data.Kind-import Data.List (foldl', (\\))-import Data.Typeable (Typeable)-import GHC.Stack (HasCallStack)-import GHC.TypeLits (Symbol)-import Language.Haskell.TH hiding (Match, match)-import Language.Haskell.TH.Syntax (Lift (lift))-import Test.HMock-import Test.HMock.Internal.TH.Util---- | Custom options for deriving a 'Mockable' class.-data MockableOptions = MockableOptions-  { -- | Suffix to add to 'Action' and 'Matcher' names.  Defaults to @""@.-    mockSuffix :: String,-    -- | Whether to warn about limitations of the generated mocks.  This is-    -- mostly useful temporarily for finding out why generated code doesn't-    -- match your expectations.  Defaults to @'False'@.-    mockVerbose :: Bool-  }--instance Default MockableOptions where-  def = MockableOptions {mockSuffix = "", mockVerbose = False}---- | Define all instances necessary to use HMock with the given class.--- Equivalent to both 'deriveMockable' and 'deriveForMockT'.------ If @MyClass@ is a class and @myMethod@ is one of its methods, then--- @'makeMockable' MyClass@ generates all of the following:------ If @MyClass@ is a class and @myMethod@ is one of its methods, then--- @'makeMockable' MyClass@ generates everything generated by--- 'makeMockableBase', as well as a 'Mockable' instance that does no setup.-makeMockable :: Name -> Q [Dec]-makeMockable = makeMockableType . conT---- | Define all instances necessary to use HMock with the given constraint type,--- which should be a class applied to zero or more type arguments.  Equivalent--- to both 'deriveMockableType' and 'deriveTypeForMockT'.------ See 'makeMockable' for a list of what is generated by this splice.-makeMockableType :: Q Type -> Q [Dec]-makeMockableType = makeMockableTypeWithOptions def---- | Define all instances necessary to use HMock with the given class.  This is--- like 'makeMockable', but with the ability to specify custom options.------ See 'makeMockable' for a list of what is generated by this splice.-makeMockableWithOptions :: MockableOptions -> Name -> Q [Dec]-makeMockableWithOptions options = makeMockableTypeWithOptions options . conT---- | Define all instances necessary to use HMock with the given constraint type,--- which should be a class applied to zero or more type arguments.  This is--- like 'makeMockableType', but with the ability to specify custom options.------ See 'makeMockable' for a list of what is generated by this splice.-makeMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]-makeMockableTypeWithOptions options qt =-  (++) <$> deriveMockableTypeWithOptions options qt-    <*> deriveTypeForMockTWithOptions options qt---- | Defines almost all instances necessary to use HMock with the given class.--- Equivalent to both 'deriveMockableBase' and 'deriveForMockT'.-makeMockableBase :: Name -> Q [Dec]-makeMockableBase = makeMockableBaseType . conT---- | Defines almost all instances necessary to use HMock with the given--- constraint type, which should be a class applied to zero or more type--- arguments.  Equivalent to both 'deriveMockableBaseType' and--- 'deriveTypeForMockT'.-makeMockableBaseType :: Q Type -> Q [Dec]-makeMockableBaseType = makeMockableBaseTypeWithOptions def---- | Defines almost all instances necessary to use HMock with the given class.--- This is like 'makeMockable', but with the ability to specify custom options.-makeMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]-makeMockableBaseWithOptions options =-  makeMockableBaseTypeWithOptions options . conT---- | Defines almost all instances necessary to use HMock with the given--- constraint type, which should be a class applied to zero or more type--- arguments.  This is like 'makeMockableType', but with the ability to specify--- custom options.-makeMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]-makeMockableBaseTypeWithOptions options qt =-  (++) <$> deriveMockableBaseTypeWithOptions options qt-    <*> deriveTypeForMockTWithOptions options qt---- | Defines the 'Mockable' instance for the given class.------ If @MyClass@ is a class and @myMethod@ is one of its methods, then--- @'deriveMockable' MyClass@ generates everything generated by--- 'makeMockableBase', as well as a 'Mockable' instance that does no setup.-deriveMockable :: Name -> Q [Dec]-deriveMockable = deriveMockableType . conT---- | Defines the 'Mockable' instance for the given constraint type, which should--- be a class applied to zero or more type arguments.------ See 'deriveMockable' for a list of what is generated by this splice.-deriveMockableType :: Q Type -> Q [Dec]-deriveMockableType = deriveMockableTypeWithOptions def---- | Defines the 'Mockable' instance for the given class.  This is like--- 'deriveMockable', but with the ability to specify custom options.------ See 'deriveMockable' for a list of what is generated by this splice.-deriveMockableWithOptions :: MockableOptions -> Name -> Q [Dec]-deriveMockableWithOptions options = deriveMockableTypeWithOptions options . conT---- | Defines the 'Mockable' instance for the given constraint type, which should--- be a class applied to zero or more type arguments.  This is like--- 'deriveMockableType', but with the ability to specify custom options.------ See 'deriveMockable' for a list of what is generated by this splice.-deriveMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]-deriveMockableTypeWithOptions = deriveMockableImpl False---- | Defines the 'MockableBase' instance for the given class.------ If @MyClass@ is a class and @myMethod@ is one of its methods, then--- @'deriveMockableBase' MyClass@ generates all of the following:------ * A @'MockableBase' MyClass@ instance.--- * An associated type @'Action' MyClass@, with a constructor @MyMethod@.--- * An associated type @'Matcher' MyClass@, with a constructor @MyMethod_@.--- * An 'Expectable' instance for @'Action' MyClass@ which matches an exact set---   of arguments, if and only if all of @myMethod@'s arguments have 'Eq' and---   'Show' instances.-deriveMockableBase :: Name -> Q [Dec]-deriveMockableBase = deriveMockableBaseType . conT---- | Defines the 'MockableBase' instance for the given constraint type, which--- should be a class applied to zero or more type arguments.------ See 'deriveMockableBase' for a list of what is generated by this splice.-deriveMockableBaseType :: Q Type -> Q [Dec]-deriveMockableBaseType = deriveMockableBaseTypeWithOptions def---- | Defines the 'MockableBase' instance for the given class.  This is like--- 'deriveMockableBase', but with the ability to specify custom options.------ See 'deriveMockableBase' for a list of what is generated by this splice.-deriveMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]-deriveMockableBaseWithOptions options =-  deriveMockableBaseTypeWithOptions options . conT---- | Defines the 'MockableBase' instance for the given constraint type, which--- should be a class applied to zero or more type arguments.  This is like--- 'deriveMockableBaseType', but with the ability to specify custom options.------ See 'deriveMockableBase' for a list of what is generated by this splice.-deriveMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]-deriveMockableBaseTypeWithOptions = deriveMockableImpl True---- | Defines an instance of the given class for @'MockT' m@, delegating all of--- its methods to 'mockMethod' to be handled by HMock.------ This may only be used if all members of the class are mockable methods.  If--- the class contains some unmockable methods, associated types, or other--- members, you will need to define this instance yourself, delegating the--- mockable methods as follows:------ @--- instance MyClass ('MockT' m) where---   myMethod x y = 'mockMethod' (MyMethod x y)---   ...--- @-deriveForMockT :: Name -> Q [Dec]-deriveForMockT = deriveTypeForMockT . conT---- | Defines an instance of the given constraint type for @'MockT' m@,--- delegating all of its methods to 'mockMethod' to be handled by HMock.--- The type should be a class applied to zero or more type arguments.------ See 'deriveForMockT' for restrictions on the use of this splice.-deriveTypeForMockT :: Q Type -> Q [Dec]-deriveTypeForMockT = deriveTypeForMockTWithOptions def---- | Defines an instance of the given class for @'MockT' m@, delegating all of--- its methods to 'mockMethod' to be handled by HMock.  This is like--- 'deriveForMockT', but with the ability to specify custom options.------ See 'deriveForMockT' for restrictions on the use of this splice.-deriveForMockTWithOptions :: MockableOptions -> Name -> Q [Dec]-deriveForMockTWithOptions options = deriveTypeForMockTWithOptions options . conT---- | Defines an instance of the given constraint type for @'MockT' m@,--- delegating all of its methods to 'mockMethod' to be handled by HMock.--- The type should be a class applied to zero or more type arguments.  This is--- like 'deriveTypeForMockT', but with the ability to specify custom options.------ See 'deriveForMockT' for restrictions on the use of this splice.-deriveTypeForMockTWithOptions :: MockableOptions -> Q Type -> Q [Dec]-deriveTypeForMockTWithOptions = deriveForMockTImpl--data Instance = Instance-  { instType :: Type,-    instRequiredContext :: Cxt,-    instGeneralParams :: [Name],-    instMonadVar :: Name,-    instMethods :: [Method],-    instExtraMembers :: [Dec]-  }-  deriving (Show)--data Method = Method-  { methodName :: Name,-    methodTyVars :: [Name],-    methodCxt :: Cxt,-    methodArgs :: [Type],-    methodResult :: Type-  }-  deriving (Show)--withClass :: Type -> (Dec -> Q a) -> Q a-withClass t f = do-  case unappliedName t of-    Just cls -> do-      info <- reify cls-      case info of-        ClassI dec@ClassD {} _ -> f dec-        _ -> fail $ "Expected " ++ show cls ++ " to be a class, but it wasn't."-    _ -> fail "Expected a class, but got something else."--getInstance :: MockableOptions -> Type -> Q Instance-getInstance options ty = withClass ty go-  where-    go (ClassD _ className [] _ _) =-      fail $ "Class " ++ nameBase className ++ " has no type parameters."-    go (ClassD cx _ params _ members) = matchVars ty [] (tvName <$> params)-      where-        matchVars :: Type -> [Type] -> [Name] -> Q Instance-        matchVars _ _ [] = internalError-        matchVars (AppT _ _) _ [_] =-          fail $ pprint ty ++ " is applied to too many arguments."-        matchVars (AppT a b) ts (_ : ps) =-          checkExt FlexibleInstances >> matchVars a (b : ts) ps-        matchVars _ ts ps = do-          let t = foldl' (\t' v -> AppT t' (VarT v)) ty (init ps)-          let tbl = zip (tvName <$> params) ts-          let cx' = substTypeVars tbl <$> cx-          makeInstance options t cx' tbl (init ps) (last ps) members-    go _ = internalError--makeInstance ::-  MockableOptions ->-  Type ->-  Cxt ->-  [(Name, Type)] ->-  [Name] ->-  Name ->-  [Dec] ->-  Q Instance-makeInstance options ty cx tbl ps m members = do-  processedMembers <- mapM (getMethod ty m tbl) members-  (extraMembers, methods) <--    partitionEithers <$> zipWithM memberOrMethod members processedMembers-  return $-    Instance-      { instType = ty,-        instRequiredContext = cx,-        instGeneralParams = ps,-        instMonadVar = m,-        instMethods = methods,-        instExtraMembers = extraMembers-      }-  where-    memberOrMethod :: Dec -> Either String Method -> Q (Either Dec Method)-    memberOrMethod dec (Left warning) = do-      when (mockVerbose options) $ reportWarning warning-      return (Left dec)-    memberOrMethod _ (Right method) = return (Right method)--getMethod :: Type -> Name -> [(Name, Type)] -> Dec -> Q (Either String Method)-getMethod instTy m tbl (SigD name ty) = do-  simpleTy <- localizeMember instTy m (substTypeVars tbl ty)-  return $ do-    let (tvs, cx, argsAndReturn) = splitType simpleTy-    (m', result) <- case last argsAndReturn of-      AppT (VarT m') result -> return (m', result)-      _ ->-        Left $-          nameBase name-            ++ " can't be mocked: non-monadic result."-    when (m' /= m) $-      Left $-        nameBase name-          ++ " can't be mocked: return value in wrong monad."-    when (relevantContext result (tvs, cx) /= ([], [])) $-      Left $-        nameBase name-          ++ " can't be mocked: polymorphic return value."-    let argTypes =-          map-            (substTypeVar m (AppT (ConT ''MockT) (VarT m)))-            (init argsAndReturn)-    when (any hasNestedPolyType argTypes) $-      Left $-        nameBase name-          ++ " can't be mocked: rank-n types nested in arguments."-    return $-      Method-        { methodName = name,-          methodTyVars = tvs,-          methodCxt = cx,-          methodArgs = argTypes,-          methodResult = result-        }-getMethod _ _ _ _ = return (Left "A non-value member cannot be mocked.")--isKnownType :: Method -> Type -> Bool-isKnownType method ty = null tyVars && null cx-  where-    (tyVars, cx) =-      relevantContext ty (methodTyVars method, methodCxt method)+import Control.Monad.Extra (mapMaybeM)+import Data.Generics+import Data.List ((\\))+import Data.Maybe (catMaybes, fromMaybe)+import Language.Haskell.TH+import Language.Haskell.TH.Syntax (NameFlavour (..))+import Test.HMock.Internal.Util (choices) -withMethodParams :: Instance -> Method -> TypeQ -> TypeQ-withMethodParams inst method t =-  [t|-    $t-      $(pure (instType inst))-      $(litT (strTyLit (nameBase (methodName method))))-      $(varT (instMonadVar inst))-      $(pure (methodResult method))-    |]+#if MIN_VERSION_template_haskell(2,17,0) -deriveMockableImpl :: Bool -> MockableOptions -> Q Type -> Q [Dec]-deriveMockableImpl baseOnly options qt = do-  checkExt DataKinds-  checkExt FlexibleInstances-  checkExt GADTs-  checkExt MultiParamTypeClasses-  checkExt TypeFamilies+-- | Fetches the 'Name' of a 'TyVarBndr'.+tvName :: TyVarBndr flag -> Name+tvName (PlainTV name _) = name+tvName (KindedTV name _ _) = name -  inst <- getInstance options =<< qt+-- | Creates a 'TyVarBndr' for a plain variable without a kind annotation.+bindVar :: Name -> TyVarBndr Specificity+bindVar n = PlainTV n SpecifiedSpec -  when (null (instMethods inst)) $ do-    fail $-      "Cannot derive Mockable because " ++ pprint (instType inst)-        ++ " has no mockable methods."+#else -  typeableCxts <- constrainVars [conT ''Typeable] (instGeneralParams inst)+-- | Fetches the 'Name' of a 'TyVarBndr'.+tvName :: TyVarBndr -> Name+tvName (PlainTV name) = name+tvName (KindedTV name _) = name -  mockableBase <--    instanceD-      (pure typeableCxts)-      [t|MockableBase $(pure (instType inst))|]-      [ defineActionType options inst,-        defineMatcherType options inst,-        defineShowAction options (instMethods inst),-        defineShowMatcher options (instMethods inst),-        defineMatchAction options (instMethods inst)-      ]-  mockable <--    if baseOnly-      then return []-      else-        (: [])-          <$> instanceD-            (pure typeableCxts)-            [t|Mockable $(pure (instType inst))|]-            []-  expectables <- defineExpectableActions options inst+-- | Creates a 'TyVarBndr' for a plain variable without a kind annotation.+bindVar :: Name -> TyVarBndr+bindVar = PlainTV -  return $ mockableBase : mockable ++ expectables+#endif -defineActionType :: MockableOptions -> Instance -> DecQ-defineActionType options inst = do-  kind <--    [t|-      Symbol ->-      (Data.Kind.Type -> Data.Kind.Type) ->-      Data.Kind.Type ->-      Data.Kind.Type-      |]-  let cons = actionConstructor options inst <$> instMethods inst-  dataInstD (pure []) ''Action [pure (instType inst)] (Just kind) cons []+-- | Gets the unapplied top-level name from a type application.+unappliedName :: Type -> Maybe Name+unappliedName (AppT a _) = unappliedName a+unappliedName (ConT a) = Just a+unappliedName _ = Nothing -actionConstructor :: MockableOptions -> Instance -> Method -> ConQ-actionConstructor options inst method = do-  forallC [] (return (methodCxt method)) $-    gadtC-      [getActionName options method]-      [ return (Bang NoSourceUnpackedness NoSourceStrictness, argTy)-        | argTy <- methodArgs method-      ]-      (withMethodParams inst method [t|Action|])+-- | Substitutes a 'Type' for all occurrences of the given 'Name'.+substTypeVar :: Name -> Type -> Type -> Type+substTypeVar n t = substTypeVars [(n, t)] -getActionName :: MockableOptions -> Method -> Name-getActionName options method =-  mkName (map toUpper (take 1 name) ++ drop 1 name ++ mockSuffix options)+-- | Makes variable substitutions from the given table.+substTypeVars :: [(Name, Type)] -> Type -> Type+substTypeVars classVars = everywhere (mkT subst)   where-    name = nameBase (methodName method)--defineMatcherType :: MockableOptions -> Instance -> Q Dec-defineMatcherType options inst = do-  kind <--    [t|-      Symbol ->-      (Data.Kind.Type -> Data.Kind.Type) ->-      Data.Kind.Type ->-      Data.Kind.Type-      |]-  let cons = matcherConstructor options inst <$> instMethods inst-  dataInstD (pure []) ''Matcher [pure (instType inst)] (Just kind) cons []+    subst (VarT x) | Just t <- lookup x classVars = t+    subst t = t -matcherConstructor :: MockableOptions -> Instance -> Method -> ConQ-matcherConstructor options inst method = do-  gadtC-    [getMatcherName options method]-    [ (Bang NoSourceUnpackedness NoSourceStrictness,) <$> mkPredicate argTy-      | argTy <- methodArgs method-    ]-    (withMethodParams inst method [t|Matcher|])-  where-    mkPredicate argTy-      | hasPolyType argTy = do-        checkExt RankNTypes-        v <- newName "t"-        forallT [bindVar v] (pure []) [t|Predicate $(varT v)|]-      | null tyVars && null cx = [t|Predicate $(pure argTy)|]-      | otherwise = do-        checkExt RankNTypes-        forallT (bindVar <$> tyVars) (pure cx) [t|Predicate $(pure argTy)|]-      where-        (tyVars, cx) =-          relevantContext argTy (methodTyVars method, methodCxt method)+-- | Splits a function type into a list of bound type vars, context, and+-- parameters and return value.  The return value is the last element of the+-- list.+splitType :: Type -> ([Name], Cxt, [Type])+splitType (ForallT tv cx b) =+  let (tvs, cxs, parts) = splitType b+   in (map tvName tv ++ tvs, cx ++ cxs, parts)+splitType (AppT (AppT ArrowT a) b) =+  let (tvs, cx, parts) = splitType b in (tvs, cx, a : parts)+splitType r = ([], [], [r]) -getMatcherName :: MockableOptions -> Method -> Name-getMatcherName options method =-  mkName (map toUpper (take 1 name) ++ drop 1 name ++ mockSuffix options ++ "_")+-- | Gets all free type variable 'Name's in the given 'Type'.+freeTypeVars :: Type -> [Name]+freeTypeVars = everythingWithContext [] (++) (mkQ ([],) go)   where-    name = nameBase (methodName method)+    go (VarT v) bound+      | v `elem` bound = ([], bound)+      | otherwise = ([v], bound)+    go (ForallT vs _ _) bound = ([], map tvName vs ++ bound)+    go _ bound = ([], bound) -defineShowAction :: MockableOptions -> [Method] -> Q Dec-defineShowAction options methods =-  funD 'showAction (showActionClause options <$> methods)+-- | Produces a 'CxtQ' that gives all given variable 'Name's all of the given+-- class 'Type's.+constrainVars :: [TypeQ] -> [Name] -> CxtQ+constrainVars cs vs = sequence [appT c (varT v) | c <- cs, v <- vs] -showActionClause :: MockableOptions -> Method -> Q Clause-showActionClause options method = do-  argVars <- replicateM (length (methodArgs method)) (newName "a")-  clause-    [ conP-        (getActionName options method)-        (zipWith argPattern (methodArgs method) argVars)-    ]-    ( normalB-        [|-          unwords-            ( $(lift (nameBase (methodName method))) :-              $(listE (zipWith showArg (methodArgs method) argVars))-            )-          |]-    )-    []+-- | Culls the given binders and constraints to choose only those that apply to+-- free variables in the given type.+relevantContext :: Type -> ([Name], Cxt) -> ([Name], Cxt)+relevantContext ty (tvs, cx) = (filter needsTv tvs, filteredCx)   where-    canShow ty-      | not (null (freeTypeVars ty)) = return False-      | otherwise = isInstance ''Show [ty]-    argPattern ty v = canShow ty >>= bool wildP (varP v)-    showArg ty var =-      canShow ty-        >>= bool-          (lift ("(_ :: " ++ pprint (removeModNames ty) ++ ")"))-          [|showsPrec 11 $(varE var) ""|]--defineShowMatcher :: MockableOptions -> [Method] -> Q Dec-defineShowMatcher options methods = do-  clauses <- concatMapM (showMatcherClauses options) methods-  funD 'showMatcher clauses+    filteredCx = filter (any (`elem` freeTypeVars ty) . freeTypeVars) cx+    needsTv v = any ((v `elem`) . freeTypeVars) (ty : filteredCx) -showMatcherClauses :: MockableOptions -> Method -> Q [ClauseQ]-showMatcherClauses options method = do-  argTVars <- replicateM (length (methodArgs method)) (newName "t")-  predVars <- replicateM (length (methodArgs method)) (newName "p")-  let actionArgs = zipWith actionArg argTVars (methodArgs method)-  let matcherArgs = varP <$> predVars-  let printedArgs = zipWith3 printedArg predVars argTVars (methodArgs method)-  let polyMatcherArgs = zipWith matcherArg predVars (methodArgs method)-  let printedPolyArgs = zipWith printedPolyArg predVars (methodArgs method)-  let body name args = normalB [|unwords ($(lift name) : $(listE args))|]-  return-    [ clause-        [ conP 'Just [conP (getActionName options method) actionArgs],-          conP (getMatcherName options method) matcherArgs-        ]-        (body (nameBase (methodName method)) printedArgs)-        [],-      clause-        [ conP 'Nothing [],-          conP (getMatcherName options method) polyMatcherArgs-        ]-        (body (nameBase (methodName method)) printedPolyArgs)-        []-    ]+-- | Attempts to unify the given types by constructing a table of substitutions+-- for the variables of the left type that obtain the right one.+unifyTypes :: Type -> Type -> Q (Maybe [(Name, Type)])+unifyTypes = unifyTypesWith []   where-    actionArg t ty-      | isKnownType method ty = wildP-      | otherwise = checkExt ScopedTypeVariables >> sigP wildP (varT t)+    unifyTypesWith :: [(Name, Type)] -> Type -> Type -> Q (Maybe [(Name, Type)])+    unifyTypesWith tbl (VarT v) t2+      | Just t1 <- lookup v tbl = unifyTypesWith tbl t1 t2+      | otherwise = return (Just ((v, t2) : tbl))+    unifyTypesWith tbl (ConT a) (ConT b) | a == b = return (Just tbl)+    unifyTypesWith tbl a b = do+      mbA <- replaceSyn a+      mbB <- replaceSyn b+      case (mbA, mbB) of+        (Nothing, Nothing) -> unifyGen tbl a b+        _ -> unifyTypesWith tbl (fromMaybe a mbA) (fromMaybe b mbB) -    matcherArg p ty-      | isKnownType method ty = varP p-      | otherwise = wildP+    replaceSyn :: Type -> Q (Maybe Type)+    replaceSyn (ConT n) = do+      info <- reify n+      case info of+        TyConI (TySynD _ [] t) -> return (Just t)+        _ -> return Nothing+    replaceSyn _ = return Nothing -    printedArg p t ty-      | isKnownType method ty = [|"«" ++ show $(varE p) ++ "»"|]-      | otherwise =-        [|"«" ++ show ($(varE p) :: Predicate $(varT t)) ++ "»"|]+    unifyGen ::+      (Data a, Data b) => [(Name, Type)] -> a -> b -> Q (Maybe [(Name, Type)])+    unifyGen tbl a b+      | toConstr a == toConstr b =+        compose (gzipWithQ (\a' b' tbl' -> unify tbl' a' b') a b) tbl+      | otherwise = return Nothing -    printedPolyArg p ty-      | isKnownType method ty = [|"«" ++ show $(varE p) ++ "»"|]-      | otherwise = [|"«polymorphic»"|]+    unify ::+      (Data a, Data b) => [(Name, Type)] -> a -> b -> Q (Maybe [(Name, Type)])+    unify tbl a b = do+      case (cast a, cast b) of+        (Just a', Just b') -> unifyTypesWith tbl a' b'+        _ -> unifyGen tbl a b -defineMatchAction :: MockableOptions -> [Method] -> Q Dec-defineMatchAction options methods =-  funD 'matchAction (matchActionClause options <$> methods)+    compose :: Monad m => [t -> m (Maybe t)] -> t -> m (Maybe t)+    compose [] x = return (Just x)+    compose (f : fs) x = do+      y <- f x+      case y of+        Just y' -> compose fs y'+        _ -> return Nothing -matchActionClause :: MockableOptions -> Method -> Q Clause-matchActionClause options method = do-  argVars <--    replicateM-      (length (methodArgs method))-      ((,) <$> newName "p" <*> newName "a")-  mmVar <- newName "mismatches"-  clause-    [ conP-        (getMatcherName options method)-        (varP . fst <$> argVars),-      conP (getActionName options method) (varP . snd <$> argVars)-    ]-    ( guardedB-        [ (,) <$> normalG [|$(varE mmVar) == 0|] <*> [|Match|],-          (,) <$> normalG [|otherwise|] <*> [|NoMatch $(varE mmVar)|]-        ]-    )-    [ valD-        (varP mmVar)-        (normalB [|length (filter not $(listE (mkAccept <$> argVars)))|])-        []-    ]+-- | Removes all module names from 'Name's in the given value, so that it will+-- pretty-print more cleanly.+removeModNames :: Data a => a -> a+removeModNames = everywhere (mkT unMod)   where-    mkAccept (p, a) = [|accept $(return (VarE p)) $(return (VarE a))|]+    unMod NameG {} = NameS+    unMod other = other -defineExpectableActions :: MockableOptions -> Instance -> Q [Dec]-defineExpectableActions options inst =-  concatMapM (defineExpectableAction options inst) (instMethods inst)+-- | Determines if there is a polytype nested anywhere in the given type.+-- Top-level quantification doesn't count.+hasNestedPolyType :: Type -> Bool+hasNestedPolyType (ForallT _ _ t) = hasPolyType t+hasNestedPolyType t = hasPolyType t -defineExpectableAction :: MockableOptions -> Instance -> Method -> Q [Dec]-defineExpectableAction options inst method = do-  maybeCxt <- wholeCxt (methodArgs method)-  argVars <- replicateM (length (methodArgs method)) (newName "a")-  case maybeCxt of-    Just cx -> do-      (: [])-        <$> instanceD-          (pure (methodCxt method ++ cx))-          ( appT-              (withMethodParams inst method [t|Expectable|])-              (withMethodParams inst method [t|Action|])-          )-          [ funD-              'toRule-              [ clause-                  [conP (getActionName options method) (map varP argVars)]-                  ( normalB $-                      let matcherCon = conE (getMatcherName options method)-                       in appE (varE 'toRule) (makeBody argVars matcherCon)-                  )-                  []-              ]-          ]-    _ -> pure []+-- | Determines if this is a polytype, including top-level quantification.+hasPolyType :: Type -> Bool+hasPolyType = everything (||) (mkQ False isPolyType)   where-    makeBody [] e = e-    makeBody (v : vs) e = makeBody vs [|$e (eq $(varE v))|]--    wholeCxt :: [Type] -> Q (Maybe Cxt)-    wholeCxt (ty : ts) = do-      thisCxt <- argCxt ty-      otherCxt <- wholeCxt ts-      return ((++) <$> thisCxt <*> otherCxt)-    wholeCxt [] = return (Just [])--    argCxt :: Type -> Q (Maybe Cxt)-    argCxt argTy-      | not (isKnownType method argTy) = return Nothing-      | VarT v <- argTy =-        Just <$> sequence [[t|Eq $(varT v)|], [t|Show $(varT v)|]]-      | otherwise = do-        eqCxt <- resolveInstance ''Eq argTy-        showCxt <- resolveInstance ''Show argTy-        return ((++) <$> eqCxt <*> showCxt)--deriveForMockTImpl :: MockableOptions -> Q Type -> Q [Dec]-deriveForMockTImpl options qt = do-  inst <- getInstance options =<< qt--  unless (null (instExtraMembers inst)) $-    fail $-      "Cannot derive MockT because " ++ pprint (instType inst)-        ++ " has unmockable methods."--  m <- newName "m"-  let decs = map (implementMethod options) (instMethods inst)--  let cx =-        instRequiredContext inst-          \\ [ AppT (ConT ''Typeable) (VarT (instMonadVar inst)),-               AppT (ConT ''Functor) (VarT (instMonadVar inst)),-               AppT (ConT ''Applicative) (VarT (instMonadVar inst)),-               AppT (ConT ''Monad) (VarT (instMonadVar inst)),-               AppT (ConT ''MonadIO) (VarT (instMonadVar inst))-             ]--  simplifyContext-    (substTypeVar (instMonadVar inst) (AppT (ConT ''MockT) (VarT m)) <$> cx)-    >>= \case-      Just cxMockT ->-        (: [])-          <$> instanceD-            ( concat-                <$> sequence-                  [ return cxMockT,-                    constrainVars [[t|Typeable|]] (instGeneralParams inst),-                    constrainVars [[t|Typeable|], [t|MonadIO|]] [m]-                  ]-            )-            [t|$(pure (instType inst)) (MockT $(varT m))|]-            decs-      Nothing -> fail "Missing MockT instance for a superclass."+    isPolyType (ForallT tvs _ _) = not (null tvs)+    isPolyType _ = False -implementMethod :: MockableOptions -> Method -> Q Dec-implementMethod options method = do-  argVars <- replicateM (length (methodArgs method)) (newName "a")-  funD-    (methodName method)-    [clause (varP <$> argVars) (normalB (body argVars)) []]+-- | Attempts to produce sufficient constraints for the given 'Type' to be an+-- instance of the given class 'Name'.+resolveInstance :: Name -> Type -> Q (Maybe Cxt)+resolveInstance cls t@(VarT _) = return (Just [AppT (ConT cls) t])+resolveInstance cls t = do+  decs <- reifyInstances cls [t]+  result <- traverse (tryInstance t) decs+  case catMaybes result of+    [cx] -> return (Just (filter (not . null . freeTypeVars) cx))+    _ -> return Nothing   where-    actionExp [] e = e-    actionExp (v : vs) e = actionExp vs [|$e $(varE v)|]+    tryInstance :: Type -> InstanceDec -> Q (Maybe Cxt)+    tryInstance actualTy (InstanceD _ cx (AppT (ConT cls') genTy) _)+      | cls' == cls =+        unifyTypes genTy actualTy >>= \case+          Just tbl ->+            let cx' = substTypeVars tbl <$> cx+             in fmap concat . sequence <$> mapM resolveInstanceType cx'+          Nothing -> return Nothing+    tryInstance _ _ = return Nothing -    body argVars = do-      defaultCxt <- resolveInstance ''Default (methodResult method)-      let someMockMethod = case defaultCxt of-            Just [] -> [|mockMethod|]-            _ -> [|mockDefaultlessMethod|]-      [|-        $someMockMethod-          $(actionExp argVars (conE (getActionName options method)))-        |]+    resolveInstanceType :: Type -> Q (Maybe Cxt)+    resolveInstanceType (AppT (ConT cls') t') = resolveInstance cls' t'+    resolveInstanceType _ = return Nothing -checkExt :: Extension -> Q ()-checkExt e = do-  enabled <- isExtEnabled e-  unless enabled $-    fail $ "Please enable " ++ show e ++ " to generate this mock."+-- | Simplifies a context with complex types (requiring FlexibleContexts) to try+-- to obtain one with all constraints applied to variables.+simplifyContext :: Cxt -> Q (Maybe Cxt)+simplifyContext (AppT (ConT cls) t : preds) = resolveInstance cls t >>= \case+  Just cxt' -> fmap (cxt' ++) <$> simplifyContext preds+  Nothing -> return Nothing+simplifyContext (otherPred : preds) = fmap (otherPred :) <$> simplifyContext preds+simplifyContext [] = return (Just []) -internalError :: HasCallStack => Q a-internalError = error "Internal error in HMock.  Please report this as a bug."+-- | Remove instance context from a method.+--+-- Some GHC versions report class members including the instance context (for+-- example, @show :: Show a => a -> String@, instead of @show :: a -> String@).+-- This looks for the instance context, and substitutes if needed to eliminate+-- it.+localizeMember :: Type -> Name -> Type -> Q Type+localizeMember instTy m t@(ForallT tvs cx ty) = do+  let fullConstraint = AppT instTy (VarT m)+  let unifyLeft (c, cs) = fmap (,cs) <$> unifyTypes c fullConstraint+  results <- mapMaybeM unifyLeft (choices cx)+  case results of+    ((tbl, remainingCx) : _) -> do+      let cx' = substTypeVars tbl <$> remainingCx+          ty' = substTypeVars tbl ty+          (tvs', cx'') =+            relevantContext+              ty'+              ((tvName <$> tvs) \\ (fst <$> tbl), cx')+          t'+            | null tvs' && null cx'' = ty'+            | otherwise = ForallT (bindVar <$> tvs') cx'' ty'+      return t'+    _ -> return t+localizeMember _ _ t = return t
− src/Test/HMock/Internal/TH/Util.hs
@@ -1,208 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TupleSections #-}--module Test.HMock.Internal.TH.Util-  ( unappliedName,-    tvName,-    bindVar,-    substTypeVar,-    substTypeVars,-    splitType,-    freeTypeVars,-    relevantContext,-    constrainVars,-    unifyTypes,-    removeModNames,-    hasPolyType,-    hasNestedPolyType,-    resolveInstance,-    simplifyContext,-    localizeMember,-  )-where--import Control.Monad.Extra (mapMaybeM)-import Data.Generics-import Data.List ((\\))-import Data.Maybe (catMaybes, fromMaybe)-import Language.Haskell.TH-import Language.Haskell.TH.Syntax (NameFlavour (..))-import Test.HMock.Internal.Util (choices)--#if MIN_VERSION_template_haskell(2,17,0)--tvName :: TyVarBndr flag -> Name-tvName (PlainTV name _) = name-tvName (KindedTV name _ _) = name--bindVar :: Name -> TyVarBndr Specificity-bindVar n = PlainTV n SpecifiedSpec--#else--tvName :: TyVarBndr -> Name-tvName (PlainTV name) = name-tvName (KindedTV name _) = name--bindVar :: Name -> TyVarBndr-bindVar = PlainTV--#endif--unappliedName :: Type -> Maybe Name-unappliedName (AppT a _) = unappliedName a-unappliedName (ConT a) = Just a-unappliedName _ = Nothing--substTypeVar :: Name -> Type -> Type -> Type-substTypeVar n t = substTypeVars [(n, t)]--substTypeVars :: [(Name, Type)] -> Type -> Type-substTypeVars classVars = everywhere (mkT subst)-  where-    subst (VarT x) | Just t <- lookup x classVars = t-    subst t = t--splitType :: Type -> ([Name], Cxt, [Type])-splitType (ForallT tv cx b) =-  let (tvs, cxs, parts) = splitType b-   in (map tvName tv ++ tvs, cx ++ cxs, parts)-splitType (AppT (AppT ArrowT a) b) =-  let (tvs, cx, parts) = splitType b in (tvs, cx, a : parts)-splitType r = ([], [], [r])--freeTypeVars :: Type -> [Name]-freeTypeVars = everythingWithContext [] (++) (mkQ ([],) go)-  where-    go (VarT v) bound-      | v `elem` bound = ([], bound)-      | otherwise = ([v], bound)-    go (ForallT vs _ _) bound = ([], map tvName vs ++ bound)-    go _ bound = ([], bound)--constrainVars :: [TypeQ] -> [Name] -> CxtQ-constrainVars cs vs = sequence [appT c (varT v) | c <- cs, v <- vs]--relevantContext :: Type -> ([Name], Cxt) -> ([Name], Cxt)-relevantContext ty (tvs, cx) = (filter needsTv tvs, filteredCx)-  where-    filteredCx = filter (any (`elem` freeTypeVars ty) . freeTypeVars) cx-    needsTv v = any ((v `elem`) . freeTypeVars) (ty : filteredCx)--unifyTypes :: Type -> Type -> Q (Maybe [(Name, Type)])-unifyTypes = unifyTypesWith []--unifyTypesWith :: [(Name, Type)] -> Type -> Type -> Q (Maybe [(Name, Type)])-unifyTypesWith tbl (VarT v) t2-  | Just t1 <- lookup v tbl = unifyTypesWith tbl t1 t2-  | otherwise = return (Just ((v, t2) : tbl))-unifyTypesWith tbl (ConT a) (ConT b) | a == b = return (Just tbl)-unifyTypesWith tbl a b = do-  mbA <- replaceSyn a-  mbB <- replaceSyn b-  case (mbA, mbB) of-    (Nothing, Nothing) -> unifyGen tbl a b-    _ -> unifyTypesWith tbl (fromMaybe a mbA) (fromMaybe b mbB)--replaceSyn :: Type -> Q (Maybe Type)-replaceSyn (ConT n) = do-  info <- reify n-  case info of-    TyConI (TySynD _ [] t) -> return (Just t)-    _ -> return Nothing-replaceSyn _ = return Nothing--unifyGen ::-  (Data a, Data b) => [(Name, Type)] -> a -> b -> Q (Maybe [(Name, Type)])-unifyGen tbl a b-  | toConstr a == toConstr b =-    compose (gzipWithQ (\a' b' tbl' -> unify tbl' a' b') a b) tbl-  | otherwise = return Nothing--unify ::-  (Data a, Data b) => [(Name, Type)] -> a -> b -> Q (Maybe [(Name, Type)])-unify tbl a b = do-  case (cast a, cast b) of-    (Just a', Just b') -> unifyTypesWith tbl a' b'-    _ -> unifyGen tbl a b--compose :: Monad m => [t -> m (Maybe t)] -> t -> m (Maybe t)-compose [] x = return (Just x)-compose (f : fs) x = do-  y <- f x-  case y of-    Just y' -> compose fs y'-    _ -> return Nothing--removeModNames :: Data a => a -> a-removeModNames = everywhere (mkT unMod)-  where-    unMod NameG {} = NameS-    unMod other = other--hasNestedPolyType :: Type -> Bool-hasNestedPolyType (ForallT _ _ t) = hasPolyType t-hasNestedPolyType t = hasPolyType t--hasPolyType :: Type -> Bool-hasPolyType = everything (||) (mkQ False isPolyType)-  where-    isPolyType (ForallT tvs _ _) = not (null tvs)-    isPolyType _ = False--resolveInstance :: Name -> Type -> Q (Maybe Cxt)-resolveInstance cls t@(VarT _) = return (Just [AppT (ConT cls) t])-resolveInstance cls t = do-  decs <- reifyInstances cls [t]-  result <- traverse (tryInstance t) decs-  case catMaybes result of-    [cx] -> return (Just (filter (not . null . freeTypeVars) cx))-    _ -> return Nothing-  where-    tryInstance :: Type -> InstanceDec -> Q (Maybe Cxt)-    tryInstance actualTy (InstanceD _ cx (AppT (ConT cls') genTy) _)-      | cls' == cls =-        unifyTypes genTy actualTy >>= \case-          Just tbl ->-            let cx' = substTypeVars tbl <$> cx-             in fmap concat . sequence <$> mapM resolveInstanceType cx'-          Nothing -> return Nothing-    tryInstance _ _ = return Nothing--    resolveInstanceType :: Type -> Q (Maybe Cxt)-    resolveInstanceType (AppT (ConT cls') t') = resolveInstance cls' t'-    resolveInstanceType _ = return Nothing--simplifyContext :: Cxt -> Q (Maybe Cxt)-simplifyContext (AppT (ConT cls) t : preds) = resolveInstance cls t >>= \case-  Just cxt' -> fmap (cxt' ++) <$> simplifyContext preds-  Nothing -> return Nothing-simplifyContext (otherPred : preds) = fmap (otherPred :) <$> simplifyContext preds-simplifyContext [] = return (Just [])---- | Remove instance context from a method.------ Some GHC versions report class members including the instance context (for--- example, @show :: Show a => a -> String@, instead of @show :: a -> String@).--- This looks for the instance context, and substitutes if needed to eliminate--- it.-localizeMember :: Type -> Name -> Type -> Q Type-localizeMember instTy m t@(ForallT tvs cx ty) = do-  let fullConstraint = AppT instTy (VarT m)-  let unifyLeft (c, cs) = fmap (,cs) <$> unifyTypes c fullConstraint-  results <- mapMaybeM unifyLeft (choices cx)-  case results of-    ((tbl, remainingCx) : _) -> do-      let cx' = substTypeVars tbl <$> remainingCx-          ty' = substTypeVars tbl ty-          (tvs', cx'') =-            relevantContext-              ty'-              ((tvName <$> tvs) \\ (fst <$> tbl), cx')-          t'-            | null tvs' && null cx'' = ty'-            | otherwise = ForallT (bindVar <$> tvs') cx'' ty'-      return t'-    _ -> return t-localizeMember _ _ t = return t
src/Test/HMock/Internal/Util.hs view
@@ -1,27 +1,34 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleContexts #-} +-- | Internal utilities used for HMock implementation. module Test.HMock.Internal.Util where  import Data.MonoTraversable (Element) import qualified Data.Sequences as Seq import GHC.Stack (CallStack, getCallStack, prettySrcLoc) +-- | A value together with its source location. data Located a = Loc (Maybe String) a deriving (Eq, Ord, Functor) +-- | Annotates a value with its source location from the call stack. locate :: CallStack -> a -> Located a locate stack = case map snd (getCallStack stack) of   (loc : _) -> Loc (Just (prettySrcLoc loc))   _ -> Loc Nothing +-- | Formats a 'Located' 'String' to include its source location. withLoc :: Located String -> String withLoc (Loc Nothing s) = s withLoc (Loc (Just loc) s) = s ++ " at " ++ loc +-- | Returns all ways to choose one element from a list, and the corresponding+-- remaining list. choices :: [a] -> [(a, [a])] choices [] = [] choices (x : xs) = (x, xs) : (fmap (x :) <$> choices xs) +-- | Checks if one sequence is a subsequence of another. isSubsequenceOf :: (Seq.IsSequence t, Eq (Element t)) => t -> t -> Bool xs `isSubsequenceOf` ys = case Seq.uncons xs of   Nothing -> True
+ src/Test/HMock/MockMethod.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE ScopedTypeVariables #-}++-- | Functions to delegate 'Action's to HMock to match expectations.  There is+-- one delegation function that works if the return type has a 'Default'+-- instance, and another that doesn't require the 'Default' instance, but causes+-- the method to return 'undefined' by default.+module Test.HMock.MockMethod+  ( mockMethod,+    mockDefaultlessMethod,+  )+where++import Control.Concurrent.STM (TVar, readTVar, writeTVar)+import Control.Monad (forM, join)+import Control.Monad.Extra (concatMapM)+import Control.Monad.IO.Class (MonadIO)+import Control.Monad.Reader (ask)+import Data.Bifunctor (bimap)+import Data.Default (Default (def))+import Data.Either (partitionEithers)+import Data.Function (on)+import Data.Functor (($>))+import Data.List (intercalate, sortBy)+import Data.Maybe (catMaybes, fromMaybe, isNothing)+import Data.Proxy (Proxy (Proxy))+import Data.Typeable (cast)+import GHC.Stack (HasCallStack, withFrozenCallStack)+import Test.HMock.ExpectContext (MockableMethod)+import Test.HMock.Internal.ExpectSet (ExpectSet, liveSteps)+import Test.HMock.Internal.State+  ( MockContext (..),+    MockSetup (..),+    MockState (..),+    MockT,+    allStates,+    initClassIfNeeded,+    mockSetupSTM,+  )+import Test.HMock.Internal.Step (SingleRule ((:->)), Step (Step))+import Test.HMock.Internal.Util (Located (Loc), withLoc)+import Test.HMock.MockT (describeExpectations)+import Test.HMock.Mockable (MatchResult (..), Mockable (..), MockableBase (..))+import Control.Applicative ((<|>))++-- | Implements mock delegation for actions.+mockMethodImpl ::+  forall cls name m r.+  (HasCallStack, MonadIO m, MockableMethod cls name m r) =>+  r ->+  Action cls name m r ->+  MockT m r+mockMethodImpl surrogate action = join $+  fromMockSetup $ do+    initClassIfNeeded (Proxy :: Proxy cls)+    states <- allStates <$> MockSetup ask+    (partial, full) <- fmap (bimap concat concat . unzip) $+      forM states $ \state -> do+        expectSet <- mockSetupSTM $ readTVar (mockExpectSet state)+        return $+          partitionEithers+            (tryMatch (mockExpectSet state) <$> liveSteps expectSet)+    let orderedPartial = snd <$> sortBy (compare `on` fst) (catMaybes partial)+    defaults <- concatMapM (mockSetupSTM . readTVar . mockDefaults) states+    checkAmbig <- mockSetupSTM $ readTVar . mockCheckAmbiguity . head $ states+    case (full, orderedPartial, findDefault defaults) of+      (opts@(_ : _ : _), _, _)+        | checkAmbig ->+          return $+            ambiguityError+              action+              ((\(s, _, _) -> s) <$> opts)+      ((_, choose, Just response) : _, _, _) -> choose >> return response+      ((_, choose, Nothing) : _, _, (_, d)) -> choose >> return d+      ([], _, (True, d)) -> return d+      ([], [], _) -> return (noMatchError action)+      ([], _, _) ->+        return (partialMatchError action orderedPartial)+  where+    tryMatch ::+      TVar (ExpectSet (Step m)) ->+      (Step m, ExpectSet (Step m)) ->+      Either+        (Maybe (Int, String))+        (String, MockSetup m (), Maybe (MockT m r))+    tryMatch tvar (Step expected, e)+      | Just lrule@(Loc _ (m :-> impl)) <- cast expected =+        case matchAction m action of+          NoMatch n ->+            Left (Just (n, withLoc (showMatcher (Just action) m <$ lrule)))+          Match ->+            Right+              ( withLoc (lrule $> showMatcher (Just action) m),+                mockSetupSTM $ writeTVar tvar e,+                ($ action) <$> impl+              )+      | otherwise = Left Nothing++    findDefault :: [(Bool, Step m)] -> (Bool, MockT m r)+    findDefault defaults = go False Nothing defaults+      where go True (Just r) _ = (True, r)+            go allowed r ((thisAllowed, Step expected) : steps)+              | thisAllowed || isNothing r,+                Just (Loc _ (m :-> r')) <- cast expected,+                Match <- matchAction m action =+                  go (allowed || thisAllowed) (r <|> (($ action) <$> r')) steps+              | otherwise = go allowed r steps+            go allowed r [] = (allowed, fromMaybe (return surrogate) r)++-- | Implements a method in a 'Mockable' monad by delegating to the mock+-- framework.  If the method is called unexpectedly, an exception will be+-- thrown.  However, an expected invocation without a specified response will+-- return the default value.+mockMethod ::+  ( HasCallStack,+    MonadIO m,+    MockableMethod cls name m r,+    Default r+  ) =>+  Action cls name m r ->+  MockT m r+mockMethod action =+  withFrozenCallStack $ mockMethodImpl def action++-- | Implements a method in a 'Mockable' monad by delegating to the mock+-- framework.  If the method is called unexpectedly, an exception will be+-- thrown.  However, an expected invocation without a specified response will+-- return undefined.  This can be used in place of 'mockMethod' when the return+-- type has no default.+mockDefaultlessMethod ::+  ( HasCallStack,+    MonadIO m,+    MockableMethod cls name m r+  ) =>+  Action cls name m r ->+  MockT m r+mockDefaultlessMethod action =+  withFrozenCallStack $ mockMethodImpl undefined action++-- | An error for an action that matches no expectations at all.+noMatchError ::+  (Mockable cls, MonadIO m) => Action cls name m r -> MockT m a+noMatchError a = do+  fullExpectations <- describeExpectations+  error $+    "Unexpected action: " ++ showAction a+      ++ "\n\nFull expectations:\n"+      ++ fullExpectations++-- | An error for an action that doesn't match the argument predicates for any+-- of the method's expectations.+partialMatchError ::+  (Mockable cls, MonadIO m) =>+  Action cls name m r ->+  [String] ->+  MockT m a+partialMatchError a partials = do+  fullExpectations <- describeExpectations+  error $+    "Wrong arguments: "+      ++ showAction a+      ++ "\n\nClosest matches:\n - "+      ++ intercalate "\n - " (take 5 partials)+      ++ "\n\nFull expectations:\n"+      ++ fullExpectations++-- | An error for an 'Action' that matches more than one 'Matcher'.  This only+-- triggers an error if ambiguity checks are on.+ambiguityError ::+  (Mockable cls, MonadIO m) =>+  Action cls name m r ->+  [String] ->+  MockT m a+ambiguityError a choices = do+  fullExpectations <- describeExpectations+  error $+    "Ambiguous action matched multiple expectations: "+      ++ showAction a+      ++ "\n\nMatches:\n - "+      ++ intercalate "\n - " choices+      ++ "\n\nFull expectations:\n"+      ++ fullExpectations
+ src/Test/HMock/MockT.hs view
@@ -0,0 +1,206 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This module defines monads for working with mocks.  HMock tests run in the+-- 'MockT' monad transformer.  A more limited monad, 'MockSetup', is used for+-- setting up defaults for each class.  Both are instances of the 'MockContext'+-- monad, which defines a shared API.+module Test.HMock.MockT+  ( MockT,+    runMockT,+    withMockT,+    nestMockT,+    withNestedMockT,+    setAmbiguityCheck,+    describeExpectations,+    verifyExpectations,+    MockSetup,+    MockContext,+    allowUnexpected,+    byDefault,+  )+where++import Control.Monad.Reader+  ( MonadReader (..),+    runReaderT,+  )+import Control.Monad.Trans (lift)+import Data.List (intercalate)+import Data.Proxy (Proxy (Proxy))+import GHC.Stack (callStack)+import Test.HMock.ExpectContext (MockableMethod)+import Test.HMock.Internal.ExpectSet+import Test.HMock.Internal.Rule (Rule ((:=>)))+import Test.HMock.Internal.State+import Test.HMock.Internal.Step (SingleRule ((:->)), Step (Step))+import Test.HMock.Internal.Util (locate)+import Test.HMock.Rule (Expectable (toRule))+import UnliftIO+import Data.Maybe (listToMaybe)++-- | Runs a test in the 'MockT' monad, handling all of the mocks.+runMockT :: forall m a. MonadIO m => MockT m a -> m a+runMockT test = withMockT constTest+  where+    constTest :: (forall b. MockT m b -> m b) -> MockT m a+    constTest _inMockT = test++-- | Runs a test in the 'MockT' monad.  The test can unlift other MockT pieces+-- to the base monad while still acting on the same set of expectations.  This+-- can be useful for testing concurrency or similar mechanisms.+--+-- @+-- test = 'withMockT' '$' \inMockT -> do+--    'Test.HMock.Expectable.expect' '$' ...+--+--    'liftIO' '$' 'Control.Concurrent.forkIO' '$' inMockT firstThread+--    'liftIO' '$' 'Control.Concurrent.forkIO' '$' inMockT secondThread+-- @+--+-- This is a low-level primitive.  Consider using the @unliftio@ package for+-- higher level implementations of multithreading and other primitives.+withMockT ::+  forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b+withMockT test = do+  state <- initMockState Nothing+  let inMockT :: forall a. MockT m a -> m a+      inMockT m = runReaderT (unMockT m) state+  flip runReaderT state $+    unMockT $ do+      a <- test inMockT+      verifyExpectations+      return a++-- | Starts a nested block within 'MockT'.  The nested block has its own set of+-- expectations, which must be fulfilled before the end of the block.+--+-- Beware: use of 'nestMockT' might signify that you are doing too much in a+-- single test.  Consider splitting large tests into a separate test for each+-- case.+nestMockT :: forall m a. MonadIO m => MockT m a -> MockT m a+nestMockT nest = withNestedMockT constNest+  where+    constNest :: (forall b. MockT m b -> m b) -> MockT m a+    constNest _inMockT = nest++-- | Starts a nested block within 'MockT'.  The nested block has its own set of+-- expectations, which must be fulfilled before the end of the block.  It can+-- unlift other MockT pieces to the base monad while still acting on the same+-- set of expectations.  This can be useful for testing concurrency or similar+-- mechanisms.+--+-- Beware: use of 'nestMockT' might signify that you are doing too much in a+-- single test.  Consider splitting large tests into a separate test for each+-- case.+withNestedMockT ::+  forall m b.+  MonadIO m =>+  ((forall a. MockT m a -> m a) -> MockT m b) ->+  MockT m b+withNestedMockT nest = do+  parent <- MockT ask+  state <- lift $ initMockState (Just parent)+  withState state $ do+    a <- nest (flip runReaderT state . unMockT)+    verifyExpectations+    return a+  where+    withState state = MockT . local (const state) . unMockT++-- | Sets whether to check for ambiguous actions.  If 'True', then actions that+-- match expectations in more than one way will fail.  If 'False', then the+-- most recently added action will take precedence.  This defaults to 'False'.+setAmbiguityCheck :: MonadIO m => Bool -> MockT m ()+setAmbiguityCheck flag = fromMockSetup $ do+  state <- MockSetup ask+  mockSetupSTM $ writeTVar (mockCheckAmbiguity state) flag++-- | Fetches a 'String' that describes the current set of outstanding+-- expectations.  This is sometimes useful for debugging test code.  The exact+-- format is not specified.+describeExpectations :: MonadIO m => MockT m String+describeExpectations = fromMockSetup $ do+  states <- allStates <$> MockSetup ask+  expectSets <- mapM (mockSetupSTM . readTVar . mockExpectSet) states+  return $+    intercalate "\n----- (next layer) -----\n" $+      formatExpectSet <$> expectSets++-- | Verifies that all mock expectations are satisfied.  If there is a nested+-- block in effect, only the expectations of that nested block are verified+-- You normally don't need to do this, because it happens automatically at the+-- end of your test or nested block.  However, it's occasionally useful to check+-- expectations early.+--+-- Beware: use of 'verifyExpectations' might signify that you are doing too much+-- in a single test.  Consider splitting large tests into a separate test for+-- each case.+verifyExpectations :: MonadIO m => MockT m ()+verifyExpectations = do+  fromMockSetup $ do+    expectSet <- MockSetup ask >>= mockSetupSTM . readTVar . mockExpectSet+    case excess expectSet of+      ExpectNothing -> return ()+      missing -> error $ "Unmet expectations:\n" ++ formatExpectSet missing++-- | Adds a handler for unexpected actions.  Matching calls will not fail, but+-- will use a default response instead.  The rule passed in must have zero or+-- one responses: if there is a response, @'allowUnexpected' (m+-- 'Test.HMock.Rule.|=>' r)@ is equivalent to @'allowUnexpected' m >>+-- 'byDefault' (m 'Test.HMock.Rule.|=>' r)@.+--+-- The difference between 'Test.HMock.Expectable.expectAny' and+-- 'allowUnexpected' is subtle, but comes down to ambiguity:+--+-- * 'allowUnexpected' is not an expectation, so it cannot be ambiguous.  It+--   only has an effect if no true expectation matches, regardless of when the+--   expectations were added.+-- * 'Test.HMock.Expectable.expectAny' adds an expectation, so if another+--   expectation is in effect at the same time, a call to the method is+--   ambiguous.  If ambiguity checking is enabled, the method will throw an+--   error; otherwise, the more recently added of the two expectations is used.+allowUnexpected ::+  forall cls name m r rule ctx.+  ( MonadIO m,+    MockableMethod cls name m r,+    Expectable cls name m r rule,+    MockContext ctx+  ) =>+  rule ->+  ctx m ()+allowUnexpected e = fromMockSetup $ case toRule e of+  _ :=> (_ : _ : _) -> error "allowUnexpected may not have multiple responses."+  m :=> r -> do+    initClassIfNeeded (Proxy :: Proxy cls)+    state <- MockSetup ask+    mockSetupSTM $+      modifyTVar'+        (mockDefaults state)+        ((True, Step (locate callStack (m :-> listToMaybe r))) :)++-- | Sets a default action for *expected* matching calls.  The new default only+-- applies to calls for which an expectation exists, but it lacks an explicit+-- response.  The rule passed in must have exactly one response.+byDefault ::+  forall cls name m r ctx.+  ( MonadIO m,+    MockableMethod cls name m r,+    MockContext ctx+  ) =>+  Rule cls name m r ->+  ctx m ()+byDefault (m :=> [r]) = fromMockSetup $ do+  initClassIfNeeded (Proxy :: Proxy cls)+  state <- MockSetup ask+  mockSetupSTM $+    modifyTVar'+      (mockDefaults state)+      ((False, Step (locate callStack (m :-> Just r))) :)+byDefault _ = error "Defaults must have exactly one response."
+ src/Test/HMock/Mockable.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This module defines the 'MockableBase' and 'Mockable' classes that are+-- needed to use an MTL-style type class with 'Test.HMock.MockT.MockT'.  You+-- will typically derive 'MockableBase' with Template Haskell, since it's mostly+-- boilerplate.  The 'Mockable' class adds a customizable setup method which you+-- can define yourself to add the right defaults for methods in the mocked+-- class.+module Test.HMock.Mockable+  ( Mockable (..),+    MockableBase (..),+    MatchResult (..),+  )+where++import Control.Monad.Trans (MonadIO)+import Data.Kind (Constraint, Type)+import Data.Typeable (Typeable)+import GHC.TypeLits (Symbol)+import {-# SOURCE #-} Test.HMock.Internal.State (MockSetup)++-- | The result of matching a @'Matcher' a@ with an @'Action' b@.  Because the+-- types should already guarantee that the methods match, all that's left is to+-- match arguments.+data MatchResult where+  -- | No match.  The int is the number of arguments that don't match.+  NoMatch :: Int -> MatchResult+  -- | Match. Stores a witness to the equality of return types.+  Match :: MatchResult++-- | A base class for 'Monad' subclasses whose methods can be mocked.  You+-- usually want to generate this instance using 'Test.HMock.TH.makeMockable',+-- 'Test.HMock.TH.makeMockableBase', 'Test.HMock.TH.deriveMockable', or+-- 'Test.HMock.TH.deriveMockableBase'.  It's just boilerplate.+class (Typeable cls) => MockableBase (cls :: (Type -> Type) -> Constraint) where+  -- | An action that is performed.  This data type will have one constructor+  -- for each method.+  data Action cls :: Symbol -> (Type -> Type) -> Type -> Type++  -- | A specification for matching actions.  The actual arguments should be+  -- replaced with predicates.+  data Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type++  -- | Gets a text description of an 'Action', for use in error messages.+  showAction :: Action cls name m a -> String++  -- | Gets a text description of a 'Matcher', for use in error messages.+  showMatcher :: Maybe (Action cls name m a) -> Matcher cls name m b -> String++  -- | Attempts to match an 'Action' with a 'Matcher'.+  matchAction :: Matcher cls name m a -> Action cls name m a -> MatchResult++-- | A class for 'Monad' subclasses whose methods can be mocked.  This class+-- augments 'MockableBase' with a setup method that is run before HMock touches+-- the 'Monad' subclass for the first time.  The default implementation does+-- nothing, but you can derive your own instances that add setup behavior.+class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint) where+  -- An action to run and set up defaults for this class.  The action will be+  -- run before HMock touches the class, either to add expectations or to+  -- delegate a method.+  --+  -- By default, unexpected actions throw errors, and actions with no explicit+  -- default always return the default value of their return type, or+  -- 'undefined' if there is none.  You can change this on a per-class or+  -- per-test basis.+  --+  -- * To change defaults on a per-class basis, you should use+  --   'Test.HMock.MockT.allowUnexpected' and/or 'Test.HMock.MockT.byDefault'+  --   to perform the setup you need here.+  -- * To change defaults on a per-test basis, you should use+  --   'Test.HMock.MockT.allowUnexpected' and/or 'Test.HMock.MockT.byDefault'+  --   directly from the test.+  setupMockable :: (MonadIO m, Typeable m) => proxy cls -> MockSetup m ()+  setupMockable _ = return ()
+ src/Test/HMock/Multiplicity.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE DeriveDataTypeable #-}++-- | This module provides the basic vocabulary for talking about multiplicity,+-- which is the number of times something is allowed to happen.  Multiplicities+-- can be any range of natural numbers, with or without an upper bound.+module Test.HMock.Multiplicity+  ( Multiplicity,+    meetsMultiplicity,+    feasible,+    once,+    anyMultiplicity,+    atLeast,+    atMost,+    between,+  )+where++-- | An acceptable range of number of times for something to happen.+--+-- A multiplicity can have a lower and an upper bound.+data Multiplicity = Multiplicity Int (Maybe Int) deriving (Eq)++instance Show Multiplicity where+  show mult = go (normalize mult) where+    go m | not (feasible m) = "infeasible"+    go (Multiplicity 0 (Just 0)) = "never"+    go (Multiplicity 1 (Just 1)) = "once"+    go (Multiplicity 2 (Just 2)) = "twice"+    go (Multiplicity 0 Nothing) = "any number of times"+    go (Multiplicity 1 Nothing) = "at least once"+    go (Multiplicity 2 Nothing) = "at least twice"+    go (Multiplicity n Nothing) = "at least " ++ show n ++ " times"+    go (Multiplicity 0 (Just 1)) = "at most once"+    go (Multiplicity 0 (Just 2)) = "at most twice"+    go (Multiplicity 0 (Just n)) = "at most " ++ show n ++ " times"+    go (Multiplicity m (Just n))+      | m == n = show n ++ " times"+      | m == n - 1 = show m ++ " or " ++ show n ++ " times"+      | otherwise = show m ++ " to " ++ show n ++ " times"++-- | A 'Multiplicity' value representing inconsistent expectations.+infeasible :: Multiplicity+infeasible = Multiplicity 0 (Just (-1))++-- | This is an incomplete instance, provided for convenience.+--+-- >>> meetsMultiplicity 5 4+-- False+-- >>> meetsMultiplicity 5 5+-- True+-- >>> between 4 6 - between 1 2+-- 2 to 5 times+instance Num Multiplicity where+  fromInteger n+    | n < 0 = infeasible+    | otherwise =+      normalize $+        Multiplicity (fromInteger n) (Just (fromInteger n))++  m1@(Multiplicity a b) + m2@(Multiplicity c d)+    | feasible m1 && feasible m2 =+      normalize $ Multiplicity (a + c) ((+) <$> b <*> d)+    | otherwise = infeasible++  m1@(Multiplicity a b) - m2@(Multiplicity c d)+    | feasible m1 && feasible m2 =+      normalize $ Multiplicity (maybe 0 (a -) d) (subtract c <$> b)+    | otherwise = infeasible++  (*) = error "Multiplicities are not closed under multiplication"++  abs = id++  signum (Multiplicity 0 (Just 0)) = 0+  signum _ = 1++normalize :: Multiplicity -> Multiplicity+normalize (Multiplicity a b) = Multiplicity (max a 0) b++-- | Checks whether a certain number satisfies the 'Multiplicity'.+meetsMultiplicity :: Multiplicity -> Int -> Bool+meetsMultiplicity (Multiplicity lo mbhi) n+  | n < lo = False+  | Just hi <- mbhi, n > hi = False+  | otherwise = True++-- | A 'Multiplicity' that means exactly once.+--+-- >>> meetsMultiplicity once 0+-- False+-- >>> meetsMultiplicity once 1+-- True+-- >>> meetsMultiplicity once 2+-- False+once :: Multiplicity+once = 1++-- | A 'Multiplicity' that means any number of times.+-- >>> meetsMultiplicity anyMultiplicity 0+-- True+-- >>> meetsMultiplicity anyMultiplicity 1+-- True+-- >>> meetsMultiplicity anyMultiplicity 10+-- True+anyMultiplicity :: Multiplicity+anyMultiplicity = atLeast 0++-- | A 'Multiplicity' that means at least this many times.+--+-- >>> meetsMultiplicity (atLeast 2) 1+-- False+-- >>> meetsMultiplicity (atLeast 2) 2+-- True+-- >>> meetsMultiplicity (atLeast 2) 3+-- True+atLeast :: Multiplicity -> Multiplicity+atLeast (Multiplicity n _) = Multiplicity n Nothing++-- | A 'Multiplicity' that means at most this many times.+--+-- >>> meetsMultiplicity (atMost 2) 1+-- True+-- >>> meetsMultiplicity (atMost 2) 2+-- True+-- >>> meetsMultiplicity (atMost 2) 3+-- False+atMost :: Multiplicity -> Multiplicity+atMost (Multiplicity _ n) = Multiplicity 0 n++-- | A 'Multiplicity' that means any number in this interval, endpoints+-- included.  For example, @'between' 2 3@ means 2 or 3 times, while+-- @'between' n n@ is equivalent to @n@.+--+-- >>> meetsMultiplicity (between 2 3) 1+-- False+-- >>> meetsMultiplicity (between 2 3) 2+-- True+-- >>> meetsMultiplicity (between 2 3) 3+-- True+-- >>> meetsMultiplicity (between 2 3) 4+-- False+between :: Multiplicity -> Multiplicity -> Multiplicity+between (Multiplicity m _) (Multiplicity _ n) = Multiplicity m n++-- | Checks whether a 'Multiplicity' is capable of matching any number at all.+--+-- >>> feasible once+-- True+-- >>> feasible 0+-- True+-- >>> feasible (once - 2)+-- False+feasible :: Multiplicity -> Bool+feasible (Multiplicity a b) = maybe True (>= a) b
+ src/Test/HMock/Predicates.hs view
@@ -0,0 +1,980 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- | This module defines 'Predicate's which you can use to match the arguments of+-- a method in your execution plan.+module Test.HMock.Predicates+  ( Predicate (..),+    anything,+    eq,+    neq,+    gt,+    geq,+    lt,+    leq,+    just,+    left,+    right,+    zipP,+    zip3P,+    zip4P,+    zip5P,+    andP,+    orP,+    notP,+    startsWith,+    endsWith,+    hasSubstr,+    hasSubsequence,+    caseInsensitive,+    matchesRegex,+    matchesCaseInsensitiveRegex,+    containsRegex,+    containsCaseInsensitiveRegex,+    isEmpty,+    nonEmpty,+    sizeIs,+    elemsAre,+    unorderedElemsAre,+    each,+    contains,+    containsAll,+    containsOnly,+    containsKey,+    containsEntry,+    keysAre,+    entriesAre,+    approxEq,+    finite,+    infinite,+    nAn,+    is,+    qIs,+    with,+    qWith,+    qMatch,+    typed,+  )+where++import Data.Char (toUpper)+import Data.Maybe (isJust)+import Data.MonoTraversable+import qualified Data.Sequences as Seq+import Data.Typeable (Proxy (..), Typeable, cast, typeRep)+import GHC.Exts (IsList (Item, toList))+import GHC.Stack (HasCallStack, callStack)+import Language.Haskell.TH (ExpQ, PatQ, pprint)+import Language.Haskell.TH.Syntax (lift)+import Test.HMock.Internal.TH (removeModNames)+import Test.HMock.Internal.Util (choices, isSubsequenceOf, locate, withLoc)+import Text.Regex.TDFA hiding (match)++-- $setup+-- >>> :set -XTemplateHaskell+-- >>> :set -XTypeApplications+-- >>> :set -Wno-type-defaults++-- | A predicate, which tests values and either accepts or rejects them.  This+-- is similar to @a -> 'Bool'@, but also has a 'Show' instance to describe what+-- it is checking.+--+-- 'Predicate's are used to define which arguments a general matcher should+-- accept.+data Predicate a = Predicate+  { showPredicate :: String,+    accept :: a -> Bool+  }++instance Show (Predicate a) where show = showPredicate++-- | A 'Predicate' that accepts anything at all.+--+-- >>> accept anything "foo"+-- True+-- >>> accept anything undefined+-- True+anything :: Predicate a+anything =+  Predicate+    { showPredicate = "anything",+      accept = const True+    }++-- | A 'Predicate' that accepts only the given value.+--+-- >>> accept (eq "foo") "foo"+-- True+-- >>> accept (eq "foo") "bar"+-- False+eq :: (Show a, Eq a) => a -> Predicate a+eq x =+  Predicate+    { showPredicate = show x,+      accept = (== x)+    }++-- | A 'Predicate' that accepts anything but the given value.+--+-- >>> accept (neq "foo") "foo"+-- False+-- >>> accept (neq "foo") "bar"+-- True+neq :: (Show a, Eq a) => a -> Predicate a+neq x =+  Predicate+    { showPredicate = "≠ " ++ show x,+      accept = (/= x)+    }++-- | A 'Predicate' that accepts anything greater than the given value.+--+-- >>> accept (gt 5) 4+-- False+-- >>> accept (gt 5) 5+-- False+-- >>> accept (gt 5) 6+-- True+gt :: (Show a, Ord a) => a -> Predicate a+gt x =+  Predicate+    { showPredicate = "> " ++ show x,+      accept = (> x)+    }++-- | A 'Predicate' that accepts anything greater than or equal to the given+-- value.+--+-- >>> accept (geq 5) 4+-- False+-- >>> accept (geq 5) 5+-- True+-- >>> accept (geq 5) 6+-- True+geq :: (Show a, Ord a) => a -> Predicate a+geq x =+  Predicate+    { showPredicate = "≥ " ++ show x,+      accept = (>= x)+    }++-- | A 'Predicate' that accepts anything less than the given value.+--+-- >>> accept (lt 5) 4+-- True+-- >>> accept (lt 5) 5+-- False+-- >>> accept (lt 5) 6+-- False+lt :: (Show a, Ord a) => a -> Predicate a+lt x =+  Predicate+    { showPredicate = "< " ++ show x,+      accept = (< x)+    }++-- | A 'Predicate' that accepts anything less than or equal to the given value.+--+-- >>> accept (leq 5) 4+-- True+-- >>> accept (leq 5) 5+-- True+-- >>> accept (leq 5) 6+-- False+leq :: (Show a, Ord a) => a -> Predicate a+leq x =+  Predicate+    { showPredicate = "≤ " ++ show x,+      accept = (<= x)+    }++-- | A 'Predicate' that accepts 'Maybe' values of @'Just' x@, where @x@ matches+-- the given child 'Predicate'.+--+-- >>> accept (just (eq "value")) Nothing+-- False+-- >>> accept (just (eq "value")) (Just "value")+-- True+-- >>> accept (just (eq "value")) (Just "wrong value")+-- False+just :: Predicate a -> Predicate (Maybe a)+just p =+  Predicate+    { showPredicate = "Just (" ++ showPredicate p ++ ")",+      accept = \case Just x -> accept p x; _ -> False+    }++-- | A 'Predicate' that accepts an 'Either' value of @'Left' x@, where @x@+-- matches the given child 'Predicate'.+--+-- >>> accept (left (eq "value")) (Left "value")+-- True+-- >>> accept (left (eq "value")) (Right "value")+-- False+-- >>> accept (left (eq "value")) (Left "wrong value")+-- False+left :: Predicate a -> Predicate (Either a b)+left p =+  Predicate+    { showPredicate = "Left (" ++ showPredicate p ++ ")",+      accept = \case Left x -> accept p x; _ -> False+    }++-- | A 'Predicate' that accepts an 'Either' value of @'Right' x@, where @x@+-- matches the given child 'Predicate'.+--+-- >>> accept (right (eq "value")) (Right "value")+-- True+-- >>> accept (right (eq "value")) (Right "wrong value")+-- False+-- >>> accept (right (eq "value")) (Left "value")+-- False+right :: Predicate b -> Predicate (Either a b)+right p =+  Predicate+    { showPredicate = "Right (" ++ showPredicate p ++ ")",+      accept = \case Right x -> accept p x; _ -> False+    }++-- | A 'Predicate' that accepts pairs whose elements satisfy the corresponding+-- child 'Predicate's.+--+-- >>> accept (zipP (eq "foo") (eq "bar")) ("foo", "bar")+-- True+-- >>> accept (zipP (eq "foo") (eq "bar")) ("bar", "foo")+-- False+zipP :: Predicate a -> Predicate b -> Predicate (a, b)+zipP p q =+  Predicate+    { showPredicate = show (p, q),+      accept = \(x, y) -> accept p x && accept q y+    }++-- | A 'Predicate' that accepts 3-tuples whose elements satisfy the+-- corresponding child 'Predicate's.+--+-- >>> accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("foo", "bar", "qux")+-- True+-- >>> accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("qux", "bar", "foo")+-- False+zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)+zip3P p1 p2 p3 =+  Predicate+    { showPredicate = show (p1, p2, p3),+      accept = \(x1, x2, x3) -> accept p1 x1 && accept p2 x2 && accept p3 x3+    }++-- | A 'Predicate' that accepts 3-tuples whose elements satisfy the+-- corresponding child 'Predicate's.+--+-- >>> accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (1, 2, 3, 4)+-- True+-- >>> accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (4, 3, 2, 1)+-- False+zip4P ::+  Predicate a ->+  Predicate b ->+  Predicate c ->+  Predicate d ->+  Predicate (a, b, c, d)+zip4P p1 p2 p3 p4 =+  Predicate+    { showPredicate = show (p1, p2, p3, p4),+      accept = \(x1, x2, x3, x4) ->+        accept p1 x1 && accept p2 x2 && accept p3 x3 && accept p4 x4+    }++-- | A 'Predicate' that accepts 3-tuples whose elements satisfy the+-- corresponding child 'Predicate's.+--+-- >>> accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (1, 2, 3, 4, 5)+-- True+-- >>> accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (5, 4, 3, 2, 1)+-- False+zip5P ::+  Predicate a ->+  Predicate b ->+  Predicate c ->+  Predicate d ->+  Predicate e ->+  Predicate (a, b, c, d, e)+zip5P p1 p2 p3 p4 p5 =+  Predicate+    { showPredicate = show (p1, p2, p3, p4, p5),+      accept = \(x1, x2, x3, x4, x5) ->+        accept p1 x1 && accept p2 x2 && accept p3 x3 && accept p4 x4+          && accept p5 x5+    }++-- | A 'Predicate' that accepts anything accepted by both of its children.+--+-- >>> accept (lt "foo" `andP` gt "bar") "eta"+-- True+-- >>> accept (lt "foo" `andP` gt "bar") "quz"+-- False+-- >>> accept (lt "foo" `andP` gt "bar") "alpha"+-- False+andP :: Predicate a -> Predicate a -> Predicate a+p `andP` q =+  Predicate+    { showPredicate = showPredicate p ++ " and " ++ showPredicate q,+      accept = \x -> accept p x && accept q x+    }++-- | A 'Predicate' that accepts anything accepted by either of its children.+--+-- >>> accept (lt "bar" `orP` gt "foo") "eta"+-- False+-- >>> accept (lt "bar" `orP` gt "foo") "quz"+-- True+-- >>> accept (lt "bar" `orP` gt "foo") "alpha"+-- True+orP :: Predicate a -> Predicate a -> Predicate a+p `orP` q =+  Predicate+    { showPredicate = showPredicate p ++ " or " ++ showPredicate q,+      accept = \x -> accept p x || accept q x+    }++-- | A 'Predicate' that inverts another 'Predicate', accepting whatever its+-- child rejects, and rejecting whatever its child accepts.+--+-- >>> accept (notP (eq "negative")) "positive"+-- True+-- >>> accept (notP (eq "negative")) "negative"+-- False+notP :: Predicate a -> Predicate a+notP p =+  Predicate+    { showPredicate = "not " ++ showPredicate p,+      accept = not . accept p+    }++-- | A 'Predicate' that accepts sequences that start with the given prefix.+--+-- >>> accept (startsWith "fun") "fungible"+-- True+-- >>> accept (startsWith "gib") "fungible"+-- False+startsWith :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t+startsWith pfx =+  Predicate+    { showPredicate = "starts with " ++ show pfx,+      accept = (pfx `Seq.isPrefixOf`)+    }++-- | A 'Predicate' that accepts sequences that end with the given suffix.+--+-- >>> accept (endsWith "ow") "crossbow"+-- True+-- >>> accept (endsWith "ow") "trebuchet"+-- False+endsWith :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t+endsWith sfx =+  Predicate+    { showPredicate = "ends with " ++ show sfx,+      accept = (sfx `Seq.isSuffixOf`)+    }++-- | A 'Predicate' that accepts sequences that contain the given (consecutive)+-- substring.+--+-- >>> accept (hasSubstr "i") "team"+-- False+-- >>> accept (hasSubstr "i") "partnership"+-- True+hasSubstr :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t+hasSubstr s =+  Predicate+    { showPredicate = "has substring " ++ show s,+      accept = (s `Seq.isInfixOf`)+    }++-- | A 'Predicate' that accepts sequences that contain the given (not+-- necessarily consecutive) subsequence.+--+-- >>> accept (hasSubsequence [1..5]) [1, 2, 3, 4, 5]+-- True+-- >>> accept (hasSubsequence [1..5]) [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]+-- True+-- >>> accept (hasSubsequence [1..5]) [2, 3, 5, 7, 11]+-- False+hasSubsequence :: (Show t, Seq.IsSequence t, Eq (Element t)) => t -> Predicate t+hasSubsequence s =+  Predicate+    { showPredicate = "has subsequence " ++ show s,+      accept = (s `isSubsequenceOf`)+    }++-- | Transforms a 'Predicate' on 'String's or string-like types to match without+-- regard to case.+--+-- >>> accept (caseInsensitive startsWith "foo") "FOOTBALL!"+-- True+-- >>> accept (caseInsensitive endsWith "ball") "soccer"+-- False+-- >>> accept (caseInsensitive eq "time") "TIME"+-- True+-- >>> accept (caseInsensitive gt "NOTHING") "everything"+-- False+caseInsensitive ::+  ( MonoFunctor t,+    MonoFunctor a,+    Element t ~ Char,+    Element a ~ Char+  ) =>+  (t -> Predicate a) ->+  (t -> Predicate a)+caseInsensitive p s =+  Predicate+    { showPredicate = "(case insensitive) " ++ show (p s),+      accept = accept capP . omap toUpper+    }+  where+    capP = p (omap toUpper s)++-- | A 'Predicate' that accepts 'String's or string-like values matching a+-- regular expression.  The expression must match the entire argument.+--+-- You should not use @'caseInsensitive' 'matchesRegex'@, because regular+-- expression syntax itself is still case-sensitive even when the text you are+-- matching is not.  Instead, use 'matchesCaseInsensitiveRegex'.+--+-- >>> accept (matchesRegex "x{2,5}y?") "xxxy"+-- True+-- >>> accept (matchesRegex "x{2,5}y?") "xyy"+-- False+-- >>> accept (matchesRegex "x{2,5}y?") "wxxxyz"+-- False+matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a+matchesRegex s =+  Predicate+    { showPredicate = "/" ++ init (tail $ show s) ++ "/",+      accept = \x -> case matchOnceText r x of+        Just (a, _, b) -> a == empty && b == empty+        Nothing -> False+    }+  where+    r = makeRegexOpts comp exec s :: Regex+    comp = defaultCompOpt {newSyntax = True, lastStarGreedy = True}+    exec = defaultExecOpt {captureGroups = False}++-- | A 'Predicate' that accepts 'String's or string-like values matching a+-- regular expression in a case-insensitive way.  The expression must match the+-- entire argument.+--+-- You should use this instead of @'caseInsensitive' 'matchesRegex'@, because+-- regular expression syntax itself is still case-sensitive even when the text+-- you are matching is not.+--+-- >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XXXY"+-- True+-- >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XYY"+-- False+-- >>> accept (matchesCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"+-- False+matchesCaseInsensitiveRegex ::+  (RegexLike Regex a, Eq a) => String -> Predicate a+matchesCaseInsensitiveRegex s =+  Predicate+    { showPredicate = "/" ++ init (tail $ show s) ++ "/i",+      accept = \x -> case matchOnceText r x of+        Just (a, _, b) -> a == empty && b == empty+        Nothing -> False+    }+  where+    r = makeRegexOpts comp exec s :: Regex+    comp =+      defaultCompOpt+        { newSyntax = True,+          lastStarGreedy = True,+          caseSensitive = False+        }+    exec = defaultExecOpt {captureGroups = False}++-- | A 'Predicate' that accepts 'String's or string-like values containing a+-- match for a regular expression.  The expression need not match the entire+-- argument.+--+-- You should not use @'caseInsensitive' 'containsRegex'@, because regular+-- expression syntax itself is still case-sensitive even when the text you are+-- matching is not.  Instead, use 'containsCaseInsensitiveRegex'.+--+-- >>> accept (containsRegex "x{2,5}y?") "xxxy"+-- True+-- >>> accept (containsRegex "x{2,5}y?") "xyy"+-- False+-- >>> accept (containsRegex "x{2,5}y?") "wxxxyz"+-- True+containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a+containsRegex s =+  Predicate+    { showPredicate = "contains /" ++ init (tail $ show s) ++ "/",+      accept = isJust . matchOnce r+    }+  where+    r = makeRegexOpts comp exec s :: Regex+    comp = defaultCompOpt {newSyntax = True, lastStarGreedy = True}+    exec = defaultExecOpt {captureGroups = False}++-- | A 'Predicate' that accepts 'String's or string-like values containing a+-- match for a regular expression in a case-insensitive way.  The expression+-- need match the entire argument.+--+-- You should use this instead of @'caseInsensitive' 'containsRegex'@, because+-- regular expression syntax itself is still case-sensitive even when the text+-- you are matching is not.+--+-- >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "XXXY"+-- True+-- >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "XYY"+-- False+-- >>> accept (containsCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"+-- True+containsCaseInsensitiveRegex ::+  (RegexLike Regex a, Eq a) => String -> Predicate a+containsCaseInsensitiveRegex s =+  Predicate+    { showPredicate = "contains /" ++ init (tail $ show s) ++ "/i",+      accept = isJust . matchOnce r+    }+  where+    r = makeRegexOpts comp exec s :: Regex+    comp =+      defaultCompOpt+        { newSyntax = True,+          lastStarGreedy = True,+          caseSensitive = False+        }+    exec = defaultExecOpt {captureGroups = False}++-- | A 'Predicate' that accepts empty data structures.+--+-- >>> accept isEmpty []+-- True+-- >>> accept isEmpty [1, 2, 3]+-- False+-- >>> accept isEmpty ""+-- True+-- >>> accept isEmpty "gas tank"+-- False+isEmpty :: MonoFoldable t => Predicate t+isEmpty =+  Predicate+    { showPredicate = "empty",+      accept = onull+    }++-- | A 'Predicate' that accepts non-empty data structures.+--+-- >>> accept nonEmpty []+-- False+-- >>> accept nonEmpty [1, 2, 3]+-- True+-- >>> accept nonEmpty ""+-- False+-- >>> accept nonEmpty "gas tank"+-- True+nonEmpty :: MonoFoldable t => Predicate t+nonEmpty =+  Predicate+    { showPredicate = "nonempty",+      accept = not . onull+    }++-- | A 'Predicate' that accepts data structures whose number of elements match+-- the child 'Predicate'.+--+-- >>> accept (sizeIs (lt 3)) ['a' .. 'f']+-- False+-- >>> accept (sizeIs (lt 3)) ['a' .. 'b']+-- True+sizeIs :: MonoFoldable t => Predicate Int -> Predicate t+sizeIs p =+  Predicate+    { showPredicate = "size " ++ showPredicate p,+      accept = accept p . olength+    }++-- | A 'Predicate' that accepts data structures whose contents each match the+-- corresponding 'Predicate' in the given list, in the same order.+--+-- >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4]+-- True+-- >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4, 5]+-- False+-- >>> accept (elemsAre [lt 3, lt 4, lt 5]) [2, 10, 4]+-- False+elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t+elemsAre ps =+  Predicate+    { showPredicate = show ps,+      accept = \xs ->+        olength xs == olength ps+          && and (zipWith accept ps (otoList xs))+    }++-- | A 'Predicate' that accepts data structures whose contents each match the+-- corresponding 'Predicate' in the given list, in any order.+--+-- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3]+-- True+-- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [2, 3, 1]+-- True+-- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3, 4]+-- False+-- >>> accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 3]+-- False+unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t+unorderedElemsAre ps =+  Predicate+    { showPredicate =+        "(any order) " ++ show ps,+      accept = matches ps . otoList+    }+  where+    matches (q : qs) xs = or [matches qs ys | (y, ys) <- choices xs, accept q y]+    matches [] xs = null xs++-- | A 'Predicate' that accepts data structures whose elements each match the+-- child 'Predicate'.+--+-- >>> accept (each (gt 5)) [4, 5, 6]+-- False+-- >>> accept (each (gt 5)) [6, 7, 8]+-- True+-- >>> accept (each (gt 5)) []+-- True+each :: MonoFoldable t => Predicate (Element t) -> Predicate t+each p =+  Predicate+    { showPredicate = "each (" ++ showPredicate p ++ ")",+      accept = oall (accept p)+    }++-- | A 'Predicate' that accepts data structures which contain at least one+-- element matching the child 'Predicate'.+--+-- >>> accept (contains (gt 5)) [3, 4, 5]+-- False+-- >>> accept (contains (gt 5)) [4, 5, 6]+-- True+-- >>> accept (contains (gt 5)) []+-- False+contains :: MonoFoldable t => Predicate (Element t) -> Predicate t+contains p =+  Predicate+    { showPredicate = "contains (" ++ showPredicate p ++ ")",+      accept = oany (accept p)+    }++-- | A 'Predicate' that accepts data structures which contain an element+-- satisfying each of the child 'Predicate's.  @'containsAll' [p1, p2, ..., pn]@+-- is equivalent to @'contains' p1 `'andP'` 'contains' p2 `'andP'` ... `'andP'`+-- 'contains' pn@.+--+-- >>> accept (containsAll [eq "foo", eq "bar"]) ["bar", "foo"]+-- True+-- >>> accept (containsAll [eq "foo", eq "bar"]) ["foo"]+-- False+-- >>> accept (containsAll [eq "foo", eq "bar"]) ["foo", "bar", "qux"]+-- True+containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t+containsAll ps =+  Predicate+    { showPredicate = "contains all of " ++ show ps,+      accept = \xs -> all (flip oany xs . accept) ps+    }++-- | A 'Predicate' that accepts data structures whose elements all satisfy at+-- least one of the child 'Predicate's.  @'containsOnly' [p1, p2, ..., pn]@ is+-- equivalent to @'each' (p1 `'orP'` p2 `'orP'` ... `'orP'` pn)@.+--+-- >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "foo"]+-- True+-- >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "bar"]+-- True+-- >>> accept (containsOnly [eq "foo", eq "bar"]) ["foo", "qux"]+-- False+containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t+containsOnly ps =+  Predicate+    { showPredicate = "contains only " ++ show ps,+      accept = oall (\x -> any (`accept` x) ps)+    }++-- | A 'Predicate' that accepts map-like structures which contain a key matching+-- the child 'Predicate'.+--+-- >>> accept (containsKey (eq "foo")) [("foo", 1), ("bar", 2)]+-- True+-- >>> accept (containsKey (eq "foo")) [("bar", 1), ("qux", 2)]+-- False+containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t+containsKey p =+  Predicate+    { showPredicate = "contains key " ++ show p,+      accept = \m -> any (accept p) (fst <$> toList m)+    }++-- | A 'Predicate' that accepts map-like structures which contain a key/value+-- pair matched by the given child 'Predicate's (one for the key, and one for+-- the value).+--+-- >>> accept (containsEntry (eq "foo") (gt 10)) [("foo", 12), ("bar", 5)]+-- True+-- >>> accept (containsEntry (eq "foo") (gt 10)) [("foo", 5), ("bar", 12)]+-- False+-- >>> accept (containsEntry (eq "foo") (gt 10)) [("bar", 12)]+-- False+containsEntry ::+  (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t+containsEntry p q =+  Predicate+    { showPredicate = "contains entry " ++ show (p, q),+      accept = any (\(x, y) -> accept p x && accept q y) . toList+    }++-- | A 'Predicate' that accepts map-like structures whose keys are exactly those+-- matched by the given list of 'Predicate's, in any order.+--+-- >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("b", 2), ("c", 3)]+-- True+-- >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("c", 1), ("b", 2), ("a", 3)]+-- True+-- >>> accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("c", 3)]+-- False+-- >>> accept (keysAre [eq "a", eq "b"]) [("a", 1), ("b", 2), ("c", 3)]+-- False+keysAre ::+  (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t+keysAre ps =+  Predicate+    { showPredicate = "keys are " ++ show ps,+      accept = matches ps . map fst . toList+    }+  where+    matches (q : qs) xs = or [matches qs ys | (y, ys) <- choices xs, accept q y]+    matches [] xs = null xs++-- | A 'Predicate' that accepts map-like structures whose entries are exactly+-- those matched by the given list of 'Predicate' pairs, in any order.+--+-- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4)]+-- True+-- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(3, 4), (1, 2)]+-- True+-- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 4), (3, 2)]+-- False+-- >>> accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4), (5, 6)]+-- False+entriesAre ::+  (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t+entriesAre ps =+  Predicate+    { showPredicate = "entries are " ++ show ps,+      accept = matches ps . toList+    }+  where+    matches ((p, q) : pqs) xs =+      or [matches pqs ys | ((k, v), ys) <- choices xs, accept p k, accept q v]+    matches [] xs = null xs++-- | A 'Predicate' that accepts values of 'RealFloat' types that are close to+-- the given number.  The expected precision is scaled based on the target+-- value, so that reasonable rounding error is accepted but grossly inaccurate+-- results are not.+--+-- The following naive use of 'eq' fails due to rounding:+--+-- >>> accept (eq 1.0) (sum (replicate 100 0.01))+-- False+--+-- The solution is to use 'approxEq', which accounts for rounding error.+-- However, 'approxEq' doesn't accept results that are far enough off that they+-- likely arise from incorrect calculations instead of rounding error.+--+-- >>> accept (approxEq 1.0) (sum (replicate 100 0.01))+-- True+-- >>> accept (approxEq 1.0) (sum (replicate 100 0.009999))+-- False+approxEq :: (RealFloat a, Show a) => a -> Predicate a+approxEq x =+  Predicate+    { showPredicate = "≈ " ++ show x,+      accept = \y -> abs (x - y) < diff+    }+  where+    diff = encodeFloat 1 (snd (decodeFloat x) + floatDigits x `div` 2)++-- | A 'Predicate' that accepts finite numbers of any 'RealFloat' type.+--+-- >>> accept finite 1.0+-- True+-- >>> accept finite (0 / 0)+-- False+-- >>> accept finite (1 / 0)+-- False+finite :: RealFloat a => Predicate a+finite =+  Predicate+    { showPredicate = "finite",+      accept = \x -> not (isInfinite x) && not (isNaN x)+    }++-- | A 'Predicate' that accepts infinite numbers of any 'RealFloat' type.+--+-- >>> accept infinite 1.0+-- False+-- >>> accept infinite (0 / 0)+-- False+-- >>> accept infinite (1 / 0)+-- True+infinite :: RealFloat a => Predicate a+infinite =+  Predicate+    { showPredicate = "infinite",+      accept = isInfinite+    }++-- | A 'Predicate' that accepts NaN values of any 'RealFloat' type.+--+-- >>> accept nAn 1.0+-- False+-- >>> accept nAn (0 / 0)+-- True+-- >>> accept nAn (1 / 0)+-- False+nAn :: RealFloat a => Predicate a+nAn =+  Predicate+    { showPredicate = "NaN",+      accept = isNaN+    }++-- | A conversion from @a -> 'Bool'@ to 'Predicate'.  This is a fallback that+-- can be used to build a 'Predicate' that checks anything at all.  However, its+-- description will be less helpful than standard 'Predicate's.+--+-- >>> accept (is even) 3+-- False+-- >>> accept (is even) 4+-- True+is :: HasCallStack => (a -> Bool) -> Predicate a+is f =+  Predicate+    { showPredicate = withLoc (locate callStack "custom predicate"),+      accept = f+    }++-- | A Template Haskell splice that acts like 'is', but receives a quoted+-- expression at compile time and has a more helpful description for error+-- messages.+--+-- >>> accept $(qIs [| even |]) 3+-- False+-- >>> accept $(qIs [| even |]) 4+-- True+--+-- >>> show $(qIs [| even |])+-- "even"+qIs :: HasCallStack => ExpQ -> ExpQ+qIs f =+  [|+    Predicate+      { showPredicate = $(lift . pprint . removeModNames =<< f),+        accept = $f+      }+    |]++-- | A combinator to lift a 'Predicate' to work on a property or computed value+-- of the original value.+--+-- >>> accept (with abs (gt 5)) (-6)+-- True+-- >>> accept (with abs (gt 5)) (-5)+-- False+-- >>> accept (with reverse (eq "olleh")) "hello"+-- True+-- >>> accept (with reverse (eq "olleh")) "goodbye"+-- False+with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a+with f p =+  Predicate+    { showPredicate =+        withLoc (locate callStack "property") ++ ": " ++ show p,+      accept = accept p . f+    }++-- | A Template Haskell splice that acts like 'is', but receives a quoted typed+-- expression at compile time and has a more helpful description for error+-- messages.+--+-- >>> accept ($(qWith [| abs |]) (gt 5)) (-6)+-- True+-- >>> accept ($(qWith [| abs |]) (gt 5)) (-5)+-- False+-- >>> accept ($(qWith [| reverse |]) (eq "olleh")) "hello"+-- True+-- >>> accept ($(qWith [| reverse |]) (eq "olleh")) "goodbye"+-- False+--+-- >>> show ($(qWith [| abs |]) (gt 5))+-- "abs: > 5"+qWith :: ExpQ -> ExpQ+qWith f =+  [|+    \p ->+      Predicate+        { showPredicate =+            $(lift . pprint . removeModNames =<< f) ++ ": " ++ show p,+          accept = accept p . $f+        }+    |]++-- | A Template Haskell splice that turns a quoted pattern into a predicate that+-- accepts values that match the pattern.+--+-- >>> accept $(qMatch [p| Just (Left _) |]) Nothing+-- False+-- >>> accept $(qMatch [p| Just (Left _) |]) (Just (Left 5))+-- True+-- >>> accept $(qMatch [p| Just (Left _) |]) (Just (Right 5))+-- False+--+-- >>> show $(qMatch [p| Just (Left _) |])+-- "Just (Left _)"+qMatch :: PatQ -> ExpQ+qMatch qpat =+  [|+    Predicate+      { showPredicate = $(lift . pprint . removeModNames =<< qpat),+        accept = \case+          $(qpat) -> True+          _ -> False+      }+    |]++-- | Converts a 'Predicate' to a new type.  Typically used with visible type+-- application, as in the examples below.+--+-- >>> accept (typed @String anything) "foo"+-- True+-- >>> accept (typed @String (sizeIs (gt 5))) "foo"+-- False+-- >>> accept (typed @String anything) (42 :: Int)+-- False+typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b+typed p =+  Predicate+    { showPredicate =+        showPredicate p ++ " :: " ++ show (typeRep (Proxy :: Proxy a)),+      accept = \x -> case cast x of+        Nothing -> False+        Just y -> accept p y+    }
+ src/Test/HMock/Rule.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}++-- | This module defines the 'Rule' type, which describes a matcher for methods+-- and a possibly-empty list of responses to use for successive calls to+-- matching methods.  The 'Expectable' type class generalizes 'Rule', so that+-- you can specify a bare 'Matcher' or 'Action' in most situations where a+-- 'Rule' is needed but you don't want to specify the response.+module Test.HMock.Rule (Rule, Expectable (..), (|->), (|=>)) where++import Test.HMock.Internal.Rule (Rule (..))+import {-# SOURCE #-} Test.HMock.Internal.State (MockT)+import Test.HMock.Mockable (MockableBase (Action, Matcher))++-- | Class for things that can be expected.  This is includes 'Rule's, but also+-- bare 'Matcher's and 'Action's with no explicit response.+class Expectable cls name m r ex | ex -> cls name m r where+  -- | Converts an expectable to a Rule that means the same thing.+  toRule :: ex -> Rule cls name m r++-- | Attaches a response to an expectation.  This is a flexible response,+-- which can look at arguments, do things in the base monad, set up more+-- expectations, etc.  A matching 'Action' is passed to the response.+(|=>) ::+  Expectable cls name m r ex =>+  ex ->+  (Action cls name m r -> MockT m r) ->+  Rule cls name m r+e |=> r = m :=> (rs ++ [r]) where m :=> rs = toRule e++infixl 1 |=>++-- | Attaches a return value to an expectation.  This is more convenient than+-- '|=>' in the common case where you just want to return a known result.+-- @e '|->' r@ means the same thing as @e '|=>' 'const' ('return' r)@.+(|->) ::+  (Monad m, Expectable cls name m r ex) =>+  ex ->+  r ->+  Rule cls name m r+m |-> r = m |=> const (return r)++infixl 1 |->++instance Expectable cls name m r (Rule cls name m r) where+  toRule = id++instance Expectable cls name m r (Matcher cls name m r) where+  toRule m = m :=> []
src/Test/HMock/TH.hs view
@@ -1,40 +1,714 @@-{- |--This module provides Template Haskell splices that can be used to derive-boilerplate instances for HMock.--There are 12 splices described here, based on all combinations of three choices:--* Whether to generate a 'Test.HMock.Mockable' instance, an instance for-  'Test.HMock.MockT', or both.-* Whether the argument is a class name, or a type which may be partially applied-  to concrete arguments.-* Whether options are passed to customize the behavior.--}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-} +-- | This module provides Template Haskell splices that can be used to derive+-- boilerplate instances for HMock.+--+-- There are 20 splices described here, based on combinations of four+-- choices:+--+-- * Whether to generate a 'Test.HMock.MockableBase', an instance for+--   'Test.HMock.MockT', or both.+-- * When generating 'Test.HMock.MockableBase', whether to also generate a+--   'Test.HMock.Mockable' instance with an empty setup.+-- * Whether the argument is a class name, or a type which may be partially+--   applied to concrete arguments.+-- * Whether options are passed to customize the behavior. module Test.HMock.TH-  ( makeMockable,-    makeMockableWithOptions,-    makeMockableBase,-    makeMockableBaseWithOptions,-    deriveMockable,-    deriveMockableWithOptions,-    deriveMockableBase,-    deriveMockableBaseWithOptions,-    deriveForMockT,-    deriveForMockTWithOptions,+  ( MockableOptions (..),+    makeMockable,     makeMockableType,+    makeMockableWithOptions,     makeMockableTypeWithOptions,+    makeMockableBase,     makeMockableBaseType,+    makeMockableBaseWithOptions,     makeMockableBaseTypeWithOptions,+    deriveMockable,     deriveMockableType,+    deriveMockableWithOptions,     deriveMockableTypeWithOptions,+    deriveMockableBase,     deriveMockableBaseType,+    deriveMockableBaseWithOptions,     deriveMockableBaseTypeWithOptions,+    deriveForMockT,     deriveTypeForMockT,+    deriveForMockTWithOptions,     deriveTypeForMockTWithOptions,-    MockableOptions (..),   ) where +import Control.Monad (replicateM, unless, when, zipWithM)+import Control.Monad.Extra (concatMapM)+import Control.Monad.Trans (MonadIO)+import Data.Bool (bool)+import Data.Char (toUpper)+import Data.Default (Default (..))+import Data.Either (partitionEithers)+import qualified Data.Kind+import Data.List (foldl', (\\))+import Data.Typeable (Typeable)+import GHC.Stack (HasCallStack)+import GHC.TypeLits (Symbol)+import Language.Haskell.TH hiding (Match, match)+import Language.Haskell.TH.Syntax (Lift (lift)) import Test.HMock.Internal.TH+import Test.HMock.MockT (MockT)+import Test.HMock.MockMethod (mockMethod, mockDefaultlessMethod)+import Test.HMock.Mockable (MatchResult (..), Mockable, MockableBase (..))+import Test.HMock.Predicates (Predicate (..), eq)+import Test.HMock.Rule (Expectable (..))++-- | Custom options for deriving a 'Mockable' class.+data MockableOptions = MockableOptions+  { -- | Suffix to add to 'Action' and 'Matcher' names.  Defaults to @""@.+    mockSuffix :: String,+    -- | Whether to warn about limitations of the generated mocks.  This is+    -- mostly useful temporarily for finding out why generated code doesn't+    -- match your expectations.  Defaults to @'False'@.+    mockVerbose :: Bool+  }++instance Default MockableOptions where+  def = MockableOptions {mockSuffix = "", mockVerbose = False}++-- | Define all instances necessary to use HMock with the given class.+-- Equivalent to both 'deriveMockable' and 'deriveForMockT'.+--+-- If @MyClass@ is a class and @myMethod@ is one of its methods, then+-- @'makeMockable' MyClass@ generates all of the following:+--+-- If @MyClass@ is a class and @myMethod@ is one of its methods, then+-- @'makeMockable' MyClass@ generates everything generated by+-- 'makeMockableBase', as well as a 'Mockable' instance that does no setup.+makeMockable :: Name -> Q [Dec]+makeMockable = makeMockableType . conT++-- | Define all instances necessary to use HMock with the given constraint type,+-- which should be a class applied to zero or more type arguments.  Equivalent+-- to both 'deriveMockableType' and 'deriveTypeForMockT'.+--+-- See 'makeMockable' for a list of what is generated by this splice.+makeMockableType :: Q Type -> Q [Dec]+makeMockableType = makeMockableTypeWithOptions def++-- | Define all instances necessary to use HMock with the given class.  This is+-- like 'makeMockable', but with the ability to specify custom options.+--+-- See 'makeMockable' for a list of what is generated by this splice.+makeMockableWithOptions :: MockableOptions -> Name -> Q [Dec]+makeMockableWithOptions options = makeMockableTypeWithOptions options . conT++-- | Define all instances necessary to use HMock with the given constraint type,+-- which should be a class applied to zero or more type arguments.  This is+-- like 'makeMockableType', but with the ability to specify custom options.+--+-- See 'makeMockable' for a list of what is generated by this splice.+makeMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]+makeMockableTypeWithOptions options qt =+  (++) <$> deriveMockableTypeWithOptions options qt+    <*> deriveTypeForMockTWithOptions options qt++-- | Defines almost all instances necessary to use HMock with the given class.+-- Equivalent to both 'deriveMockableBase' and 'deriveForMockT'.+makeMockableBase :: Name -> Q [Dec]+makeMockableBase = makeMockableBaseType . conT++-- | Defines almost all instances necessary to use HMock with the given+-- constraint type, which should be a class applied to zero or more type+-- arguments.  Equivalent to both 'deriveMockableBaseType' and+-- 'deriveTypeForMockT'.+makeMockableBaseType :: Q Type -> Q [Dec]+makeMockableBaseType = makeMockableBaseTypeWithOptions def++-- | Defines almost all instances necessary to use HMock with the given class.+-- This is like 'makeMockable', but with the ability to specify custom options.+makeMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]+makeMockableBaseWithOptions options =+  makeMockableBaseTypeWithOptions options . conT++-- | Defines almost all instances necessary to use HMock with the given+-- constraint type, which should be a class applied to zero or more type+-- arguments.  This is like 'makeMockableType', but with the ability to specify+-- custom options.+makeMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]+makeMockableBaseTypeWithOptions options qt =+  (++) <$> deriveMockableBaseTypeWithOptions options qt+    <*> deriveTypeForMockTWithOptions options qt++-- | Defines the 'Mockable' instance for the given class.+--+-- If @MyClass@ is a class and @myMethod@ is one of its methods, then+-- @'deriveMockable' MyClass@ generates everything generated by+-- 'makeMockableBase', as well as a 'Mockable' instance that does no setup.+deriveMockable :: Name -> Q [Dec]+deriveMockable = deriveMockableType . conT++-- | Defines the 'Mockable' instance for the given constraint type, which should+-- be a class applied to zero or more type arguments.+--+-- See 'deriveMockable' for a list of what is generated by this splice.+deriveMockableType :: Q Type -> Q [Dec]+deriveMockableType = deriveMockableTypeWithOptions def++-- | Defines the 'Mockable' instance for the given class.  This is like+-- 'deriveMockable', but with the ability to specify custom options.+--+-- See 'deriveMockable' for a list of what is generated by this splice.+deriveMockableWithOptions :: MockableOptions -> Name -> Q [Dec]+deriveMockableWithOptions options = deriveMockableTypeWithOptions options . conT++-- | Defines the 'Mockable' instance for the given constraint type, which should+-- be a class applied to zero or more type arguments.  This is like+-- 'deriveMockableType', but with the ability to specify custom options.+--+-- See 'deriveMockable' for a list of what is generated by this splice.+deriveMockableTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]+deriveMockableTypeWithOptions = deriveMockableImpl False++-- | Defines the 'MockableBase' instance for the given class.+--+-- If @MyClass@ is a class and @myMethod@ is one of its methods, then+-- @'deriveMockableBase' MyClass@ generates all of the following:+--+-- * A @'MockableBase' MyClass@ instance.+-- * An associated type @'Action' MyClass@, with a constructor @MyMethod@.+-- * An associated type @'Matcher' MyClass@, with a constructor @MyMethod_@.+-- * An 'Expectable' instance for @'Action' MyClass@ which matches an exact set+--   of arguments, if and only if all of @myMethod@'s arguments have 'Eq' and+--   'Show' instances.+deriveMockableBase :: Name -> Q [Dec]+deriveMockableBase = deriveMockableBaseType . conT++-- | Defines the 'MockableBase' instance for the given constraint type, which+-- should be a class applied to zero or more type arguments.+--+-- See 'deriveMockableBase' for a list of what is generated by this splice.+deriveMockableBaseType :: Q Type -> Q [Dec]+deriveMockableBaseType = deriveMockableBaseTypeWithOptions def++-- | Defines the 'MockableBase' instance for the given class.  This is like+-- 'deriveMockableBase', but with the ability to specify custom options.+--+-- See 'deriveMockableBase' for a list of what is generated by this splice.+deriveMockableBaseWithOptions :: MockableOptions -> Name -> Q [Dec]+deriveMockableBaseWithOptions options =+  deriveMockableBaseTypeWithOptions options . conT++-- | Defines the 'MockableBase' instance for the given constraint type, which+-- should be a class applied to zero or more type arguments.  This is like+-- 'deriveMockableBaseType', but with the ability to specify custom options.+--+-- See 'deriveMockableBase' for a list of what is generated by this splice.+deriveMockableBaseTypeWithOptions :: MockableOptions -> Q Type -> Q [Dec]+deriveMockableBaseTypeWithOptions = deriveMockableImpl True++-- | Defines an instance of the given class for @'MockT' m@, delegating all of+-- its methods to 'mockMethod' to be handled by HMock.+--+-- This may only be used if all members of the class are mockable methods.  If+-- the class contains some unmockable methods, associated types, or other+-- members, you will need to define this instance yourself, delegating the+-- mockable methods as follows:+--+-- @+-- instance MyClass ('MockT' m) where+--   myMethod x y = 'mockMethod' (MyMethod x y)+--   ...+-- @+deriveForMockT :: Name -> Q [Dec]+deriveForMockT = deriveTypeForMockT . conT++-- | Defines an instance of the given constraint type for @'MockT' m@,+-- delegating all of its methods to 'mockMethod' to be handled by HMock.+-- The type should be a class applied to zero or more type arguments.+--+-- See 'deriveForMockT' for restrictions on the use of this splice.+deriveTypeForMockT :: Q Type -> Q [Dec]+deriveTypeForMockT = deriveTypeForMockTWithOptions def++-- | Defines an instance of the given class for @'MockT' m@, delegating all of+-- its methods to 'mockMethod' to be handled by HMock.  This is like+-- 'deriveForMockT', but with the ability to specify custom options.+--+-- See 'deriveForMockT' for restrictions on the use of this splice.+deriveForMockTWithOptions :: MockableOptions -> Name -> Q [Dec]+deriveForMockTWithOptions options = deriveTypeForMockTWithOptions options . conT++-- | Defines an instance of the given constraint type for @'MockT' m@,+-- delegating all of its methods to 'mockMethod' to be handled by HMock.+-- The type should be a class applied to zero or more type arguments.  This is+-- like 'deriveTypeForMockT', but with the ability to specify custom options.+--+-- See 'deriveForMockT' for restrictions on the use of this splice.+deriveTypeForMockTWithOptions :: MockableOptions -> Q Type -> Q [Dec]+deriveTypeForMockTWithOptions = deriveForMockTImpl++data Instance = Instance+  { instType :: Type,+    instRequiredContext :: Cxt,+    instGeneralParams :: [Name],+    instMonadVar :: Name,+    instMethods :: [Method],+    instExtraMembers :: [Dec]+  }+  deriving (Show)++data Method = Method+  { methodName :: Name,+    methodTyVars :: [Name],+    methodCxt :: Cxt,+    methodArgs :: [Type],+    methodResult :: Type+  }+  deriving (Show)++withClass :: Type -> (Dec -> Q a) -> Q a+withClass t f = do+  case unappliedName t of+    Just cls -> do+      info <- reify cls+      case info of+        ClassI dec@ClassD {} _ -> f dec+        _ -> fail $ "Expected " ++ show cls ++ " to be a class, but it wasn't."+    _ -> fail "Expected a class, but got something else."++getInstance :: MockableOptions -> Type -> Q Instance+getInstance options ty = withClass ty go+  where+    go (ClassD _ className [] _ _) =+      fail $ "Class " ++ nameBase className ++ " has no type parameters."+    go (ClassD cx _ params _ members) = matchVars ty [] (tvName <$> params)+      where+        matchVars :: Type -> [Type] -> [Name] -> Q Instance+        matchVars _ _ [] = internalError+        matchVars (AppT _ _) _ [_] =+          fail $ pprint ty ++ " is applied to too many arguments."+        matchVars (AppT a b) ts (_ : ps) =+          checkExt FlexibleInstances >> matchVars a (b : ts) ps+        matchVars _ ts ps = do+          let t = foldl' (\t' v -> AppT t' (VarT v)) ty (init ps)+          let tbl = zip (tvName <$> params) ts+          let cx' = substTypeVars tbl <$> cx+          makeInstance options t cx' tbl (init ps) (last ps) members+    go _ = internalError++makeInstance ::+  MockableOptions ->+  Type ->+  Cxt ->+  [(Name, Type)] ->+  [Name] ->+  Name ->+  [Dec] ->+  Q Instance+makeInstance options ty cx tbl ps m members = do+  processedMembers <- mapM (getMethod ty m tbl) members+  (extraMembers, methods) <-+    partitionEithers <$> zipWithM memberOrMethod members processedMembers+  return $+    Instance+      { instType = ty,+        instRequiredContext = cx,+        instGeneralParams = ps,+        instMonadVar = m,+        instMethods = methods,+        instExtraMembers = extraMembers+      }+  where+    memberOrMethod :: Dec -> Either String Method -> Q (Either Dec Method)+    memberOrMethod dec (Left warning) = do+      when (mockVerbose options) $ reportWarning warning+      return (Left dec)+    memberOrMethod _ (Right method) = return (Right method)++getMethod :: Type -> Name -> [(Name, Type)] -> Dec -> Q (Either String Method)+getMethod instTy m tbl (SigD name ty) = do+  simpleTy <- localizeMember instTy m (substTypeVars tbl ty)+  return $ do+    let (tvs, cx, argsAndReturn) = splitType simpleTy+    (m', result) <- case last argsAndReturn of+      AppT (VarT m') result -> return (m', result)+      _ ->+        Left $+          nameBase name+            ++ " can't be mocked: non-monadic result."+    when (m' /= m) $+      Left $+        nameBase name+          ++ " can't be mocked: return value in wrong monad."+    when (relevantContext result (tvs, cx) /= ([], [])) $+      Left $+        nameBase name+          ++ " can't be mocked: polymorphic return value."+    let argTypes =+          map+            (substTypeVar m (AppT (ConT ''MockT) (VarT m)))+            (init argsAndReturn)+    when (any hasNestedPolyType argTypes) $+      Left $+        nameBase name+          ++ " can't be mocked: rank-n types nested in arguments."+    return $+      Method+        { methodName = name,+          methodTyVars = tvs,+          methodCxt = cx,+          methodArgs = argTypes,+          methodResult = result+        }+getMethod _ _ _ _ = return (Left "A non-value member cannot be mocked.")++isKnownType :: Method -> Type -> Bool+isKnownType method ty = null tyVars && null cx+  where+    (tyVars, cx) =+      relevantContext ty (methodTyVars method, methodCxt method)++withMethodParams :: Instance -> Method -> TypeQ -> TypeQ+withMethodParams inst method t =+  [t|+    $t+      $(pure (instType inst))+      $(litT (strTyLit (nameBase (methodName method))))+      $(varT (instMonadVar inst))+      $(pure (methodResult method))+    |]++deriveMockableImpl :: Bool -> MockableOptions -> Q Type -> Q [Dec]+deriveMockableImpl baseOnly options qt = do+  checkExt DataKinds+  checkExt FlexibleInstances+  checkExt GADTs+  checkExt MultiParamTypeClasses+  checkExt TypeFamilies++  inst <- getInstance options =<< qt++  when (null (instMethods inst)) $ do+    fail $+      "Cannot derive Mockable because " ++ pprint (instType inst)+        ++ " has no mockable methods."++  typeableCxts <- constrainVars [conT ''Typeable] (instGeneralParams inst)++  mockableBase <-+    instanceD+      (pure typeableCxts)+      [t|MockableBase $(pure (instType inst))|]+      [ defineActionType options inst,+        defineMatcherType options inst,+        defineShowAction options (instMethods inst),+        defineShowMatcher options (instMethods inst),+        defineMatchAction options (instMethods inst)+      ]+  mockable <-+    if baseOnly+      then return []+      else+        (: [])+          <$> instanceD+            (pure typeableCxts)+            [t|Mockable $(pure (instType inst))|]+            []+  expectables <- defineExpectableActions options inst++  return $ mockableBase : mockable ++ expectables++defineActionType :: MockableOptions -> Instance -> DecQ+defineActionType options inst = do+  kind <-+    [t|+      Symbol ->+      (Data.Kind.Type -> Data.Kind.Type) ->+      Data.Kind.Type ->+      Data.Kind.Type+      |]+  let cons = actionConstructor options inst <$> instMethods inst+  dataInstD (pure []) ''Action [pure (instType inst)] (Just kind) cons []++actionConstructor :: MockableOptions -> Instance -> Method -> ConQ+actionConstructor options inst method = do+  forallC [] (return (methodCxt method)) $+    gadtC+      [getActionName options method]+      [ return (Bang NoSourceUnpackedness NoSourceStrictness, argTy)+        | argTy <- methodArgs method+      ]+      (withMethodParams inst method [t|Action|])++getActionName :: MockableOptions -> Method -> Name+getActionName options method =+  mkName (map toUpper (take 1 name) ++ drop 1 name ++ mockSuffix options)+  where+    name = nameBase (methodName method)++defineMatcherType :: MockableOptions -> Instance -> Q Dec+defineMatcherType options inst = do+  kind <-+    [t|+      Symbol ->+      (Data.Kind.Type -> Data.Kind.Type) ->+      Data.Kind.Type ->+      Data.Kind.Type+      |]+  let cons = matcherConstructor options inst <$> instMethods inst+  dataInstD (pure []) ''Matcher [pure (instType inst)] (Just kind) cons []++matcherConstructor :: MockableOptions -> Instance -> Method -> ConQ+matcherConstructor options inst method = do+  gadtC+    [getMatcherName options method]+    [ (Bang NoSourceUnpackedness NoSourceStrictness,) <$> mkPredicate argTy+      | argTy <- methodArgs method+    ]+    (withMethodParams inst method [t|Matcher|])+  where+    mkPredicate argTy+      | hasPolyType argTy = do+        checkExt RankNTypes+        v <- newName "t"+        forallT [bindVar v] (pure []) [t|Predicate $(varT v)|]+      | null tyVars && null cx = [t|Predicate $(pure argTy)|]+      | otherwise = do+        checkExt RankNTypes+        forallT (bindVar <$> tyVars) (pure cx) [t|Predicate $(pure argTy)|]+      where+        (tyVars, cx) =+          relevantContext argTy (methodTyVars method, methodCxt method)++getMatcherName :: MockableOptions -> Method -> Name+getMatcherName options method =+  mkName (map toUpper (take 1 name) ++ drop 1 name ++ mockSuffix options ++ "_")+  where+    name = nameBase (methodName method)++defineShowAction :: MockableOptions -> [Method] -> Q Dec+defineShowAction options methods =+  funD 'showAction (showActionClause options <$> methods)++showActionClause :: MockableOptions -> Method -> Q Clause+showActionClause options method = do+  argVars <- replicateM (length (methodArgs method)) (newName "a")+  clause+    [ conP+        (getActionName options method)+        (zipWith argPattern (methodArgs method) argVars)+    ]+    ( normalB+        [|+          unwords+            ( $(lift (nameBase (methodName method))) :+              $(listE (zipWith showArg (methodArgs method) argVars))+            )+          |]+    )+    []+  where+    canShow ty+      | not (null (freeTypeVars ty)) = return False+      | otherwise = isInstance ''Show [ty]+    argPattern ty v = canShow ty >>= bool wildP (varP v)+    showArg ty var =+      canShow ty+        >>= bool+          (lift ("(_ :: " ++ pprint (removeModNames ty) ++ ")"))+          [|showsPrec 11 $(varE var) ""|]++defineShowMatcher :: MockableOptions -> [Method] -> Q Dec+defineShowMatcher options methods = do+  clauses <- concatMapM (showMatcherClauses options) methods+  funD 'showMatcher clauses++showMatcherClauses :: MockableOptions -> Method -> Q [ClauseQ]+showMatcherClauses options method = do+  argTVars <- replicateM (length (methodArgs method)) (newName "t")+  predVars <- replicateM (length (methodArgs method)) (newName "p")+  let actionArgs = zipWith actionArg argTVars (methodArgs method)+  let matcherArgs = varP <$> predVars+  let printedArgs = zipWith3 printedArg predVars argTVars (methodArgs method)+  let polyMatcherArgs = zipWith matcherArg predVars (methodArgs method)+  let printedPolyArgs = zipWith printedPolyArg predVars (methodArgs method)+  let body name args = normalB [|unwords ($(lift name) : $(listE args))|]+  return+    [ clause+        [ conP 'Just [conP (getActionName options method) actionArgs],+          conP (getMatcherName options method) matcherArgs+        ]+        (body (nameBase (methodName method)) printedArgs)+        [],+      clause+        [ conP 'Nothing [],+          conP (getMatcherName options method) polyMatcherArgs+        ]+        (body (nameBase (methodName method)) printedPolyArgs)+        []+    ]+  where+    actionArg t ty+      | isKnownType method ty = wildP+      | otherwise = checkExt ScopedTypeVariables >> sigP wildP (varT t)++    matcherArg p ty+      | isKnownType method ty = varP p+      | otherwise = wildP++    printedArg p t ty+      | isKnownType method ty = [|"«" ++ show $(varE p) ++ "»"|]+      | otherwise =+        [|"«" ++ show ($(varE p) :: Predicate $(varT t)) ++ "»"|]++    printedPolyArg p ty+      | isKnownType method ty = [|"«" ++ show $(varE p) ++ "»"|]+      | otherwise = [|"«polymorphic»"|]++defineMatchAction :: MockableOptions -> [Method] -> Q Dec+defineMatchAction options methods =+  funD 'matchAction (matchActionClause options <$> methods)++matchActionClause :: MockableOptions -> Method -> Q Clause+matchActionClause options method = do+  argVars <-+    replicateM+      (length (methodArgs method))+      ((,) <$> newName "p" <*> newName "a")+  mmVar <- newName "mismatches"+  clause+    [ conP+        (getMatcherName options method)+        (varP . fst <$> argVars),+      conP (getActionName options method) (varP . snd <$> argVars)+    ]+    ( guardedB+        [ (,) <$> normalG [|$(varE mmVar) == 0|] <*> [|Match|],+          (,) <$> normalG [|otherwise|] <*> [|NoMatch $(varE mmVar)|]+        ]+    )+    [ valD+        (varP mmVar)+        (normalB [|length (filter not $(listE (mkAccept <$> argVars)))|])+        []+    ]+  where+    mkAccept (p, a) = [|accept $(return (VarE p)) $(return (VarE a))|]++defineExpectableActions :: MockableOptions -> Instance -> Q [Dec]+defineExpectableActions options inst =+  concatMapM (defineExpectableAction options inst) (instMethods inst)++defineExpectableAction :: MockableOptions -> Instance -> Method -> Q [Dec]+defineExpectableAction options inst method = do+  maybeCxt <- wholeCxt (methodArgs method)+  argVars <- replicateM (length (methodArgs method)) (newName "a")+  case maybeCxt of+    Just cx -> do+      (: [])+        <$> instanceD+          (pure (methodCxt method ++ cx))+          ( appT+              (withMethodParams inst method [t|Expectable|])+              (withMethodParams inst method [t|Action|])+          )+          [ funD+              'toRule+              [ clause+                  [conP (getActionName options method) (map varP argVars)]+                  ( normalB $+                      let matcherCon = conE (getMatcherName options method)+                       in appE (varE 'toRule) (makeBody argVars matcherCon)+                  )+                  []+              ]+          ]+    _ -> pure []+  where+    makeBody [] e = e+    makeBody (v : vs) e = makeBody vs [|$e (eq $(varE v))|]++    wholeCxt :: [Type] -> Q (Maybe Cxt)+    wholeCxt (ty : ts) = do+      thisCxt <- argCxt ty+      otherCxt <- wholeCxt ts+      return ((++) <$> thisCxt <*> otherCxt)+    wholeCxt [] = return (Just [])++    argCxt :: Type -> Q (Maybe Cxt)+    argCxt argTy+      | not (isKnownType method argTy) = return Nothing+      | VarT v <- argTy =+        Just <$> sequence [[t|Eq $(varT v)|], [t|Show $(varT v)|]]+      | otherwise = do+        eqCxt <- resolveInstance ''Eq argTy+        showCxt <- resolveInstance ''Show argTy+        return ((++) <$> eqCxt <*> showCxt)++deriveForMockTImpl :: MockableOptions -> Q Type -> Q [Dec]+deriveForMockTImpl options qt = do+  inst <- getInstance options =<< qt++  unless (null (instExtraMembers inst)) $+    fail $+      "Cannot derive MockT because " ++ pprint (instType inst)+        ++ " has unmockable methods."++  m <- newName "m"+  let decs = map (implementMethod options) (instMethods inst)++  let cx =+        instRequiredContext inst+          \\ [ AppT (ConT ''Typeable) (VarT (instMonadVar inst)),+               AppT (ConT ''Functor) (VarT (instMonadVar inst)),+               AppT (ConT ''Applicative) (VarT (instMonadVar inst)),+               AppT (ConT ''Monad) (VarT (instMonadVar inst)),+               AppT (ConT ''MonadIO) (VarT (instMonadVar inst))+             ]++  simplifyContext+    (substTypeVar (instMonadVar inst) (AppT (ConT ''MockT) (VarT m)) <$> cx)+    >>= \case+      Just cxMockT ->+        (: [])+          <$> instanceD+            ( concat+                <$> sequence+                  [ return cxMockT,+                    constrainVars [[t|Typeable|]] (instGeneralParams inst),+                    constrainVars [[t|Typeable|], [t|MonadIO|]] [m]+                  ]+            )+            [t|$(pure (instType inst)) (MockT $(varT m))|]+            decs+      Nothing -> fail "Missing MockT instance for a superclass."++implementMethod :: MockableOptions -> Method -> Q Dec+implementMethod options method = do+  argVars <- replicateM (length (methodArgs method)) (newName "a")+  funD+    (methodName method)+    [clause (varP <$> argVars) (normalB (body argVars)) []]+  where+    actionExp [] e = e+    actionExp (v : vs) e = actionExp vs [|$e $(varE v)|]++    body argVars = do+      defaultCxt <- resolveInstance ''Default (methodResult method)+      let someMockMethod = case defaultCxt of+            Just [] -> [|mockMethod|]+            _ -> [|mockDefaultlessMethod|]+      [|+        $someMockMethod+          $(actionExp argVars (conE (getActionName options method)))+        |]++checkExt :: Extension -> Q ()+checkExt e = do+  enabled <- isExtEnabled e+  unless enabled $+    fail $ "Please enable " ++ show e ++ " to generate this mock."++internalError :: HasCallStack => Q a+internalError = error "Internal error in HMock.  Please report this as a bug."
test/Classes.hs view
@@ -23,15 +23,10 @@ import Data.Dynamic (Typeable) import Data.Kind (Type) import Language.Haskell.TH.Syntax hiding (Type)-import QuasiMock (Action (..), Matcher (..))+import QuasiMock import Test.HMock-import Test.HMock.TH import Test.Hspec-import Util.TH (deriveRecursive, reifyInstancesStatic, reifyStatic)--#if !MIN_VERSION_base(4, 13, 0)-import Control.Monad.Fail (MonadFail)-#endif+import Util.DeriveRecursive (deriveRecursive)  #if MIN_VERSION_template_haskell(2, 16, 0) -- Pre-define low-level instance to prevent deriveRecursive from trying.@@ -50,14 +45,13 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadSimple |-> $(reifyStatic ''MonadSimple)-+        $(onReify [|expectAny|] ''MonadSimple)         runQ (makeMockable ''MonadSimple)       evaluate (rnf decs)    it "doesn't require unnecessary extensions for simple cases" $     example . runMockT $ do-      expectAny $ QReify ''MonadSimple |-> $(reifyStatic ''MonadSimple)+      $(onReify [|expectAny|] ''MonadSimple)       expectAny $ QIsExtEnabled ScopedTypeVariables |-> False       expectAny $ QIsExtEnabled RankNTypes |-> False @@ -68,7 +62,7 @@     example $ do       let missingGADTs = runMockT $ do             expectAny $ QIsExtEnabled GADTs |-> False-            expect $ QReport_ anything (hasSubstr "Please enable GADTs") |-> ()+            expect $ QReport_ anything (hasSubstr "Please enable GADTs")              _ <- runQ (makeMockable ''MonadSimple)             return ()@@ -79,8 +73,7 @@     example $ do       let missingTypeFamilies = runMockT $ do             expectAny $ QIsExtEnabled TypeFamilies |-> False-            expect $-              QReport_ anything (hasSubstr "Please enable TypeFamilies") |-> ()+            expect $ QReport_ anything (hasSubstr "Please enable TypeFamilies")              _ <- runQ (makeMockable ''MonadSimple)             return ()@@ -91,8 +84,7 @@     example $ do       let missingDataKinds = runMockT $ do             expectAny $ QIsExtEnabled DataKinds |-> False-            expect $-              QReport_ anything (hasSubstr "Please enable DataKinds") |-> ()+            expect $ QReport_ anything (hasSubstr "Please enable DataKinds")              _ <- runQ (makeMockable ''MonadSimple)             return ()@@ -105,7 +97,6 @@             expectAny $ QIsExtEnabled FlexibleInstances |-> False             expect $               QReport_ anything (hasSubstr "Please enable FlexibleInstances")-                |-> ()              _ <- runQ (makeMockable ''MonadSimple)             return ()@@ -120,7 +111,6 @@               QReport_                 anything                 (hasSubstr "Please enable MultiParamTypeClasses")-                |-> ()              _ <- runQ (makeMockable ''MonadSimple)             return ()@@ -130,10 +120,9 @@   it "fails when too many params are given" $     example $ do       let tooManyParams = runMockT $ do-            expectAny $ QReify ''MonadSimple |-> $(reifyStatic ''MonadSimple)+            $(onReify [|expectAny|] ''MonadSimple)             expect $               QReport_ anything (hasSubstr "is applied to too many arguments")-                |-> ()              _ <- runQ (makeMockableType [t|MonadSimple IO|])             return ()@@ -143,11 +132,11 @@   it "is mockable" $     example $ do       let success = runMockT $ do-            expect $ Simple "foo" |-> ()+            expect $ Simple "foo"             simple "foo"            failure = runMockT $ do-            expect $ Simple "foo" |-> ()+            expect $ Simple "foo"             simple "bar"        success@@ -163,19 +152,18 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadSuffix |-> $(reifyStatic ''MonadSuffix)-+        $(onReify [|expectAny|] ''MonadSuffix)         runQ (makeMockableWithOptions def {mockSuffix = "Blah"} ''MonadSuffix)       evaluate (rnf decs)    it "is mockable" $     example $ do       let success = runMockT $ do-            expect $ SuffixBlah "foo" |-> ()+            expect $ SuffixBlah "foo"             suffix "foo"            failure = runMockT $ do-            expect $ SuffixBlah "foo" |-> ()+            expect $ SuffixBlah "foo"             suffix "bar"        success@@ -188,15 +176,14 @@  instance Mockable MonadWithSetup where   setupMockable _ = do-    byDefault $ WithSetup |-> "custom default"+    allowUnexpected $ WithSetup |-> "custom default"  setupTests :: SpecWith () setupTests = describe "MonadWithSetup" $ do   it "generates mock impl" $ do     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadWithSetup |-> $(reifyStatic ''MonadWithSetup)-+        $(onReify [|expectAny|] ''MonadWithSetup)         runQ (makeMockableBase ''MonadWithSetup)       evaluate (rnf decs) @@ -208,6 +195,23 @@         result <- withSetup         liftIO (result `shouldBe` "custom default") +  it "uses default in a nested context" $ do+    example $+      runMockT $ do+        nestMockT $ do+          result <- withSetup+          liftIO (result `shouldBe` "custom default")++  it "retains default when initialized in nested context" $ do+    example $+      runMockT $ do+        nestMockT $ do+          _ <- withSetup+          return ()+        result <- withSetup++        liftIO (result `shouldBe` "custom default")+ class SuperClass (m :: Type -> Type)  instance SuperClass m@@ -222,16 +226,14 @@   it "generated mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadSuper |-> $(reifyStatic ''MonadSuper)+        $(onReify [|expectAny|] ''MonadSuper)         expectAny $           QReifyInstances_             (eq ''SuperClass)             $(qMatch [p|[AppT (ConT (Name (OccName "MockT") _)) (VarT _)]|])-            |-> $( do-                     v <- runQ (newName "m")-                     reifyInstancesStatic-                       ''SuperClass-                       [AppT (ConT ''MockT) (VarT v)]+            |-> $( reifyInstancesStatic+                     ''SuperClass+                     [AppT (ConT ''MockT) (VarT (mkName "v"))]                  )          runQ (makeMockable ''MonadSuper)@@ -240,7 +242,7 @@   it "is mockable" $     example $ do       let success = runMockT $ do-            expect $ WithSuper |-> ()+            expect WithSuper             withSuper            failure = runMockT withSuper@@ -259,19 +261,18 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadMPTC |-> $(reifyStatic ''MonadMPTC)-+        $(onReify [|expectAny|] ''MonadMPTC)         runQ (makeMockable ''MonadMPTC)       evaluate (rnf decs)    it "is mockable" $     example $ do       let success = runMockT $ do-            expect $ Mptc "foo" |-> ()+            expect $ Mptc "foo"             mptc "foo"            failure = runMockT $ do-            expect $ Mptc "foo" |-> ()+            expect $ Mptc "foo"             mptc "bar"        success@@ -287,10 +288,7 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $-          QReify ''MonadFDSpecialized-            |-> $(reifyStatic ''MonadFDSpecialized)-+        $(onReify [|expectAny|] ''MonadFDSpecialized)         runQ (makeMockableType [t|MonadFDSpecialized String|])       evaluate (rnf decs) @@ -327,8 +325,7 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadFDGeneral |-> $(reifyStatic ''MonadFDGeneral)-+        $(onReify [|expectAny|] ''MonadFDGeneral)         runQ (deriveMockable ''MonadFDGeneral)       evaluate (rnf decs) @@ -356,7 +353,7 @@ fdMixedTests = describe "MonadFDMixed" $ do   it "generates mock impl" $     example . runMockT $ do-      expectAny $ QReify ''MonadFDMixed |-> $(reifyStatic ''MonadFDMixed)+      $(onReify [|expectAny|] ''MonadFDMixed)        decs1 <- runQ (deriveMockableType [t|MonadFDMixed String Int|])       decs2 <-@@ -389,20 +386,17 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadPolyArg |-> $(reifyStatic ''MonadPolyArg)-+        $(onReify [|expectAny|] ''MonadPolyArg)         runQ (makeMockable ''MonadPolyArg)       evaluate (rnf decs)    it "fails without ScopedTypeVariables" $     example $ do       let missingScopedTypeVariables = runMockT $ do-            expectAny $-              QReify ''MonadPolyArg |-> $(reifyStatic ''MonadPolyArg)+            $(onReify [|expectAny|] ''MonadPolyArg)             expectAny $ QIsExtEnabled ScopedTypeVariables |-> False             expect $               QReport_ anything (hasSubstr "Please enable ScopedTypeVariables")-                |-> ()              _ <- runQ (makeMockable ''MonadPolyArg)             return ()@@ -412,10 +406,10 @@   it "fails without RankNTypes" $     example $ do       let missingRankNTypes = runMockT $ do-            expectAny $ QReify ''MonadPolyArg |-> $(reifyStatic ''MonadPolyArg)+            $(onReify [|expectAny|] ''MonadPolyArg)             expectAny $ QIsExtEnabled RankNTypes |-> False             expect $-              QReport_ anything (hasSubstr "Please enable RankNTypes") |-> ()+              QReport_ anything (hasSubstr "Please enable RankNTypes")              _ <- runQ (makeMockable ''MonadPolyArg)             return ()@@ -426,12 +420,12 @@     example $ do       let success = runMyBase . runMockT $ do             expect $-              PolyArg_ (eq "foo") (with fromEnum (eq 1)) anything |-> ()+              PolyArg_ (eq "foo") (with fromEnum (eq 1)) anything             polyArg "foo" (toEnum 1 :: Bool) "hello"            failure = runMyBase . runMockT $ do             expect $-              PolyArg_ (eq "foo") (with fromEnum (eq 1)) anything |-> ()+              PolyArg_ (eq "foo") (with fromEnum (eq 1)) anything             polyArg "foo" (toEnum 2 :: Bool) "hello"        success@@ -447,20 +441,18 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $-          QReify ''MonadUnshowableArg |-> $(reifyStatic ''MonadUnshowableArg)-+        $(onReify [|expectAny|] ''MonadUnshowableArg)         runQ (makeMockable ''MonadUnshowableArg)       evaluate (rnf decs)    it "is mockable" $     example $ do       let success = runMyBase . runMockT $ do-            expect $ UnshowableArg_ anything |-> ()+            expect $ UnshowableArg_ anything             unshowableArg (+ 1)            failure = runMyBase . runMockT $ do-            expect $ UnshowableArg_ anything |-> ()+            expect $ UnshowableArg_ anything              unshowableArg (+ 1)             unshowableArg (+ 1)@@ -478,19 +470,18 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadInArg |-> $(reifyStatic ''MonadInArg)-+        $(onReify [|expectAny|] ''MonadInArg)         runQ (makeMockable ''MonadInArg)       evaluate (rnf decs)    it "is mockable" $     example $ do       let success = runMyBase . runMockT $ do-            expect $ MonadInArg_ anything |-> ()+            expect $ MonadInArg_ anything             monadInArg (const (return ()))            failure = runMyBase . runMockT $ do-            expect $ UnshowableArg_ anything |-> ()+            expect $ UnshowableArg_ anything              monadInArg (const (return ()))             monadInArg (const (return ()))@@ -523,36 +514,27 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $-          QReify ''MonadExtraneousMembers-            |-> $(reifyStatic ''MonadExtraneousMembers)-+        $(onReify [|expectAny|] ''MonadExtraneousMembers)         runQ (deriveMockable ''MonadExtraneousMembers)       evaluate (rnf decs)    it "warns about non-methods" $     example $ do       decs <- runMockT $ do-        expectAny $-          QReify ''MonadExtraneousMembers-            |-> $(reifyStatic ''MonadExtraneousMembers)-        expect $ QReport False "A non-value member cannot be mocked." |-> ()+        $(onReify [|expectAny|] ''MonadExtraneousMembers)+        expect $ QReport False "A non-value member cannot be mocked."         expect $           QReport False "favoriteNumber can't be mocked: non-monadic result."-            |-> ()         expect $           QReport             False             "wrongMonad can't be mocked: return value in wrong monad."-            |-> ()         expect $           QReport False "polyResult can't be mocked: polymorphic return value."-            |-> ()         expect $           QReport             False             "nestedRankN can't be mocked: rank-n types nested in arguments."-            |-> ()          runQ           ( deriveMockableWithOptions@@ -564,11 +546,9 @@   it "fails to derive MockT when class has extra methods" $     example $ do       let unmockableMethods = runMockT $ do-            expectAny $-              QReify ''MonadExtraneousMembers-                |-> $(reifyStatic ''MonadExtraneousMembers)+            $(onReify [|expectAny|] ''MonadExtraneousMembers)             expect $-              QReport_ anything (hasSubstr "has unmockable methods") |-> ()+              QReport_ anything (hasSubstr "has unmockable methods")              _ <- runQ (makeMockable ''MonadExtraneousMembers)             return ()@@ -578,11 +558,11 @@   it "is mockable" $     example $ do       let success = runMyBase . runMockT $ do-            expect $ MockableMethod 42 |-> ()+            expect $ MockableMethod 42             mockableMethod (favoriteNumber (SomeCon @(MockT IO)))            failure = runMyBase . runMockT $ do-            expect $ MockableMethod 42 |-> ()+            expect $ MockableMethod 42             mockableMethod 12        success@@ -598,19 +578,18 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $ QReify ''MonadRankN |-> $(reifyStatic ''MonadRankN)-+        $(onReify [|expectAny|] ''MonadRankN)         runQ (deriveMockable ''MonadRankN)       evaluate (rnf decs)    it "is mockable" $     example $ do       let success = runMockT $ do-            expect $ RankN_ anything (eq True) |-> ()+            expect $ RankN_ anything (eq True)             rankN (const True) True            failure = runMockT $ do-            expect $ RankN_ anything (eq True) |-> ()+            expect $ RankN_ anything (eq True)             rankN (const True) False        success@@ -634,11 +613,8 @@     it "generates mock impl" $       example $ do         decs <- runMockT $ do-          expectAny $-            QReify ''MonadManyReturns |-> $(reifyStatic ''MonadManyReturns)-          expectAny $-            QReifyInstances ''Default [ConT ''NoDefault]-              |-> $(reifyInstancesStatic ''Default [ConT ''NoDefault])+          $(onReify [|expectAny|] ''MonadManyReturns)+          $(onReifyInstances [|expectAny|] ''Default [ConT ''NoDefault])            runQ (makeMockable ''MonadManyReturns)         evaluate (rnf decs)@@ -692,19 +668,11 @@   it "generates mock impl" $     example $ do       decs <- runMockT $ do-        expectAny $-          QReify ''MonadNestedNoDef |-> $(reifyStatic ''MonadNestedNoDef)-        expectAny $-          QReifyInstances-            ''Default-            [AppT (AppT (TupleT 2) (ConT ''NoDefault)) (ConT ''String)]-            |-> $( reifyInstancesStatic-                     ''Default-                     [AppT (AppT (TupleT 2) (ConT ''NoDefault)) (ConT ''String)]-                 )-        expectAny $-          QReifyInstances ''Default [ConT ''NoDefault]-            |-> $(reifyInstancesStatic ''Default [ConT ''NoDefault])+        $(onReify [|expectAny|] ''MonadNestedNoDef)+        $( [t|(NoDefault, String)|]+             >>= onReifyInstances [|expectAny|] ''Default . (: [])+         )+        $(onReifyInstances [|expectAny|] ''Default [ConT ''NoDefault])          runQ (makeMockable ''MonadNestedNoDef)       evaluate (rnf decs)@@ -722,7 +690,6 @@               QReport_                 anything                 (hasSubstr "Expected GHC.Types.Int to be a class")-                |-> ()              _ <- runQ (makeMockable ''Int)             return ()@@ -732,7 +699,7 @@   it "fails when given an unexpected type construct" $     example $ do       let notClass = runMockT $ do-            expect $ QReport_ anything (hasSubstr "Expected a class") |-> ()+            expect $ QReport_ anything (hasSubstr "Expected a class")              _ <- runQ (makeMockableType [t|(Int, String)|])             return ()@@ -742,13 +709,11 @@   it "fails when class has no params" $     example $ do       let tooManyParams = runMockT $ do-            expectAny $-              QReify ''ClassWithNoParams |-> $(reifyStatic ''ClassWithNoParams)+            $(onReify [|expectAny|] ''ClassWithNoParams)             expect $               QReport_                 anything                 (hasSubstr "ClassWithNoParams has no type parameters")-                |-> ()              _ <- runQ (makeMockable ''ClassWithNoParams)             return ()@@ -758,10 +723,8 @@   it "fails when class has no mockable methods" $     example $ do       let noMockableMethods = runMockT $ do-            expectAny $ QReify ''Show |-> $(reifyStatic ''Show)-            expect $-              QReport_ anything (hasSubstr "has no mockable methods") |-> ()-+            $(onReify [|expectAny|] ''Show)+            expect $ QReport_ anything (hasSubstr "has no mockable methods")             _ <- runQ (deriveMockable ''Show)             return () 
test/Core.hs view
@@ -17,7 +17,6 @@ import Data.IORef (newIORef, readIORef, writeIORef) import Data.List (isInfixOf, isPrefixOf) import Test.HMock-import Test.HMock.TH (makeMockable) import Test.Hspec import qualified UnliftIO.Concurrent as UnliftIO import Prelude hiding (readFile, writeFile)@@ -493,6 +492,8 @@               <*> readFile "foo.txt"           liftIO $ result `shouldBe` ("A", "B", "A", "B") +    it "repeats response sequences during consecutive repetition" $+      example $ do         runMockT $ do           consecutiveTimes 2 $ expect $ ReadFile "foo.txt" |-> "A" |-> "B" @@ -593,7 +594,7 @@          test `shouldThrow` anyException -    it "allows the user to override a default" $+    it "allows the user to override a default with byDefault" $       example $         runMockT $ do           expectAny $ ReadFile_ anything@@ -607,6 +608,108 @@           liftIO (r1 `shouldBe` "")           liftIO (r2 `shouldBe` "foo")           liftIO (r3 `shouldBe` "")++    it "adopts lax behavior for allowUnexpected" $+      example $+        runMockT $ do+          allowUnexpected $ ReadFile "foo.txt" |-> "foo"+          r <- readFile "foo.txt"+          liftIO (r `shouldBe` "foo")++    it "prefers expect over allowUnexpected" $+      example $+        runMockT $ do+          expectAny $ ReadFile_ anything |-> "bar"+          allowUnexpected $ ReadFile "foo.txt" |-> "foo"+          r <- readFile "foo.txt"+          liftIO (r `shouldBe` "bar")++    it "uses defaults when allowUnexpected is not explicit" $+      example $ do+        runMockT $ do+          byDefault $ ReadFile "foo.txt" |-> "foo" -- added before allow+          allowUnexpected $ ReadFile_ anything+          byDefault $ ReadFile "bar.txt" |-> "bar" -- added after allow+          result <-+            (,,)+              <$> readFile "foo.txt"+              <*> readFile "bar.txt"+              <*> readFile "baz.txt"+          liftIO (result `shouldBe` ("foo", "bar", ""))++    it "doesn't adopt lax behavior for byDefault" $+      example $ do+        let test = runMockT $ do+              byDefault $ ReadFile "foo.txt" |-> "foo"+              readFile "foo.txt"+        liftIO (test `shouldThrow` anyException)++    it "checks ambiguity when asked" $+      example $ do+        let setExpectations = do+              expect $ ReadFile_ anything+              expect $ ReadFile "foo.txt"+              setAmbiguityCheck True++            failure = runMockT $ do+              setExpectations+              _ <- readFile "foo.txt"+              _ <- readFile "bar.txt"+              return ()++            success = runMockT $ do+              setExpectations+              _ <- readFile "bar.txt"+              _ <- readFile "foo.txt"+              return ()++        success+        failure `shouldThrow` errorWith ("Ambiguous action" `isInfixOf`)++    describe "nestMockT" $ do+      it "checks nested context early" $ do+        example $ do+          let success = runMockT $ do+                expect $ WriteFile "final.txt" "final"+                nestMockT $ do+                  expect $ WriteFile "foo.txt" "foo"+                  writeFile "foo.txt" "foo"+                writeFile "final.txt" "final"++              failure = runMockT $ do+                nestMockT $ do+                  expect $ WriteFile "foo.txt" "foo"+                writeFile "foo.txt" "foo"++          success+          failure `shouldThrow` anyException++      it "updates the right context when nesting" $+        example $+          runMockT $ do+            expect $ ReadFile "foo.txt" |-> "foo #1" |-> "foo #2"+            result <- nestMockT $ do+              expect $ ReadFile "bar.txt" |-> "bar #1" |-> "bar #2"+              (,,,)+                <$> readFile "foo.txt"+                <*> readFile "bar.txt"+                <*> readFile "foo.txt"+                <*> readFile "bar.txt"+            liftIO (result `shouldBe` ("foo #1", "bar #1", "foo #2", "bar #2"))++      it "inherits defaults correctly" $+        example $+          runMockT $ do+            allowUnexpected $ ReadFile "foo.txt" |-> "foo"+            allowUnexpected $ ReadFile "bar.txt" |-> "bar"+            result <- nestMockT $ do+              allowUnexpected $ ReadFile "foo.txt" |-> "foo #2"+              (,) <$> readFile "foo.txt" <*> readFile "bar.txt"++            liftIO (result `shouldBe` ("foo #2", "bar"))++            result2 <- readFile "foo.txt"+            liftIO (result2 `shouldBe` "foo")  errorWith :: (String -> Bool) -> SomeException -> Bool errorWith p e = p (show e)
test/Demo.hs view
@@ -19,13 +19,15 @@ import Test.HMock   ( Mockable (..),     anything,+    allowUnexpected,     expect,     expectAny,+    makeMockable,+    makeMockableBase,     runMockT,     (|->),     (|=>),   )-import Test.HMock.TH (makeMockable, makeMockableBase) import Test.Hspec (SpecWith, describe, example, it) import Prelude hiding (appendFile, readFile, writeFile) @@ -156,7 +158,7 @@   setupMockable _ = do     -- Ensure that when the chatbot logs in with the right username and     -- password.-    expectAny $+    allowUnexpected $       Login "HMockBot" "secretish"         |=> \_ -> do           -- Every login should be accompanied by a logout@@ -164,13 +166,13 @@      -- By default, assume that the bot has all permissions.  Individual tests     -- can override this assumption.-    expectAny $ HasPermission_ anything |-> True+    allowUnexpected $ HasPermission_ anything |-> True  makeMockableBase ''MonadChat  instance Mockable MonadChat where   setupMockable _ = do-    expectAny $+    allowUnexpected $       JoinRoom_ anything         |=> \(JoinRoom room) -> do           -- The bot should leave every room it joins.@@ -179,7 +181,7 @@      -- Our tests aren't generally concerned with what the bot says.  Individual     -- tests can add expectations to check for specific messages.-    expectAny $ SendChat_ anything anything+    allowUnexpected $ SendChat_ anything anything |-> ()  ------------------------------------------------------------------------------- -- PART 4: TESTS@@ -229,7 +231,7 @@          chatbot "#haskell" -  it "doesn't ban people for using four-letter words in big reports" $ do+  it "doesn't ban people for using four-letter words in bug reports" $ do     example $       runMockT $ do         -- A four letter word is used in a bug report.  This is understandable,
test/DocTests/All.hs view
@@ -1,12 +1,12 @@ -- Do not edit! Automatically created with doctest-extract. module DocTests.All where -import qualified DocTests.Test.HMock.Internal.Predicates-import qualified DocTests.Test.HMock.Internal.Multiplicity+import qualified DocTests.Test.HMock.Predicates+import qualified DocTests.Test.HMock.Multiplicity  import qualified Test.DocTest.Driver as DocTest  main :: DocTest.T () main = do-    DocTests.Test.HMock.Internal.Predicates.test-    DocTests.Test.HMock.Internal.Multiplicity.test+    DocTests.Test.HMock.Predicates.test+    DocTests.Test.HMock.Multiplicity.test
− test/DocTests/Test/HMock/Internal/Multiplicity.hs
@@ -1,166 +0,0 @@--- Do not edit! Automatically created with doctest-extract from src/Test/HMock/Internal/Multiplicity.hs-module DocTests.Test.HMock.Internal.Multiplicity where--import Test.HMock.Internal.Multiplicity-import Test.DocTest.Base-import qualified Test.DocTest.Driver as DocTest---test :: DocTest.T ()-test = do- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:33: "-{-# LINE 33 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 33 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity 5 4)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:35: "-{-# LINE 35 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 35 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity 5 5)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:37: "-{-# LINE 37 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 37 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (between 4 6 - between 1 2)-  [ExpectedLine [LineChunk "2 to 5 times"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:75: "-{-# LINE 75 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 75 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity once 0)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:77: "-{-# LINE 77 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 77 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity once 1)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:79: "-{-# LINE 79 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 79 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity once 2)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:85: "-{-# LINE 85 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 85 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity anyMultiplicity 0)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:87: "-{-# LINE 87 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 87 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity anyMultiplicity 1)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:89: "-{-# LINE 89 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 89 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity anyMultiplicity 10)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:96: "-{-# LINE 96 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 96 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atLeast 2) 1)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:98: "-{-# LINE 98 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 98 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atLeast 2) 2)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:100: "-{-# LINE 100 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 100 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atLeast 2) 3)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:107: "-{-# LINE 107 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 107 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atMost 2) 1)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:109: "-{-# LINE 109 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 109 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atMost 2) 2)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:111: "-{-# LINE 111 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 111 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (atMost 2) 3)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:120: "-{-# LINE 120 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 120 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (between 2 3) 1)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:122: "-{-# LINE 122 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 122 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (between 2 3) 2)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:124: "-{-# LINE 124 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 124 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (between 2 3) 3)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:126: "-{-# LINE 126 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 126 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (meetsMultiplicity (between 2 3) 4)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:133: "-{-# LINE 133 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 133 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (exhaustable anyMultiplicity)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:135: "-{-# LINE 135 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 135 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (exhaustable (atLeast 2))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:137: "-{-# LINE 137 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 137 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (exhaustable (atMost 3))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:139: "-{-# LINE 139 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 139 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (exhaustable (between 0 2))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:146: "-{-# LINE 146 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 146 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (feasible once)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:148: "-{-# LINE 148 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 148 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (feasible 0)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Multiplicity:150: "-{-# LINE 150 "src/Test/HMock/Internal/Multiplicity.hs" #-}- DocTest.example-{-# LINE 150 "src/Test/HMock/Internal/Multiplicity.hs" #-}-      (feasible (once - 2))-  [ExpectedLine [LineChunk "False"]]
− test/DocTests/Test/HMock/Internal/Predicates.hs
@@ -1,898 +0,0 @@--- Do not edit! Automatically created with doctest-extract from src/Test/HMock/Internal/Predicates.hs-{-# LINE 24 "src/Test/HMock/Internal/Predicates.hs" #-}--{-# OPTIONS_GHC -XTemplateHaskell #-}-{-# OPTIONS_GHC -XTypeApplications #-}-{-# OPTIONS_GHC -Wno-type-defaults #-}-module DocTests.Test.HMock.Internal.Predicates where--import Test.HMock.Internal.Predicates-import Test.DocTest.Base-import qualified Test.DocTest.Driver as DocTest--{-# LINE 28 "src/Test/HMock/Internal/Predicates.hs" #-}--test :: DocTest.T ()-test = do- DocTest.printPrefix "Test.HMock.Internal.Predicates:44: "-{-# LINE 44 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 44 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept anything "foo")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:46: "-{-# LINE 46 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 46 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept anything undefined)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:57: "-{-# LINE 57 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 57 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (eq "foo") "foo")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:59: "-{-# LINE 59 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 59 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (eq "foo") "bar")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:70: "-{-# LINE 70 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 70 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (neq "foo") "foo")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:72: "-{-# LINE 72 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 72 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (neq "foo") "bar")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:83: "-{-# LINE 83 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 83 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (gt 5) 4)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:85: "-{-# LINE 85 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 85 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (gt 5) 5)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:87: "-{-# LINE 87 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 87 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (gt 5) 6)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:99: "-{-# LINE 99 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 99 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (geq 5) 4)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:101: "-{-# LINE 101 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 101 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (geq 5) 5)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:103: "-{-# LINE 103 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 103 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (geq 5) 6)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:114: "-{-# LINE 114 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 114 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt 5) 4)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:116: "-{-# LINE 116 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 116 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt 5) 5)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:118: "-{-# LINE 118 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 118 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt 5) 6)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:129: "-{-# LINE 129 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 129 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (leq 5) 4)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:131: "-{-# LINE 131 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 131 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (leq 5) 5)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:133: "-{-# LINE 133 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 133 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (leq 5) 6)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:144: "-{-# LINE 144 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 144 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept true True)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:146: "-{-# LINE 146 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 146 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept true False)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:153: "-{-# LINE 153 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 153 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept false True)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:155: "-{-# LINE 155 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 155 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept false False)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:163: "-{-# LINE 163 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 163 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (just (eq "value")) Nothing)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:165: "-{-# LINE 165 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 165 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (just (eq "value")) (Just "value"))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:167: "-{-# LINE 167 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 167 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (just (eq "value")) (Just "wrong value"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:179: "-{-# LINE 179 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 179 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (left (eq "value")) (Left "value"))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:181: "-{-# LINE 181 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 181 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (left (eq "value")) (Right "value"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:183: "-{-# LINE 183 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 183 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (left (eq "value")) (Left "wrong value"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:195: "-{-# LINE 195 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 195 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (right (eq "value")) (Right "value"))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:197: "-{-# LINE 197 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 197 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (right (eq "value")) (Right "wrong value"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:199: "-{-# LINE 199 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 199 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (right (eq "value")) (Left "value"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:211: "-{-# LINE 211 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 211 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zipP (eq "foo") (eq "bar")) ("foo", "bar"))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:213: "-{-# LINE 213 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 213 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zipP (eq "foo") (eq "bar")) ("bar", "foo"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:225: "-{-# LINE 225 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 225 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("foo", "bar", "qux"))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:227: "-{-# LINE 227 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 227 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("qux", "bar", "foo"))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:239: "-{-# LINE 239 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 239 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (1, 2, 3, 4))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:241: "-{-# LINE 241 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 241 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (4, 3, 2, 1))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:259: "-{-# LINE 259 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 259 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (1, 2, 3, 4, 5))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:261: "-{-# LINE 261 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 261 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (5, 4, 3, 2, 1))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:280: "-{-# LINE 280 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 280 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "foo" `andP` gt "bar") "eta")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:282: "-{-# LINE 282 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 282 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "foo" `andP` gt "bar") "quz")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:284: "-{-# LINE 284 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 284 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "foo" `andP` gt "bar") "alpha")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:295: "-{-# LINE 295 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 295 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "bar" `orP` gt "foo") "eta")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:297: "-{-# LINE 297 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 297 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "bar" `orP` gt "foo") "quz")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:299: "-{-# LINE 299 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 299 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (lt "bar" `orP` gt "foo") "alpha")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:311: "-{-# LINE 311 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 311 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (notP (eq "negative")) "positive")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:313: "-{-# LINE 313 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 313 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (notP (eq "negative")) "negative")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:324: "-{-# LINE 324 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 324 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (startsWith "fun") "fungible")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:326: "-{-# LINE 326 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 326 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (startsWith "gib") "fungible")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:337: "-{-# LINE 337 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 337 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (endsWith "ow") "crossbow")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:339: "-{-# LINE 339 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 339 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (endsWith "ow") "trebuchet")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:351: "-{-# LINE 351 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 351 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (hasSubstr "i") "team")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:353: "-{-# LINE 353 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 353 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (hasSubstr "i") "partnership")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:365: "-{-# LINE 365 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 365 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (hasSubsequence [1..5]) [1, 2, 3, 4, 5])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:367: "-{-# LINE 367 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 367 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (hasSubsequence [1..5]) [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:369: "-{-# LINE 369 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 369 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (hasSubsequence [1..5]) [2, 3, 5, 7, 11])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:381: "-{-# LINE 381 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 381 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (caseInsensitive startsWith "foo") "FOOTBALL!")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:383: "-{-# LINE 383 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 383 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (caseInsensitive endsWith "ball") "soccer")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:385: "-{-# LINE 385 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 385 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (caseInsensitive eq "time") "TIME")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:387: "-{-# LINE 387 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 387 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (caseInsensitive gt "NOTHING") "everything")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:412: "-{-# LINE 412 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 412 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesRegex "x{2,5}y?") "xxxy")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:414: "-{-# LINE 414 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 414 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesRegex "x{2,5}y?") "xyy")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:416: "-{-# LINE 416 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 416 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesRegex "x{2,5}y?") "wxxxyz")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:439: "-{-# LINE 439 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 439 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XXXY")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:441: "-{-# LINE 441 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 441 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XYY")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:443: "-{-# LINE 443 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 443 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:472: "-{-# LINE 472 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 472 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsRegex "x{2,5}y?") "xxxy")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:474: "-{-# LINE 474 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 474 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsRegex "x{2,5}y?") "xyy")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:476: "-{-# LINE 476 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 476 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsRegex "x{2,5}y?") "wxxxyz")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:497: "-{-# LINE 497 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 497 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "XXXY")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:499: "-{-# LINE 499 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 499 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "XYY")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:501: "-{-# LINE 501 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 501 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:522: "-{-# LINE 522 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 522 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept isEmpty [])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:524: "-{-# LINE 524 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 524 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept isEmpty [1, 2, 3])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:526: "-{-# LINE 526 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 526 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept isEmpty "")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:528: "-{-# LINE 528 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 528 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept isEmpty "gas tank")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:539: "-{-# LINE 539 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 539 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nonEmpty [])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:541: "-{-# LINE 541 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 541 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nonEmpty [1, 2, 3])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:543: "-{-# LINE 543 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 543 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nonEmpty "")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:545: "-{-# LINE 545 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 545 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nonEmpty "gas tank")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:557: "-{-# LINE 557 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 557 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (sizeIs (lt 3)) ['a' .. 'f'])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:559: "-{-# LINE 559 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 559 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (sizeIs (lt 3)) ['a' .. 'b'])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:571: "-{-# LINE 571 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 571 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:573: "-{-# LINE 573 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 573 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4, 5])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:575: "-{-# LINE 575 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 575 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 10, 4])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:589: "-{-# LINE 589 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 589 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:591: "-{-# LINE 591 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 591 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [2, 3, 1])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:593: "-{-# LINE 593 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 593 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3, 4])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:595: "-{-# LINE 595 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 595 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 3])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:611: "-{-# LINE 611 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 611 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (each (gt 5)) [4, 5, 6])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:613: "-{-# LINE 613 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 613 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (each (gt 5)) [6, 7, 8])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:615: "-{-# LINE 615 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 615 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (each (gt 5)) [])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:627: "-{-# LINE 627 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 627 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (contains (gt 5)) [3, 4, 5])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:629: "-{-# LINE 629 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 629 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (contains (gt 5)) [4, 5, 6])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:631: "-{-# LINE 631 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 631 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (contains (gt 5)) [])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:645: "-{-# LINE 645 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 645 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsAll [eq "foo", eq "bar"]) ["bar", "foo"])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:647: "-{-# LINE 647 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 647 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsAll [eq "foo", eq "bar"]) ["foo"])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:649: "-{-# LINE 649 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 649 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsAll [eq "foo", eq "bar"]) ["foo", "bar", "qux"])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:662: "-{-# LINE 662 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 662 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "foo"])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:664: "-{-# LINE 664 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 664 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "bar"])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:666: "-{-# LINE 666 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 666 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "qux"])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:678: "-{-# LINE 678 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 678 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsKey (eq "foo")) [("foo", 1), ("bar", 2)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:680: "-{-# LINE 680 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 680 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsKey (eq "foo")) [("bar", 1), ("qux", 2)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:693: "-{-# LINE 693 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 693 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsEntry (eq "foo") (gt 10)) [("foo", 12), ("bar", 5)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:695: "-{-# LINE 695 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 695 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsEntry (eq "foo") (gt 10)) [("foo", 5), ("bar", 12)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:697: "-{-# LINE 697 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 697 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (containsEntry (eq "foo") (gt 10)) [("bar", 12)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:710: "-{-# LINE 710 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 710 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("b", 2), ("c", 3)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:712: "-{-# LINE 712 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 712 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (keysAre [eq "a", eq "b", eq "c"]) [("c", 1), ("b", 2), ("a", 3)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:714: "-{-# LINE 714 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 714 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("c", 3)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:716: "-{-# LINE 716 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 716 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (keysAre [eq "a", eq "b"]) [("a", 1), ("b", 2), ("c", 3)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:732: "-{-# LINE 732 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 732 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:734: "-{-# LINE 734 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 734 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(3, 4), (1, 2)])-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:736: "-{-# LINE 736 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 736 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 4), (3, 2)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:738: "-{-# LINE 738 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 738 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4), (5, 6)])-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:759: "-{-# LINE 759 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 759 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (eq 1.0) (sum (replicate 100 0.01)))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:766: "-{-# LINE 766 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 766 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (approxEq 1.0) (sum (replicate 100 0.01)))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:768: "-{-# LINE 768 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 768 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (approxEq 1.0) (sum (replicate 100 0.009999)))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:781: "-{-# LINE 781 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 781 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept finite 1.0)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:783: "-{-# LINE 783 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 783 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept finite (0 / 0))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:785: "-{-# LINE 785 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 785 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept finite (1 / 0))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:796: "-{-# LINE 796 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 796 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept infinite 1.0)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:798: "-{-# LINE 798 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 798 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept infinite (0 / 0))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:800: "-{-# LINE 800 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 800 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept infinite (1 / 0))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:811: "-{-# LINE 811 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 811 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nAn 1.0)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:813: "-{-# LINE 813 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 813 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nAn (0 / 0))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:815: "-{-# LINE 815 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 815 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept nAn (1 / 0))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:828: "-{-# LINE 828 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 828 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (is even) 3)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:830: "-{-# LINE 830 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 830 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (is even) 4)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:843: "-{-# LINE 843 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 843 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept $(qIs [| even |]) 3)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:845: "-{-# LINE 845 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 845 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept $(qIs [| even |]) 4)-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:848: "-{-# LINE 848 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 848 "src/Test/HMock/Internal/Predicates.hs" #-}-      (show $(qIs [| even |]))-  [ExpectedLine [LineChunk "\"even\""]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:862: "-{-# LINE 862 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 862 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (with abs (gt 5)) (-6))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:864: "-{-# LINE 864 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 864 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (with abs (gt 5)) (-5))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:866: "-{-# LINE 866 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 866 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (with reverse (eq "olleh")) "hello")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:868: "-{-# LINE 868 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 868 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (with reverse (eq "olleh")) "goodbye")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:882: "-{-# LINE 882 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 882 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept ($(qWith [| abs |]) (gt 5)) (-6))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:884: "-{-# LINE 884 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 884 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept ($(qWith [| abs |]) (gt 5)) (-5))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:886: "-{-# LINE 886 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 886 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept ($(qWith [| reverse |]) (eq "olleh")) "hello")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:888: "-{-# LINE 888 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 888 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept ($(qWith [| reverse |]) (eq "olleh")) "goodbye")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:891: "-{-# LINE 891 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 891 "src/Test/HMock/Internal/Predicates.hs" #-}-      (show ($(qWith [| abs |]) (gt 5)))-  [ExpectedLine [LineChunk "\"abs: > 5\""]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:907: "-{-# LINE 907 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 907 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept $(qMatch [p| Just (Left _) |]) Nothing)-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:909: "-{-# LINE 909 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 909 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept $(qMatch [p| Just (Left _) |]) (Just (Left 5)))-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:911: "-{-# LINE 911 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 911 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept $(qMatch [p| Just (Left _) |]) (Just (Right 5)))-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:914: "-{-# LINE 914 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 914 "src/Test/HMock/Internal/Predicates.hs" #-}-      (show $(qMatch [p| Just (Left _) |]))-  [ExpectedLine [LineChunk "\"Just (Left _)\""]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:930: "-{-# LINE 930 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 930 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (typed @String anything) "foo")-  [ExpectedLine [LineChunk "True"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:932: "-{-# LINE 932 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 932 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (typed @String (sizeIs (gt 5))) "foo")-  [ExpectedLine [LineChunk "False"]]- DocTest.printPrefix "Test.HMock.Internal.Predicates:934: "-{-# LINE 934 "src/Test/HMock/Internal/Predicates.hs" #-}- DocTest.example-{-# LINE 934 "src/Test/HMock/Internal/Predicates.hs" #-}-      (accept (typed @String anything) (42 :: Int))-  [ExpectedLine [LineChunk "False"]]
+ test/DocTests/Test/HMock/Multiplicity.hs view
@@ -0,0 +1,142 @@+-- Do not edit! Automatically created with doctest-extract from src/Test/HMock/Multiplicity.hs+module DocTests.Test.HMock.Multiplicity where++import Test.HMock.Multiplicity+import Test.DocTest.Base+import qualified Test.DocTest.Driver as DocTest+++test :: DocTest.T ()+test = do+ DocTest.printPrefix "Test.HMock.Multiplicity:47: "+{-# LINE 47 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 47 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity 5 4)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:49: "+{-# LINE 49 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 49 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity 5 5)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:51: "+{-# LINE 51 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 51 "src/Test/HMock/Multiplicity.hs" #-}+      (between 4 6 - between 1 2)+  [ExpectedLine [LineChunk "2 to 5 times"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:89: "+{-# LINE 89 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 89 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity once 0)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:91: "+{-# LINE 91 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 91 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity once 1)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:93: "+{-# LINE 93 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 93 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity once 2)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:99: "+{-# LINE 99 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 99 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity anyMultiplicity 0)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:101: "+{-# LINE 101 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 101 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity anyMultiplicity 1)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:103: "+{-# LINE 103 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 103 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity anyMultiplicity 10)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:110: "+{-# LINE 110 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 110 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atLeast 2) 1)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:112: "+{-# LINE 112 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 112 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atLeast 2) 2)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:114: "+{-# LINE 114 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 114 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atLeast 2) 3)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:121: "+{-# LINE 121 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 121 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atMost 2) 1)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:123: "+{-# LINE 123 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 123 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atMost 2) 2)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:125: "+{-# LINE 125 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 125 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (atMost 2) 3)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:134: "+{-# LINE 134 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 134 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (between 2 3) 1)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:136: "+{-# LINE 136 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 136 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (between 2 3) 2)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:138: "+{-# LINE 138 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 138 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (between 2 3) 3)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:140: "+{-# LINE 140 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 140 "src/Test/HMock/Multiplicity.hs" #-}+      (meetsMultiplicity (between 2 3) 4)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:147: "+{-# LINE 147 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 147 "src/Test/HMock/Multiplicity.hs" #-}+      (feasible once)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:149: "+{-# LINE 149 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 149 "src/Test/HMock/Multiplicity.hs" #-}+      (feasible 0)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Multiplicity:151: "+{-# LINE 151 "src/Test/HMock/Multiplicity.hs" #-}+ DocTest.example+{-# LINE 151 "src/Test/HMock/Multiplicity.hs" #-}+      (feasible (once - 2))+  [ExpectedLine [LineChunk "False"]]
+ test/DocTests/Test/HMock/Predicates.hs view
@@ -0,0 +1,874 @@+-- Do not edit! Automatically created with doctest-extract from src/Test/HMock/Predicates.hs+{-# LINE 78 "src/Test/HMock/Predicates.hs" #-}++{-# OPTIONS_GHC -XTemplateHaskell #-}+{-# OPTIONS_GHC -XTypeApplications #-}+{-# OPTIONS_GHC -Wno-type-defaults #-}+module DocTests.Test.HMock.Predicates where++import Test.HMock.Predicates+import Test.DocTest.Base+import qualified Test.DocTest.Driver as DocTest++{-# LINE 82 "src/Test/HMock/Predicates.hs" #-}++test :: DocTest.T ()+test = do+ DocTest.printPrefix "Test.HMock.Predicates:98: "+{-# LINE 98 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 98 "src/Test/HMock/Predicates.hs" #-}+      (accept anything "foo")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:100: "+{-# LINE 100 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 100 "src/Test/HMock/Predicates.hs" #-}+      (accept anything undefined)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:111: "+{-# LINE 111 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 111 "src/Test/HMock/Predicates.hs" #-}+      (accept (eq "foo") "foo")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:113: "+{-# LINE 113 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 113 "src/Test/HMock/Predicates.hs" #-}+      (accept (eq "foo") "bar")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:124: "+{-# LINE 124 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 124 "src/Test/HMock/Predicates.hs" #-}+      (accept (neq "foo") "foo")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:126: "+{-# LINE 126 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 126 "src/Test/HMock/Predicates.hs" #-}+      (accept (neq "foo") "bar")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:137: "+{-# LINE 137 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 137 "src/Test/HMock/Predicates.hs" #-}+      (accept (gt 5) 4)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:139: "+{-# LINE 139 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 139 "src/Test/HMock/Predicates.hs" #-}+      (accept (gt 5) 5)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:141: "+{-# LINE 141 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 141 "src/Test/HMock/Predicates.hs" #-}+      (accept (gt 5) 6)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:153: "+{-# LINE 153 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 153 "src/Test/HMock/Predicates.hs" #-}+      (accept (geq 5) 4)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:155: "+{-# LINE 155 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 155 "src/Test/HMock/Predicates.hs" #-}+      (accept (geq 5) 5)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:157: "+{-# LINE 157 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 157 "src/Test/HMock/Predicates.hs" #-}+      (accept (geq 5) 6)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:168: "+{-# LINE 168 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 168 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt 5) 4)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:170: "+{-# LINE 170 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 170 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt 5) 5)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:172: "+{-# LINE 172 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 172 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt 5) 6)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:183: "+{-# LINE 183 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 183 "src/Test/HMock/Predicates.hs" #-}+      (accept (leq 5) 4)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:185: "+{-# LINE 185 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 185 "src/Test/HMock/Predicates.hs" #-}+      (accept (leq 5) 5)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:187: "+{-# LINE 187 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 187 "src/Test/HMock/Predicates.hs" #-}+      (accept (leq 5) 6)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:199: "+{-# LINE 199 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 199 "src/Test/HMock/Predicates.hs" #-}+      (accept (just (eq "value")) Nothing)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:201: "+{-# LINE 201 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 201 "src/Test/HMock/Predicates.hs" #-}+      (accept (just (eq "value")) (Just "value"))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:203: "+{-# LINE 203 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 203 "src/Test/HMock/Predicates.hs" #-}+      (accept (just (eq "value")) (Just "wrong value"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:215: "+{-# LINE 215 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 215 "src/Test/HMock/Predicates.hs" #-}+      (accept (left (eq "value")) (Left "value"))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:217: "+{-# LINE 217 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 217 "src/Test/HMock/Predicates.hs" #-}+      (accept (left (eq "value")) (Right "value"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:219: "+{-# LINE 219 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 219 "src/Test/HMock/Predicates.hs" #-}+      (accept (left (eq "value")) (Left "wrong value"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:231: "+{-# LINE 231 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 231 "src/Test/HMock/Predicates.hs" #-}+      (accept (right (eq "value")) (Right "value"))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:233: "+{-# LINE 233 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 233 "src/Test/HMock/Predicates.hs" #-}+      (accept (right (eq "value")) (Right "wrong value"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:235: "+{-# LINE 235 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 235 "src/Test/HMock/Predicates.hs" #-}+      (accept (right (eq "value")) (Left "value"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:247: "+{-# LINE 247 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 247 "src/Test/HMock/Predicates.hs" #-}+      (accept (zipP (eq "foo") (eq "bar")) ("foo", "bar"))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:249: "+{-# LINE 249 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 249 "src/Test/HMock/Predicates.hs" #-}+      (accept (zipP (eq "foo") (eq "bar")) ("bar", "foo"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:261: "+{-# LINE 261 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 261 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("foo", "bar", "qux"))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:263: "+{-# LINE 263 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 263 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip3P (eq "foo") (eq "bar") (eq "qux")) ("qux", "bar", "foo"))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:275: "+{-# LINE 275 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 275 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (1, 2, 3, 4))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:277: "+{-# LINE 277 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 277 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip4P (eq 1) (eq 2) (eq 3) (eq 4)) (4, 3, 2, 1))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:295: "+{-# LINE 295 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 295 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (1, 2, 3, 4, 5))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:297: "+{-# LINE 297 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 297 "src/Test/HMock/Predicates.hs" #-}+      (accept (zip5P (eq 1) (eq 2) (eq 3) (eq 4) (eq 5)) (5, 4, 3, 2, 1))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:316: "+{-# LINE 316 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 316 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "foo" `andP` gt "bar") "eta")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:318: "+{-# LINE 318 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 318 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "foo" `andP` gt "bar") "quz")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:320: "+{-# LINE 320 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 320 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "foo" `andP` gt "bar") "alpha")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:331: "+{-# LINE 331 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 331 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "bar" `orP` gt "foo") "eta")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:333: "+{-# LINE 333 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 333 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "bar" `orP` gt "foo") "quz")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:335: "+{-# LINE 335 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 335 "src/Test/HMock/Predicates.hs" #-}+      (accept (lt "bar" `orP` gt "foo") "alpha")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:347: "+{-# LINE 347 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 347 "src/Test/HMock/Predicates.hs" #-}+      (accept (notP (eq "negative")) "positive")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:349: "+{-# LINE 349 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 349 "src/Test/HMock/Predicates.hs" #-}+      (accept (notP (eq "negative")) "negative")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:360: "+{-# LINE 360 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 360 "src/Test/HMock/Predicates.hs" #-}+      (accept (startsWith "fun") "fungible")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:362: "+{-# LINE 362 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 362 "src/Test/HMock/Predicates.hs" #-}+      (accept (startsWith "gib") "fungible")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:373: "+{-# LINE 373 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 373 "src/Test/HMock/Predicates.hs" #-}+      (accept (endsWith "ow") "crossbow")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:375: "+{-# LINE 375 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 375 "src/Test/HMock/Predicates.hs" #-}+      (accept (endsWith "ow") "trebuchet")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:387: "+{-# LINE 387 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 387 "src/Test/HMock/Predicates.hs" #-}+      (accept (hasSubstr "i") "team")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:389: "+{-# LINE 389 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 389 "src/Test/HMock/Predicates.hs" #-}+      (accept (hasSubstr "i") "partnership")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:401: "+{-# LINE 401 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 401 "src/Test/HMock/Predicates.hs" #-}+      (accept (hasSubsequence [1..5]) [1, 2, 3, 4, 5])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:403: "+{-# LINE 403 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 403 "src/Test/HMock/Predicates.hs" #-}+      (accept (hasSubsequence [1..5]) [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:405: "+{-# LINE 405 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 405 "src/Test/HMock/Predicates.hs" #-}+      (accept (hasSubsequence [1..5]) [2, 3, 5, 7, 11])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:417: "+{-# LINE 417 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 417 "src/Test/HMock/Predicates.hs" #-}+      (accept (caseInsensitive startsWith "foo") "FOOTBALL!")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:419: "+{-# LINE 419 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 419 "src/Test/HMock/Predicates.hs" #-}+      (accept (caseInsensitive endsWith "ball") "soccer")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:421: "+{-# LINE 421 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 421 "src/Test/HMock/Predicates.hs" #-}+      (accept (caseInsensitive eq "time") "TIME")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:423: "+{-# LINE 423 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 423 "src/Test/HMock/Predicates.hs" #-}+      (accept (caseInsensitive gt "NOTHING") "everything")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:448: "+{-# LINE 448 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 448 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesRegex "x{2,5}y?") "xxxy")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:450: "+{-# LINE 450 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 450 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesRegex "x{2,5}y?") "xyy")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:452: "+{-# LINE 452 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 452 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesRegex "x{2,5}y?") "wxxxyz")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:475: "+{-# LINE 475 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 475 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XXXY")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:477: "+{-# LINE 477 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 477 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XYY")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:479: "+{-# LINE 479 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 479 "src/Test/HMock/Predicates.hs" #-}+      (accept (matchesCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:508: "+{-# LINE 508 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 508 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsRegex "x{2,5}y?") "xxxy")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:510: "+{-# LINE 510 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 510 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsRegex "x{2,5}y?") "xyy")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:512: "+{-# LINE 512 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 512 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsRegex "x{2,5}y?") "wxxxyz")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:533: "+{-# LINE 533 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 533 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "XXXY")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:535: "+{-# LINE 535 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 535 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "XYY")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:537: "+{-# LINE 537 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 537 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:558: "+{-# LINE 558 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 558 "src/Test/HMock/Predicates.hs" #-}+      (accept isEmpty [])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:560: "+{-# LINE 560 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 560 "src/Test/HMock/Predicates.hs" #-}+      (accept isEmpty [1, 2, 3])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:562: "+{-# LINE 562 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 562 "src/Test/HMock/Predicates.hs" #-}+      (accept isEmpty "")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:564: "+{-# LINE 564 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 564 "src/Test/HMock/Predicates.hs" #-}+      (accept isEmpty "gas tank")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:575: "+{-# LINE 575 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 575 "src/Test/HMock/Predicates.hs" #-}+      (accept nonEmpty [])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:577: "+{-# LINE 577 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 577 "src/Test/HMock/Predicates.hs" #-}+      (accept nonEmpty [1, 2, 3])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:579: "+{-# LINE 579 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 579 "src/Test/HMock/Predicates.hs" #-}+      (accept nonEmpty "")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:581: "+{-# LINE 581 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 581 "src/Test/HMock/Predicates.hs" #-}+      (accept nonEmpty "gas tank")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:593: "+{-# LINE 593 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 593 "src/Test/HMock/Predicates.hs" #-}+      (accept (sizeIs (lt 3)) ['a' .. 'f'])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:595: "+{-# LINE 595 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 595 "src/Test/HMock/Predicates.hs" #-}+      (accept (sizeIs (lt 3)) ['a' .. 'b'])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:607: "+{-# LINE 607 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 607 "src/Test/HMock/Predicates.hs" #-}+      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:609: "+{-# LINE 609 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 609 "src/Test/HMock/Predicates.hs" #-}+      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4, 5])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:611: "+{-# LINE 611 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 611 "src/Test/HMock/Predicates.hs" #-}+      (accept (elemsAre [lt 3, lt 4, lt 5]) [2, 10, 4])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:625: "+{-# LINE 625 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 625 "src/Test/HMock/Predicates.hs" #-}+      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:627: "+{-# LINE 627 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 627 "src/Test/HMock/Predicates.hs" #-}+      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [2, 3, 1])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:629: "+{-# LINE 629 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 629 "src/Test/HMock/Predicates.hs" #-}+      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3, 4])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:631: "+{-# LINE 631 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 631 "src/Test/HMock/Predicates.hs" #-}+      (accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 3])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:647: "+{-# LINE 647 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 647 "src/Test/HMock/Predicates.hs" #-}+      (accept (each (gt 5)) [4, 5, 6])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:649: "+{-# LINE 649 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 649 "src/Test/HMock/Predicates.hs" #-}+      (accept (each (gt 5)) [6, 7, 8])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:651: "+{-# LINE 651 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 651 "src/Test/HMock/Predicates.hs" #-}+      (accept (each (gt 5)) [])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:663: "+{-# LINE 663 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 663 "src/Test/HMock/Predicates.hs" #-}+      (accept (contains (gt 5)) [3, 4, 5])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:665: "+{-# LINE 665 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 665 "src/Test/HMock/Predicates.hs" #-}+      (accept (contains (gt 5)) [4, 5, 6])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:667: "+{-# LINE 667 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 667 "src/Test/HMock/Predicates.hs" #-}+      (accept (contains (gt 5)) [])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:681: "+{-# LINE 681 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 681 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsAll [eq "foo", eq "bar"]) ["bar", "foo"])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:683: "+{-# LINE 683 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 683 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsAll [eq "foo", eq "bar"]) ["foo"])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:685: "+{-# LINE 685 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 685 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsAll [eq "foo", eq "bar"]) ["foo", "bar", "qux"])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:698: "+{-# LINE 698 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 698 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "foo"])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:700: "+{-# LINE 700 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 700 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "bar"])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:702: "+{-# LINE 702 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 702 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsOnly [eq "foo", eq "bar"]) ["foo", "qux"])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:714: "+{-# LINE 714 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 714 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsKey (eq "foo")) [("foo", 1), ("bar", 2)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:716: "+{-# LINE 716 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 716 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsKey (eq "foo")) [("bar", 1), ("qux", 2)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:729: "+{-# LINE 729 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 729 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsEntry (eq "foo") (gt 10)) [("foo", 12), ("bar", 5)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:731: "+{-# LINE 731 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 731 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsEntry (eq "foo") (gt 10)) [("foo", 5), ("bar", 12)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:733: "+{-# LINE 733 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 733 "src/Test/HMock/Predicates.hs" #-}+      (accept (containsEntry (eq "foo") (gt 10)) [("bar", 12)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:746: "+{-# LINE 746 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 746 "src/Test/HMock/Predicates.hs" #-}+      (accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("b", 2), ("c", 3)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:748: "+{-# LINE 748 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 748 "src/Test/HMock/Predicates.hs" #-}+      (accept (keysAre [eq "a", eq "b", eq "c"]) [("c", 1), ("b", 2), ("a", 3)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:750: "+{-# LINE 750 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 750 "src/Test/HMock/Predicates.hs" #-}+      (accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("c", 3)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:752: "+{-# LINE 752 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 752 "src/Test/HMock/Predicates.hs" #-}+      (accept (keysAre [eq "a", eq "b"]) [("a", 1), ("b", 2), ("c", 3)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:768: "+{-# LINE 768 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 768 "src/Test/HMock/Predicates.hs" #-}+      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:770: "+{-# LINE 770 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 770 "src/Test/HMock/Predicates.hs" #-}+      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(3, 4), (1, 2)])+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:772: "+{-# LINE 772 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 772 "src/Test/HMock/Predicates.hs" #-}+      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 4), (3, 2)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:774: "+{-# LINE 774 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 774 "src/Test/HMock/Predicates.hs" #-}+      (accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4), (5, 6)])+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:795: "+{-# LINE 795 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 795 "src/Test/HMock/Predicates.hs" #-}+      (accept (eq 1.0) (sum (replicate 100 0.01)))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:802: "+{-# LINE 802 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 802 "src/Test/HMock/Predicates.hs" #-}+      (accept (approxEq 1.0) (sum (replicate 100 0.01)))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:804: "+{-# LINE 804 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 804 "src/Test/HMock/Predicates.hs" #-}+      (accept (approxEq 1.0) (sum (replicate 100 0.009999)))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:817: "+{-# LINE 817 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 817 "src/Test/HMock/Predicates.hs" #-}+      (accept finite 1.0)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:819: "+{-# LINE 819 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 819 "src/Test/HMock/Predicates.hs" #-}+      (accept finite (0 / 0))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:821: "+{-# LINE 821 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 821 "src/Test/HMock/Predicates.hs" #-}+      (accept finite (1 / 0))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:832: "+{-# LINE 832 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 832 "src/Test/HMock/Predicates.hs" #-}+      (accept infinite 1.0)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:834: "+{-# LINE 834 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 834 "src/Test/HMock/Predicates.hs" #-}+      (accept infinite (0 / 0))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:836: "+{-# LINE 836 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 836 "src/Test/HMock/Predicates.hs" #-}+      (accept infinite (1 / 0))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:847: "+{-# LINE 847 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 847 "src/Test/HMock/Predicates.hs" #-}+      (accept nAn 1.0)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:849: "+{-# LINE 849 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 849 "src/Test/HMock/Predicates.hs" #-}+      (accept nAn (0 / 0))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:851: "+{-# LINE 851 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 851 "src/Test/HMock/Predicates.hs" #-}+      (accept nAn (1 / 0))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:864: "+{-# LINE 864 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 864 "src/Test/HMock/Predicates.hs" #-}+      (accept (is even) 3)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:866: "+{-# LINE 866 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 866 "src/Test/HMock/Predicates.hs" #-}+      (accept (is even) 4)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:879: "+{-# LINE 879 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 879 "src/Test/HMock/Predicates.hs" #-}+      (accept $(qIs [| even |]) 3)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:881: "+{-# LINE 881 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 881 "src/Test/HMock/Predicates.hs" #-}+      (accept $(qIs [| even |]) 4)+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:884: "+{-# LINE 884 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 884 "src/Test/HMock/Predicates.hs" #-}+      (show $(qIs [| even |]))+  [ExpectedLine [LineChunk "\"even\""]]+ DocTest.printPrefix "Test.HMock.Predicates:898: "+{-# LINE 898 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 898 "src/Test/HMock/Predicates.hs" #-}+      (accept (with abs (gt 5)) (-6))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:900: "+{-# LINE 900 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 900 "src/Test/HMock/Predicates.hs" #-}+      (accept (with abs (gt 5)) (-5))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:902: "+{-# LINE 902 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 902 "src/Test/HMock/Predicates.hs" #-}+      (accept (with reverse (eq "olleh")) "hello")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:904: "+{-# LINE 904 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 904 "src/Test/HMock/Predicates.hs" #-}+      (accept (with reverse (eq "olleh")) "goodbye")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:918: "+{-# LINE 918 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 918 "src/Test/HMock/Predicates.hs" #-}+      (accept ($(qWith [| abs |]) (gt 5)) (-6))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:920: "+{-# LINE 920 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 920 "src/Test/HMock/Predicates.hs" #-}+      (accept ($(qWith [| abs |]) (gt 5)) (-5))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:922: "+{-# LINE 922 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 922 "src/Test/HMock/Predicates.hs" #-}+      (accept ($(qWith [| reverse |]) (eq "olleh")) "hello")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:924: "+{-# LINE 924 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 924 "src/Test/HMock/Predicates.hs" #-}+      (accept ($(qWith [| reverse |]) (eq "olleh")) "goodbye")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:927: "+{-# LINE 927 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 927 "src/Test/HMock/Predicates.hs" #-}+      (show ($(qWith [| abs |]) (gt 5)))+  [ExpectedLine [LineChunk "\"abs: > 5\""]]+ DocTest.printPrefix "Test.HMock.Predicates:943: "+{-# LINE 943 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 943 "src/Test/HMock/Predicates.hs" #-}+      (accept $(qMatch [p| Just (Left _) |]) Nothing)+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:945: "+{-# LINE 945 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 945 "src/Test/HMock/Predicates.hs" #-}+      (accept $(qMatch [p| Just (Left _) |]) (Just (Left 5)))+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:947: "+{-# LINE 947 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 947 "src/Test/HMock/Predicates.hs" #-}+      (accept $(qMatch [p| Just (Left _) |]) (Just (Right 5)))+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:950: "+{-# LINE 950 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 950 "src/Test/HMock/Predicates.hs" #-}+      (show $(qMatch [p| Just (Left _) |]))+  [ExpectedLine [LineChunk "\"Just (Left _)\""]]+ DocTest.printPrefix "Test.HMock.Predicates:966: "+{-# LINE 966 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 966 "src/Test/HMock/Predicates.hs" #-}+      (accept (typed @String anything) "foo")+  [ExpectedLine [LineChunk "True"]]+ DocTest.printPrefix "Test.HMock.Predicates:968: "+{-# LINE 968 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 968 "src/Test/HMock/Predicates.hs" #-}+      (accept (typed @String (sizeIs (gt 5))) "foo")+  [ExpectedLine [LineChunk "False"]]+ DocTest.printPrefix "Test.HMock.Predicates:970: "+{-# LINE 970 "src/Test/HMock/Predicates.hs" #-}+ DocTest.example+{-# LINE 970 "src/Test/HMock/Predicates.hs" #-}+      (accept (typed @String anything) (42 :: Int))+  [ExpectedLine [LineChunk "False"]]
test/ExpectSet.hs view
@@ -6,7 +6,7 @@ import Control.Arrow (second) import Data.List (foldl') import Test.HMock.Internal.ExpectSet-import Test.HMock.Internal.Multiplicity+import Test.HMock.Multiplicity import Test.Hspec import Test.Hspec.QuickCheck (modifyMaxSuccess) import Test.QuickCheck@@ -48,7 +48,10 @@       ++ [e]  instance Arbitrary Multiplicity where-  arbitrary = normalize <$> (Multiplicity <$> arbitrary <*> arbitrary)+  arbitrary =+    between+      <$> (fromInteger <$> arbitrary)+      <*> (fromInteger . getNonNegative <$> arbitrary)  liveSteps' :: ExpectSet step -> [(step, ExpectSet step)] liveSteps' = map (second simplify) . liveSteps
test/Extras.hs view
@@ -6,12 +6,14 @@ import Data.List (isPrefixOf) import Data.Typeable (Typeable) import Test.HMock-import Test.HMock.Internal.Multiplicity import Test.Hspec import Test.QuickCheck hiding (once)  instance Arbitrary Multiplicity where-  arbitrary = normalize <$> (Multiplicity <$> arbitrary <*> arbitrary)+  arbitrary =+    between+      <$> (fromInteger <$> arbitrary)+      <*> (fromInteger . getNonNegative <$> arbitrary)  multiplicityTests :: SpecWith () multiplicityTests = do
test/QuasiMock.hs view
@@ -1,32 +1,20 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-} -module QuasiMock where+module QuasiMock (module QuasiMock, module QuasiMockBase) where  import Control.Monad.Trans (MonadIO, liftIO) import Data.Default (Default (..)) import Data.Generics (Typeable, everything, mkQ) import Language.Haskell.TH hiding (Match) import Language.Haskell.TH.Syntax hiding (Match)+import QuasiMockBase import Test.HMock-import Test.HMock.TH (deriveMockableBase)-import Util.TH (reifyInstancesStatic, reifyStatic)  #if !MIN_VERSION_base(4, 13, 0) import Control.Monad.Fail (MonadFail) #endif -deriveMockableBase ''Quasi- -- Because not all methods of Quasi are mockable, the instance must be written -- by hand. instance (Typeable m, MonadFail m, MonadIO m) => Quasi (MockT m) where@@ -75,58 +63,42 @@  instance Mockable Quasi where   setupMockable _ = do-    expectAny $ QIsExtEnabled_ anything |-> True+    allowUnexpected $ QIsExtEnabled_ anything |-> True -    expectAny $ QReify ''String |-> $(reifyStatic ''String)-    expectAny $ QReify ''Char |-> $(reifyStatic ''Char)-    expectAny $ QReify ''Int |-> $(reifyStatic ''Int)-    expectAny $ QReify ''Bool |-> $(reifyStatic ''Bool)-    expectAny $ QReify ''Enum |-> $(reifyStatic ''Enum)-    expectAny $ QReify ''Monad |-> $(reifyStatic ''Monad)-    expectAny $-      QReifyInstances ''Show [ConT ''String]-        |-> $(reifyInstancesStatic ''Show [ConT ''String])-    expectAny $-      QReifyInstances ''Eq [ConT ''String]-        |-> $(reifyInstancesStatic ''Eq [ConT ''String])-    expectAny $-      QReifyInstances ''Show [ConT ''Char]-        |-> $(reifyInstancesStatic ''Show [ConT ''Char])-    expectAny $-      QReifyInstances ''Eq [ConT ''Char]-        |-> $(reifyInstancesStatic ''Eq [ConT ''Char])-    expectAny $-      QReifyInstances ''Show [ConT ''Int]-        |-> $(reifyInstancesStatic ''Show [ConT ''Int])-    expectAny $-      QReifyInstances ''Eq [ConT ''Int]-        |-> $(reifyInstancesStatic ''Eq [ConT ''Int])-    expectAny $-      QReifyInstances ''Show [ConT ''Bool]-        |-> $(reifyInstancesStatic ''Show [ConT ''Bool])-    expectAny $-      QReifyInstances ''Eq [ConT ''Bool]-        |-> $(reifyInstancesStatic ''Eq [ConT ''Bool])-    expectAny $-      QReifyInstances ''Default [TupleT 0]-        |-> $(reifyInstancesStatic ''Default [TupleT 0])-    expectAny $-      QReifyInstances ''Default [ConT ''String]-        |-> $(reifyInstancesStatic ''Default [ConT ''String])-    expectAny $-      QReifyInstances ''Default [ConT ''Int]-        |-> $(reifyInstancesStatic ''Default [ConT ''Int])-    expectAny $-      QReifyInstances ''Default [AppT (ConT ''Maybe) (ConT ''Bool)]-        |-> $(reifyInstancesStatic ''Default [AppT (ConT ''Maybe) (ConT ''Bool)])-    expectAny $-      QReifyInstances_ (eq ''Show) (is functionType) |-> []-    expectAny $-      QReifyInstances_ (eq ''Eq) (is functionType) |-> []+    $(onReify [|allowUnexpected|] ''String)+    $(onReify [|allowUnexpected|] ''Char)+    $(onReify [|allowUnexpected|] ''Int)+    $(onReify [|allowUnexpected|] ''Bool)+    $(onReify [|allowUnexpected|] ''Enum)+    $(onReify [|allowUnexpected|] ''Monad) -    expectAny $-      QReifyInstances_ (eq ''Show) (elemsAre [$(qMatch [p|AppT ListT (VarT _)|])])-        |-> $(reifyInstancesStatic ''Show [AppT ListT (VarT (mkName "a_0"))])-    expectAny $-      QReifyInstances_ (eq ''Eq) (elemsAre [$(qMatch [p|AppT ListT (VarT _)|])])-        |-> $(reifyInstancesStatic ''Eq [AppT ListT (VarT (mkName "a_0"))])+    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''String])+    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''String])+    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Char])+    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Char])+    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Int])+    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Int])+    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Bool])+    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Bool])+    $(onReifyInstances [|allowUnexpected|] ''Default [TupleT 0])+    $(onReifyInstances [|allowUnexpected|] ''Default [ConT ''String])+    $(onReifyInstances [|allowUnexpected|] ''Default [ConT ''Int])+    $( onReifyInstances+         [|allowUnexpected|]+         ''Default+         [AppT (ConT ''Maybe) (ConT ''Bool)]+     )++    allowUnexpected $ QReifyInstances_ (eq ''Show) (is functionType) |-> []+    allowUnexpected $ QReifyInstances_ (eq ''Eq) (is functionType) |-> []++    allowUnexpected $+      QReifyInstances_+        (eq ''Show)+        (elemsAre [$(qMatch [p|AppT ListT (VarT _)|])])+        |-> $(reifyInstancesStatic ''Show [AppT ListT (VarT (mkName "a"))])+    allowUnexpected $+      QReifyInstances_+        (eq ''Eq)+        (elemsAre [$(qMatch [p|AppT ListT (VarT _)|])])+        |-> $(reifyInstancesStatic ''Eq [AppT ListT (VarT (mkName "a"))])
+ test/QuasiMockBase.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++module QuasiMockBase where++import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Test.HMock.TH (deriveMockableBase)+import Util.DeriveRecursive (deriveRecursive)++#if MIN_VERSION_template_haskell(2, 16, 0)+-- Pre-define low-level instance to prevent deriveRecursive from trying.+instance Lift Bytes where lift = undefined; liftTyped = undefined+#endif++deriveRecursive Nothing ''Lift ''Info++deriveMockableBase ''Quasi++reifyStatic :: Name -> Q Exp+reifyStatic n = reify n >>= lift++onReify :: Q Exp -> Name -> Q Exp+onReify handler n = do+  result <- reify n+  [| $handler (QReify $(lift n) |-> $(lift result))|]++deriveRecursive Nothing ''Lift ''InstanceDec++reifyInstancesStatic :: Name -> [Type] -> Q Exp+reifyInstancesStatic n ts = reifyInstances n ts >>= lift++onReifyInstances :: Q Exp -> Name -> [Type] -> Q Exp+onReifyInstances handler n ts = do+  result <- reifyInstances n ts+  [|$handler (QReifyInstances $(lift n) $(lift ts) |-> $(lift result))|]
test/TH.hs view
@@ -8,9 +8,8 @@ import Language.Haskell.TH import QuasiMock import Test.HMock-import Test.HMock.Internal.TH.Util (resolveInstance, unifyTypes)+import Test.HMock.Internal.TH (resolveInstance, unifyTypes) import Test.Hspec-import Util.TH (reifyInstancesStatic, reifyStatic)  data NotShowable @@ -66,21 +65,11 @@     it "recognizes when a nested type lacks instance" $       example $         runMockT $ do-          expectAny $ QReify ''NotShowable |-> $(reifyStatic ''NotShowable)-          expectAny $-            QReifyInstances ''Show [ConT ''NotShowable]-              |-> $(reifyInstancesStatic ''Show [ConT ''NotShowable])-          expectAny $-            QReifyInstances-              ''Show-              [AppT (AppT (TupleT 2) (ConT ''Int)) (ConT ''NotShowable)]-              |-> $( reifyInstancesStatic-                       ''Show-                       [ AppT-                           (AppT (TupleT 2) (ConT ''Int))-                           (ConT ''NotShowable)-                       ]-                   )+          $(onReify [|expectAny|] ''NotShowable)+          $(onReifyInstances [|expectAny|] ''Show [ConT ''NotShowable])+          $( [t|(Int, NotShowable)|]+               >>= onReifyInstances [|expectAny|] ''Show . (: [])+           )            t <- runQ [t|(Int, NotShowable)|]           result <- runQ $ resolveInstance ''Show t
− test/Util/TH.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}--module Util.TH (deriveRecursive, reifyStatic, reifyInstancesStatic) where--import Language.Haskell.TH-import Language.Haskell.TH.Syntax-import Util.DeriveRecursive (deriveRecursive)--#if MIN_VERSION_template_haskell(2, 16, 0)--- Pre-define low-level instance to prevent deriveRecursive from trying.-instance Lift Bytes where lift = undefined; liftTyped = undefined-#endif--deriveRecursive Nothing ''Lift ''Info--reifyStatic :: Name -> Q Exp-reifyStatic n = reify n >>= lift--deriveRecursive Nothing ''Lift ''InstanceDec--reifyInstancesStatic :: Name -> [Type] -> Q Exp-reifyInstancesStatic n ts = reifyInstances n ts >>= lift