## root / test / hs / Test / Ganeti / HTools / Types.hs @ d46c9fd6

History | View | Annotate | Download (6.2 kB)

1 |
{-# LANGUAGE TemplateHaskell, FlexibleInstances, TypeSynonymInstances #-} |
---|---|

2 |
{-# OPTIONS_GHC -fno-warn-orphans #-} |

3 | |

4 |
{-| Unittests for ganeti-htools. |

5 | |

6 |
-} |

7 | |

8 |
{- |

9 | |

10 |
Copyright (C) 2009, 2010, 2011, 2012 Google Inc. |

11 | |

12 |
This program is free software; you can redistribute it and/or modify |

13 |
it under the terms of the GNU General Public License as published by |

14 |
the Free Software Foundation; either version 2 of the License, or |

15 |
(at your option) any later version. |

16 | |

17 |
This program is distributed in the hope that it will be useful, but |

18 |
WITHOUT ANY WARRANTY; without even the implied warranty of |

19 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |

20 |
General Public License for more details. |

21 | |

22 |
You should have received a copy of the GNU General Public License |

23 |
along with this program; if not, write to the Free Software |

24 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |

25 |
02110-1301, USA. |

26 | |

27 |
-} |

28 | |

29 |
module Test.Ganeti.HTools.Types |

30 |
( testHTools_Types |

31 |
, Types.AllocPolicy(..) |

32 |
, Types.DiskTemplate(..) |

33 |
, Types.FailMode(..) |

34 |
, Types.EvacMode(..) |

35 |
, Types.ISpec(..) |

36 |
, Types.IPolicy(..) |

37 |
, nullIPolicy |

38 |
) where |

39 | |

40 |
import Test.QuickCheck hiding (Result) |

41 |
import Test.HUnit |

42 | |

43 |
import Control.Applicative |

44 |
import Data.List (sort) |

45 | |

46 |
import Test.Ganeti.TestHelper |

47 |
import Test.Ganeti.TestCommon |

48 |
import Test.Ganeti.TestHTools |

49 |
import Test.Ganeti.Types () |

50 | |

51 |
import Ganeti.BasicTypes |

52 |
import qualified Ganeti.Constants as C |

53 |
import qualified Ganeti.HTools.Types as Types |

54 | |

55 |
{-# ANN module "HLint: ignore Use camelCase" #-} |

56 | |

57 |
-- * Helpers |

58 | |

59 |
-- | All disk templates (used later) |

60 |
allDiskTemplates :: [Types.DiskTemplate] |

61 |
allDiskTemplates = [minBound..maxBound] |

62 | |

63 |
-- * Arbitrary instance |

64 | |

65 |
$(genArbitrary ''Types.FailMode) |

66 | |

67 |
$(genArbitrary ''Types.EvacMode) |

68 | |

69 |
instance Arbitrary a => Arbitrary (Types.OpResult a) where |

70 |
arbitrary = arbitrary >>= \c -> |

71 |
if c |

72 |
then Ok <$> arbitrary |

73 |
else Bad <$> arbitrary |

74 | |

75 |
instance Arbitrary Types.ISpec where |

76 |
arbitrary = do |

77 |
mem_s <- arbitrary::Gen (NonNegative Int) |

78 |
dsk_c <- arbitrary::Gen (NonNegative Int) |

79 |
dsk_s <- arbitrary::Gen (NonNegative Int) |

80 |
cpu_c <- arbitrary::Gen (NonNegative Int) |

81 |
nic_c <- arbitrary::Gen (NonNegative Int) |

82 |
su <- arbitrary::Gen (NonNegative Int) |

83 |
return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s |

84 |
, Types.iSpecCpuCount = fromIntegral cpu_c |

85 |
, Types.iSpecDiskSize = fromIntegral dsk_s |

86 |
, Types.iSpecDiskCount = fromIntegral dsk_c |

87 |
, Types.iSpecNicCount = fromIntegral nic_c |

88 |
, Types.iSpecSpindleUse = fromIntegral su |

89 |
} |

90 | |

91 |
-- | Generates an ispec bigger than the given one. |

92 |
genBiggerISpec :: Types.ISpec -> Gen Types.ISpec |

93 |
genBiggerISpec imin = do |

94 |
mem_s <- choose (Types.iSpecMemorySize imin, maxBound) |

95 |
dsk_c <- choose (Types.iSpecDiskCount imin, maxBound) |

96 |
dsk_s <- choose (Types.iSpecDiskSize imin, maxBound) |

97 |
cpu_c <- choose (Types.iSpecCpuCount imin, maxBound) |

98 |
nic_c <- choose (Types.iSpecNicCount imin, maxBound) |

99 |
su <- choose (Types.iSpecSpindleUse imin, maxBound) |

100 |
return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s |

101 |
, Types.iSpecCpuCount = fromIntegral cpu_c |

102 |
, Types.iSpecDiskSize = fromIntegral dsk_s |

103 |
, Types.iSpecDiskCount = fromIntegral dsk_c |

104 |
, Types.iSpecNicCount = fromIntegral nic_c |

105 |
, Types.iSpecSpindleUse = fromIntegral su |

106 |
} |

107 | |

108 |
instance Arbitrary Types.IPolicy where |

109 |
arbitrary = do |

110 |
imin <- arbitrary |

111 |
istd <- genBiggerISpec imin |

112 |
imax <- genBiggerISpec istd |

113 |
num_tmpl <- choose (0, length allDiskTemplates) |

114 |
dts <- genUniquesList num_tmpl arbitrary |

115 |
vcpu_ratio <- choose (1.0, maxVcpuRatio) |

116 |
spindle_ratio <- choose (1.0, maxSpindleRatio) |

117 |
return Types.IPolicy { Types.iPolicyMinSpec = imin |

118 |
, Types.iPolicyStdSpec = istd |

119 |
, Types.iPolicyMaxSpec = imax |

120 |
, Types.iPolicyDiskTemplates = dts |

121 |
, Types.iPolicyVcpuRatio = vcpu_ratio |

122 |
, Types.iPolicySpindleRatio = spindle_ratio |

123 |
} |

124 | |

125 |
-- * Test cases |

126 | |

127 |
prop_ISpec_serialisation :: Types.ISpec -> Property |

128 |
prop_ISpec_serialisation = testSerialisation |

129 | |

130 |
prop_IPolicy_serialisation :: Types.IPolicy -> Property |

131 |
prop_IPolicy_serialisation = testSerialisation |

132 | |

133 |
prop_EvacMode_serialisation :: Types.EvacMode -> Property |

134 |
prop_EvacMode_serialisation = testSerialisation |

135 | |

136 |
prop_opToResult :: Types.OpResult Int -> Property |

137 |
prop_opToResult op = |

138 |
case op of |

139 |
Bad _ -> printTestCase ("expected bad but got " ++ show r) $ isBad r |

140 |
Ok v -> case r of |

141 |
Bad msg -> failTest ("expected Ok but got Bad " ++ msg) |

142 |
Ok v' -> v ==? v' |

143 |
where r = Types.opToResult op |

144 | |

145 |
prop_eitherToResult :: Either String Int -> Bool |

146 |
prop_eitherToResult ei = |

147 |
case ei of |

148 |
Left _ -> isBad r |

149 |
Right v -> case r of |

150 |
Bad _ -> False |

151 |
Ok v' -> v == v' |

152 |
where r = eitherToResult ei |

153 | |

154 |
-- | Test 'AutoRepairType' ordering is as expected and consistent with Python |

155 |
-- codebase. |

156 |
case_AutoRepairType_sort :: Assertion |

157 |
case_AutoRepairType_sort = do |

158 |
let expected = [ Types.ArFixStorage |

159 |
, Types.ArMigrate |

160 |
, Types.ArFailover |

161 |
, Types.ArReinstall |

162 |
] |

163 |
all_hs_raw = map Types.autoRepairTypeToRaw [minBound..maxBound] |

164 |
assertEqual "Haskell order" expected [minBound..maxBound] |

165 |
assertEqual "consistent with Python" C.autoRepairAllTypes all_hs_raw |

166 | |

167 |
-- | Test 'AutoRepairResult' type is equivalent with Python codebase. |

168 |
case_AutoRepairResult_pyequiv :: Assertion |

169 |
case_AutoRepairResult_pyequiv = do |

170 |
let all_py_results = sort C.autoRepairAllResults |

171 |
all_hs_results = sort $ |

172 |
map Types.autoRepairResultToRaw [minBound..maxBound] |

173 |
assertEqual "for AutoRepairResult equivalence" all_py_results all_hs_results |

174 | |

175 |
testSuite "HTools/Types" |

176 |
[ 'prop_ISpec_serialisation |

177 |
, 'prop_IPolicy_serialisation |

178 |
, 'prop_EvacMode_serialisation |

179 |
, 'prop_opToResult |

180 |
, 'prop_eitherToResult |

181 |
, 'case_AutoRepairType_sort |

182 |
, 'case_AutoRepairResult_pyequiv |

183 |
] |