Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / HTools / Instance.hs @ fcfc0c2d

History | View | Annotate | Download (7.6 kB)

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, 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.Instance
30
  ( testHTools_Instance
31
  , genInstanceSmallerThanNode
32
  , genInstanceMaybeBiggerThanNode
33
  , genInstanceOnNodeList
34
  , genInstanceList
35
  , Instance.Instance(..)
36
  ) where
37

    
38
import Control.Monad (liftM)
39
import Test.QuickCheck hiding (Result)
40

    
41
import Test.Ganeti.TestHelper
42
import Test.Ganeti.TestCommon
43
import Test.Ganeti.HTools.Types ()
44

    
45
import Ganeti.BasicTypes
46
import qualified Ganeti.HTools.Instance as Instance
47
import qualified Ganeti.HTools.Node as Node
48
import qualified Ganeti.HTools.Container as Container
49
import qualified Ganeti.HTools.Loader as Loader
50
import qualified Ganeti.HTools.Types as Types
51

    
52
-- * Arbitrary instances
53

    
54
-- | Generates a random instance with maximum disk/mem/cpu values.
55
genInstanceSmallerThan :: Int -> Int -> Int -> Maybe Int ->
56
                          Gen Instance.Instance
57
genInstanceSmallerThan lim_mem lim_dsk lim_cpu lim_spin = do
58
  name <- genFQDN
59
  mem <- choose (0, lim_mem)
60
  dsk <- choose (0, lim_dsk)
61
  run_st <- arbitrary
62
  pn <- arbitrary
63
  sn <- arbitrary
64
  vcpus <- choose (0, lim_cpu)
65
  dt <- arbitrary
66
  spindles <- case lim_spin of
67
    Nothing -> genMaybe $ choose (0, maxSpindles)
68
    Just ls -> liftM Just $ choose (0, ls)
69
  let disk = Instance.Disk dsk spindles
70
  return $ Instance.create
71
    name mem dsk [disk] vcpus run_st [] True pn sn dt 1 []
72

    
73
-- | Generates an instance smaller than a node.
74
genInstanceSmallerThanNode :: Node.Node -> Gen Instance.Instance
75
genInstanceSmallerThanNode node =
76
  genInstanceSmallerThan (Node.availMem node `div` 2)
77
                         (Node.availDisk node `div` 2)
78
                         (Node.availCpu node `div` 2)
79
                         (if Node.exclStorage node
80
                          then Just $ Node.fSpindles node `div` 2
81
                          else Nothing)
82

    
83
-- | Generates an instance possibly bigger than a node.
84
genInstanceMaybeBiggerThanNode :: Node.Node -> Gen Instance.Instance
85
genInstanceMaybeBiggerThanNode node =
86
  genInstanceSmallerThan (Node.availMem  node + Types.unitMem * 2)
87
                         (Node.availDisk node + Types.unitDsk * 3)
88
                         (Node.availCpu  node + Types.unitCpu * 4)
89
                         (if Node.exclStorage node
90
                          then Just $ Node.fSpindles node +
91
                               Types.unitSpindle * 5
92
                          else Nothing)
93

    
94
-- | Generates an instance with nodes on a node list.
95
-- The following rules are respected:
96
-- 1. The instance is never bigger than its primary node
97
-- 2. If possible the instance has different pnode and snode
98
-- 3. Else disk templates which require secondary nodes are disabled
99
genInstanceOnNodeList :: Node.List -> Gen Instance.Instance
100
genInstanceOnNodeList nl = do
101
  let nsize = Container.size nl
102
  pnode <- choose (0, nsize-1)
103
  let (snodefilter, dtfilter) =
104
        if nsize >= 2
105
          then ((/= pnode), const True)
106
          else (const True, not . Instance.hasSecondary)
107
  snode <- choose (0, nsize-1) `suchThat` snodefilter
108
  i <- genInstanceSmallerThanNode (Container.find pnode nl) `suchThat` dtfilter
109
  return $ i { Instance.pNode = pnode, Instance.sNode = snode }
110

    
111
-- | Generates an instance list given an instance generator.
112
genInstanceList :: Gen Instance.Instance -> Gen Instance.List
113
genInstanceList igen = fmap (snd . Loader.assignIndices) names_instances
114
    where names_instances =
115
            (fmap . map) (\n -> (Instance.name n, n)) $ listOf igen
116

    
117
-- let's generate a random instance
118
instance Arbitrary Instance.Instance where
119
  arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu Nothing
