{- | Properties for testing that instances of the 'Eq' class perform correctly. 'p_reflexive', 'p_symmetric' and 'p_transitive' check the basic properties of an equity relation. In other words, they test the '==' method. 'p_not_equal' checks for the extraordinarily unlikely case of '==' and '/=' not agreeing on equity. (The default implementation of '/=' automatically guarantees that this test will pass, and that's what most people presumably use.) -} module Test.AC.Class.Eq where import Test.AC.Test -- | Check that @x == x@. p_reflexive :: (Show x, Eq x) => x -> Test p_reflexive x = title "x == x" $ x ?= x -- | Check that if @x == y@ then @y == x@ as well. p_symmetric :: (Show x, Eq x) => x -> x -> Test p_symmetric x y = title "if x == y then y == x" $ argument "x" x $ argument "y" y $ temporary "x == y" (x == y) $ (y == x) ?= (x == y) -- | Check that if @x == y@ and @y == z@ then @x == z@. p_transitive :: (Show x, Eq x) => x -> x -> x -> Test p_transitive x y z = title "if x == y and y == z then x == z" $ argument "x" x $ argument "y" y $ argument "z" z $ temporary "x == y" (x == y) $ temporary "y == z" (y == z) $ if (x /= y) && (y /= z) then inapplicable else (x == z) ?= ((x == y) && (y == z)) -- | Check that @x /= y@ is the same as @not (x == y)@. p_not_equal :: (Show x, Eq x) => x -> x -> Test p_not_equal x y = title "x /= y is not(x == y)" $ argument "x" x $ argument "y" y $ temporary "x == y" (x == y) $ (x /= y) ?= not (x == y) {- | Given a list of /distinct/ values, perform all applicable tests on all possible combinations of inputs. (If the inputs are not distinct, some redundant tests are performed.) -} p_Eq :: (Show x, Eq x) => [x] -> Test p_Eq xs = title "p_Eq" $ argument "xs" xs $ tests [ title "p_reflexive" $ tests [ p_reflexive x | x <- xs ], title "p_symmetric" $ tests [ p_symmetric x y | x <- xs, y <- xs ], title "p_transitive" $ tests [ p_transitive x y z | x <- xs, y <- xs, z <- xs ], title "p_not_equal" $ tests [ p_not_equal x y | x <- xs, y <- xs ] ]