Statistics
| Branch: | Tag: | Revision:

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
            ]