Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / QC.hs @ 79a72ce7

History | View | Annotate | Download (6.3 kB)

1
{-| Unittests for ganeti-htools
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2009 Google Inc.
8

    
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13

    
14
This program is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
General Public License for more details.
18

    
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Ganeti.HTools.QC
27
    ( test_PeerMap
28
    , test_Container
29
    , test_Instance
30
    , test_Node
31
    ) where
32

    
33
import Test.QuickCheck
34
import Test.QuickCheck.Batch
35
import Data.Maybe
36
import qualified Ganeti.HTools.CLI as CLI
37
import qualified Ganeti.HTools.Cluster as Cluster
38
import qualified Ganeti.HTools.Container as Container
39
import qualified Ganeti.HTools.IAlloc as IAlloc
40
import qualified Ganeti.HTools.Instance as Instance
41
import qualified Ganeti.HTools.Loader as Loader
42
import qualified Ganeti.HTools.Node as Node
43
import qualified Ganeti.HTools.PeerMap as PeerMap
44
import qualified Ganeti.HTools.Rapi as Rapi
45
import qualified Ganeti.HTools.Text as Text
46
import qualified Ganeti.HTools.Types as Types
47
import qualified Ganeti.HTools.Utils as Utils
48

    
49
-- | Simple checker for whether OpResult is fail or pass
50
isFailure :: Types.OpResult a -> Bool
51
isFailure (Types.OpFail _) = True
52
isFailure _ = False
53

    
54
-- copied from the introduction to quickcheck
55
instance Arbitrary Char where
56
    arbitrary = choose ('\32', '\128')
57

    
58
-- let's generate a random instance
59
instance Arbitrary Instance.Instance where
60
    arbitrary = do
61
      name <- arbitrary
62
      mem <- choose(0, 100)
63
      dsk <- choose(0, 100)
64
      run_st <- arbitrary
65
      pn <- arbitrary
66
      sn <- arbitrary
67
      vcpus <- arbitrary
68
      return $ Instance.create name mem dsk vcpus run_st pn sn
69

    
70
-- and a random node
71
instance Arbitrary Node.Node where
72
    arbitrary = do
73
      name <- arbitrary
74
      mem_t <- arbitrary
75
      mem_f <- choose (0, mem_t)
76
      mem_n <- choose (0, mem_t - mem_f)
77
      dsk_t <- arbitrary
78
      dsk_f <- choose (0, dsk_t)
79
      cpu_t <- arbitrary
80
      offl <- arbitrary
81
      let n = Node.create name (fromIntegral mem_t) mem_n mem_f
82
              (fromIntegral dsk_t) dsk_f cpu_t offl
83
          n' = Node.buildPeers n Container.empty
84
      return n'
85

    
86
-- | Make sure add is idempotent
87
prop_PeerMap_addIdempotent pmap key elem =
88
    fn puniq == fn (fn puniq)
89
    where _types = (pmap::PeerMap.PeerMap,
90
                    key::PeerMap.Key, elem::PeerMap.Elem)
91
          fn = PeerMap.add key elem
92
          puniq = PeerMap.accumArray const pmap
93

    
94
-- | Make sure remove is idempotent
95
prop_PeerMap_removeIdempotent pmap key =
96
    fn puniq == fn (fn puniq)
97
    where _types = (pmap::PeerMap.PeerMap, key::PeerMap.Key)
98
          fn = PeerMap.remove key
99
          puniq = PeerMap.accumArray const pmap
100

    
101
-- | Make sure a missing item returns 0
102
prop_PeerMap_findMissing pmap key =
103
    PeerMap.find key (PeerMap.remove key puniq) == 0
104
    where _types = (pmap::PeerMap.PeerMap, key::PeerMap.Key)
105
          puniq = PeerMap.accumArray const pmap
106

    
107
-- | Make sure an added item is found
108
prop_PeerMap_addFind pmap key elem =
109
    PeerMap.find key (PeerMap.add key elem puniq) == elem
110
    where _types = (pmap::PeerMap.PeerMap,
111
                    key::PeerMap.Key, elem::PeerMap.Elem)
112
          puniq = PeerMap.accumArray const pmap
113

    
114
-- | Manual check that maxElem returns the maximum indeed, or 0 for null
115
prop_PeerMap_maxElem pmap =
116
    PeerMap.maxElem puniq == if null puniq then 0
117
                             else (maximum . snd . unzip) puniq
118
    where _types = pmap::PeerMap.PeerMap
119
          puniq = PeerMap.accumArray const pmap
120

    
121
test_PeerMap =
122
    [ run prop_PeerMap_addIdempotent
123
    , run prop_PeerMap_removeIdempotent
124
    , run prop_PeerMap_maxElem
125
    , run prop_PeerMap_addFind
126
    , run prop_PeerMap_findMissing
127
    ]
128

    
129
-- Container tests
130

    
131
prop_Container_addTwo cdata i1 i2 =
132
    fn i1 i2 cont == fn i2 i1 cont &&
133
       fn i1 i2 cont == fn i1 i2 (fn i1 i2 cont)
134
    where _types = (cdata::[Int],
135
                    i1::Int, i2::Int)
136
          cont = foldl (\c x -> Container.add x x c) Container.empty cdata
137
          fn x1 x2 = Container.addTwo x1 x1 x2 x2
138

    
139
test_Container =
140
    [ run prop_Container_addTwo ]
141

    
142
-- Simple instance tests, we only have setter/getters
143

    
144
prop_Instance_setIdx inst idx =
145
    Instance.idx (Instance.setIdx inst idx) == idx
146
    where _types = (inst::Instance.Instance, idx::Types.Idx)
147

    
148
prop_Instance_setName inst name =
149
    Instance.name (Instance.setName inst name) == name
150
    where _types = (inst::Instance.Instance, name::String)
151

    
152
prop_Instance_setPri inst pdx =
153
    Instance.pnode (Instance.setPri inst pdx) == pdx
154
    where _types = (inst::Instance.Instance, pdx::Types.Ndx)
155

    
156
prop_Instance_setSec inst sdx =
157
    Instance.snode (Instance.setSec inst sdx) == sdx
158
    where _types = (inst::Instance.Instance, sdx::Types.Ndx)
159

    
160
prop_Instance_setBoth inst pdx sdx =
161
    Instance.pnode si == pdx && Instance.snode si == sdx
162
    where _types = (inst::Instance.Instance, pdx::Types.Ndx, sdx::Types.Ndx)
163
          si = Instance.setBoth inst pdx sdx
164

    
165
test_Instance =
166
    [ run prop_Instance_setIdx
167
    , run prop_Instance_setName
168
    , run prop_Instance_setPri
169
    , run prop_Instance_setSec
170
    , run prop_Instance_setBoth
171
    ]
172

    
173
-- Node tests
174

    
175
-- | Check that an instance add with too high memory or disk will be rejected
176
prop_Node_addPri node inst = (Instance.mem inst >= Node.f_mem node ||
177
                              Instance.dsk inst >= Node.f_dsk node) &&
178
                             not (Node.failN1 node)
179
                             ==>
180
                             isFailure (Node.addPri node inst)
181
    where _types = (node::Node.Node, inst::Instance.Instance)
182

    
183

    
184
-- | Check that an instance add with too high memory or disk will be rejected
185
prop_Node_addSec node inst pdx =
186
    (Instance.mem inst >= (Node.f_mem node - Node.r_mem node) ||
187
     Instance.dsk inst >= Node.f_dsk node) &&
188
    not (Node.failN1 node)
189
    ==> isFailure (Node.addSec node inst pdx)
190
        where _types = (node::Node.Node, inst::Instance.Instance, pdx::Int)
191

    
192
test_Node =
193
    [ run prop_Node_addPri
194
    , run prop_Node_addSec
195
    ]