-- | Note: this module is re-exported as a whole from "Test.Tasty.Runners"
module Test.Tasty.Runners.Utils where

import Control.Exception
import Control.Applicative
import Prelude  -- Silence AMP import warnings
import Text.Printf

-- | Catch possible exceptions that may arise when evaluating a string.
-- For normal (total) strings, this is a no-op.
--
-- This function should be used to display messages generated by the test
-- suite (such as test result descriptions).
--
-- See e.g. <https://github.com/feuerbach/tasty/issues/25>
formatMessage :: String -> IO String
formatMessage :: String -> IO String
formatMessage = Int -> String -> IO String
go 3
  where
    -- to avoid infinite recursion, we introduce the recursion limit
    go :: Int -> String -> IO String
    go :: Int -> String -> IO String
go 0        _ = String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return "exceptions keep throwing other exceptions!"
    go recLimit :: Int
recLimit msg :: String
msg = do
      Either SomeException ()
mbStr <- IO () -> IO (Either SomeException ())
forall e a. Exception e => IO a -> IO (Either e a)
try (IO () -> IO (Either SomeException ()))
-> IO () -> IO (Either SomeException ())
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall a. a -> IO a
evaluate (() -> IO ()) -> () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> ()
forall a. [a] -> ()
forceElements String
msg
      case Either SomeException ()
mbStr of
        Right () -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
msg
        Left e' :: SomeException
e' -> String -> String -> String
forall r. PrintfType r => String -> r
printf "message threw an exception: %s" (String -> String) -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> String -> IO String
go (Int
recLimitInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) (SomeException -> String
forall a. Show a => a -> String
show (SomeException
e' :: SomeException))

-- https://ro-che.info/articles/2015-05-28-force-list
forceElements :: [a] -> ()
forceElements :: [a] -> ()
forceElements = (a -> () -> ()) -> () -> [a] -> ()
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> () -> ()
forall a b. a -> b -> b
seq ()