Split most HTools test code into separate files
[ganeti-local] / htest / Test / Ganeti / HTools / Types.hs
1 {-# LANGUAGE TemplateHaskell #-}
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   ( testTypes
31   , Types.AllocPolicy(..)
32   , Types.DiskTemplate(..)
33   , Types.FailMode(..)
34   , Types.EvacMode(..)
35   , Types.OpResult(..)
36   , Types.ISpec(..)
37   , Types.IPolicy(..)
38   , nullIPolicy
39   ) where
40
41 import Test.QuickCheck
42
43 import Control.Applicative
44 import qualified Text.JSON as J
45
46 import Test.Ganeti.TestHelper
47 import Test.Ganeti.TestCommon
48 import Test.Ganeti.TestHTools
49
50 import qualified Ganeti.HTools.Types as Types
51
52 -- * Helpers
53
54 -- | All disk templates (used later)
55 allDiskTemplates :: [Types.DiskTemplate]
56 allDiskTemplates = [minBound..maxBound]
57
58 -- * Arbitrary instance
59
60 instance Arbitrary Types.AllocPolicy where
61   arbitrary = elements [minBound..maxBound]
62
63 instance Arbitrary Types.DiskTemplate where
64   arbitrary = elements [minBound..maxBound]
65
66 instance Arbitrary Types.FailMode where
67   arbitrary = elements [minBound..maxBound]
68
69 instance Arbitrary Types.EvacMode where
70   arbitrary = elements [minBound..maxBound]
71
72 instance Arbitrary a => Arbitrary (Types.OpResult a) where
73   arbitrary = arbitrary >>= \c ->
74               if c
75                 then Types.OpGood <$> arbitrary
76                 else Types.OpFail <$> arbitrary
77
78 instance Arbitrary Types.ISpec where
79   arbitrary = do
80     mem_s <- arbitrary::Gen (NonNegative Int)
81     dsk_c <- arbitrary::Gen (NonNegative Int)
82     dsk_s <- arbitrary::Gen (NonNegative Int)
83     cpu_c <- arbitrary::Gen (NonNegative Int)
84     nic_c <- arbitrary::Gen (NonNegative Int)
85     su    <- arbitrary::Gen (NonNegative Int)
86     return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s
87                        , Types.iSpecCpuCount   = fromIntegral cpu_c
88                        , Types.iSpecDiskSize   = fromIntegral dsk_s
89                        , Types.iSpecDiskCount  = fromIntegral dsk_c
90                        , Types.iSpecNicCount   = fromIntegral nic_c
91                        , Types.iSpecSpindleUse = fromIntegral su
92                        }
93
94 -- | Generates an ispec bigger than the given one.
95 genBiggerISpec :: Types.ISpec -> Gen Types.ISpec
96 genBiggerISpec imin = do
97   mem_s <- choose (Types.iSpecMemorySize imin, maxBound)
98   dsk_c <- choose (Types.iSpecDiskCount imin, maxBound)
99   dsk_s <- choose (Types.iSpecDiskSize imin, maxBound)
100   cpu_c <- choose (Types.iSpecCpuCount imin, maxBound)
101   nic_c <- choose (Types.iSpecNicCount imin, maxBound)
102   su    <- choose (Types.iSpecSpindleUse imin, maxBound)
103   return Types.ISpec { Types.iSpecMemorySize = fromIntegral mem_s
104                      , Types.iSpecCpuCount   = fromIntegral cpu_c
105                      , Types.iSpecDiskSize   = fromIntegral dsk_s
106                      , Types.iSpecDiskCount  = fromIntegral dsk_c
107                      , Types.iSpecNicCount   = fromIntegral nic_c
108                      , Types.iSpecSpindleUse = fromIntegral su
109                      }
110
111 instance Arbitrary Types.IPolicy where
112   arbitrary = do
113     imin <- arbitrary
114     istd <- genBiggerISpec imin
115     imax <- genBiggerISpec istd
116     num_tmpl <- choose (0, length allDiskTemplates)
117     dts  <- genUniquesList num_tmpl
118     vcpu_ratio <- choose (1.0, maxVcpuRatio)
119     spindle_ratio <- choose (1.0, maxSpindleRatio)
120     return Types.IPolicy { Types.iPolicyMinSpec = imin
121                          , Types.iPolicyStdSpec = istd
122                          , Types.iPolicyMaxSpec = imax
123                          , Types.iPolicyDiskTemplates = dts
124                          , Types.iPolicyVcpuRatio = vcpu_ratio
125                          , Types.iPolicySpindleRatio = spindle_ratio
126                          }
127
128 -- * Test cases
129
130 prop_Types_AllocPolicy_serialisation :: Types.AllocPolicy -> Property
131 prop_Types_AllocPolicy_serialisation apol =
132   case J.readJSON (J.showJSON apol) of
133     J.Ok p -> p ==? apol
134     J.Error s -> failTest $ "Failed to deserialise: " ++ s
135
136 prop_Types_DiskTemplate_serialisation :: Types.DiskTemplate -> Property
137 prop_Types_DiskTemplate_serialisation dt =
138   case J.readJSON (J.showJSON dt) of
139     J.Ok p -> p ==? dt
140     J.Error s -> failTest $ "Failed to deserialise: " ++ s
141
142 prop_Types_ISpec_serialisation :: Types.ISpec -> Property
143 prop_Types_ISpec_serialisation ispec =
144   case J.readJSON (J.showJSON ispec) of
145     J.Ok p -> p ==? ispec
146     J.Error s -> failTest $ "Failed to deserialise: " ++ s
147
148 prop_Types_IPolicy_serialisation :: Types.IPolicy -> Property
149 prop_Types_IPolicy_serialisation ipol =
150   case J.readJSON (J.showJSON ipol) of
151     J.Ok p -> p ==? ipol
152     J.Error s -> failTest $ "Failed to deserialise: " ++ s
153
154 prop_Types_EvacMode_serialisation :: Types.EvacMode -> Property
155 prop_Types_EvacMode_serialisation em =
156   case J.readJSON (J.showJSON em) of
157     J.Ok p -> p ==? em
158     J.Error s -> failTest $ "Failed to deserialise: " ++ s
159
160 prop_Types_opToResult :: Types.OpResult Int -> Bool
161 prop_Types_opToResult op =
162   case op of
163     Types.OpFail _ -> Types.isBad r
164     Types.OpGood v -> case r of
165                         Types.Bad _ -> False
166                         Types.Ok v' -> v == v'
167   where r = Types.opToResult op
168
169 prop_Types_eitherToResult :: Either String Int -> Bool
170 prop_Types_eitherToResult ei =
171   case ei of
172     Left _ -> Types.isBad r
173     Right v -> case r of
174                  Types.Bad _ -> False
175                  Types.Ok v' -> v == v'
176     where r = Types.eitherToResult ei
177
178 testSuite "Types"
179             [ 'prop_Types_AllocPolicy_serialisation
180             , 'prop_Types_DiskTemplate_serialisation
181             , 'prop_Types_ISpec_serialisation
182             , 'prop_Types_IPolicy_serialisation
183             , 'prop_Types_EvacMode_serialisation
184             , 'prop_Types_opToResult
185             , 'prop_Types_eitherToResult
186             ]