Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / HTools / Types.hs @ 09d8b0fc

History | View | Annotate | Download (7.1 kB)

1 a8038349 Iustin Pop
{-# LANGUAGE TemplateHaskell, FlexibleInstances, TypeSynonymInstances #-}
2 e1ee7d5a Iustin Pop
{-# OPTIONS_GHC -fno-warn-orphans #-}
3 e1ee7d5a Iustin Pop
4 e1ee7d5a Iustin Pop
{-| Unittests for ganeti-htools.
5 e1ee7d5a Iustin Pop
6 e1ee7d5a Iustin Pop
-}
7 e1ee7d5a Iustin Pop
8 e1ee7d5a Iustin Pop
{-
9 e1ee7d5a Iustin Pop
10 3cbd5808 Iustin Pop
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
11 e1ee7d5a Iustin Pop
12 e1ee7d5a Iustin Pop
This program is free software; you can redistribute it and/or modify
13 e1ee7d5a Iustin Pop
it under the terms of the GNU General Public License as published by
14 e1ee7d5a Iustin Pop
the Free Software Foundation; either version 2 of the License, or
15 e1ee7d5a Iustin Pop
(at your option) any later version.
16 e1ee7d5a Iustin Pop
17 e1ee7d5a Iustin Pop
This program is distributed in the hope that it will be useful, but
18 e1ee7d5a Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
19 e1ee7d5a Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 e1ee7d5a Iustin Pop
General Public License for more details.
21 e1ee7d5a Iustin Pop
22 e1ee7d5a Iustin Pop
You should have received a copy of the GNU General Public License
23 e1ee7d5a Iustin Pop
along with this program; if not, write to the Free Software
24 e1ee7d5a Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 e1ee7d5a Iustin Pop
02110-1301, USA.
26 e1ee7d5a Iustin Pop
27 e1ee7d5a Iustin Pop
-}
28 e1ee7d5a Iustin Pop
29 e1ee7d5a Iustin Pop
module Test.Ganeti.HTools.Types
30 e09c1fa0 Iustin Pop
  ( testHTools_Types
31 e1ee7d5a Iustin Pop
  , Types.AllocPolicy(..)
32 e1ee7d5a Iustin Pop
  , Types.DiskTemplate(..)
33 e1ee7d5a Iustin Pop
  , Types.FailMode(..)
34 e1ee7d5a Iustin Pop
  , Types.EvacMode(..)
35 e1ee7d5a Iustin Pop
  , Types.ISpec(..)
36 e1ee7d5a Iustin Pop
  , Types.IPolicy(..)
37 e1ee7d5a Iustin Pop
  , nullIPolicy
38 e1ee7d5a Iustin Pop
  ) where
39 e1ee7d5a Iustin Pop
40 01e52493 Iustin Pop
import Test.QuickCheck hiding (Result)
41 3e77a36c Dato Simó
import Test.HUnit
42 e1ee7d5a Iustin Pop
43 e1ee7d5a Iustin Pop
import Control.Applicative
44 3e77a36c Dato Simó
import Data.List (sort)
45 41044e04 Bernardo Dal Seno
import Control.Monad (replicateM)
46 e1ee7d5a Iustin Pop
47 e1ee7d5a Iustin Pop
import Test.Ganeti.TestHelper
48 e1ee7d5a Iustin Pop
import Test.Ganeti.TestCommon
49 e1ee7d5a Iustin Pop
import Test.Ganeti.TestHTools
50 3cbd5808 Iustin Pop
import Test.Ganeti.Types (allDiskTemplates)
51 e1ee7d5a Iustin Pop
52 01e52493 Iustin Pop
import Ganeti.BasicTypes
53 3e77a36c Dato Simó
import qualified Ganeti.Constants as C
54 e1ee7d5a Iustin Pop
import qualified Ganeti.HTools.Types as Types
55 e1ee7d5a Iustin Pop
56 d46c9fd6 Dato Simó
{-# ANN module "HLint: ignore Use camelCase" #-}
57 d46c9fd6 Dato Simó
58 e1ee7d5a Iustin Pop
-- * Helpers
59 e1ee7d5a Iustin Pop
60 e1ee7d5a Iustin Pop
-- * Arbitrary instance
61 e1ee7d5a Iustin Pop
62 7022db83 Iustin Pop
$(genArbitrary ''Types.FailMode)
63 e1ee7d5a Iustin Pop
64 7022db83 Iustin Pop
$(genArbitrary ''Types.EvacMode)
65 e1ee7d5a Iustin Pop
66 e1ee7d5a Iustin Pop
instance Arbitrary a => Arbitrary (Types.OpResult a) where
67 e1ee7d5a Iustin Pop
  arbitrary = arbitrary >>= \c ->
68 e1ee7d5a Iustin Pop
              if c
69 a8038349 Iustin Pop
                then Ok  <$> arbitrary
70 a8038349 Iustin Pop
                else Bad <$> arbitrary
71 e1ee7d5a Iustin Pop
72 e1ee7d5a Iustin Pop
instance Arbitrary Types.ISpec where
73 e1ee7d5a Iustin Pop
  arbitrary = do
74 e1ee7d5a Iustin Pop
    mem_s <- arbitrary::Gen (NonNegative Int)
75 e1ee7d5a Iustin Pop
    dsk_c <- arbitrary::Gen (NonNegative Int)
76 e1ee7d5a Iustin Pop
    dsk_s <- arbitrary::Gen (NonNegative Int)
77 e1ee7d5a Iustin Pop
    cpu_c <- arbitrary::Gen (NonNegative Int)
78 e1ee7d5a Iustin Pop
    nic_c <- arbitrary::Gen (NonNegative Int)
79 e1ee7d5a Iustin Pop
    su    <- arbitrary::Gen (NonNegative Int)
80 e1ee7d5a Iustin Pop
    return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s
81 e1ee7d5a Iustin Pop
                       , Types.iSpecCpuCount   = fromIntegral cpu_c
82 e1ee7d5a Iustin Pop
                       , Types.iSpecDiskSize   = fromIntegral dsk_s
83 e1ee7d5a Iustin Pop
                       , Types.iSpecDiskCount  = fromIntegral dsk_c
84 e1ee7d5a Iustin Pop
                       , Types.iSpecNicCount   = fromIntegral nic_c
85 e1ee7d5a Iustin Pop
                       , Types.iSpecSpindleUse = fromIntegral su
86 e1ee7d5a Iustin Pop
                       }
87 e1ee7d5a Iustin Pop
88 e1ee7d5a Iustin Pop
-- | Generates an ispec bigger than the given one.
89 e1ee7d5a Iustin Pop
genBiggerISpec :: Types.ISpec -> Gen Types.ISpec
90 e1ee7d5a Iustin Pop
genBiggerISpec imin = do
91 e1ee7d5a Iustin Pop
  mem_s <- choose (Types.iSpecMemorySize imin, maxBound)
92 e1ee7d5a Iustin Pop
  dsk_c <- choose (Types.iSpecDiskCount imin, maxBound)
93 e1ee7d5a Iustin Pop
  dsk_s <- choose (Types.iSpecDiskSize imin, maxBound)
94 e1ee7d5a Iustin Pop
  cpu_c <- choose (Types.iSpecCpuCount imin, maxBound)
95 e1ee7d5a Iustin Pop
  nic_c <- choose (Types.iSpecNicCount imin, maxBound)
96 e1ee7d5a Iustin Pop
  su    <- choose (Types.iSpecSpindleUse imin, maxBound)
97 e1ee7d5a Iustin Pop
  return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s
98 e1ee7d5a Iustin Pop
                     , Types.iSpecCpuCount   = fromIntegral cpu_c
99 e1ee7d5a Iustin Pop
                     , Types.iSpecDiskSize   = fromIntegral dsk_s
100 e1ee7d5a Iustin Pop
                     , Types.iSpecDiskCount  = fromIntegral dsk_c
101 e1ee7d5a Iustin Pop
                     , Types.iSpecNicCount   = fromIntegral nic_c
102 e1ee7d5a Iustin Pop
                     , Types.iSpecSpindleUse = fromIntegral su
103 e1ee7d5a Iustin Pop
                     }
104 e1ee7d5a Iustin Pop
105 41044e04 Bernardo Dal Seno
genMinMaxISpecs :: Gen Types.MinMaxISpecs
106 41044e04 Bernardo Dal Seno
genMinMaxISpecs = do
107 41044e04 Bernardo Dal Seno
  imin <- arbitrary
108 41044e04 Bernardo Dal Seno
  imax <- genBiggerISpec imin
109 41044e04 Bernardo Dal Seno
  return Types.MinMaxISpecs { Types.minMaxISpecsMinSpec = imin
110 41044e04 Bernardo Dal Seno
                             , Types.minMaxISpecsMaxSpec = imax
111 41044e04 Bernardo Dal Seno
                             }
112 41044e04 Bernardo Dal Seno
113 41044e04 Bernardo Dal Seno
instance Arbitrary Types.MinMaxISpecs where
114 41044e04 Bernardo Dal Seno
  arbitrary = genMinMaxISpecs
115 41044e04 Bernardo Dal Seno
116 41044e04 Bernardo Dal Seno
genMinMaxStdISpecs :: Gen (Types.MinMaxISpecs, Types.ISpec)
117 41044e04 Bernardo Dal Seno
genMinMaxStdISpecs = do
118 41044e04 Bernardo Dal Seno
  imin <- arbitrary
119 41044e04 Bernardo Dal Seno
  istd <- genBiggerISpec imin
120 41044e04 Bernardo Dal Seno
  imax <- genBiggerISpec istd
121 41044e04 Bernardo Dal Seno
  return (Types.MinMaxISpecs { Types.minMaxISpecsMinSpec = imin
122 41044e04 Bernardo Dal Seno
                             , Types.minMaxISpecsMaxSpec = imax
123 41044e04 Bernardo Dal Seno
                             },
124 41044e04 Bernardo Dal Seno
          istd)
125 41044e04 Bernardo Dal Seno
126 41044e04 Bernardo Dal Seno
genIPolicySpecs :: Gen ([Types.MinMaxISpecs], Types.ISpec)
127 41044e04 Bernardo Dal Seno
genIPolicySpecs = do
128 41044e04 Bernardo Dal Seno
  num_mm <- choose (1, 6) -- 6 is just an arbitrary limit
129 41044e04 Bernardo Dal Seno
  std_compl <- choose (1, num_mm)
130 41044e04 Bernardo Dal Seno
  mm_head <- replicateM (std_compl - 1) genMinMaxISpecs
131 41044e04 Bernardo Dal Seno
  (mm_middle, istd) <- genMinMaxStdISpecs
132 41044e04 Bernardo Dal Seno
  mm_tail <- replicateM (num_mm - std_compl) genMinMaxISpecs
133 41044e04 Bernardo Dal Seno
  return (mm_head ++ (mm_middle : mm_tail), istd)
134 41044e04 Bernardo Dal Seno
135 41044e04 Bernardo Dal Seno
136 e1ee7d5a Iustin Pop
instance Arbitrary Types.IPolicy where
137 e1ee7d5a Iustin Pop
  arbitrary = do
138 41044e04 Bernardo Dal Seno
    (iminmax, istd) <- genIPolicySpecs
139 e1ee7d5a Iustin Pop
    num_tmpl <- choose (0, length allDiskTemplates)
140 df8578fb Iustin Pop
    dts  <- genUniquesList num_tmpl arbitrary
141 e1ee7d5a Iustin Pop
    vcpu_ratio <- choose (1.0, maxVcpuRatio)
142 e1ee7d5a Iustin Pop
    spindle_ratio <- choose (1.0, maxSpindleRatio)
143 41044e04 Bernardo Dal Seno
    return Types.IPolicy { Types.iPolicyMinMaxISpecs = iminmax
144 e1ee7d5a Iustin Pop
                         , Types.iPolicyStdSpec = istd
145 e1ee7d5a Iustin Pop
                         , Types.iPolicyDiskTemplates = dts
146 e1ee7d5a Iustin Pop
                         , Types.iPolicyVcpuRatio = vcpu_ratio
147 e1ee7d5a Iustin Pop
                         , Types.iPolicySpindleRatio = spindle_ratio
148 e1ee7d5a Iustin Pop
                         }
149 e1ee7d5a Iustin Pop
150 e1ee7d5a Iustin Pop
-- * Test cases
151 e1ee7d5a Iustin Pop
152 20bc5360 Iustin Pop
prop_ISpec_serialisation :: Types.ISpec -> Property
153 63b068c1 Iustin Pop
prop_ISpec_serialisation = testSerialisation
154 e1ee7d5a Iustin Pop
155 20bc5360 Iustin Pop
prop_IPolicy_serialisation :: Types.IPolicy -> Property
156 63b068c1 Iustin Pop
prop_IPolicy_serialisation = testSerialisation
157 e1ee7d5a Iustin Pop
158 20bc5360 Iustin Pop
prop_EvacMode_serialisation :: Types.EvacMode -> Property
159 63b068c1 Iustin Pop
prop_EvacMode_serialisation = testSerialisation
160 e1ee7d5a Iustin Pop
161 a8038349 Iustin Pop
prop_opToResult :: Types.OpResult Int -> Property
162 20bc5360 Iustin Pop
prop_opToResult op =
163 e1ee7d5a Iustin Pop
  case op of
164 a8038349 Iustin Pop
    Bad _ -> printTestCase ("expected bad but got " ++ show r) $ isBad r
165 a8038349 Iustin Pop
    Ok v  -> case r of
166 a8038349 Iustin Pop
               Bad msg -> failTest ("expected Ok but got Bad " ++ msg)
167 a8038349 Iustin Pop
               Ok v' -> v ==? v'
168 e1ee7d5a Iustin Pop
  where r = Types.opToResult op
169 e1ee7d5a Iustin Pop
170 20bc5360 Iustin Pop
prop_eitherToResult :: Either String Int -> Bool
171 20bc5360 Iustin Pop
prop_eitherToResult ei =
172 e1ee7d5a Iustin Pop
  case ei of
173 01e52493 Iustin Pop
    Left _ -> isBad r
174 e1ee7d5a Iustin Pop
    Right v -> case r of
175 01e52493 Iustin Pop
                 Bad _ -> False
176 01e52493 Iustin Pop
                 Ok v' -> v == v'
177 01e52493 Iustin Pop
    where r = eitherToResult ei
178 e1ee7d5a Iustin Pop
179 3e77a36c Dato Simó
-- | Test 'AutoRepairType' ordering is as expected and consistent with Python
180 3e77a36c Dato Simó
-- codebase.
181 3e77a36c Dato Simó
case_AutoRepairType_sort :: Assertion
182 3e77a36c Dato Simó
case_AutoRepairType_sort = do
183 3e77a36c Dato Simó
  let expected = [ Types.ArFixStorage
184 3e77a36c Dato Simó
                 , Types.ArMigrate
185 3e77a36c Dato Simó
                 , Types.ArFailover
186 3e77a36c Dato Simó
                 , Types.ArReinstall
187 3e77a36c Dato Simó
                 ]
188 3e77a36c Dato Simó
      all_hs_raw = map Types.autoRepairTypeToRaw [minBound..maxBound]
189 3e77a36c Dato Simó
  assertEqual "Haskell order" expected [minBound..maxBound]
190 3e77a36c Dato Simó
  assertEqual "consistent with Python" C.autoRepairAllTypes all_hs_raw
191 3e77a36c Dato Simó
192 3e77a36c Dato Simó
-- | Test 'AutoRepairResult' type is equivalent with Python codebase.
193 3e77a36c Dato Simó
case_AutoRepairResult_pyequiv :: Assertion
194 3e77a36c Dato Simó
case_AutoRepairResult_pyequiv = do
195 3e77a36c Dato Simó
  let all_py_results = sort C.autoRepairAllResults
196 3e77a36c Dato Simó
      all_hs_results = sort $
197 3e77a36c Dato Simó
                       map Types.autoRepairResultToRaw [minBound..maxBound]
198 3e77a36c Dato Simó
  assertEqual "for AutoRepairResult equivalence" all_py_results all_hs_results
199 3e77a36c Dato Simó
200 e09c1fa0 Iustin Pop
testSuite "HTools/Types"
201 5e9deac0 Iustin Pop
            [ 'prop_ISpec_serialisation
202 20bc5360 Iustin Pop
            , 'prop_IPolicy_serialisation
203 20bc5360 Iustin Pop
            , 'prop_EvacMode_serialisation
204 20bc5360 Iustin Pop
            , 'prop_opToResult
205 20bc5360 Iustin Pop
            , 'prop_eitherToResult
206 3e77a36c Dato Simó
            , 'case_AutoRepairType_sort
207 3e77a36c Dato Simó
            , 'case_AutoRepairResult_pyequiv
208 e1ee7d5a Iustin Pop
            ]