darcs-beta-2.7.98.1: src/Darcs/Test/Patch/Unit2.hs
-- Copyright (C) 2007 David Roundy
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-- Boston, MA 02110-1301, USA.
{-# LANGUAGE CPP #-}
#include "gadts.h"
-- This module was split out from Darcs.Test.Patch.Unit to assist with
-- adding witnesses.
module Darcs.Test.Patch.Unit2 ( patchUnitTests2, notDuplicatestriple ) where
import Darcs.Test.Util.TestResult ( TestResult, fromMaybe )
import Darcs.Patch.FileHunk ( FileHunk(..), IsHunk(..) )
import Darcs.Patch.Prim ( PrimPatch, PrimOf, join )
import Darcs.Patch.Prim.V1 ( Prim )
import Darcs.Patch.Merge ( Merge(..) )
import Darcs.Patch.Patchy ( Patchy, Commute(..) )
import Darcs.Patch.RepoPatch ( RepoPatch )
import Darcs.Patch.V2 ( RealPatch )
import Darcs.Patch.V2.Real ( isConsistent, isDuplicate )
import Darcs.Test.Patch.Prim.V1 () -- Arbitrary instances
import Darcs.Test.Patch.Properties
( invertSymmetry, invertRollback
, recommute, commuteInverses, effectPreserving
, permutivity, partialPermutivity
, mergeEitherWay, show_read
, joinEffectPreserving, joinCommute
)
import Darcs.Test.Patch.QuickCheck
( Tree, TreeWithFlattenPos
, propIsMergeable, propConsistentTreeFlattenings
)
import qualified Darcs.Test.Patch.QuickCheck as T
( commuteTripleFromTree, commutePairFromTree, commutePairFromTWFP
, mergePairFromTree, mergePairFromTWFP
, patchFromTree
)
import Darcs.Test.Patch.Utils ( testConditional )
import Darcs.Test.Patch.RepoModel ( RepoModel )
import Darcs.Test.Patch.WithState ( WithState(..), WithStartState )
import Darcs.Witnesses.Eq ( unsafeCompare )
import Darcs.Witnesses.Ordered ( (:>)(..), (:/\:)(..), (:\/:)(..), FL, allFL )
import Darcs.Witnesses.Sealed ( Sealed, unseal, Sealed2, unseal2 )
import Data.Maybe ( isNothing )
import Test.Framework ( Test )
import Test.Framework.Providers.QuickCheck2 ( testProperty )
patchFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) p C(y z) -> t) -> WithStartState RepoModel (Tree Prim) C(x) -> t
patchFromTree = T.patchFromTree
mergePairFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) (p :\/: p) C(y z) -> t) -> WithStartState RepoModel (Tree Prim) C(x) -> t
mergePairFromTree = T.mergePairFromTree
mergePairFromTWFP :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) (p :\/: p) C(y z) -> t) -> WithStartState RepoModel (TreeWithFlattenPos Prim) C(x) -> t
mergePairFromTWFP = T.mergePairFromTWFP
commutePairFromTWFP :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) (p :> p) C(y z) -> t) -> WithStartState RepoModel (TreeWithFlattenPos Prim) C(x) -> t
commutePairFromTWFP = T.commutePairFromTWFP
commutePairFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) (p :> p) C(y z) -> t) -> WithStartState RepoModel (Tree Prim) C(x) -> t
commutePairFromTree = T.commutePairFromTree
commuteTripleFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (FORALL(y z) (p :> p :> p) C(y z) -> t) -> WithStartState RepoModel (Tree Prim) C(x) -> t
commuteTripleFromTree = T.commuteTripleFromTree
patchUnitTests2 :: [Test]
patchUnitTests2 = [ testProperty "Checking Prim invert symmetry..."
(unseal2 $ invertSymmetry :: Sealed2 Prim -> TestResult),
testProperty "Checking FL Prim invert symmetry..."
(unseal2 $ invertSymmetry :: Sealed2 (FL Prim) -> TestResult),
testProperty "Checking Prim invert rollback..."
(unseal2 $ invertRollback :: Sealed2 (WithState RepoModel Prim) -> TestResult),
testProperty "Checking FL Prim invert rollback..."
(unseal2 $ invertRollback :: Sealed2 (WithState RepoModel (FL Prim)) -> TestResult),
testConditional "Checking Prim effect preserving..."
(unseal2 $ nonEmptyHunksPair . wsPatch)
(unseal2 $ effectPreserving commute :: Sealed2 (WithState RepoModel (Prim :> Prim)) -> TestResult),
testConditional "Checking FL Prim effect preserving..."
(unseal2 $ nonEmptyHunksFLPair . wsPatch)
(unseal2 $ effectPreserving commute :: Sealed2 (WithState RepoModel (FL Prim :> FL Prim)) -> TestResult),
testProperty "Checking Prim recommute..."
(unseal2 $ recommute commute :: Sealed2 (Prim :> Prim) -> TestResult),
testProperty "Checking FL Prim recommute..."
(unseal2 $ recommute commute :: Sealed2 (FL Prim :> FL Prim) -> TestResult),
testProperty "Checking Prim inverses commute..."
(unseal2 $ commuteInverses commute :: Sealed2 (Prim :> Prim) -> TestResult),
testProperty "Checking FL Prim inverses commute..."
(unseal2 $ commuteInverses commute :: Sealed2 (FL Prim :> FL Prim) -> TestResult),
--do putStr "Checking with quickcheck that real patches have consistent flattenings... "
-- quickCheck (not . isBottomTimeOut (Just 10) . propConsistentTreeFlattenings) >> return 0
-- The following fails because of setpref patches...
--,do putStr "Checking prim inverse doesn't commute using QuickCheck... "
-- simpleCheck (inverseDoesntCommute :: Prim -> Maybe Doc)
testProperty "Checking prim join effect preserving... "
(unseal2 (joinEffectPreserving join)),
testConditional "Checking prim join commute using QuickCheck... "
(unseal2 nonEmptyHunksTriple)
(unseal2 (joinCommute join)),
--,do putStr "Checking prim recommute using QuickCheck... "
-- simpleCheck (recommute
-- (commute :: Prim :> Prim
-- -> Maybe (Prim :> Prim)))
testProperty "Checking that readPatch and showPatch work on RealPatch... "
(unseal $ patchFromTree $ (show_read :: RealPatch Prim C(x y) -> TestResult)),
testProperty "Checking that readPatch and showPatch work on FL RealPatch... "
(unseal2 $ (show_read :: FL (RealPatch Prim) C(x y) -> TestResult)),
testProperty "Checking that tree flattenings are consistent... " propConsistentTreeFlattenings,
testProperty "Checking with quickcheck that real patches are consistent... "
(unseal $ patchFromTree $ fromMaybe . isConsistent),
testProperty "Checking we can do merges using QuickCheck"
(isNothing . (propIsMergeable ::
Sealed (WithStartState RepoModel (Tree Prim))
-> Maybe (Tree (RealPatch Prim) C(x)))),
testProperty "Checking recommute using QuickCheck Tree generator"
(unseal $ commutePairFromTree
(recommute commuteReals)),
testProperty "Checking recommute using QuickCheck TWFP generator"
(unseal $ commutePairFromTWFP
(recommute commuteReals)),
testConditional "Checking nontrivial recommute"
(unseal $ commutePairFromTree $ nontrivialReals)
(unseal $ commutePairFromTree $
(recommute commuteReals)),
testConditional "Checking nontrivial recommute using TWFP"
(unseal $ commutePairFromTWFP $ nontrivialReals)
(unseal $ commutePairFromTWFP $
(recommute commuteReals)),
testProperty "Checking inverses commute using QuickCheck Tree generator"
(unseal $ commutePairFromTree $
(commuteInverses commuteReals)),
testProperty "Checking inverses commute using QuickCheck TWFP generator"
(unseal $ commutePairFromTWFP $
(commuteInverses commuteReals)),
testConditional "Checking nontrivial inverses commute"
(unseal $ commutePairFromTree $ nontrivialReals)
(unseal $ commutePairFromTree $
(commuteInverses commuteReals)),
testConditional "Checking nontrivial inverses commute using TWFP"
(unseal $ commutePairFromTWFP $ nontrivialReals)
(unseal $ commutePairFromTWFP $
(commuteInverses commuteReals)),
testProperty "Checking merge either way using QuickCheck TWFP generator"
(unseal $ mergePairFromTWFP $ mergeEitherWayReals),
testProperty "Checking merge either way using QuickCheck Tree generator"
(unseal $ mergePairFromTree $ mergeEitherWayReals),
testConditional "Checking nontrivial merge either way"
(unseal $ mergePairFromTree $ nontrivialMergeReals)
(unseal $ mergePairFromTree $ mergeEitherWayReals),
testConditional "Checking nontrivial merge either way using TWFP"
(unseal $ mergePairFromTWFP $ nontrivialMergeReals)
(unseal $ mergePairFromTWFP $ mergeEitherWayReals),
testConditional "Checking permutivity"
(unseal $ commuteTripleFromTree notDuplicatestriple)
(unseal $ commuteTripleFromTree $ permutivity commuteReals),
testConditional "Checking partial permutivity"
(unseal $ commuteTripleFromTree notDuplicatestriple)
(unseal $ commuteTripleFromTree $ partialPermutivity commuteReals),
testConditional "Checking nontrivial permutivity"
(unseal $ commuteTripleFromTree
(\t -> nontrivialTriple t && notDuplicatestriple t))
(unseal $ commuteTripleFromTree $
(permutivity commuteReals))
]
notDuplicatestriple :: (RealPatch prim :> RealPatch prim :> RealPatch prim) C(x y) -> Bool
notDuplicatestriple (a :> b :> c) = not (isDuplicate a || isDuplicate b || isDuplicate c)
--not_duplicates_pair :: RealPatch prim :> RealPatch prim -> Bool
--not_duplicates_pair (a :> b) = not $ any isDuplicate [a,b]
nontrivialTriple :: PrimPatch prim => (RealPatch prim :> RealPatch prim :> RealPatch prim) C(x y) -> Bool
nontrivialTriple (a :> b :> c) =
case commute (a :> b) of
Nothing -> False
Just (b' :> a') ->
case commute (a' :> c) of
Nothing -> False
Just (c'' :> a'') ->
case commute (b :> c) of
Nothing -> False
Just (c' :> b'') -> (not (a `unsafeCompare` a') || not (b `unsafeCompare` b')) &&
(not (c' `unsafeCompare` c) || not (b'' `unsafeCompare` b)) &&
(not (c'' `unsafeCompare` c) || not (a'' `unsafeCompare` a'))
nonEmptyHunk :: (IsHunk p) => p C(x y) -> Bool
nonEmptyHunk p
| Just (FileHunk _ _ [] []) <- isHunk p = False
| otherwise = True
nonEmptyHunksPair :: (IsHunk p) => (p :> p) C(x y) -> Bool
nonEmptyHunksPair (p1 :> p2) = nonEmptyHunk p1 && nonEmptyHunk p2
nonEmptyHunksTriple :: (IsHunk p) => (p :> p :> p) C(x y) -> Bool
nonEmptyHunksTriple (p1 :> p2 :> p3) = nonEmptyHunk p1 && nonEmptyHunk p2 && nonEmptyHunk p3
nonEmptyHunksFLPair :: (IsHunk p) => (FL p :> FL p) C(x y) -> Bool
nonEmptyHunksFLPair (ps :> qs) = allFL nonEmptyHunk ps && allFL nonEmptyHunk qs
commuteReals :: PrimPatch prim => (RealPatch prim :> RealPatch prim) C(x y) -> Maybe ((RealPatch prim :> RealPatch prim) C(x y))
commuteReals = commute
mergeEitherWayReals :: PrimPatch prim => (RealPatch prim :\/: RealPatch prim) C(x y) -> TestResult
mergeEitherWayReals = mergeEitherWay
nontrivialReals :: PrimPatch prim => (RealPatch prim :> RealPatch prim) C(x y) -> Bool
nontrivialReals = nontrivialCommute
nontrivialCommute :: Patchy p => (p :> p) C(x y) -> Bool
nontrivialCommute (x :> y) = case commute (x :> y) of
Just (y' :> x') -> not (y' `unsafeCompare` y) ||
not (x' `unsafeCompare` x)
Nothing -> False
nontrivialMergeReals :: PrimPatch prim => (RealPatch prim :\/: RealPatch prim) C(x y) -> Bool
nontrivialMergeReals = nontrivialMerge
nontrivialMerge :: (Patchy p, Merge p) => (p :\/: p) C(x y) -> Bool
nontrivialMerge (x :\/: y) = case merge (x :\/: y) of
y' :/\: x' -> not (y' `unsafeCompare` y) ||
not (x' `unsafeCompare` x)