120

    
121
-- * Test cases
122

    
123
-- Simple instance tests, we only have setter/getters
124

    
125
prop_creat :: Instance.Instance -> Property
126
prop_creat inst =
127
  Instance.name inst ==? Instance.alias inst
128

    
129
prop_setIdx :: Instance.Instance -> Types.Idx -> Property
130
prop_setIdx inst idx =
131
  Instance.idx (Instance.setIdx inst idx) ==? idx
132

    
133
prop_setName :: Instance.Instance -> String -> Bool
134
prop_setName inst name =
135
  Instance.name newinst == name &&
136
  Instance.alias newinst == name
137
    where newinst = Instance.setName inst name
138

    
139
prop_setAlias :: Instance.Instance -> String -> Bool
140
prop_setAlias inst name =
141
  Instance.name newinst == Instance.name inst &&
142
  Instance.alias newinst == name
143
    where newinst = Instance.setAlias inst name
144

    
145
prop_setPri :: Instance.Instance -> Types.Ndx -> Property
146
prop_setPri inst pdx =
147
  Instance.pNode (Instance.setPri inst pdx) ==? pdx
148

    
149
prop_setSec :: Instance.Instance -> Types.Ndx -> Property
150
prop_setSec inst sdx =
151
  Instance.sNode (Instance.setSec inst sdx) ==? sdx
152

    
153
prop_setBoth :: Instance.Instance -> Types.Ndx -> Types.Ndx -> Bool
154
prop_setBoth inst pdx sdx =
155
  Instance.pNode si == pdx && Instance.sNode si == sdx
156
    where si = Instance.setBoth inst pdx sdx
157

    
158
prop_shrinkMG :: Instance.Instance -> Property
159
prop_shrinkMG inst =
160
  Instance.mem inst >= 2 * Types.unitMem ==>
161
    case Instance.shrinkByType inst Types.FailMem of
162
      Ok inst' -> Instance.mem inst' ==? Instance.mem inst - Types.unitMem
163
      Bad msg -> failTest msg
164

    
165
prop_shrinkMF :: Instance.Instance -> Property
166
prop_shrinkMF inst =
167
  forAll (choose (0, 2 * Types.unitMem - 1)) $ \mem ->
168
    let inst' = inst { Instance.mem = mem}
169
    in isBad $ Instance.shrinkByType inst' Types.FailMem
170

    
171
prop_shrinkCG :: Instance.Instance -> Property
172
prop_shrinkCG inst =
173
  Instance.vcpus inst >= 2 * Types.unitCpu ==>
174
    case Instance.shrinkByType inst Types.FailCPU of
175
      Ok inst' -> Instance.vcpus inst' ==? Instance.vcpus inst - Types.unitCpu
176
      Bad msg -> failTest msg
177

    
178
prop_shrinkCF :: Instance.Instance -> Property
179
prop_shrinkCF inst =
180
  forAll (choose (0, 2 * Types.unitCpu - 1)) $ \vcpus ->
181
    let inst' = inst { Instance.vcpus = vcpus }
182
    in isBad $ Instance.shrinkByType inst' Types.FailCPU
183

    
184
prop_shrinkDG :: Instance.Instance -> Property
185
prop_shrinkDG inst =
186
  Instance.dsk inst >= 2 * Types.unitDsk ==>
187
    case Instance.shrinkByType inst Types.FailDisk of
188
      Ok inst' -> Instance.dsk inst' ==? Instance.dsk inst - Types.unitDsk
189
      Bad msg -> failTest msg
190

    
191
prop_shrinkDF :: Instance.Instance -> Property
192
prop_shrinkDF inst =
193
  forAll (choose (0, 2 * Types.unitDsk - 1)) $ \dsk ->
194
    let inst' = inst { Instance.dsk = dsk }
195
    in isBad $ Instance.shrinkByType inst' Types.FailDisk
196

    
197
prop_setMovable :: Instance.Instance -> Bool -> Property
198
prop_setMovable inst m =
199
  Instance.movable inst' ==? m
200
    where inst' = Instance.setMovable inst m
201

    
202
testSuite "HTools/Instance"
203
            [ 'prop_creat
204
            , 'prop_setIdx
205
            , 'prop_setName
206
            , 'prop_setAlias
207
            , 'prop_setPri
208
            , 'prop_setSec
209
            , 'prop_setBoth
210
            , 'prop_shrinkMG
211
            , 'prop_shrinkMF
212
            , 'prop_shrinkCG
213
            , 'prop_shrinkCF
214
            , 'prop_shrinkDG
215
            , 'prop_shrinkDF
216
            , 'prop_setMovable
217
            ]