{-# language DerivingStrategies #-} {-# language DerivingVia #-} {-# language GeneralizedNewtypeDeriving #-} {-# language LambdaCase #-} {-# language ScopedTypeVariables #-} {-# language TypeApplications #-} import Test.Tasty (TestTree,defaultMain,testGroup,adjustOption) import Test.QuickCheck (Arbitrary) import Data.Proxy (Proxy(..)) import Data.Set (Set) import Data.Primitive (Array) import Control.Monad (forM_,replicateM) import Data.Monoid (All(..)) import Test.QuickCheck.Classes (eqLaws,ordLaws) import Data.Typeable (Typeable,typeRep) import Data.Coerce (coerce) import Data.Set (Set) import qualified Data.Set as S import qualified Data.List as L import qualified GHC.Exts as E import qualified Test.QuickCheck as QC import qualified Test.Tasty.QuickCheck as TQC import qualified Test.QuickCheck.Classes as QCC main :: IO () main = defaultMain tests tests :: TestTree tests = testGroup "universe" [ testGroup "deriving" [ testGroup "strict" [ laws @A [eqLaws,ordLaws] , laws @B [eqLaws,ordLaws] , laws @C [eqLaws,ordLaws] , laws @D [eqLaws,ordLaws] , laws @E [eqLaws,ordLaws] , laws @F [eqLaws,ordLaws] , laws @G [eqLaws,ordLaws] , laws @H [eqLaws,ordLaws] , laws @I [eqLaws,ordLaws] , laws @K [eqLaws,ordLaws] ] , testGroup "thunk" [ laws @(Thunk A) [eqLaws,ordLaws] , laws @(Thunk B) [eqLaws,ordLaws] , laws @(Thunk C) [eqLaws,ordLaws] , laws @(Thunk D) [eqLaws,ordLaws] , laws @(Thunk E) [eqLaws,ordLaws] , laws @(Thunk F) [eqLaws,ordLaws] , laws @(Thunk G) [eqLaws,ordLaws] , laws @(Thunk H) [eqLaws,ordLaws] , laws @(Thunk I) [eqLaws,ordLaws] , laws @(Thunk K) [eqLaws,ordLaws] ] , testGroup "lazy" [ laws @(Lazy A) [eqLaws,ordLaws] , laws @(Lazy B) [eqLaws,ordLaws] , laws @(Lazy C) [eqLaws,ordLaws] , laws @(Lazy D) [eqLaws,ordLaws] , laws @(Lazy E) [eqLaws,ordLaws] , laws @(Lazy F) [eqLaws,ordLaws] , laws @(Lazy G) [eqLaws,ordLaws] , laws @(Lazy H) [eqLaws,ordLaws] , laws @(Lazy I) [eqLaws,ordLaws] , laws @(Lazy K) [eqLaws,ordLaws] ] ] , testGroup "containers" [ testGroup "strict" [ laws @(Set A) [eqLaws,ordLaws] , laws @(Set B) [eqLaws,ordLaws] , laws @(Set C) [eqLaws,ordLaws] , laws @(Set D) [eqLaws,ordLaws] , laws @(Set E) [eqLaws,ordLaws] , laws @(Set F) [eqLaws,ordLaws] , laws @(Set G) [eqLaws,ordLaws] , laws @(Set H) [eqLaws,ordLaws] , laws @(Set I) [eqLaws,ordLaws] , laws @(Set K) [eqLaws,ordLaws] ] , testGroup "lazy" [ laws @(SmallLazySet A) [eqLaws,ordLaws] , laws @(SmallLazySet B) [eqLaws,ordLaws] , laws @(SmallLazySet C) [eqLaws,ordLaws] , laws @(SmallLazySet D) [eqLaws,ordLaws] , laws @(SmallLazySet E) [eqLaws,ordLaws] , laws @(SmallLazySet F) [eqLaws,ordLaws] , laws @(SmallLazySet G) [eqLaws,ordLaws] , laws @(SmallLazySet H) [eqLaws,ordLaws] , laws @(SmallLazySet I) [eqLaws,ordLaws] , laws @(SmallLazySet K) [eqLaws,ordLaws] ] ] ] data A = A0 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration A) data B = B0 | B1 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration B) data C = C0 | C1 | C2 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration C) data D = D0 | D1 | D2 | D3 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration D) data E = E0 | E1 | E2 | E3 | E4 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration E) data F = F0 | F1 | F2 | F3 | F4 | F5 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration F) data G = G0 | G1 | G2 | G3 | G4 | G5 | G6 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration G) data H = H0 | H1 | H2 | H3 | H4 | H5 | H6 | H7 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration H) data I = I0 | I1 | I2 | I3 | I4 | I5 | I6 | I7 | I8 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration I) data J = J0 | J1 | J2 | J3 | J4 | J5 | J6 | J7 | J8 | J9 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration J) data K = K0 | K1 | K2 | K3 | K4 | K5 | K6 | K7 | K8 | K9 | K10 deriving stock (Eq,Ord,Show,Read,Bounded,Enum) deriving Arbitrary via (Enumeration K) laws :: forall a. Typeable a => [Proxy a -> QCC.Laws] -> TestTree laws = testGroup (show (typeRep (Proxy :: Proxy a))) . map ( \f -> let QCC.Laws name pairs = f (Proxy :: Proxy a) in testGroup name (map (uncurry TQC.testProperty) pairs) ) newtype Enumeration a = Enumeration a instance (Bounded a, Enum a, Eq a) => Arbitrary (Enumeration a) where arbitrary = fmap Enumeration TQC.arbitraryBoundedEnum shrink (Enumeration x) = if x == minBound then [] else [Enumeration (pred x)] data Thunk a = Thunk a deriving stock (Eq,Ord,Show,Read) newtype Lazy a = Lazy a deriving newtype (Eq,Ord,Show,Read) newtype SmallLazySet a = SmallLazySet (Set a) deriving newtype (Eq,Ord,Show,Read) instance Arbitrary a => Arbitrary (Thunk a) where arbitrary = do a <- TQC.arbitrary let {-# NOINLINE b #-} b () = a pure (Thunk (b ())) shrink (Thunk x) = map Thunk (TQC.shrink x) instance Arbitrary a => Arbitrary (Lazy a) where arbitrary = do a <- TQC.arbitrary let {-# NOINLINE b #-} b () = a pure (Lazy (b ())) shrink (Lazy x) = map Lazy (TQC.shrink x) instance (Arbitrary a, Ord a) => Arbitrary (SmallLazySet a) where arbitrary = do a <- TQC.arbitrary b <- TQC.arbitrary c <- TQC.arbitrary let {-# NOINLINE a' #-} a' () = a let {-# NOINLINE b' #-} b' () = b let {-# NOINLINE c' #-} c' () = c pure (SmallLazySet (S.fromList [a' (), b' (), c' (), a' (), b' (), c' ()]))