Statistics
| Branch: | Tag: | Revision:

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
            ]