module DCLabel.QC_Core where
import Test.QuickCheck hiding (label)
import Control.Monad (liftM)
import DCLabel.Core
import DCLabel.Lattice
import Data.List
instance Arbitrary Principal where
arbitrary = do p <- oneof $ map return ["A", "B", "C"]
return $ principal p
instance Arbitrary a => Arbitrary (Disj a) where
arbitrary = sized disjunction
where disjunction 0 = return $ MkDisj { disj = [] }
disjunction n = do a <- arbitrary
m <- choose (0, n1)
djs <- disjunction m
return $ MkDisj $ a:(disj djs)
shrink (MkDisj ls) = [MkDisj l | l <- tails ls]
instance Arbitrary a => Arbitrary (Conj (Disj a)) where
arbitrary = sized conjunction
where conjunction 0 = oneof [return $ MkConj { conj = [] } ,
return $ MkConj { conj = [MkDisj []] },
return $ MkConj { conj = [MkDisj [], MkDisj []] } ]
conjunction n = do a <- arbitrary
m <- choose (0, n1)
cjs <- conjunction m
return $ MkConj $ a:(conj cjs)
shrink (MkConj ls) = [MkConj ll | l <- tails ls, ll <- shrink l]
instance Arbitrary a => Arbitrary (Label a) where
arbitrary = mkArbLbl arbitrary
where mkArbLbl :: Gen (Conj (Disj a)) -> Gen (Label a)
mkArbLbl = liftM MkLabel
instance Arbitrary a => Arbitrary (DCLabel a) where
arbitrary = do s <- arbitrary
i <- arbitrary
return $ MkDCLabel { secrecy = s, integrity = i }
prop_nubLabel :: Ord a => Label a -> Bool
prop_nubLabel l = let l' = nubLabel l
in l `implies` l' && l' `implies` l
prop_reduce :: Ord a => Label a -> Bool
prop_reduce l = let l' = reduceLabel l
in l `implies` l' && l' `implies` l
prop_reduce_idem :: Ord a => Label a -> Bool
prop_reduce_idem l = let l' = reduceLabel l
l'' = reduceLabel l'
in l' == l''
prop_dc_porder :: Ord a => (DCLabel a, DCLabel a) -> Bool
prop_dc_porder (l1,l2) = let l1' = reduceDC l1
l2' = reduceDC l2
ge = l1' `canflowto` l2'
le = l2' `canflowto` l1'
eq = l2' == l1'
in (eq && ge && le) ||
((not eq) && (ge || le) && (ge /= le)) ||
(not (eq || ge || le))
prop_DC_join :: Ord a => (DCLabel a, DCLabel a) -> Bool
prop_DC_join (l1,l2) = let l3 = l1 `join` l2
t1 = l1 `canflowto` l3
t2 = l2 `canflowto` l3
in t1 && t2
prop_dc_join_lub :: (Ord a, Show a, Arbitrary a)
=> (DCLabel a, DCLabel a) -> Property
prop_dc_join_lub (l1,l2) = forAll (gen l1) $ \l3' ->
(l1 `canflowto` l3') && (l2 `canflowto` l3') ==> (l1 `join` l2) `canflowto` l3'
where gen :: Arbitrary a => DCLabel a -> Gen (DCLabel a)
gen _ = arbitrary
prop_dc_meet :: Ord a => (DCLabel a, DCLabel a) -> Bool
prop_dc_meet (l1,l2) = let l3 = l1 `meet` l2
t1 = l3 `canflowto` l1
t2 = l3 `canflowto` l2
in t1 && t2
prop_dc_meet_glb :: (Ord a, Show a, Arbitrary a)
=> (DCLabel a, DCLabel a) -> Property
prop_dc_meet_glb (l1,l2) = forAll (gen l1) $ \l3' ->
(l3' `canflowto` l1) && (l3' `canflowto` l2) ==> l3' `canflowto` (l1 `meet` l2)
where gen :: Arbitrary a => DCLabel a -> Gen (DCLabel a)
gen _ = arbitrary
type DCLabelPair a = (DCLabel a, DCLabel a)
checks n = do
let args = stdArgs { maxSuccess = n, maxSize = n, maxDiscard = 10000}
putStrLn "Checking function nubLabel..."
quickCheckWith args (prop_nubLabel :: Label Principal -> Bool)
putStrLn "Checking function reduce..."
quickCheckWith args (prop_reduce :: Label Principal -> Bool)
putStrLn "Checking idempotence of function reduce..."
quickCheckWith args (prop_reduce_idem :: Label Principal -> Bool)
putStrLn "Checking the join operation..."
quickCheckWith args (prop_DC_join :: DCLabelPair Principal -> Bool)
putStrLn "Checking the join operation is indeed the least upper bound..."
quickCheckWith args (prop_dc_join_lub :: DCLabelPair Principal -> Property)
putStrLn "Checking the meet operation..."
quickCheckWith args (prop_dc_meet :: DCLabelPair Principal -> Bool)
putStrLn "Checking the meet operation is indeed the greatest lower bound..."
quickCheckWith args (prop_dc_meet_glb :: DCLabelPair Principal -> Property)
putStrLn "Checking DC labels form a partial order..."
quickCheckWith args (prop_dc_porder :: DCLabelPair Principal -> Bool)
l1 = MkDCLabel {secrecy = MkLabel {label = MkConj {conj = [MkDisj {disj = [MkPrincipal {name = "B"}]},MkDisj {disj = []},MkDisj {disj = []}]}}, integrity = MkLabel {label = MkConj {conj = [MkDisj {disj = [MkPrincipal {name = "A"}]},MkDisj {disj = []},MkDisj {disj = []}]}}}
l2 = MkDCLabel {secrecy = MkLabel {label = MkConj {conj = [MkDisj {disj = [MkPrincipal {name = "C"}]},MkDisj {disj = []}]}}, integrity = MkLabel {label = MkConj {conj = [MkDisj {disj = [MkPrincipal {name = "B"}]}]}}}