module Test.Ganeti.HTools.Types
( testHTools_Types
, Types.AllocPolicy(..)
, Types.DiskTemplate(..)
, Types.FailMode(..)
, Types.ISpec(..)
, Types.IPolicy(..)
, nullIPolicy
) where
import Test.QuickCheck hiding (Result)
import Test.HUnit
import Control.Applicative
import Control.Monad (replicateM)
import Test.Ganeti.TestHelper
import Test.Ganeti.TestCommon
import Test.Ganeti.TestHTools
import Test.Ganeti.Types (allDiskTemplates)
import Ganeti.BasicTypes
import qualified Ganeti.Constants as C
import Ganeti.ConstantUtils
import qualified Ganeti.HTools.Types as Types
$(genArbitrary ''Types.FailMode)
instance Arbitrary a => Arbitrary (Types.OpResult a) where
arbitrary = arbitrary >>= \c ->
if c
then Ok <$> arbitrary
else Bad <$> arbitrary
instance Arbitrary Types.ISpec where
arbitrary = do
mem_s <- arbitrary::Gen (NonNegative Int)
dsk_c <- arbitrary::Gen (NonNegative Int)
dsk_s <- arbitrary::Gen (NonNegative Int)
cpu_c <- arbitrary::Gen (NonNegative Int)
nic_c <- arbitrary::Gen (NonNegative Int)
su <- arbitrary::Gen (NonNegative Int)
return Types.ISpec { Types.iSpecMemorySize = fromEnum mem_s
, Types.iSpecCpuCount = fromEnum cpu_c
, Types.iSpecDiskSize = fromEnum dsk_s
, Types.iSpecDiskCount = fromEnum dsk_c
, Types.iSpecNicCount = fromEnum nic_c
, Types.iSpecSpindleUse = fromEnum su
}
genBiggerISpec :: Types.ISpec -> Gen Types.ISpec
genBiggerISpec imin = do
mem_s <- choose (Types.iSpecMemorySize imin, maxBound)
dsk_c <- choose (Types.iSpecDiskCount imin, maxBound)
dsk_s <- choose (Types.iSpecDiskSize imin, maxBound)
cpu_c <- choose (Types.iSpecCpuCount imin, maxBound)
nic_c <- choose (Types.iSpecNicCount imin, maxBound)
su <- choose (Types.iSpecSpindleUse imin, maxBound)
return Types.ISpec { Types.iSpecMemorySize = fromEnum mem_s
, Types.iSpecCpuCount = fromEnum cpu_c
, Types.iSpecDiskSize = fromEnum dsk_s
, Types.iSpecDiskCount = fromEnum dsk_c
, Types.iSpecNicCount = fromEnum nic_c
, Types.iSpecSpindleUse = fromEnum su
}
genMinMaxISpecs :: Gen Types.MinMaxISpecs
genMinMaxISpecs = do
imin <- arbitrary
imax <- genBiggerISpec imin
return Types.MinMaxISpecs { Types.minMaxISpecsMinSpec = imin
, Types.minMaxISpecsMaxSpec = imax
}
instance Arbitrary Types.MinMaxISpecs where
arbitrary = genMinMaxISpecs
genMinMaxStdISpecs :: Gen (Types.MinMaxISpecs, Types.ISpec)
genMinMaxStdISpecs = do
imin <- arbitrary
istd <- genBiggerISpec imin
imax <- genBiggerISpec istd
return (Types.MinMaxISpecs { Types.minMaxISpecsMinSpec = imin
, Types.minMaxISpecsMaxSpec = imax
},
istd)
genIPolicySpecs :: Gen ([Types.MinMaxISpecs], Types.ISpec)
genIPolicySpecs = do
num_mm <- choose (1, 6)
std_compl <- choose (1, num_mm)
mm_head <- replicateM (std_compl 1) genMinMaxISpecs
(mm_middle, istd) <- genMinMaxStdISpecs
mm_tail <- replicateM (num_mm std_compl) genMinMaxISpecs
return (mm_head ++ (mm_middle : mm_tail), istd)
instance Arbitrary Types.IPolicy where
arbitrary = do
(iminmax, istd) <- genIPolicySpecs
num_tmpl <- choose (0, length allDiskTemplates)
dts <- genUniquesList num_tmpl arbitrary
vcpu_ratio <- choose (1.0, maxVcpuRatio)
spindle_ratio <- choose (1.0, maxSpindleRatio)
return Types.IPolicy { Types.iPolicyMinMaxISpecs = iminmax
, Types.iPolicyStdSpec = istd
, Types.iPolicyDiskTemplates = dts
, Types.iPolicyVcpuRatio = vcpu_ratio
, Types.iPolicySpindleRatio = spindle_ratio
}
prop_ISpec_serialisation :: Types.ISpec -> Property
prop_ISpec_serialisation = testSerialisation
prop_IPolicy_serialisation :: Types.IPolicy -> Property
prop_IPolicy_serialisation = testSerialisation
prop_opToResult :: Types.OpResult Int -> Property
prop_opToResult op =
case op of
Bad _ -> counterexample ("expected bad but got " ++ show r) $ isBad r
Ok v -> case r of
Bad msg -> failTest ("expected Ok but got Bad " ++ msg)
Ok v' -> v ==? v'
where r = Types.opToResult op
prop_eitherToResult :: Either String Int -> Bool
prop_eitherToResult ei =
case ei of
Left _ -> isBad r
Right v -> case r of
Bad _ -> False
Ok v' -> v == v'
where r = eitherToResult ei :: Result Int
case_AutoRepairType_sort :: Assertion
case_AutoRepairType_sort = do
let expected = [ Types.ArFixStorage
, Types.ArMigrate
, Types.ArFailover
, Types.ArReinstall
]
all_hs_raw = mkSet $ map Types.autoRepairTypeToRaw [minBound..maxBound]
assertEqual "Haskell order" expected [minBound..maxBound]
assertEqual "consistent with Python" C.autoRepairAllTypes all_hs_raw
case_AutoRepairResult_pyequiv :: Assertion
case_AutoRepairResult_pyequiv = do
let all_py_results = C.autoRepairAllResults
all_hs_results = mkSet $
map Types.autoRepairResultToRaw [minBound..maxBound]
assertEqual "for AutoRepairResult equivalence" all_py_results all_hs_results
testSuite "HTools/Types"
[ 'prop_ISpec_serialisation
, 'prop_IPolicy_serialisation
, 'prop_opToResult
, 'prop_eitherToResult
, 'case_AutoRepairType_sort
, 'case_AutoRepairResult_pyequiv
]