commutative-0.0.1.3: test/Data/CommutativeSpec.hs
module Data.CommutativeSpec (spec) where
import Data.Commutative
import Data.Mergeable
import Data.Monoid
import Data.Maybe (isJust)
import Data.List (permutations)
import Test.Tasty
import Test.Tasty.QuickCheck as QC
import Test.QuickCheck
import Test.QuickCheck.Instances
spec :: [TestTree]
spec =
[ testGroup "Commutative Operation"
[ QC.testProperty "Unit `()` should commute" (commutes :: () -> () -> Bool)
, QC.testProperty "`Any` should commute" (commutes :: Any -> Any -> Bool)
, QC.testProperty "`All` should commute" (commutes :: All -> All -> Bool)
, QC.testProperty "`OneOf ()` should commute" (commutes :: OneOf () -> OneOf () -> Bool)
, QC.testProperty "`Sum` should commute" (commutes :: Sum Int -> Sum Int -> Bool)
, QC.testProperty "`Product` should commute" (commutes :: Product Int -> Product Int -> Bool)
]
, testGroup "Left / Right Identity"
[ QC.testProperty "Unit `()` should have id" (lridentity :: () -> Bool)
, QC.testProperty "`Any` should have id" (lridentity :: Any -> Bool)
, QC.testProperty "`All` should have id" (lridentity :: All -> Bool)
, QC.testProperty "`OneOf ()` should have id" (lridentity :: OneOf () -> Bool)
, QC.testProperty "`Sum` should have id" (lridentity :: Sum Int -> Bool)
, QC.testProperty "`Product` should have id" (lridentity :: Product Int -> Bool)
]
, testGroup "Mergeable"
[ QC.testProperty "Lists should merge" (merges :: Under10 (Sum Int) -> Bool )]
]
commutes :: (Eq a, Commutative a) => a -> a -> Bool
commutes x y = x <~> y == y <~> x
lridentity :: (Eq a, CommutativeId a) => a -> Bool
lridentity x = x <~> cempty == x
&& cempty <~> x == x
merges :: (Eq a, CommutativeId a) => Under10 a -> Bool
merges (Under10 xs) = let merge' = merge (<~>) cempty
in equal $ map merge' $ permutations xs
-----------------------------
newtype Under10 a = Under10 {unUnder10 :: [a]}
deriving (Show, Eq)
instance Arbitrary a => Arbitrary (Under10 a) where
arbitrary = Under10 <$> arbitrary `suchThat` (\x -> length x < 10)
instance Arbitrary Any where
arbitrary = Any <$> arbitrary
instance Arbitrary All where
arbitrary = All <$> arbitrary
instance Arbitrary a => Arbitrary (OneOf a) where
arbitrary = OneOf <$> arbitrary
instance Arbitrary a => Arbitrary (Sum a) where
arbitrary = Sum <$> arbitrary
instance Arbitrary a => Arbitrary (Product a) where
arbitrary = Product <$> arbitrary
equal :: (Eq a, Foldable f) => f a -> Bool
equal = maybe True snd
. foldr (\a mb -> Just $ maybe (a, True)
(\(b, p) -> (b, p && (a == b))) mb) Nothing