packages feed

sign-0.1.0: test/TestSign.hs

{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, FlexibleInstances #-}

import Control.Monad
import Data.List
import Data.Maybe
import Data.Ratio
import qualified Data.Set as Set
import Data.Set (Set)
import Test.HUnit hiding (Test)
import Test.QuickCheck
import Test.Framework (Test, defaultMain, testGroup)
import Test.Framework.TH
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2

import qualified Data.Sign as Sign
import Data.Sign (Sign (..))

{--------------------------------------------------------------------
  Sign
--------------------------------------------------------------------}

prop_mult_comm =
  forAll arbitrary $ \a ->
  forAll arbitrary $ \b ->
    a `Sign.mult` b == b `Sign.mult` a

prop_mult_assoc =
  forAll arbitrary $ \a ->
  forAll arbitrary $ \b ->
  forAll arbitrary $ \c ->
    a `Sign.mult` (b `Sign.mult` c) == (a `Sign.mult` b) `Sign.mult` c

prop_mult_unitL =
  forAll arbitrary $ \a ->
    Pos `Sign.mult` a == a

prop_mult_unitR =
  forAll arbitrary $ \a ->
    a `Sign.mult` Pos == a

prop_mult_signOf_comm =
  forAll arbitrary $ \(a::Rational) ->
  forAll arbitrary $ \b ->
    Sign.signOf (a * b) == Sign.signOf a `Sign.mult` Sign.signOf b

prop_negate_involution =
  forAll arbitrary $ \a ->
    Sign.negate (Sign.negate a) == a

prop_negate_signOf_comm =
  forAll arbitrary $ \(a::Rational) ->
    Sign.signOf (negate a) == Sign.negate (Sign.signOf a)

prop_abs_non_neg =
  forAll arbitrary $ \a ->
    Sign.abs a /= Neg

prop_abs_mult_orig =
  forAll arbitrary $ \a ->
    Sign.abs a `Sign.mult` a == a

prop_abs_idempotent =
  forAll arbitrary $ \a ->
    Sign.abs (Sign.abs a) == Sign.abs a

prop_abs_signOf_comm =
  forAll arbitrary $ \(a::Rational) ->
    Sign.signOf (abs a) == Sign.abs (Sign.signOf a)

prop_recip_div =
  forAll arbitrary $ \a ->
    a /= Zero ==>
      Sign.recip a == Pos `Sign.div` a

prop_div_inv_mult =
  forAll arbitrary $ \a ->
    forAll arbitrary $ \b ->
      b /= Zero ==>
        a == (a `Sign.div` b) `Sign.mult` b

prop_pow =
  forAll arbitrary $ \a ->
    forAll (choose (0, 10)) $ \(i::Int) ->
      Sign.pow a i == foldl' Sign.mult Pos (replicate i a)

{--------------------------------------------------------------------
  Sign set
--------------------------------------------------------------------}

prop_SetSign_add_comm =
  forAll arbitrary $ \(a :: Set Sign) ->
  forAll arbitrary $ \b ->
    a + b == b + a

prop_SetSign_add_assoc =
  forAll arbitrary $ \(a :: Set Sign) ->
  forAll arbitrary $ \b ->
  forAll arbitrary $ \c ->
    a + (b + c) == (a + b) + c

prop_SetSign_add_unitL =
  forAll arbitrary $ \a ->
    Set.singleton Zero + a == a

prop_SetSign_add_unitR =
  forAll arbitrary $ \a ->
    a + Set.singleton Zero == a

prop_SetSign_add_signOf_comm =
  forAll arbitrary $ \(a::Rational) ->
  forAll arbitrary $ \b ->
    Sign.signOf (a+b) `Set.member` (Set.singleton (Sign.signOf a) + Set.singleton (Sign.signOf b))

prop_SetSign_mult_comm =
  forAll arbitrary $ \(a :: Set Sign) ->
  forAll arbitrary $ \b ->
    a * b == b * a

prop_SetSign_mult_assoc =
  forAll arbitrary $ \(a :: Set Sign) ->
  forAll arbitrary $ \b ->
  forAll arbitrary $ \c ->
    a * (b * c) == (a * b) * c

prop_SetSign_mult_unitL =
  forAll arbitrary $ \a ->
    Set.singleton Pos * a == a

prop_SetSign_mult_unitR =
  forAll arbitrary $ \a ->
    a * Set.singleton Pos == a

prop_SetSign_mult_signOf_comm =
  forAll arbitrary $ \(a::Rational) ->
  forAll arbitrary $ \b ->
    Sign.signOf (a*b) `Set.member` (Set.singleton (Sign.signOf a) * Set.singleton (Sign.signOf b))

prop_SetSign_negate_involution =
  forAll arbitrary $ \(a :: Set Sign) ->
    negate (negate a) == a

prop_SetSign_abs_non_neg =
  forAll arbitrary $ \(a :: Set Sign) ->
    Neg `Set.notMember` abs a

prop_SetSign_abs_mult_orig =
  forAll arbitrary $ \(a :: Set Sign) ->
    a `Set.isSubsetOf` (abs a * a)

prop_SetSign_abs_idempotent =
  forAll arbitrary $ \(a :: Set Sign) ->
    abs (abs a) == abs a

prop_SetSign_pow =
  forAll arbitrary $ \a ->
    forAll (choose (0, 10)) $ \(i::Int) ->
      Sign.pow a i == foldl' Sign.mult Pos (replicate i a)

{--------------------------------------------------------------------
  Read
--------------------------------------------------------------------}

prop_show_read_invariance =
  forAll arbitrary $ \(a::Sign) -> do
    a == read (show a)

{--------------------------------------------------------------------
  Generators
--------------------------------------------------------------------}

instance Arbitrary Sign where
  arbitrary = arbitraryBoundedEnum
  shrink    = shrinkNothing

instance CoArbitrary Sign where
  coarbitrary = coarbitraryEnum

instance Arbitrary (Set Sign) where
  arbitrary = elements $ map Set.unions $
                sequence [[Set.singleton s, Set.empty] | s <- [Neg, Zero, Pos]]
  shrink ss = [Set.delete s ss | s <- Set.toList ss]

instance CoArbitrary (Set Sign) where
  coarbitrary ss g = foldr (\s g -> variant (fromEnum s) g) g (Set.toList ss)

------------------------------------------------------------------------
-- Test harness

main :: IO ()
main = $(defaultMainGenerator)