module Test.Ganeti.HTools.Instance
( testHTools_Instance
, genInstanceSmallerThanNode
, genInstanceMaybeBiggerThanNode
, genInstanceOnNodeList
, genInstanceList
, Instance.Instance(..)
) where
import Control.Arrow ((&&&))
import Control.Applicative ((<$>))
import Control.Monad (liftM)
import Test.QuickCheck hiding (Result)
import Test.Ganeti.TestHTools (nullISpec)
import Test.Ganeti.TestHelper
import Test.Ganeti.TestCommon
import Test.Ganeti.HTools.Types ()
import Ganeti.BasicTypes
import qualified Ganeti.HTools.Instance as Instance
import qualified Ganeti.HTools.Node as Node
import qualified Ganeti.HTools.Container as Container
import qualified Ganeti.HTools.Loader as Loader
import qualified Ganeti.HTools.Types as Types
genInstanceWithin :: Int -> Int -> Int -> Int
-> Int -> Int -> Int -> Maybe Int
-> Gen Instance.Instance
genInstanceWithin min_mem min_dsk min_cpu min_spin
max_mem max_dsk max_cpu max_spin = do
name <- genFQDN
mem <- choose (min_mem, max_mem)
dsk <- choose (min_dsk, max_dsk)
run_st <- arbitrary
pn <- arbitrary
sn <- arbitrary
vcpus <- choose (min_cpu, max_cpu)
dt <- arbitrary
spindles <- case max_spin of
Nothing -> genMaybe $ choose (min_spin, maxSpindles)
Just ls -> liftM Just $ choose (min_spin, ls)
forthcoming <- arbitrary
let disk = Instance.Disk dsk spindles
return $ Instance.create
name mem dsk [disk] vcpus run_st [] True pn sn dt 1 [] forthcoming
genInstanceSmallerThan :: Int -> Int -> Int -> Maybe Int
-> Gen Instance.Instance
genInstanceSmallerThan = genInstanceWithin 1 0 1 0
genInstanceSmallerThanNode :: Node.Node -> Gen Instance.Instance
genInstanceSmallerThanNode node =
genInstanceSmallerThan (Node.availMem node `div` 2)
(Node.availDisk node `div` 2)
(Node.availCpu node `div` 2)
(if Node.exclStorage node
then Just $ Node.fSpindlesForth node `div` 2
else Nothing)
genInstanceMaybeBiggerThanNode :: Node.Node -> Gen Instance.Instance
genInstanceMaybeBiggerThanNode node =
let minISpec = runListHead nullISpec Types.minMaxISpecsMinSpec
. Types.iPolicyMinMaxISpecs $ Node.iPolicy node
in genInstanceWithin (Types.iSpecMemorySize minISpec)
(Types.iSpecDiskSize minISpec)
(Types.iSpecCpuCount minISpec)
(Types.iSpecSpindleUse minISpec)
(Node.availMem node + Types.unitMem * 2)
(Node.availDisk node + Types.unitDsk * 3)
(Node.availCpu node + Types.unitCpu * 4)
(if Node.exclStorage node
then Just $ Node.fSpindles node +
Types.unitSpindle * 5
else Nothing)
genInstanceOnNodeList :: Node.List -> Gen Instance.Instance
genInstanceOnNodeList nl = do
let nsize = Container.size nl
pnode <- choose (0, nsize1)
let (snodefilter, dtfilter) =
if nsize >= 2
then ((/= pnode), const True)
else (const True, not . Instance.hasSecondary)
snode <- choose (0, nsize1) `suchThat` snodefilter
i <- genInstanceSmallerThanNode (Container.find pnode nl) `suchThat` dtfilter
return $ i { Instance.pNode = pnode, Instance.sNode = snode }
genInstanceList :: Gen Instance.Instance -> Gen Instance.List
genInstanceList igen = fmap (snd . Loader.assignIndices) names_instances
where names_instances =
map (Instance.name &&& id) <$> listOf igen
instance Arbitrary Instance.Instance where
arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu Nothing
prop_creat :: Instance.Instance -> Property
prop_creat inst =
Instance.name inst ==? Instance.alias inst
prop_setIdx :: Instance.Instance -> Types.Idx -> Property
prop_setIdx inst idx =
Instance.idx (Instance.setIdx inst idx) ==? idx
prop_setName :: Instance.Instance -> String -> Bool
prop_setName inst name =
Instance.name newinst == name &&
Instance.alias newinst == name
where newinst = Instance.setName inst name
prop_setAlias :: Instance.Instance -> String -> Bool
prop_setAlias inst name =
Instance.name newinst == Instance.name inst &&
Instance.alias newinst == name
where newinst = Instance.setAlias inst name
prop_setPri :: Instance.Instance -> Types.Ndx -> Property
prop_setPri inst pdx =
Instance.pNode (Instance.setPri inst pdx) ==? pdx
prop_setSec :: Instance.Instance -> Types.Ndx -> Property
prop_setSec inst sdx =
Instance.sNode (Instance.setSec inst sdx) ==? sdx
prop_setBoth :: Instance.Instance -> Types.Ndx -> Types.Ndx -> Bool
prop_setBoth inst pdx sdx =
Instance.pNode si == pdx && Instance.sNode si == sdx
where si = Instance.setBoth inst pdx sdx
prop_shrinkMG :: Instance.Instance -> Property
prop_shrinkMG inst =
Instance.mem inst >= 2 * Types.unitMem ==>
case Instance.shrinkByType inst Types.FailMem of
Ok inst' -> Instance.mem inst' ==? Instance.mem inst Types.unitMem
Bad msg -> failTest msg
prop_shrinkMF :: Instance.Instance -> Property
prop_shrinkMF inst =
forAll (choose (0, 2 * Types.unitMem 1)) $ \mem ->
let inst' = inst { Instance.mem = mem}
in isBad $ Instance.shrinkByType inst' Types.FailMem
prop_shrinkCG :: Instance.Instance -> Property
prop_shrinkCG inst =
Instance.vcpus inst >= 2 * Types.unitCpu ==>
case Instance.shrinkByType inst Types.FailCPU of
Ok inst' -> Instance.vcpus inst' ==? Instance.vcpus inst Types.unitCpu
Bad msg -> failTest msg
prop_shrinkCF :: Instance.Instance -> Property
prop_shrinkCF inst =
forAll (choose (0, 2 * Types.unitCpu 1)) $ \vcpus ->
let inst' = inst { Instance.vcpus = vcpus }
in isBad $ Instance.shrinkByType inst' Types.FailCPU
prop_shrinkDG :: Instance.Instance -> Property
prop_shrinkDG inst =
Instance.dsk inst >= 2 * Types.unitDsk ==>
case Instance.shrinkByType inst Types.FailDisk of
Ok inst' -> Instance.dsk inst' ==? Instance.dsk inst Types.unitDsk
Bad msg -> failTest msg
prop_shrinkDF :: Instance.Instance -> Property
prop_shrinkDF inst =
forAll (choose (0, 2 * Types.unitDsk 1)) $ \dsk ->
let inst' = inst { Instance.dsk = dsk
, Instance.disks = [Instance.Disk dsk Nothing] }
in isBad $ Instance.shrinkByType inst' Types.FailDisk
prop_setMovable :: Instance.Instance -> Bool -> Property
prop_setMovable inst m =
Instance.movable inst' ==? m
where inst' = Instance.setMovable inst m
testSuite "HTools/Instance"
[ 'prop_creat
, 'prop_setIdx
, 'prop_setName
, 'prop_setAlias
, 'prop_setPri
, 'prop_setSec
, 'prop_setBoth
, 'prop_shrinkMG
, 'prop_shrinkMF
, 'prop_shrinkCG
, 'prop_shrinkCF
, 'prop_shrinkDG
, 'prop_shrinkDF
, 'prop_setMovable
]