root / htest / Test / Ganeti / HTools / Node.hs @ 61899e64
History | View | Annotate | Download (12 kB)
1 | e1ee7d5a | Iustin Pop | {-# LANGUAGE TemplateHaskell #-} |
---|---|---|---|
2 | e1ee7d5a | Iustin Pop | {-# OPTIONS_GHC -fno-warn-orphans #-} |
3 | e1ee7d5a | Iustin Pop | |
4 | e1ee7d5a | Iustin Pop | {-| Unittests for ganeti-htools. |
5 | e1ee7d5a | Iustin Pop | |
6 | e1ee7d5a | Iustin Pop | -} |
7 | e1ee7d5a | Iustin Pop | |
8 | e1ee7d5a | Iustin Pop | {- |
9 | e1ee7d5a | Iustin Pop | |
10 | e1ee7d5a | Iustin Pop | Copyright (C) 2009, 2010, 2011, 2012 Google Inc. |
11 | e1ee7d5a | Iustin Pop | |
12 | e1ee7d5a | Iustin Pop | This program is free software; you can redistribute it and/or modify |
13 | e1ee7d5a | Iustin Pop | it under the terms of the GNU General Public License as published by |
14 | e1ee7d5a | Iustin Pop | the Free Software Foundation; either version 2 of the License, or |
15 | e1ee7d5a | Iustin Pop | (at your option) any later version. |
16 | e1ee7d5a | Iustin Pop | |
17 | e1ee7d5a | Iustin Pop | This program is distributed in the hope that it will be useful, but |
18 | e1ee7d5a | Iustin Pop | WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | e1ee7d5a | Iustin Pop | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | e1ee7d5a | Iustin Pop | General Public License for more details. |
21 | e1ee7d5a | Iustin Pop | |
22 | e1ee7d5a | Iustin Pop | You should have received a copy of the GNU General Public License |
23 | e1ee7d5a | Iustin Pop | along with this program; if not, write to the Free Software |
24 | e1ee7d5a | Iustin Pop | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
25 | e1ee7d5a | Iustin Pop | 02110-1301, USA. |
26 | e1ee7d5a | Iustin Pop | |
27 | e1ee7d5a | Iustin Pop | -} |
28 | e1ee7d5a | Iustin Pop | |
29 | e1ee7d5a | Iustin Pop | module Test.Ganeti.HTools.Node |
30 | e09c1fa0 | Iustin Pop | ( testHTools_Node |
31 | e1ee7d5a | Iustin Pop | , Node.Node(..) |
32 | e1ee7d5a | Iustin Pop | , setInstanceSmallerThanNode |
33 | e1ee7d5a | Iustin Pop | , genNode |
34 | e1ee7d5a | Iustin Pop | , genOnlineNode |
35 | e1ee7d5a | Iustin Pop | ) where |
36 | e1ee7d5a | Iustin Pop | |
37 | e1ee7d5a | Iustin Pop | import Test.QuickCheck |
38 | e1ee7d5a | Iustin Pop | |
39 | e1ee7d5a | Iustin Pop | import Control.Monad |
40 | e1ee7d5a | Iustin Pop | import qualified Data.Map as Map |
41 | e1ee7d5a | Iustin Pop | import Data.List |
42 | e1ee7d5a | Iustin Pop | |
43 | e1ee7d5a | Iustin Pop | import Test.Ganeti.TestHelper |
44 | e1ee7d5a | Iustin Pop | import Test.Ganeti.TestCommon |
45 | e1ee7d5a | Iustin Pop | import Test.Ganeti.TestHTools |
46 | e1ee7d5a | Iustin Pop | import Test.Ganeti.HTools.Instance (genInstanceSmallerThanNode) |
47 | e1ee7d5a | Iustin Pop | |
48 | a8038349 | Iustin Pop | import Ganeti.BasicTypes |
49 | e1ee7d5a | Iustin Pop | import qualified Ganeti.HTools.Container as Container |
50 | e1ee7d5a | Iustin Pop | import qualified Ganeti.HTools.Instance as Instance |
51 | e1ee7d5a | Iustin Pop | import qualified Ganeti.HTools.Node as Node |
52 | e1ee7d5a | Iustin Pop | import qualified Ganeti.HTools.Types as Types |
53 | e1ee7d5a | Iustin Pop | |
54 | e1ee7d5a | Iustin Pop | -- * Arbitrary instances |
55 | e1ee7d5a | Iustin Pop | |
56 | dd77da99 | Helga Velroyen | -- | Generates an arbitrary node based on sizing information. |
57 | e1ee7d5a | Iustin Pop | genNode :: Maybe Int -- ^ Minimum node size in terms of units |
58 | e1ee7d5a | Iustin Pop | -> Maybe Int -- ^ Maximum node size (when Nothing, bounded |
59 | e1ee7d5a | Iustin Pop | -- just by the max... constants) |
60 | e1ee7d5a | Iustin Pop | -> Gen Node.Node |
61 | e1ee7d5a | Iustin Pop | genNode min_multiplier max_multiplier = do |
62 | e1ee7d5a | Iustin Pop | let (base_mem, base_dsk, base_cpu) = |
63 | e1ee7d5a | Iustin Pop | case min_multiplier of |
64 | e1ee7d5a | Iustin Pop | Just mm -> (mm * Types.unitMem, |
65 | e1ee7d5a | Iustin Pop | mm * Types.unitDsk, |
66 | e1ee7d5a | Iustin Pop | mm * Types.unitCpu) |
67 | e1ee7d5a | Iustin Pop | Nothing -> (0, 0, 0) |
68 | e1ee7d5a | Iustin Pop | (top_mem, top_dsk, top_cpu) = |
69 | e1ee7d5a | Iustin Pop | case max_multiplier of |
70 | e1ee7d5a | Iustin Pop | Just mm -> (mm * Types.unitMem, |
71 | e1ee7d5a | Iustin Pop | mm * Types.unitDsk, |
72 | e1ee7d5a | Iustin Pop | mm * Types.unitCpu) |
73 | e1ee7d5a | Iustin Pop | Nothing -> (maxMem, maxDsk, maxCpu) |
74 | e1ee7d5a | Iustin Pop | name <- getFQDN |
75 | e1ee7d5a | Iustin Pop | mem_t <- choose (base_mem, top_mem) |
76 | e1ee7d5a | Iustin Pop | mem_f <- choose (base_mem, mem_t) |
77 | e1ee7d5a | Iustin Pop | mem_n <- choose (0, mem_t - mem_f) |
78 | e1ee7d5a | Iustin Pop | dsk_t <- choose (base_dsk, top_dsk) |
79 | e1ee7d5a | Iustin Pop | dsk_f <- choose (base_dsk, dsk_t) |
80 | e1ee7d5a | Iustin Pop | cpu_t <- choose (base_cpu, top_cpu) |
81 | e1ee7d5a | Iustin Pop | offl <- arbitrary |
82 | e1ee7d5a | Iustin Pop | let n = Node.create name (fromIntegral mem_t) mem_n mem_f |
83 | e1ee7d5a | Iustin Pop | (fromIntegral dsk_t) dsk_f (fromIntegral cpu_t) offl 1 0 |
84 | e1ee7d5a | Iustin Pop | n' = Node.setPolicy nullIPolicy n |
85 | e1ee7d5a | Iustin Pop | return $ Node.buildPeers n' Container.empty |
86 | e1ee7d5a | Iustin Pop | |
87 | e1ee7d5a | Iustin Pop | -- | Helper function to generate a sane node. |
88 | e1ee7d5a | Iustin Pop | genOnlineNode :: Gen Node.Node |
89 | 5b11f8db | Iustin Pop | genOnlineNode = |
90 | e1ee7d5a | Iustin Pop | arbitrary `suchThat` (\n -> not (Node.offline n) && |
91 | e1ee7d5a | Iustin Pop | not (Node.failN1 n) && |
92 | e1ee7d5a | Iustin Pop | Node.availDisk n > 0 && |
93 | e1ee7d5a | Iustin Pop | Node.availMem n > 0 && |
94 | e1ee7d5a | Iustin Pop | Node.availCpu n > 0) |
95 | e1ee7d5a | Iustin Pop | |
96 | e1ee7d5a | Iustin Pop | -- and a random node |
97 | e1ee7d5a | Iustin Pop | instance Arbitrary Node.Node where |
98 | e1ee7d5a | Iustin Pop | arbitrary = genNode Nothing Nothing |
99 | e1ee7d5a | Iustin Pop | |
100 | e1ee7d5a | Iustin Pop | -- * Test cases |
101 | e1ee7d5a | Iustin Pop | |
102 | 20bc5360 | Iustin Pop | prop_setAlias :: Node.Node -> String -> Bool |
103 | 20bc5360 | Iustin Pop | prop_setAlias node name = |
104 | e1ee7d5a | Iustin Pop | Node.name newnode == Node.name node && |
105 | e1ee7d5a | Iustin Pop | Node.alias newnode == name |
106 | e1ee7d5a | Iustin Pop | where newnode = Node.setAlias node name |
107 | e1ee7d5a | Iustin Pop | |
108 | 20bc5360 | Iustin Pop | prop_setOffline :: Node.Node -> Bool -> Property |
109 | 20bc5360 | Iustin Pop | prop_setOffline node status = |
110 | e1ee7d5a | Iustin Pop | Node.offline newnode ==? status |
111 | e1ee7d5a | Iustin Pop | where newnode = Node.setOffline node status |
112 | e1ee7d5a | Iustin Pop | |
113 | 20bc5360 | Iustin Pop | prop_setXmem :: Node.Node -> Int -> Property |
114 | 20bc5360 | Iustin Pop | prop_setXmem node xm = |
115 | e1ee7d5a | Iustin Pop | Node.xMem newnode ==? xm |
116 | e1ee7d5a | Iustin Pop | where newnode = Node.setXmem node xm |
117 | e1ee7d5a | Iustin Pop | |
118 | 20bc5360 | Iustin Pop | prop_setMcpu :: Node.Node -> Double -> Property |
119 | 20bc5360 | Iustin Pop | prop_setMcpu node mc = |
120 | e1ee7d5a | Iustin Pop | Types.iPolicyVcpuRatio (Node.iPolicy newnode) ==? mc |
121 | e1ee7d5a | Iustin Pop | where newnode = Node.setMcpu node mc |
122 | e1ee7d5a | Iustin Pop | |
123 | 77ffd663 | Helga Velroyen | prop_setFmemGreater :: Node.Node -> Int -> Property |
124 | 77ffd663 | Helga Velroyen | prop_setFmemGreater node new_mem = |
125 | 77ffd663 | Helga Velroyen | not (Node.failN1 node) && (Node.rMem node >= 0) && |
126 | 77ffd663 | Helga Velroyen | (new_mem > Node.rMem node) ==> |
127 | 77ffd663 | Helga Velroyen | not (Node.failN1 (Node.setFmem node new_mem)) |
128 | 77ffd663 | Helga Velroyen | |
129 | 77ffd663 | Helga Velroyen | prop_setFmemExact :: Node.Node -> Property |
130 | 77ffd663 | Helga Velroyen | prop_setFmemExact node = |
131 | 77ffd663 | Helga Velroyen | not (Node.failN1 node) && (Node.rMem node >= 0) ==> |
132 | 77ffd663 | Helga Velroyen | not (Node.failN1 (Node.setFmem node (Node.rMem node))) |
133 | 77ffd663 | Helga Velroyen | |
134 | 77ffd663 | Helga Velroyen | -- Check if adding an instance that consumes exactly all reserved |
135 | 77ffd663 | Helga Velroyen | -- memory does not raise an N+1 error |
136 | 77ffd663 | Helga Velroyen | prop_addPri_NoN1Fail :: Property |
137 | 77ffd663 | Helga Velroyen | prop_addPri_NoN1Fail = |
138 | 77ffd663 | Helga Velroyen | forAll genOnlineNode $ \node -> |
139 | 77ffd663 | Helga Velroyen | forAll (genInstanceSmallerThanNode node) $ \inst -> |
140 | 77ffd663 | Helga Velroyen | let inst' = inst { Instance.mem = Node.fMem node - Node.rMem node } |
141 | dddb2bc9 | Helga Velroyen | in (Node.addPri node inst' /=? Bad Types.FailN1) |
142 | 77ffd663 | Helga Velroyen | |
143 | e1ee7d5a | Iustin Pop | -- | Check that an instance add with too high memory or disk will be |
144 | e1ee7d5a | Iustin Pop | -- rejected. |
145 | 20bc5360 | Iustin Pop | prop_addPriFM :: Node.Node -> Instance.Instance -> Property |
146 | 20bc5360 | Iustin Pop | prop_addPriFM node inst = |
147 | e1ee7d5a | Iustin Pop | Instance.mem inst >= Node.fMem node && not (Node.failN1 node) && |
148 | e1ee7d5a | Iustin Pop | not (Instance.isOffline inst) ==> |
149 | dd77da99 | Helga Velroyen | (Node.addPri node inst'' ==? Bad Types.FailMem) |
150 | e1ee7d5a | Iustin Pop | where inst' = setInstanceSmallerThanNode node inst |
151 | e1ee7d5a | Iustin Pop | inst'' = inst' { Instance.mem = Instance.mem inst } |
152 | e1ee7d5a | Iustin Pop | |
153 | e1ee7d5a | Iustin Pop | -- | Check that adding a primary instance with too much disk fails |
154 | e1ee7d5a | Iustin Pop | -- with type FailDisk. |
155 | 20bc5360 | Iustin Pop | prop_addPriFD :: Node.Node -> Instance.Instance -> Property |
156 | 20bc5360 | Iustin Pop | prop_addPriFD node inst = |
157 | e1ee7d5a | Iustin Pop | forAll (elements Instance.localStorageTemplates) $ \dt -> |
158 | e1ee7d5a | Iustin Pop | Instance.dsk inst >= Node.fDsk node && not (Node.failN1 node) ==> |
159 | e1ee7d5a | Iustin Pop | let inst' = setInstanceSmallerThanNode node inst |
160 | e1ee7d5a | Iustin Pop | inst'' = inst' { Instance.dsk = Instance.dsk inst |
161 | e1ee7d5a | Iustin Pop | , Instance.diskTemplate = dt } |
162 | dd77da99 | Helga Velroyen | in (Node.addPri node inst'' ==? Bad Types.FailDisk) |
163 | e1ee7d5a | Iustin Pop | |
164 | e1ee7d5a | Iustin Pop | -- | Check that adding a primary instance with too many VCPUs fails |
165 | e1ee7d5a | Iustin Pop | -- with type FailCPU. |
166 | 20bc5360 | Iustin Pop | prop_addPriFC :: Property |
167 | 20bc5360 | Iustin Pop | prop_addPriFC = |
168 | e1ee7d5a | Iustin Pop | forAll (choose (1, maxCpu)) $ \extra -> |
169 | e1ee7d5a | Iustin Pop | forAll genOnlineNode $ \node -> |
170 | e1ee7d5a | Iustin Pop | forAll (arbitrary `suchThat` Instance.notOffline) $ \inst -> |
171 | e1ee7d5a | Iustin Pop | let inst' = setInstanceSmallerThanNode node inst |
172 | e1ee7d5a | Iustin Pop | inst'' = inst' { Instance.vcpus = Node.availCpu node + extra } |
173 | e1ee7d5a | Iustin Pop | in case Node.addPri node inst'' of |
174 | a8038349 | Iustin Pop | Bad Types.FailCPU -> passTest |
175 | e1ee7d5a | Iustin Pop | v -> failTest $ "Expected OpFail FailCPU, but got " ++ show v |
176 | e1ee7d5a | Iustin Pop | |
177 | e1ee7d5a | Iustin Pop | -- | Check that an instance add with too high memory or disk will be |
178 | e1ee7d5a | Iustin Pop | -- rejected. |
179 | 20bc5360 | Iustin Pop | prop_addSec :: Node.Node -> Instance.Instance -> Int -> Property |
180 | 20bc5360 | Iustin Pop | prop_addSec node inst pdx = |
181 | e1ee7d5a | Iustin Pop | ((Instance.mem inst >= (Node.fMem node - Node.rMem node) && |
182 | e1ee7d5a | Iustin Pop | not (Instance.isOffline inst)) || |
183 | e1ee7d5a | Iustin Pop | Instance.dsk inst >= Node.fDsk node) && |
184 | e1ee7d5a | Iustin Pop | not (Node.failN1 node) ==> |
185 | a8038349 | Iustin Pop | isBad (Node.addSec node inst pdx) |
186 | e1ee7d5a | Iustin Pop | |
187 | e1ee7d5a | Iustin Pop | -- | Check that an offline instance with reasonable disk size but |
188 | e1ee7d5a | Iustin Pop | -- extra mem/cpu can always be added. |
189 | 20bc5360 | Iustin Pop | prop_addOfflinePri :: NonNegative Int -> NonNegative Int -> Property |
190 | 20bc5360 | Iustin Pop | prop_addOfflinePri (NonNegative extra_mem) (NonNegative extra_cpu) = |
191 | e1ee7d5a | Iustin Pop | forAll genOnlineNode $ \node -> |
192 | e1ee7d5a | Iustin Pop | forAll (genInstanceSmallerThanNode node) $ \inst -> |
193 | e1ee7d5a | Iustin Pop | let inst' = inst { Instance.runSt = Types.AdminOffline |
194 | e1ee7d5a | Iustin Pop | , Instance.mem = Node.availMem node + extra_mem |
195 | e1ee7d5a | Iustin Pop | , Instance.vcpus = Node.availCpu node + extra_cpu } |
196 | e1ee7d5a | Iustin Pop | in case Node.addPri node inst' of |
197 | a8038349 | Iustin Pop | Ok _ -> passTest |
198 | e1ee7d5a | Iustin Pop | v -> failTest $ "Expected OpGood, but got: " ++ show v |
199 | e1ee7d5a | Iustin Pop | |
200 | e1ee7d5a | Iustin Pop | -- | Check that an offline instance with reasonable disk size but |
201 | e1ee7d5a | Iustin Pop | -- extra mem/cpu can always be added. |
202 | 20bc5360 | Iustin Pop | prop_addOfflineSec :: NonNegative Int -> NonNegative Int |
203 | 20bc5360 | Iustin Pop | -> Types.Ndx -> Property |
204 | 20bc5360 | Iustin Pop | prop_addOfflineSec (NonNegative extra_mem) (NonNegative extra_cpu) pdx = |
205 | e1ee7d5a | Iustin Pop | forAll genOnlineNode $ \node -> |
206 | e1ee7d5a | Iustin Pop | forAll (genInstanceSmallerThanNode node) $ \inst -> |
207 | e1ee7d5a | Iustin Pop | let inst' = inst { Instance.runSt = Types.AdminOffline |
208 | e1ee7d5a | Iustin Pop | , Instance.mem = Node.availMem node + extra_mem |
209 | e1ee7d5a | Iustin Pop | , Instance.vcpus = Node.availCpu node + extra_cpu |
210 | e1ee7d5a | Iustin Pop | , Instance.diskTemplate = Types.DTDrbd8 } |
211 | e1ee7d5a | Iustin Pop | in case Node.addSec node inst' pdx of |
212 | a8038349 | Iustin Pop | Ok _ -> passTest |
213 | e1ee7d5a | Iustin Pop | v -> failTest $ "Expected OpGood/OpGood, but got: " ++ show v |
214 | e1ee7d5a | Iustin Pop | |
215 | e1ee7d5a | Iustin Pop | -- | Checks for memory reservation changes. |
216 | 20bc5360 | Iustin Pop | prop_rMem :: Instance.Instance -> Property |
217 | 20bc5360 | Iustin Pop | prop_rMem inst = |
218 | e1ee7d5a | Iustin Pop | not (Instance.isOffline inst) ==> |
219 | e1ee7d5a | Iustin Pop | forAll (genOnlineNode `suchThat` ((> Types.unitMem) . Node.fMem)) $ \node -> |
220 | e1ee7d5a | Iustin Pop | -- ab = auto_balance, nb = non-auto_balance |
221 | e1ee7d5a | Iustin Pop | -- we use -1 as the primary node of the instance |
222 | e1ee7d5a | Iustin Pop | let inst' = inst { Instance.pNode = -1, Instance.autoBalance = True |
223 | e1ee7d5a | Iustin Pop | , Instance.diskTemplate = Types.DTDrbd8 } |
224 | e1ee7d5a | Iustin Pop | inst_ab = setInstanceSmallerThanNode node inst' |
225 | e1ee7d5a | Iustin Pop | inst_nb = inst_ab { Instance.autoBalance = False } |
226 | e1ee7d5a | Iustin Pop | -- now we have the two instances, identical except the |
227 | e1ee7d5a | Iustin Pop | -- autoBalance attribute |
228 | e1ee7d5a | Iustin Pop | orig_rmem = Node.rMem node |
229 | e1ee7d5a | Iustin Pop | inst_idx = Instance.idx inst_ab |
230 | e1ee7d5a | Iustin Pop | node_add_ab = Node.addSec node inst_ab (-1) |
231 | e1ee7d5a | Iustin Pop | node_add_nb = Node.addSec node inst_nb (-1) |
232 | e1ee7d5a | Iustin Pop | node_del_ab = liftM (`Node.removeSec` inst_ab) node_add_ab |
233 | e1ee7d5a | Iustin Pop | node_del_nb = liftM (`Node.removeSec` inst_nb) node_add_nb |
234 | e1ee7d5a | Iustin Pop | in case (node_add_ab, node_add_nb, node_del_ab, node_del_nb) of |
235 | a8038349 | Iustin Pop | (Ok a_ab, Ok a_nb, |
236 | a8038349 | Iustin Pop | Ok d_ab, Ok d_nb) -> |
237 | e1ee7d5a | Iustin Pop | printTestCase "Consistency checks failed" $ |
238 | e1ee7d5a | Iustin Pop | Node.rMem a_ab > orig_rmem && |
239 | e1ee7d5a | Iustin Pop | Node.rMem a_ab - orig_rmem == Instance.mem inst_ab && |
240 | e1ee7d5a | Iustin Pop | Node.rMem a_nb == orig_rmem && |
241 | e1ee7d5a | Iustin Pop | Node.rMem d_ab == orig_rmem && |
242 | e1ee7d5a | Iustin Pop | Node.rMem d_nb == orig_rmem && |
243 | e1ee7d5a | Iustin Pop | -- this is not related to rMem, but as good a place to |
244 | e1ee7d5a | Iustin Pop | -- test as any |
245 | e1ee7d5a | Iustin Pop | inst_idx `elem` Node.sList a_ab && |
246 | e1ee7d5a | Iustin Pop | inst_idx `notElem` Node.sList d_ab |
247 | e1ee7d5a | Iustin Pop | x -> failTest $ "Failed to add/remove instances: " ++ show x |
248 | e1ee7d5a | Iustin Pop | |
249 | e1ee7d5a | Iustin Pop | -- | Check mdsk setting. |
250 | 20bc5360 | Iustin Pop | prop_setMdsk :: Node.Node -> SmallRatio -> Bool |
251 | 20bc5360 | Iustin Pop | prop_setMdsk node mx = |
252 | e1ee7d5a | Iustin Pop | Node.loDsk node' >= 0 && |
253 | e1ee7d5a | Iustin Pop | fromIntegral (Node.loDsk node') <= Node.tDsk node && |
254 | e1ee7d5a | Iustin Pop | Node.availDisk node' >= 0 && |
255 | e1ee7d5a | Iustin Pop | Node.availDisk node' <= Node.fDsk node' && |
256 | e1ee7d5a | Iustin Pop | fromIntegral (Node.availDisk node') <= Node.tDsk node' && |
257 | e1ee7d5a | Iustin Pop | Node.mDsk node' == mx' |
258 | e1ee7d5a | Iustin Pop | where node' = Node.setMdsk node mx' |
259 | e1ee7d5a | Iustin Pop | SmallRatio mx' = mx |
260 | e1ee7d5a | Iustin Pop | |
261 | e1ee7d5a | Iustin Pop | -- Check tag maps |
262 | 20bc5360 | Iustin Pop | prop_tagMaps_idempotent :: Property |
263 | 20bc5360 | Iustin Pop | prop_tagMaps_idempotent = |
264 | e1ee7d5a | Iustin Pop | forAll genTags $ \tags -> |
265 | e1ee7d5a | Iustin Pop | Node.delTags (Node.addTags m tags) tags ==? m |
266 | e1ee7d5a | Iustin Pop | where m = Map.empty |
267 | e1ee7d5a | Iustin Pop | |
268 | 20bc5360 | Iustin Pop | prop_tagMaps_reject :: Property |
269 | 20bc5360 | Iustin Pop | prop_tagMaps_reject = |
270 | e1ee7d5a | Iustin Pop | forAll (genTags `suchThat` (not . null)) $ \tags -> |
271 | e1ee7d5a | Iustin Pop | let m = Node.addTags Map.empty tags |
272 | e1ee7d5a | Iustin Pop | in all (\t -> Node.rejectAddTags m [t]) tags |
273 | e1ee7d5a | Iustin Pop | |
274 | 20bc5360 | Iustin Pop | prop_showField :: Node.Node -> Property |
275 | 20bc5360 | Iustin Pop | prop_showField node = |
276 | e1ee7d5a | Iustin Pop | forAll (elements Node.defaultFields) $ \ field -> |
277 | e1ee7d5a | Iustin Pop | fst (Node.showHeader field) /= Types.unknownField && |
278 | e1ee7d5a | Iustin Pop | Node.showField node field /= Types.unknownField |
279 | e1ee7d5a | Iustin Pop | |
280 | 20bc5360 | Iustin Pop | prop_computeGroups :: [Node.Node] -> Bool |
281 | 20bc5360 | Iustin Pop | prop_computeGroups nodes = |
282 | e1ee7d5a | Iustin Pop | let ng = Node.computeGroups nodes |
283 | e1ee7d5a | Iustin Pop | onlyuuid = map fst ng |
284 | e1ee7d5a | Iustin Pop | in length nodes == sum (map (length . snd) ng) && |
285 | e1ee7d5a | Iustin Pop | all (\(guuid, ns) -> all ((== guuid) . Node.group) ns) ng && |
286 | e1ee7d5a | Iustin Pop | length (nub onlyuuid) == length onlyuuid && |
287 | e1ee7d5a | Iustin Pop | (null nodes || not (null ng)) |
288 | e1ee7d5a | Iustin Pop | |
289 | e1ee7d5a | Iustin Pop | -- Check idempotence of add/remove operations |
290 | 20bc5360 | Iustin Pop | prop_addPri_idempotent :: Property |
291 | 20bc5360 | Iustin Pop | prop_addPri_idempotent = |
292 | e1ee7d5a | Iustin Pop | forAll genOnlineNode $ \node -> |
293 | e1ee7d5a | Iustin Pop | forAll (genInstanceSmallerThanNode node) $ \inst -> |
294 | e1ee7d5a | Iustin Pop | case Node.addPri node inst of |
295 | a8038349 | Iustin Pop | Ok node' -> Node.removePri node' inst ==? node |
296 | e1ee7d5a | Iustin Pop | _ -> failTest "Can't add instance" |
297 | e1ee7d5a | Iustin Pop | |
298 | 20bc5360 | Iustin Pop | prop_addSec_idempotent :: Property |
299 | 20bc5360 | Iustin Pop | prop_addSec_idempotent = |
300 | e1ee7d5a | Iustin Pop | forAll genOnlineNode $ \node -> |
301 | e1ee7d5a | Iustin Pop | forAll (genInstanceSmallerThanNode node) $ \inst -> |
302 | e1ee7d5a | Iustin Pop | let pdx = Node.idx node + 1 |
303 | e1ee7d5a | Iustin Pop | inst' = Instance.setPri inst pdx |
304 | e1ee7d5a | Iustin Pop | inst'' = inst' { Instance.diskTemplate = Types.DTDrbd8 } |
305 | e1ee7d5a | Iustin Pop | in case Node.addSec node inst'' pdx of |
306 | a8038349 | Iustin Pop | Ok node' -> Node.removeSec node' inst'' ==? node |
307 | e1ee7d5a | Iustin Pop | _ -> failTest "Can't add instance" |
308 | e1ee7d5a | Iustin Pop | |
309 | e09c1fa0 | Iustin Pop | testSuite "HTools/Node" |
310 | 20bc5360 | Iustin Pop | [ 'prop_setAlias |
311 | 20bc5360 | Iustin Pop | , 'prop_setOffline |
312 | 20bc5360 | Iustin Pop | , 'prop_setMcpu |
313 | 77ffd663 | Helga Velroyen | , 'prop_setFmemGreater |
314 | 77ffd663 | Helga Velroyen | , 'prop_setFmemExact |
315 | 20bc5360 | Iustin Pop | , 'prop_setXmem |
316 | 20bc5360 | Iustin Pop | , 'prop_addPriFM |
317 | 20bc5360 | Iustin Pop | , 'prop_addPriFD |
318 | 20bc5360 | Iustin Pop | , 'prop_addPriFC |
319 | 77ffd663 | Helga Velroyen | , 'prop_addPri_NoN1Fail |
320 | 20bc5360 | Iustin Pop | , 'prop_addSec |
321 | 20bc5360 | Iustin Pop | , 'prop_addOfflinePri |
322 | 20bc5360 | Iustin Pop | , 'prop_addOfflineSec |
323 | 20bc5360 | Iustin Pop | , 'prop_rMem |
324 | 20bc5360 | Iustin Pop | , 'prop_setMdsk |
325 | 20bc5360 | Iustin Pop | , 'prop_tagMaps_idempotent |
326 | 20bc5360 | Iustin Pop | , 'prop_tagMaps_reject |
327 | 20bc5360 | Iustin Pop | , 'prop_showField |
328 | 20bc5360 | Iustin Pop | , 'prop_computeGroups |
329 | 20bc5360 | Iustin Pop | , 'prop_addPri_idempotent |
330 | 20bc5360 | Iustin Pop | , 'prop_addSec_idempotent |
331 | e1ee7d5a | Iustin Pop | ] |