-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A flexible mock framework for testing effectful code. -- -- HMock is a flexible mock framework for testing effectful code in -- Haskell. Tests can set up expectations about actions that can or -- should be performed and their results, and then verify those -- expectations when the test is complete. -- -- For more information, see the module documentation for -- Test.HMock. @package HMock @version 0.2.0.0 -- | Internal utilities used for HMock implementation. module Test.HMock.Internal.Util -- | A value together with its source location. data Located a Loc :: Maybe String -> a -> Located a -- | Annotates a value with its source location from the call stack. locate :: CallStack -> a -> Located a -- | Formats a Located String to include its source location. withLoc :: Located String -> String -- | Returns all ways to choose one element from a list, and the -- corresponding remaining list. choices :: [a] -> [(a, [a])] -- | Checks if one sequence is a subsequence of another. isSubsequenceOf :: (IsSequence t, Eq (Element t)) => t -> t -> Bool instance GHC.Base.Functor Test.HMock.Internal.Util.Located instance GHC.Classes.Ord a => GHC.Classes.Ord (Test.HMock.Internal.Util.Located a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Test.HMock.Internal.Util.Located a) -- | Template Haskell utilities used to implement HMock. module Test.HMock.Internal.TH -- | Gets the unapplied top-level name from a type application. unappliedName :: Type -> Maybe Name -- | Fetches the Name of a TyVarBndr. tvName :: TyVarBndr -> Name -- | Creates a TyVarBndr for a plain variable without a kind -- annotation. bindVar :: Name -> TyVarBndr -- | Substitutes a Type for all occurrences of the given -- Name. substTypeVar :: Name -> Type -> Type -> Type -- | Makes variable substitutions from the given table. substTypeVars :: [(Name, Type)] -> Type -> Type -- | 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]) -- | Gets all free type variable Names in the given Type. freeTypeVars :: Type -> [Name] -- | 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) -- | Produces a CxtQ that gives all given variable Names all -- of the given class Types. constrainVars :: [TypeQ] -> [Name] -> CxtQ -- | 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)]) -- | Removes all module names from Names in the given value, so that -- it will pretty-print more cleanly. removeModNames :: Data a => a -> a -- | Determines if this is a polytype, including top-level quantification. hasPolyType :: Type -> Bool -- | Determines if there is a polytype nested anywhere in the given type. -- Top-level quantification doesn't count. hasNestedPolyType :: Type -> Bool -- | Attempts to produce sufficient constraints for the given Type -- to be an instance of the given class Name. resolveInstance :: Name -> Type -> Q (Maybe Cxt) -- | Simplifies a context with complex types (requiring FlexibleContexts) -- to try to obtain one with all constraints applied to variables. simplifyContext :: Cxt -> Q (Maybe Cxt) -- | 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 -- | This module defines the MockableBase and Mockable -- classes that are needed to use an MTL-style type class with -- 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 -- | 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) setupMockable :: (Mockable cls, MonadIO m, Typeable m) => proxy cls -> MockSetup m () -- | A base class for Monad subclasses whose methods can be mocked. -- You usually want to generate this instance using makeMockable, -- makeMockableBase, deriveMockable, or -- 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 family Action cls :: Symbol -> (Type -> Type) -> Type -> Type; -- | A specification for matching actions. The actual arguments should be -- replaced with predicates. data family Matcher cls :: Symbol -> (Type -> Type) -> Type -> Type; } -- | Gets a text description of an Action, for use in error -- messages. showAction :: MockableBase cls => Action cls name m a -> String -- | Gets a text description of a Matcher, for use in error -- messages. showMatcher :: MockableBase cls => Maybe (Action cls name m a) -> Matcher cls name m b -> String -- | Attempts to match an Action with a Matcher. matchAction :: MockableBase cls => Matcher cls name m a -> Action cls name m a -> MatchResult -- | 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 -- | 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 -- | Internal module to define Rule, so that its constructor can be -- visible to other implementation code. module Test.HMock.Internal.Rule -- | 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_ anything
--       |-> "hello"
--       |=> (GetLine prompt) -> "The prompt was " ++ prompt
--       |-> "quit"
--   
data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) [:=>] :: Matcher cls name m r -> [Action cls name m r -> MockT m r] -> Rule cls name m r -- | 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 -- | An acceptable range of number of times for something to happen. -- -- A multiplicity can have a lower and an upper bound. data Multiplicity -- | Checks whether a certain number satisfies the Multiplicity. meetsMultiplicity :: Multiplicity -> Int -> Bool -- | 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 -- | A Multiplicity that means exactly once. -- --
--   >>> meetsMultiplicity once 0
--   False
--   
--   >>> meetsMultiplicity once 1
--   True
--   
--   >>> meetsMultiplicity once 2
--   False
--   
once :: Multiplicity -- | A Multiplicity that means any number of times. >>> -- meetsMultiplicity anyMultiplicity 0 True >>> -- meetsMultiplicity anyMultiplicity 1 True >>> -- meetsMultiplicity anyMultiplicity 10 True anyMultiplicity :: Multiplicity -- | 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 -- | 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 -- | 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 instance GHC.Classes.Eq Test.HMock.Multiplicity.Multiplicity instance GHC.Show.Show Test.HMock.Multiplicity.Multiplicity instance GHC.Num.Num Test.HMock.Multiplicity.Multiplicity -- | The internal core language of expectations in HMock. module Test.HMock.Internal.ExpectSet -- | A set of expected steps and their responses. This is the "core" -- language of expectations for HMock. It's based roughly on -- Svenningsson, Svensson, Smallbone, Arts, Norell, and Hughes' -- Expressive Semantics of Mocking. However, there are a few small -- adjustments. We have two repetition operators which respectively -- represent general repetition with interleaving, and consecutive -- repetition. We also attach arbitrary multiplicities to repetition. data ExpectSet step [ExpectStep] :: step -> ExpectSet step [ExpectNothing] :: ExpectSet step [ExpectSequence] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectInterleave] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectEither] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectMulti] :: Multiplicity -> ExpectSet step -> ExpectSet step [ExpectConsecutive] :: Multiplicity -> ExpectSet step -> ExpectSet step -- | Checks whether an ExpectSet is in an "accepting" state. In other -- words, is it okay for the test to end here? If False, then there are -- still expectations that must be satisfied before the test can succeed. satisfied :: ExpectSet step -> Bool -- | 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 each case? liveSteps :: ExpectSet step -> [(step, ExpectSet step)] -- | Performs a complete simplification of the ExpectSet. This could be -- slow, but we intend to do it only for error messages, so it need not -- be very fast. simplify :: ExpectSet step -> ExpectSet step -- | Get a list of all steps mentioned by an ExpectSet. This is used -- to determine which classes need to be initialized before adding an -- expectation. getSteps :: ExpectSet step -> [step] -- | A higher-level intermediate form of an ExpectSet suitable for -- communication with the user. Chains of binary operators are collected -- into sequences to be displayed in lists rather than arbitrary nesting. data CollectedSet step [CollectedStep] :: step -> CollectedSet step [CollectedNothing] :: CollectedSet step [CollectedSequence] :: [CollectedSet step] -> CollectedSet step [CollectedInterleave] :: [CollectedSet step] -> CollectedSet step [CollectedChoice] :: [CollectedSet step] -> CollectedSet step [CollectedMulti] :: Multiplicity -> CollectedSet step -> CollectedSet step [CollectedConsecutive] :: Multiplicity -> CollectedSet step -> CollectedSet step -- | Collects an ExpectSet into the intermediate form for display. It's -- assumed that the expression was simplified before this operation. collect :: ExpectSet step -> CollectedSet step -- | Converts a set of expectations into a string that summarizes them, -- with the given prefix (used to indent). formatExpectSet :: Show step => ExpectSet step -> String -- | Reduces a set of expectations to the minimum steps that would be -- required to satisfy the entire set. This weeds out unnecessary -- information before reporting that there were unmet expectations at the -- end of the test. excess :: ExpectSet step -> ExpectSet step instance GHC.Classes.Eq step => GHC.Classes.Eq (Test.HMock.Internal.ExpectSet.ExpectSet step) instance GHC.Show.Show step => GHC.Show.Show (Test.HMock.Internal.ExpectSet.ExpectSet step) -- | This module defines Predicates which you can use to match the -- arguments of a method in your execution plan. module Test.HMock.Predicates -- | 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 :: String -> (a -> Bool) -> Predicate a [showPredicate] :: Predicate a -> String [accept] :: Predicate a -> a -> Bool -- | A Predicate that accepts anything at all. -- --
--   >>> accept anything "foo"
--   True
--   
--   >>> accept anything undefined
--   True
--   
anything :: Predicate a -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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) -- | 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) -- | 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) -- | 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) -- | A Predicate that accepts 3-tuples whose elements satisfy the -- corresponding child Predicates. -- --
--   >>> 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) -- | 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) -- | 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) -- | 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 -- | 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 -- | 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 -- | A Predicate that accepts sequences that start with the given -- prefix. -- --
--   >>> accept (startsWith "fun") "fungible"
--   True
--   
--   >>> accept (startsWith "gib") "fungible"
--   False
--   
startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t -- | A Predicate that accepts sequences that end with the given -- suffix. -- --
--   >>> accept (endsWith "ow") "crossbow"
--   True
--   
--   >>> accept (endsWith "ow") "trebuchet"
--   False
--   
endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t -- | A Predicate that accepts sequences that contain the given -- (consecutive) substring. -- --
--   >>> accept (hasSubstr "i") "team"
--   False
--   
--   >>> accept (hasSubstr "i") "partnership"
--   True
--   
hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t -- | 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, IsSequence t, Eq (Element t)) => t -> Predicate t -- | Transforms a Predicate on Strings 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 -- | A Predicate that accepts Strings 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 -- | A Predicate that accepts Strings 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 -- | A Predicate that accepts Strings 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 -- | A Predicate that accepts Strings 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | A Predicate that accepts map-like structures which contain a -- key/value pair matched by the given child Predicates (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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 Predicates. -- --
--   >>> accept (is even) 3
--   False
--   
--   >>> accept (is even) 4
--   True
--   
is :: HasCallStack => (a -> Bool) -> Predicate a -- | 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 -- | 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 -- | 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 -- | 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 -- | 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 instance GHC.Show.Show (Test.HMock.Predicates.Predicate a) -- | 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 -- | 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_ anything
--       |-> "hello"
--       |=> (GetLine prompt) -> "The prompt was " ++ prompt
--       |-> "quit"
--   
data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) -- | Class for things that can be expected. This is includes Rules, -- but also bare Matchers and Actions with no explicit -- response. class Expectable cls name m r ex | ex -> cls name m r -- | Converts an expectable to a Rule that means the same thing. toRule :: Expectable cls name m r ex => ex -> Rule cls name m r -- | 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 infixl 1 |-> -- | 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 infixl 1 |=> instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Internal.Rule.Rule cls name m r) instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Mockable.Matcher cls name m r) -- | This module defines the ExpectContext class, whose members -- provide the combinators for building the execution plan for your -- mocks. Notably, there is a MockT instance for -- ExpectContext, so you can use these combinators to add -- expectations inside your tests that run in MockT, as well as -- nesting them in other combinators. module Test.HMock.ExpectContext -- | 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 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) -- | 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 :: (ExpectContext ctx, 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. -- --
--   runMockT $ do
--     expect $ MakeList
--     expectN (atLeast 2) $
--       CheckList "Cindy Lou Who" |-> "nice"
--   
--     callCodeUnderTest
--   
expectN :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => Multiplicity -> expectable -> ctx m () -- | 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 expectAny overrides earlier -- uses, but only for calls that match its conditions. -- --
--   runMockT $ do
--     expectAny $ ReadFile_ anything |-> "tlhIngan maH!"
--     expectAny $ ReadFile "config.txt" |-> "lang: klingon"
--   
--     callCodeUnderTest
--   
expectAny :: (ExpectContext ctx, 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 :: (ExpectContext ctx, 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 :: (ExpectContext ctx, 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 :: (ExpectContext ctx, 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 :: (ExpectContext ctx, 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 :: (ExpectContext ctx, MonadIO m) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m () -- | This module defines the desugaring from multi-response Rules -- into multiple steps. module Test.HMock.Internal.Step -- | 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) [:->] :: 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 [Step] :: MockableMethod cls name m r => Located (SingleRule cls name m r) -> Step m -- | 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) -- | 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) -- | 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 :: ExpectSet (Step m) -> Expected m a [unwrapExpected] :: Expected m a -> ExpectSet (Step m) instance Test.HMock.ExpectContext.ExpectContext Test.HMock.Internal.Step.Expected instance GHC.Show.Show (Test.HMock.Internal.Step.Step m) -- | This module contains MockT and SetupMockT state functions. module Test.HMock.Internal.State -- | Full state of a mock. data MockState m MockState :: TVar (ExpectSet (Step m)) -> TVar [(Bool, Step m)] -> TVar Bool -> TVar (Set TypeRep) -> Maybe (MockState m) -> MockState m [mockExpectSet] :: MockState m -> TVar (ExpectSet (Step m)) [mockDefaults] :: MockState m -> TVar [(Bool, Step m)] [mockCheckAmbiguity] :: MockState m -> TVar Bool [mockClasses] :: MockState m -> TVar (Set TypeRep) [mockParent] :: MockState m -> 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) -- | Gets a list of all states, starting with the innermost. allStates :: MockState m -> [MockState m] -- | Gets the root state. rootState :: MockState m -> MockState m -- | 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 [MockSetup] :: {unMockSetup :: ReaderT (MockState m) STM a} -> MockSetup m a -- | Runs a setup action with the root state, rather than the current one. runInRootState :: MockSetup m a -> MockSetup m a -- | Run an STM action in MockSetup mockSetupSTM :: STM a -> MockSetup m a -- | 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 () -- | Runs class initialization for all uninitialized Mockable -- classes in the given ExpectSet. initClassesAsNeeded :: MonadIO m => ExpectSet (Step m) -> MockSetup m () -- | Monad transformer for running mocks. newtype MockT m a [MockT] :: {unMockT :: ReaderT (MockState m) m a} -> MockT m a -- | Applies a function to the base monad of MockT. mapMockT :: (m a -> m b) -> MockT m a -> MockT m b -- | This type class defines a shared API between the MockT and -- MockSetup monads. class MockContext ctx -- | Runs a MockSetup action in this monad. fromMockSetup :: (MockContext ctx, MonadIO m) => MockSetup m a -> ctx m a -- | Adds an expectation to the MockState for the given -- ExpectSet, interleaved with any existing expectations. expectThisSet :: MonadIO m => ExpectSet (Step m) -> MockT m () instance GHC.Base.Monad (Test.HMock.Internal.State.MockSetup m) instance GHC.Base.Applicative (Test.HMock.Internal.State.MockSetup m) instance GHC.Base.Functor (Test.HMock.Internal.State.MockSetup m) instance Control.Monad.IO.Unlift.MonadUnliftIO m => Control.Monad.IO.Unlift.MonadUnliftIO (Test.HMock.Internal.State.MockT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Test.HMock.Internal.State.MockT m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Test.HMock.Internal.State.MockT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Test.HMock.Internal.State.MockT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Test.HMock.Internal.State.MockT m) instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Test.HMock.Internal.State.MockT m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Test.HMock.Internal.State.MockT m) 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) instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Test.HMock.Internal.State.MockT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Test.HMock.Internal.State.MockT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Test.HMock.Internal.State.MockT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Test.HMock.Internal.State.MockT m) instance GHC.Base.Monad m => GHC.Base.Monad (Test.HMock.Internal.State.MockT m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Test.HMock.Internal.State.MockT m) instance GHC.Base.Functor m => GHC.Base.Functor (Test.HMock.Internal.State.MockT m) instance Test.HMock.Internal.State.MockContext Test.HMock.Internal.State.MockSetup instance Test.HMock.Internal.State.MockContext Test.HMock.Internal.State.MockT instance Control.Monad.Trans.Class.MonadTrans Test.HMock.Internal.State.MockT instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Test.HMock.Internal.State.MockT m) instance Test.HMock.ExpectContext.ExpectContext Test.HMock.Internal.State.MockT -- | 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 -- | Monad transformer for running mocks. data MockT m a -- | Runs a test in the MockT monad, handling all of the mocks. runMockT :: forall m a. MonadIO m => MockT m a -> m a -- | 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 -- | 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 -- | 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 -- | 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 () -- | 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 -- | 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 () -- | 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. data MockSetup m a -- | This type class defines a shared API between the MockT and -- MockSetup monads. class MockContext ctx -- | 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 |=> r) is equivalent to -- allowUnexpected m >> byDefault (m -- |=> r). -- -- The difference between expectAny and allowUnexpected is -- subtle, but comes down to ambiguity: -- -- 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 () -- | 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 () -- | Functions to delegate Actions 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 -- | 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 -- | 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 -- | 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: -- -- module Test.HMock.TH -- | Custom options for deriving a Mockable class. data MockableOptions MockableOptions :: String -> Bool -> MockableOptions -- | Suffix to add to Action and Matcher names. Defaults to -- "". [mockSuffix] :: MockableOptions -> 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] :: MockableOptions -> Bool -- | 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] -- | 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] -- | 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] -- | 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] -- | Defines almost all instances necessary to use HMock with the given -- class. Equivalent to both deriveMockableBase and -- deriveForMockT. makeMockableBase :: Name -> Q [Dec] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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: -- -- deriveMockableBase :: Name -> Q [Dec] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] -- | 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] instance GHC.Show.Show Test.HMock.TH.Method instance GHC.Show.Show Test.HMock.TH.Instance instance Data.Default.Class.Default Test.HMock.TH.MockableOptions -- | This module provides a monad transformer, MockT, which can be -- used to test with mocks of Haskell mtl-style type classes. To -- use a mock, you define the expected actions and their results, and -- then run the code you are testing. The framework verifies that the -- behavior of the code matched your expectations. -- -- For an introduction to the idea of mocks, see Mocks Aren't -- Stubs, by Martin Fowler. -- -- WARNING: Hmock's API is likely to change soon. Please ensure you use -- an upper bound on the version number. The current API works fine for -- mocking with MTL-style classes. I want HMock to also work with effect -- systems, servant, haxl, and more. To accomplish this, I'll need to -- make breaking changes to the API. -- -- Suppose you have a MonadFilesystem typeclass, which is -- instantiated by monads that implement filesystem operations: -- --
--   class Monad m => MonadFilesystem m where
--     readFile :: FilePath -> m String
--     writeFile :: FilePath -> String -> m ()
--   
-- -- You can use HMock to test code using MonadFilesystem like -- this: -- --
--   copyFile :: MonadFilesystem m => FilePath -> FilePath -> m ()
--   copyFile a b = readFile a >>= writeFile b
--   
--   makeMockable ''MonadFilesystem
--   
--   spec = describe "copyFile" $
--     it "reads a file and writes its contents to another file" $
--       runMockT $ do
--         expect $ ReadFile "foo.txt" |-> "contents"
--         expect $ WriteFile "bar.txt" "contents" |-> ()
--         copyFile "foo.txt" "bar.txt"
--   
-- -- The Template Haskell splice, makeMockable, generates the -- boilerplate needed to use MonadFilesystem with HMock. You -- then use runMockT to begin a test with mocks, expect to -- set up your expected actions and responses, and finally execute your -- code. module Test.HMock