-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Simple, expressive testing library
--   
--   EasyTest is a simple testing toolkit, meant to replace most uses of
--   QuickCheck, SmallCheck, HUnit, and frameworks like Tasty, etc. Here's
--   an example usage:
--   
--   <pre>
--   module Main where
--   
--   import EasyTest
--   import Control.Applicative
--   import Control.Monad
--   
--   suite :: Test ()
--   suite = tests
--     [ scope "addition.ex1" $ expect (1 + 1 == 2)
--     , scope "addition.ex2" $ expect (2 + 3 == 5)
--     , scope "list.reversal" . fork $ do
--         -- generate lists from size 0 to 10, of Ints in (0,43)
--         -- shorthand: listsOf [0..10] (int' 0 43)
--         ns &lt;- [0..10] `forM` \n -&gt; replicateM n (int' 0 43)
--         ns `forM_` \ns -&gt; expect (reverse (reverse ns) == ns)
--     -- equivalent to `scope "addition.ex3"`
--     , scope "addition" . scope "ex3" $ expect (3 + 3 == 6)
--     , scope "always passes" $ do
--         note "I'm running this test, even though it always passes!"
--         ok -- like `pure ()`, but records a success result
--     , scope "failing test" $ crash "oh noes!!" ]
--   
--   -- NB: `run suite` would run all tests, but we only run
--   -- tests whose scopes are prefixed by "addition"
--   main = runOnly "addition" suite
--   </pre>
--   
--   This generates the output:
--   
--   <pre>
--   Randomness seed for this run is 5104092164859451056
--   Raw test output to follow ...
--   ------------------------------------------------------------
--   OK addition.ex1
--   OK addition.ex2
--   OK addition.ex3
--   ------------------------------------------------------------
--   ✅  3 tests passed, no failures! 👍 🎉
--   </pre>
--   
--   The idea here is to write tests with ordinary Haskell code, with
--   control flow explicit and under programmer control.
@package easytest
@version 0.2.1

module EasyTest.Internal

-- | Record a failure at the current scope
crash :: HasCallStack => Text -> Test a

-- | Log a message
note :: Text -> Test ()

-- | Label a test. Can be nested. A "." is placed between nested scopes, so
--   <tt>scope "foo" . scope "bar"</tt> is equivalent to <tt>scope
--   "foo.bar"</tt>
scope :: Text -> Test a -> Test a

-- | Status of a test
data Status
Failed :: Status
Passed :: !Int -> Status
Skipped :: Status
data Env
Env :: TVar StdGen -> [Text] -> TBQueue (Maybe (TMVar ([Text], Status))) -> (Text -> IO ()) -> [Text] -> Env
[envRng] :: Env -> TVar StdGen
[envMessages] :: Env -> [Text]
[envResults] :: Env -> TBQueue (Maybe (TMVar ([Text], Status)))
[envNote] :: Env -> Text -> IO ()
[envAllow] :: Env -> [Text]

-- | Tests are values of type <tt>Test a</tt>, and <a>Test</a> forms a
--   monad with access to:
--   
--   <ul>
--   <li>repeatable randomness (the <a>random</a> and <a>random'</a>
--   functions for random and bounded random values, or handy specialized
--   <a>int</a>, <a>int'</a>, <a>double</a>, <a>double'</a>, etc)</li>
--   <li>I/O (via <a>liftIO</a> or <a>io</a>, which is an alias for
--   <a>liftIO</a>)</li>
--   <li>failure (via <a>crash</a>, which yields a stack trace, or
--   <a>fail</a>, which does not)</li>
--   <li>logging (via <a>note</a>, <a>noteScoped</a>, or <a>note'</a>)</li>
--   <li>hierarchically-named subcomputations (under <a>scope</a>) which
--   can be switched on and off via <a>runOnly</a></li>
--   <li>parallelism (via <a>fork</a>)</li>
--   <li>conjunction of tests via <a>MonadPlus</a> (the <a>&lt;|&gt;</a>
--   operation runs both tests, even if the first test fails, and the tests
--   function used above is just <a>msum</a>).</li>
--   </ul>
--   
--   Using any or all of these capabilities, you assemble <a>Test</a>
--   values into a "test suite" (just another <a>Test</a> value) using
--   ordinary Haskell code, not framework magic. Notice that to generate a
--   list of random values, we just <a>replicateM</a> and <a>forM</a> as
--   usual.
newtype Test a
Test :: ReaderT Env IO (Maybe a) -> Test a
actionAllowed :: Env -> Bool
putResult :: Status -> ReaderT Env IO ()
runWrap :: Env -> ReaderT Env IO (Maybe a) -> IO (Maybe a)
combineStatus :: Status -> Status -> Status
instance Control.Monad.Reader.Class.MonadReader EasyTest.Internal.Env EasyTest.Internal.Test
instance GHC.Base.Monad EasyTest.Internal.Test
instance GHC.Base.Functor EasyTest.Internal.Test
instance GHC.Base.Applicative EasyTest.Internal.Test
instance Control.Monad.IO.Class.MonadIO EasyTest.Internal.Test
instance GHC.Base.Alternative EasyTest.Internal.Test
instance GHC.Base.MonadPlus EasyTest.Internal.Test
instance Data.String.IsString (EasyTest.Internal.Test a -> EasyTest.Internal.Test a)
instance GHC.Base.Semigroup EasyTest.Internal.Status
instance GHC.Base.Monoid EasyTest.Internal.Status


-- | EasyTest is a simple testing toolkit, meant to replace most uses of
--   QuickCheck, SmallCheck, HUnit, and frameworks like Tasty, etc. Here's
--   an example usage:
--   
--   <pre>
--   module Main where
--   
--   import EasyTest
--   import Control.Applicative
--   import Control.Monad
--   
--   suite :: Test ()
--   suite = tests
--     [ scope "addition.ex1" $ expect (1 + 1 == 2)
--     , scope "addition.ex2" $ expect (2 + 3 == 5)
--     , scope "list.reversal" . fork $ do
--         -- generate lists from size 0 to 10, of Ints in (0,43)
--         -- shorthand: listsOf [0..10] (int' 0 43)
--         ns <tt>&lt;-</tt> [0..10] <tt>`</tt>forM<tt>`</tt> \n -&gt; replicateM n (int' 0 43)
--         ns <tt>`</tt>forM_<tt>`</tt> \ns -&gt; expect (reverse (reverse ns) == ns)
--     -- equivalent to `scope "addition.ex3"`
--     , scope "addition" . scope "ex3" $ expect (3 + 3 == 6)
--     , scope "always passes" $ do
--         note "I'm running this test, even though it always passes!"
--         ok -- like `pure ()`, but records a success result
--     , scope "failing test" $ crash "oh noes!!" ]
--   
--   -- NB: `run suite` would run all tests, but we only run
--   -- tests whose scopes are prefixed by "addition"
--   main = runOnly "addition" suite
--   </pre>
--   
--   This generates the output:
--   
--   <pre>
--   Randomness seed for this run is 5104092164859451056
--   Raw test output to follow ...
--   ------------------------------------------------------------
--   OK addition.ex1
--   OK addition.ex2
--   OK addition.ex3
--   ------------------------------------------------------------
--   ✅  3 tests passed, no failures! 👍 🎉
--   </pre>
--   
--   The idea here is to write tests with ordinary Haskell code, with
--   control flow explicit and under programmer control. Tests are values
--   of type <tt>Test a</tt>, and <tt>Test</tt> forms a monad with access
--   to:
--   
--   <ul>
--   <li>repeatable randomness (the <tt>random</tt> and <tt>random'</tt>
--   functions for <tt>random</tt> and bounded random values, or handy
--   specialized <tt>int</tt>, <tt>int'</tt>, <tt>double</tt>,
--   <tt>double'</tt>, etc)</li>
--   <li>I/O (via <tt>liftIO</tt> or <tt>EasyTest.io</tt>, which is an
--   alias for <tt>liftIO</tt>)</li>
--   <li>failure (via <tt>crash</tt>, which yields a stack trace, or
--   <tt>fail</tt>, which does not)</li>
--   <li>logging (via <tt>note</tt>, <tt>noteScoped</tt>, or
--   <tt>note'</tt>)</li>
--   <li>hierarchically-named subcomputations which can be switched on and
--   off (in the above code, notice that only the tests scoped under
--   "addition" are run, and we could do <tt>run</tt> instead of
--   <tt>runOnly</tt> if we wanted to run the whole suite)</li>
--   <li>parallelism (note the fork which runs that subtree of the test
--   suite in a parallel thread).</li>
--   <li>conjunction of tests via <tt>MonadPlus</tt> (the <tt><a>|</a></tt>
--   operation runs both tests, even if the first test fails, and the tests
--   function used above is just <tt>msum</tt>).</li>
--   <li>Using any or all of these capabilities, you assemble <tt>Test</tt>
--   values into a "test suite" (just another <tt>Test</tt> value) using
--   ordinary Haskell code, not framework magic. Notice that to generate a
--   list of random values, we just <tt>replicateM</tt> and <tt>forM</tt>
--   as usual. If this gets tedious... we can factor this logic out into
--   helper functions! For instance:</li>
--   </ul>
--   
--   <pre>
--   listOf :: Int -&gt; Test a -&gt; Test [a]
--   listOf = replicateM
--   
--   listsOf :: [Int] -&gt; Test a -&gt; Test [[a]]
--   listsOf sizes gen = sizes <tt>`</tt>forM<tt>`</tt> \n -&gt; listOf n gen
--   
--   ex :: Test ()
--   ex = do
--     ns &lt;- listsOf [0..100] int
--     ns <tt>`</tt>forM_<tt>`</tt> \ns -&gt; expect (reverse (reverse ns) == ns)
--   This library is opinionated and might not be for everyone. If you're curious about any of the design decisions made, see my rationale for writing it.
--   </pre>
--   
--   <h1>User guide</h1>
--   
--   The simplest tests are <tt>ok</tt>, <tt>crash</tt>, and
--   <tt>expect</tt>:
--   
--   <pre>
--   -- Record a success
--   ok :: Test ()
--   
--   -- Record a failure
--   crash :: String -&gt; Test a
--   
--   -- Record a success if True, otherwise record a failure
--   expect :: Bool -&gt; Test ()
--   </pre>
--   
--   NB: <tt>fail</tt> is equivalent to <tt>crash</tt>, but doesn't provide
--   a stack trace on failure.
--   
--   We can lift I/O into <tt>Test</tt> using <tt>io</tt> (or
--   <tt>liftIO</tt>, but I always forget where to import that from):
--   
--   <pre>
--   io :: IO a -&gt; Test a
--   </pre>
--   
--   <tt>Test</tt> is also a <tt>Monad</tt>. Note that <tt>return</tt> and
--   <tt>pure</tt> do not record a result. Use <tt>ok</tt>,
--   <tt>expect</tt>, or <tt>crash</tt> for that purpose.
--   
--   We often want to label tests so we can see when they succeed or fail.
--   For that we use <tt>scope</tt>:
--   
--   <pre>
--   -- | Label a test. Can be nested. A `'.'` is placed between nested
--   -- scopes, so `scope "foo" . scope "bar"` is equivalent to `scope "foo.bar"`
--   scope :: String -&gt; Test a -&gt; Test a
--   </pre>
--   
--   Here's an example usage, putting all these primitives together:
--   
--   <pre>
--   module Main where
--   
--   import EasyTest (ok, scope, crash, expect, run)
--   
--   suite :: Test ()
--   suite = do
--     ok
--     scope "test-crash" $ crash "oh noes!"
--     expect (1 + 1 == 2)
--   
--   main = run suite
--   </pre>
--   
--   This example is sequencing the <tt>ok</tt>, <tt>crash</tt>, and
--   <tt>expect</tt> monadically, so the test halts at the first failure.
--   The output is:
--   
--   <pre>
--   Randomness seed for this run is 1830293182471192517
--   Raw test output to follow ...
--   ------------------------------------------------------------
--   test-crash FAILURE oh noes! CallStack (from HasCallStack):
--     crash, called at <tt>/</tt>Users<tt>/</tt>pchiusano<tt>/</tt>code<tt>/</tt>easytest<tt>/</tt>tests<tt>/</tt>Suite.hs:10:24 in main:Main
--   OK
--   FAILED test-crash
--   ------------------------------------------------------------
--   
--   
--     1 passed
--     1 FAILED (failed scopes below)
--       "test-crash"
--   
--     To rerun with same random seed:
--   
--       EasyTest.rerun 1830293182471192517
--       EasyTest.rerunOnly 1830293182471192517 "test-crash"
--   
--   
--   ------------------------------------------------------------
--   ❌
--   </pre>
--   
--   In the output (which is streamed to the console), we get a stack trace
--   pointing to the line where crash was called
--   (<tt>..tests/Suite.hs:10:24</tt>), information about failing tests,
--   and instructions for rerunning the tests with an identical random seed
--   (in this case, there's no randomness, so <tt>rerun</tt> would work
--   fine, but if our test generated random data, we might want to rerun
--   with the exact same random numbers).
--   
--   The last line of the output always indicates success or failure of the
--   overall suite... and information about any failing tests is
--   immediately above that. You should NEVER have to scroll through a
--   bunch of test output just to find out which tests actually failed!
--   Also, the streaming output always has <tt>OK</tt> or <tt>FAILED</tt>
--   as the leftmost text for ease of scanning.
--   
--   If you try running a test suite that has no results recorded (like if
--   you have a typo in a call to runOnly, or you forget to use ok or
--   expect to record a test result), you'll see a warning like this:
--   
--   <pre>
--   😶  hmm ... no test results recorded
--   Tip: use <tt>`</tt>ok<tt>`</tt>, <tt>`</tt>expect<tt>`</tt>, or <tt>`</tt>crash<tt>`</tt> to record results
--   Tip: if running via <tt>`</tt>runOnly<tt>`</tt> or <tt>`</tt>rerunOnly<tt>`</tt>, check for typos
--   </pre>
--   
--   The various run functions (<tt>run</tt>, <tt>runOnly</tt>,
--   <tt>rerun</tt>, and <tt>rerunOnly</tt>) all exit the process with a
--   nonzero status in the event of a failure, so they can be used for
--   continuous integration or test running tools that key off the process
--   exit code to determine whether the suite succeeded or failed. For
--   instance, here's the relevant portion of a typical cabal file:
--   
--   <pre>
--   -- Preferred way to run EasyTest-based test suite
--   executable runtests
--     main-is:        NameOfYourTestSuite.hs
--     ghc-options:    -w -threaded -rtsopts -v0
--     hs-source-dirs: tests
--     other-modules:
--     build-depends:
--       base,
--       easytest
--   
--   -- I really have no idea why you'd ever use this, unless you
--   -- really feel the need to run your tests via cabal's "test runner"
--   -- which "conveniently" hides all output unless you pass it some
--   -- random flag I never remember
--   test-suite tests
--     type:           exitcode-stdio-1.0
--     main-is:        NameOfYourTestSuite.hs
--     ghc-options:    -w -threaded -rtsopts -v0
--     hs-source-dirs: tests
--     other-modules:
--     build-depends:
--       base,
--       easytest
--   </pre>
--   
--   For tests that are logically separate, we usually combine them into a
--   suite using <tt>tests</tt> (which is just <tt>msum</tt>), as in:
--   
--   <pre>
--   suite = tests
--     [ scope "ex1" $ expect (1 + 1 == 2)
--     , scope "ex2" $ expect (2 + 2 == 4) ]
--   
--   -- equivalently
--   suite =
--     (scope "ex1" $ expect (1 + 1 == 2)) <tt>&lt;|&gt;</tt>
--     (scope "ex2" $ expect (2 + 2 == 4))
--   </pre>
--   
--   Importantly, each branch of a <tt>&lt;|&gt;</tt> or tests gets its own
--   copy of the randomness source, so even when branches of the test suite
--   are switched on or off, the randomness received by a branch is the
--   same. This is important for being able to quickly iterate on a test
--   failure!
--   
--   Sometimes, tests take a while to run and we want to make use of
--   parallelism. For that, use <tt>EasyTest.fork</tt> or <tt>fork'</tt>:
--   
--   <pre>
--   -- | Run a test in a separate thread, not blocking for its result.
--   fork :: Test a -&gt; Test ()
--   
--   -- | Run a test in a separate thread, not blocking for its result, but
--   -- return a future which can be used to block on the result.
--   fork' :: Test a -&gt; Test (Test a)
--   </pre>
--   
--   Note: There's no "framework global" parallelism configuration setting.
--   
--   We often want to generate random data for testing purposes:
--   
--   <pre>
--   reverseTest :: Test ()
--   reverseTest = scope "list reversal" $ do
--     nums &lt;- listsOf [0..100] (int' 0 99)
--     nums <tt>forM_</tt> nums -&gt; expect (reverse (reverse nums) == nums)
--   </pre>
--   
--   Tip: generate your test cases in order of increasing size. If you get
--   a failure, your test case is closer to "minimal".
--   
--   The above code generates lists of sizes 0 through 100, consisting of
--   <tt>Int</tt> values in the range 0 through 99. <tt>int' :: Int -&gt;
--   Int -&gt; Test Int</tt>, and there are analogous functions for
--   <tt>Double</tt>, <tt>Word</tt>, etc. The most general functions are:
--   
--   <pre>
--   random :: Random a =&gt; Test a
--   random' :: Random a =&gt; a -&gt; a -&gt; Test a
--   </pre>
--   
--   The functions <tt>int</tt>, <tt>char</tt>, <tt>bool</tt>,
--   <tt>double</tt>, etc are just specialized aliases for <tt>random</tt>,
--   and <tt>int'</tt>, <tt>char'</tt>, etc are just aliases for
--   <tt>random'</tt>. The aliases are sometimes useful in situations where
--   use of the generic <tt>random</tt> or <tt>random'</tt> would require
--   type annotations.
--   
--   If our list reversal test failed, we might use <tt>runOnly "list
--   reversal"</tt> or <tt>rerunOnly &lt;randomseed&gt; "list
--   reversal"</tt> to rerun just that subtree of the test suite, and we
--   might add some additional diagnostics to see what was going on:
--   
--   <pre>
--   reverseTest :: Test ()
--   reverseTest = scope "list reversal" $ do
--     nums &lt;- listsOf [0..100] (int' 0 99)
--     nums <tt>forM_</tt> nums -&gt; do
--       note $ "nums: " ++ show nums
--       let r = reverse (reverse nums)
--       note $ "reverse (reverse nums): " ++ show r
--       expect (r == nums)
--   </pre>
--   
--   The idea is that these sorts of detailed diagnostics are added lazily
--   (and temporarily) to find and fix failing tests. You can also add
--   diagnostics via <tt>io (putStrLn "blah")</tt>, but if you have tests
--   running in parallel this can sometimes get confusing.
--   
--   That's it! Just use ordinary monadic code to generate any testing data
--   and to run your tests.
module EasyTest

-- | Tests are values of type <tt>Test a</tt>, and <a>Test</a> forms a
--   monad with access to:
--   
--   <ul>
--   <li>repeatable randomness (the <a>random</a> and <a>random'</a>
--   functions for random and bounded random values, or handy specialized
--   <a>int</a>, <a>int'</a>, <a>double</a>, <a>double'</a>, etc)</li>
--   <li>I/O (via <a>liftIO</a> or <a>io</a>, which is an alias for
--   <a>liftIO</a>)</li>
--   <li>failure (via <a>crash</a>, which yields a stack trace, or
--   <a>fail</a>, which does not)</li>
--   <li>logging (via <a>note</a>, <a>noteScoped</a>, or <a>note'</a>)</li>
--   <li>hierarchically-named subcomputations (under <a>scope</a>) which
--   can be switched on and off via <a>runOnly</a></li>
--   <li>parallelism (via <a>fork</a>)</li>
--   <li>conjunction of tests via <a>MonadPlus</a> (the <a>&lt;|&gt;</a>
--   operation runs both tests, even if the first test fails, and the tests
--   function used above is just <a>msum</a>).</li>
--   </ul>
--   
--   Using any or all of these capabilities, you assemble <a>Test</a>
--   values into a "test suite" (just another <a>Test</a> value) using
--   ordinary Haskell code, not framework magic. Notice that to generate a
--   list of random values, we just <a>replicateM</a> and <a>forM</a> as
--   usual.
data Test a
expect :: HasCallStack => Bool -> Test ()
expectJust :: HasCallStack => Maybe a -> Test ()
expectRight :: (Show e, HasCallStack) => Either e a -> Test ()
expectRightNoShow :: HasCallStack => Either e a -> Test ()
expectLeft :: (Show a, HasCallStack) => Either e a -> Test ()
expectLeftNoShow :: HasCallStack => Either e a -> Test ()
expectEq :: (Eq a, Show a, HasCallStack) => a -> a -> Test ()

-- | Run a list of tests
--   
--   This specializes <a>msum</a>, <a>asum</a>, and <a>sequence_</a>.
tests :: [Test ()] -> Test ()

-- | A test with a setup and teardown
using :: IO r -> (r -> IO ()) -> (r -> Test a) -> Test a

-- | Run all tests whose scope starts with the given prefix
runOnly :: Text -> Test a -> IO ()

-- | Rerun all tests with the given seed and whose scope starts with the
--   given prefix
rerunOnly :: Int -> Text -> Test a -> IO ()

-- | Run all tests
run :: Test a -> IO ()

-- | Rerun all tests with the given seed
rerun :: Int -> Test a -> IO ()

-- | Label a test. Can be nested. A "." is placed between nested scopes, so
--   <tt>scope "foo" . scope "bar"</tt> is equivalent to <tt>scope
--   "foo.bar"</tt>
scope :: Text -> Test a -> Test a

-- | Log a showable value
note' :: Show s => s -> Test ()

-- | Record a successful test at the current scope
ok :: Test ()

-- | Explicitly skip this test
skip :: Test ()

-- | Run a test in a separate thread, not blocking for its result.
fork :: Test a -> Test ()

-- | Run a test in a separate thread, return a future which can be used to
--   block on its result.
fork' :: Test a -> Test (Test a)

-- | Record a failure at the current scope
crash :: HasCallStack => Text -> Test a

-- | Log a message
note :: Text -> Test ()

-- | Convenient alias for <a>liftIO</a>
io :: IO a -> Test a

-- | Generate a random value
random :: forall a. Random a => Test a

-- | Generate a bounded random value. Inclusive on both sides.
random' :: Random a => a -> a -> Test a
bool :: Test Bool
word8 :: Test Word8

-- | Generate a random <a>Char</a>
char :: Test Char

-- | Generate a random <a>Int</a>
int :: Test Int

-- | Generate a random <a>Double</a>
double :: Test Double

-- | Generate a random <a>Word</a>
word :: Test Word

-- | Generate a random <a>Int</a> in the given range Note: <tt>int' 0
--   5</tt> includes both <tt>0</tt> and <tt>5</tt>
int' :: Int -> Int -> Test Int

-- | Generate a random <a>Char</a> in the given range Note: <tt>char'
--   <tt>a</tt> <tt>z</tt></tt> includes both <tt><tt>a</tt></tt> and
--   <tt><tt>z</tt></tt>.
char' :: Char -> Char -> Test Char

-- | Generate a random <a>Double</a> in the given range Note: <tt>double' 0
--   1</tt> includes both <tt>0</tt> and <tt>1</tt>.
double' :: Double -> Double -> Test Double

-- | Generate a random <a>Double</a> in the given range Note: <tt>word' 0
--   10</tt> includes both <tt>0</tt> and <tt>10</tt>.
word' :: Word -> Word -> Test Word

-- | Generate a random <a>Double</a> in the given range Note: <tt>word8' 0
--   10</tt> includes both <tt>0</tt> and <tt>10</tt>.
word8' :: Word8 -> Word8 -> Test Word8

-- | Sample uniformly from the given list of possibilities
pick :: [a] -> Test a

-- | Alias for <a>replicateM</a>
listOf :: Int -> Test a -> Test [a]

-- | Generate a list of lists of the given sizes, an alias for <tt>sizes
--   `forM` \n -&gt; listOf n gen</tt>
listsOf :: [Int] -> Test a -> Test [[a]]

-- | Alias for <tt>liftA2 (,)</tt>.
pair :: Test a -> Test b -> Test (a, b)

-- | Generate a <tt>Data.Map k v</tt> of the given size.
mapOf :: Ord k => Int -> Test k -> Test v -> Test (Map k v)

-- | Generate a <tt>[Data.Map k v]</tt> of the given sizes.
mapsOf :: Ord k => [Int] -> Test k -> Test v -> Test [Map k v]
