-- Copyright 2021 Google LLC
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

-- | Assertion functions for HUnit based on 'Diff'.

module Data.Portray.Diff.HUnit (assertNoDiff, (@?-), (@-?)) where

import GHC.Stack (HasCallStack)
import Text.PrettyPrint.HughesPJ (($+$), colon, empty, render, text)

import Test.HUnit (Assertion, assertFailure)

import Data.Portray.Diff (Diff(..))
import Data.Portray.Pretty (portrayalToDoc)

-- | Same as 'Test.HUnit.assertEqual', but using 'Diff' to compare and report
-- errors.
assertNoDiff :: (HasCallStack, Diff a) => String -> a -> a -> Assertion
assertNoDiff :: String -> a -> a -> Assertion
assertNoDiff String
msg a
a a
b = case a -> a -> Maybe Portrayal
forall a. Diff a => a -> a -> Maybe Portrayal
diff a
a a
b of
  Maybe Portrayal
Nothing -> () -> Assertion
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  Just Portrayal
d -> String -> Assertion
forall a. HasCallStack => String -> IO a
assertFailure (String -> Assertion) -> (Doc -> String) -> Doc -> Assertion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> String
render (Doc -> Assertion) -> Doc -> Assertion
forall a b. (a -> b) -> a -> b
$
    (if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
msg then Doc
empty else String -> Doc
text String
msg Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> Doc
colon) Doc -> Doc -> Doc
$+$
    Portrayal -> Doc
portrayalToDoc Portrayal
d

-- | Same as ('Test.HUnit.@?='), but using 'Diff' to compare and report errors.
(@?-) :: (HasCallStack, Diff a) => a -> a -> Assertion
a
a @?- :: a -> a -> Assertion
@?- a
b = String -> a -> a -> Assertion
forall a. (HasCallStack, Diff a) => String -> a -> a -> Assertion
assertNoDiff String
"" a
a a
b

-- | Same as ('Test.HUnit.@=?'), but using 'Diff' to compare and report errors.
(@-?) :: (HasCallStack, Diff a) => a -> a -> Assertion
a
a @-? :: a -> a -> Assertion
@-? a
b = String -> a -> a -> Assertion
forall a. (HasCallStack, Diff a) => String -> a -> a -> Assertion
assertNoDiff String
"" a
b a
a