## root / test / hs / Test / Ganeti / HTools / Types.hs @ 3cbd5808

History | View | Annotate | Download (6.1 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, 2013 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 (allDiskTemplates) |

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 |
-- * Arbitrary instance |

60 | |

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

62 | |

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

64 | |

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

66 |
arbitrary = arbitrary >>= \c -> |

67 |
if c |

68 |
then Ok <$> arbitrary |

69 |
else Bad <$> arbitrary |

70 | |

71 |
instance Arbitrary Types.ISpec where |

72 |
arbitrary = do |

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

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

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

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

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

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

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

80 |
, Types.iSpecCpuCount = fromIntegral cpu_c |

81 |
, Types.iSpecDiskSize = fromIntegral dsk_s |

82 |
, Types.iSpecDiskCount = fromIntegral dsk_c |

83 |
, Types.iSpecNicCount = fromIntegral nic_c |

84 |
, Types.iSpecSpindleUse = fromIntegral su |

85 |
} |

86 | |

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

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

89 |
genBiggerISpec imin = do |

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

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

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

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

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

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

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

97 |
, Types.iSpecCpuCount = fromIntegral cpu_c |

98 |
, Types.iSpecDiskSize = fromIntegral dsk_s |

99 |
, Types.iSpecDiskCount = fromIntegral dsk_c |

100 |
, Types.iSpecNicCount = fromIntegral nic_c |

101 |
, Types.iSpecSpindleUse = fromIntegral su |

102 |
} |

103 | |

104 |
instance Arbitrary Types.IPolicy where |

105 |
arbitrary = do |

106 |
imin <- arbitrary |

107 |
istd <- genBiggerISpec imin |

108 |
imax <- genBiggerISpec istd |

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

110 |
dts <- genUniquesList num_tmpl arbitrary |

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

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

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

114 |
, Types.iPolicyStdSpec = istd |

115 |
, Types.iPolicyMaxSpec = imax |

116 |
, Types.iPolicyDiskTemplates = dts |

117 |
, Types.iPolicyVcpuRatio = vcpu_ratio |

118 |
, Types.iPolicySpindleRatio = spindle_ratio |

119 |
} |

120 | |

121 |
-- * Test cases |

122 | |

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

124 |
prop_ISpec_serialisation = testSerialisation |

125 | |

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

127 |
prop_IPolicy_serialisation = testSerialisation |

128 | |

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

130 |
prop_EvacMode_serialisation = testSerialisation |

131 | |

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

133 |
prop_opToResult op = |

134 |
case op of |

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

136 |
Ok v -> case r of |

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

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

139 |
where r = Types.opToResult op |

140 | |

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

142 |
prop_eitherToResult ei = |

143 |
case ei of |

144 |
Left _ -> isBad r |

145 |
Right v -> case r of |

146 |
Bad _ -> False |

147 |
Ok v' -> v == v' |

148 |
where r = eitherToResult ei |

149 | |

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

151 |
-- codebase. |

152 |
case_AutoRepairType_sort :: Assertion |

153 |
case_AutoRepairType_sort = do |

154 |
let expected = [ Types.ArFixStorage |

155 |
, Types.ArMigrate |

156 |
, Types.ArFailover |

157 |
, Types.ArReinstall |

158 |
] |

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

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

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

162 | |

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

164 |
case_AutoRepairResult_pyequiv :: Assertion |

165 |
case_AutoRepairResult_pyequiv = do |

166 |
let all_py_results = sort C.autoRepairAllResults |

167 |
all_hs_results = sort $ |

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

169 |
assertEqual "for AutoRepairResult equivalence" all_py_results all_hs_results |

170 | |

171 |
testSuite "HTools/Types" |

172 |
[ 'prop_ISpec_serialisation |

173 |
, 'prop_IPolicy_serialisation |

174 |
, 'prop_EvacMode_serialisation |

175 |
, 'prop_opToResult |

176 |
, 'prop_eitherToResult |

177 |
, 'case_AutoRepairType_sort |

178 |
, 'case_AutoRepairResult_pyequiv |

179 |
] |