{-|
Module      : Buffer
Description : Testing in a monad transformer layer
Copyright   : (c) John Maraist, 2022
License     : GPL3
Maintainer  : haskell-tlt@maraist.org
Stability   : experimental
Portability : POSIX

Buffer for accumulating test results in the @TLT@ testing system.  See
`Test.TLT` for more information.

-}

module Test.TLT.Buffer where
import Test.TLT.Results

-- |Accumulator for test results, in the style of a simplified Huet's
-- zipper which only ever adds to the end of the structure.
data TRBuf = Buf TRBuf Int Int String [TestResult] | Top Int Int [TestResult]

-- |Add a single test result to a `TRBuf`.
addResult :: TRBuf -> TestResult -> TRBuf
addResult :: TRBuf -> TestResult -> TRBuf
addResult (Top Int
tc Int
fc [TestResult]
trs) TestResult
tr =
  Int -> Int -> [TestResult] -> TRBuf
Top (Int
tc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ TestResult -> Int
testCount TestResult
tr) (Int
fc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ TestResult -> Int
failCount TestResult
tr) ([TestResult] -> TRBuf) -> [TestResult] -> TRBuf
forall a b. (a -> b) -> a -> b
$ TestResult
tr TestResult -> [TestResult] -> [TestResult]
forall a. a -> [a] -> [a]
: [TestResult]
trs
addResult (Buf TRBuf
up Int
tc Int
fc String
s [TestResult]
trs) TestResult
tr =
  TRBuf -> Int -> Int -> String -> [TestResult] -> TRBuf
Buf TRBuf
up (Int
tc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ TestResult -> Int
testCount TestResult
tr) (Int
fc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ TestResult -> Int
failCount TestResult
tr) String
s ([TestResult] -> TRBuf) -> [TestResult] -> TRBuf
forall a b. (a -> b) -> a -> b
$ TestResult
tr TestResult -> [TestResult] -> [TestResult]
forall a. a -> [a] -> [a]
: [TestResult]
trs

-- |Convert the topmost group of a bottom-up `TRBuf` into a completed
-- top-down report about the group.
currentGroup :: TRBuf -> TestResult
currentGroup :: TRBuf -> TestResult
currentGroup (Buf TRBuf
up Int
tc Int
fc String
s [TestResult]
trs) = String -> Int -> Int -> [TestResult] -> TestResult
Group String
s Int
tc Int
fc ([TestResult] -> [TestResult]
forall a. [a] -> [a]
reverse [TestResult]
trs)

-- |Derive a new `TRBuf` corresponding to finishing the current group
-- and continuing to accumulate results into its enclosure.
popGroup :: TRBuf -> TRBuf
popGroup :: TRBuf -> TRBuf
popGroup trb :: TRBuf
trb@(Buf TRBuf
acc Int
_ Int
_ String
_ [TestResult]
_) = TRBuf -> TestResult -> TRBuf
addResult TRBuf
acc (TestResult -> TRBuf) -> TestResult -> TRBuf
forall a b. (a -> b) -> a -> b
$ TRBuf -> TestResult
currentGroup TRBuf
trb

-- |Convert a `TRBuf` into a list of top-down `TestResult`s.
closeTRBuf :: TRBuf -> [TestResult]
closeTRBuf :: TRBuf -> [TestResult]
closeTRBuf (Top Int
_ Int
_ [TestResult]
ts) = [TestResult] -> [TestResult]
forall a. [a] -> [a]
reverse [TestResult]
ts
closeTRBuf TRBuf
b = TRBuf -> [TestResult]
closeTRBuf (TRBuf -> [TestResult]) -> TRBuf -> [TestResult]
forall a b. (a -> b) -> a -> b
$ TRBuf -> TRBuf
popGroup TRBuf
b