{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Main where import Language.Fixpoint.Names import Language.Fixpoint.Parse import Language.Fixpoint.PrettyPrint import Language.Fixpoint.Types import Control.Monad import Data.Proxy import Data.Text (Text, cons, inits, pack) import Test.QuickCheck import Test.Tasty import Test.Tasty.Ingredients.Rerun import Test.Tasty.Options import Test.Tasty.QuickCheck import Test.Tasty.Runners main :: IO () main = run tests where run = defaultMainWithIngredients [ rerunningTests [ listingTests, consoleTestReporter ] , includingOptions [ Option (Proxy :: Proxy QuickCheckTests) ] ] tests = testGroup "Tests" [ quickCheckTests ] quickCheckTests :: TestTree quickCheckTests = testGroup "Properties" [ testProperty "prop_pprint_parse_inv_expr" prop_pprint_parse_inv_expr , testProperty "prop_pprint_parse_inv_pred" prop_pprint_parse_inv_pred ] prop_pprint_parse_inv_pred :: Pred -> Bool prop_pprint_parse_inv_pred p = p == rr (showpp p) prop_pprint_parse_inv_expr :: Expr -> Bool prop_pprint_parse_inv_expr p = simplify p == rr (showpp $ simplify p) instance Arbitrary Sort where arbitrary = sized arbSort arbSort 0 = oneof [return FInt, return FReal, return FNum] arbSort n = frequency [(1, return FInt) ,(1, return FReal) ,(1, return FNum) ,(2, fmap FObj arbitrary) ] instance Arbitrary Pred where arbitrary = sized arbPred shrink = filter valid . genericShrink where valid (PAnd []) = False valid (PAnd [_]) = False valid (POr []) = False valid (POr [_]) = False valid (PBexp (EBin _ _ _)) = True valid (PBexp _) = False valid _ = True arbPred 0 = elements [PTrue, PFalse] arbPred n = frequency [(1, return PTrue) ,(1, return PFalse) ,(2, fmap PAnd twoPreds) ,(2, fmap POr twoPreds) ,(2, fmap PNot (arbPred (n `div` 2))) ,(2, liftM2 PImp (arbPred (n `div` 2)) (arbPred (n `div` 2))) ,(2, liftM2 PIff (arbPred (n `div` 2)) (arbPred (n `div` 2))) ,(2, fmap PBexp (arbExpr (n `div` 2))) ,(2, liftM3 PAtom arbitrary (arbExpr (n `div` 2)) (arbExpr (n `div` 2))) -- ,liftM2 PAll arbitrary arbitrary -- ,return PTop ] where twoPreds = do x <- arbPred (n `div` 2) y <- arbPred (n `div` 2) return [x,y] instance Arbitrary Expr where arbitrary = sized arbExpr shrink = filter valid . genericShrink where valid (EApp _ []) = False valid _ = True arbExpr 0 = oneof [fmap ESym arbitrary, fmap ECon arbitrary, fmap EVar arbitrary, return EBot] arbExpr n = frequency [(1, fmap ESym arbitrary) ,(1, fmap ECon arbitrary) ,(1, fmap EVar arbitrary) ,(1, return EBot) -- ,liftM2 ELit arbitrary arbitrary -- restrict literals somehow ,(2, choose (1,3) >>= \m -> liftM2 EApp arbitrary (vectorOf m (arbExpr (n `div` 2)))) ,(2, liftM3 EBin arbitrary (arbExpr (n `div` 2)) (arbExpr (n `div` 2))) ,(2, liftM3 EIte (arbPred (max 2 (n `div` 2)) `suchThat` isRel) (arbExpr (n `div` 2)) (arbExpr (n `div` 2))) ,(2, liftM2 ECst (arbExpr (n `div` 2)) (arbSort (n `div` 2))) ] where isRel (PAtom _ _ _) = True isRel _ = False instance Arbitrary Brel where arbitrary = oneof (map return [Eq, Ne, Gt, Ge, Lt, Le, Ueq, Une]) instance Arbitrary Bop where arbitrary = oneof (map return [Plus, Minus, Times, Div, Mod]) instance Arbitrary SymConst where arbitrary = fmap SL arbitrary instance Arbitrary Symbol where arbitrary = fmap (symbol :: Text -> Symbol) arbitrary instance Arbitrary Text where arbitrary = choose (1,4) >>= \n -> fmap pack (vectorOf n char `suchThat` valid) where char = elements ['a'..'z'] valid x = x `notElem` fixpointNames && not (isFixKey x) instance Arbitrary FTycon where arbitrary = do c <- elements ['A'..'Z'] t <- arbitrary return $ symbolFTycon $ dummyLoc $ symbol $ cons c t instance Arbitrary Constant where arbitrary = oneof [fmap I (arbitrary `suchThat` (>=0)) -- ,fmap R arbitrary ] shrink = genericShrink instance Arbitrary a => Arbitrary (Located a) where arbitrary = fmap dummyLoc arbitrary shrink = fmap dummyLoc . shrink . val