Statistics
| Branch: | Tag: | Revision:

root / htest / Test / Ganeti / Objects.hs @ 5006418e

History | View | Annotate | Download (7.5 kB)

1
{-# LANGUAGE TemplateHaskell, TypeSynonymInstances, FlexibleInstances #-}
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.Objects
30
  ( testObjects
31
  , Node(..)
32
  , genEmptyCluster
33
  ) where
34

    
35
import Test.QuickCheck
36

    
37
import Control.Applicative
38
import qualified Data.Map as Map
39
import qualified Data.Set as Set
40

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

    
45
import qualified Ganeti.Constants as C
46
import Ganeti.Objects as Objects
47
import Ganeti.JSON
48

    
49
{-# ANN module "HLint: ignore Use camelCase" #-}
50

    
51
-- * Arbitrary instances
52

    
53
$(genArbitrary ''PartialNDParams)
54

    
55
instance Arbitrary Node where
56
  arbitrary = Node <$> genFQDN <*> genFQDN <*> genFQDN
57
              <*> arbitrary <*> arbitrary <*> arbitrary <*> genFQDN
58
              <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
59
              <*> arbitrary <*> arbitrary <*> genFQDN <*> arbitrary
60
              <*> (Set.fromList <$> genTags)
61

    
62
$(genArbitrary ''BlockDriver)
63

    
64
$(genArbitrary ''DiskMode)
65

    
66
instance Arbitrary DiskLogicalId where
67
  arbitrary = oneof [ LIDPlain <$> arbitrary <*> arbitrary
68
                    , LIDDrbd8 <$> genFQDN <*> genFQDN <*> arbitrary
69
                               <*> arbitrary <*> arbitrary <*> arbitrary
70
                    , LIDFile  <$> arbitrary <*> arbitrary
71
                    , LIDBlockDev <$> arbitrary <*> arbitrary
72
                    , LIDRados <$> arbitrary <*> arbitrary
73
                    ]
74

    
75
-- | 'Disk' 'arbitrary' instance. Since we don't test disk hierarchy
76
-- properties, we only generate disks with no children (FIXME), as
77
-- generating recursive datastructures is a bit more work.
78
instance Arbitrary Disk where
79
  arbitrary = Disk <$> arbitrary <*> pure [] <*> arbitrary
80
                   <*> arbitrary <*> arbitrary
81

    
82
-- FIXME: we should generate proper values, >=0, etc., but this is
83
-- hard for partial ones, where all must be wrapped in a 'Maybe'
84
$(genArbitrary ''PartialBeParams)
85

    
86
$(genArbitrary ''AdminState)
87

    
88
$(genArbitrary ''PartialNicParams)
89

    
90
$(genArbitrary ''PartialNic)
91

    
92
instance Arbitrary Instance where
93
  arbitrary =
94
    Instance
95
      <$> genFQDN <*> genFQDN <*> genFQDN -- OS name, but...
96
      <*> arbitrary
97
      -- FIXME: add non-empty hvparams when they're a proper type
98
      <*> pure (GenericContainer Map.empty) <*> arbitrary
99
      -- ... and for OSParams
100
      <*> pure (GenericContainer Map.empty) <*> arbitrary <*> arbitrary
101
      <*> arbitrary <*> arbitrary <*> arbitrary
102
      -- ts
103
      <*> arbitrary <*> arbitrary
104
      -- uuid
105
      <*> arbitrary
106
      -- serial
107
      <*> arbitrary
108
      -- tags
109
      <*> (Set.fromList <$> genTags)
110

    
111
-- | FIXME: This generates completely random data, without normal
112
-- validation rules.
113
$(genArbitrary ''PartialISpecParams)
114

    
115
-- | FIXME: This generates completely random data, without normal
116
-- validation rules.
117
$(genArbitrary ''PartialIPolicy)
118

    
119
-- | FIXME: This generates completely random data, without normal
120
-- validation rules.
121
instance Arbitrary NodeGroup where
122
  arbitrary = NodeGroup <$> genFQDN <*> pure [] <*> arbitrary <*> arbitrary
123
                        <*> arbitrary <*> pure (GenericContainer Map.empty)
124
                        -- ts
125
                        <*> arbitrary <*> arbitrary
126
                        -- uuid
127
                        <*> arbitrary
128
                        -- serial
129
                        <*> arbitrary
130
                        -- tags
131
                        <*> (Set.fromList <$> genTags)
132

    
133
$(genArbitrary ''FilledISpecParams)
134
$(genArbitrary ''FilledIPolicy)
135
$(genArbitrary ''IpFamily)
136
$(genArbitrary ''FilledNDParams)
137
$(genArbitrary ''FilledNicParams)
138
$(genArbitrary ''FilledBeParams)
139

    
140
-- | No real arbitrary instance for 'ClusterHvParams' yet.
141
instance Arbitrary ClusterHvParams where
142
  arbitrary = return $ GenericContainer Map.empty
143

    
144
-- | No real arbitrary instance for 'OsHvParams' yet.
145
instance Arbitrary OsHvParams where
146
  arbitrary = return $ GenericContainer Map.empty
147

    
148
instance Arbitrary ClusterNicParams where
149
  arbitrary = (GenericContainer . Map.singleton C.ppDefault) <$> arbitrary
150

    
151
instance Arbitrary OsParams where
152
  arbitrary = (GenericContainer . Map.fromList) <$> arbitrary
153

    
154
instance Arbitrary ClusterOsParams where
155
  arbitrary = (GenericContainer . Map.fromList) <$> arbitrary
156

    
157
instance Arbitrary ClusterBeParams where
158
  arbitrary = (GenericContainer . Map.fromList) <$> arbitrary
159

    
160
instance Arbitrary TagSet where
161
  arbitrary = Set.fromList <$> genTags
162

    
163
$(genArbitrary ''Cluster)
164

    
165
-- | Generator for config data with an empty cluster (no instances),
166
-- with N defined nodes.
167
genEmptyCluster :: Int -> Gen ConfigData
168
genEmptyCluster ncount = do
169
  nodes <- vector ncount
170
  version <- arbitrary
171
  let guuid = "00"
172
      nodes' = zipWith (\n idx -> n { nodeGroup = guuid,
173
                                      nodeName = nodeName n ++ show idx })
174
               nodes [(1::Int)..]
175
      contnodes = GenericContainer . Map.fromList $
176
                  map (\n -> (nodeName n, n)) nodes'
177
      continsts = GenericContainer Map.empty
178
  grp <- arbitrary
179
  let contgroups = GenericContainer $ Map.singleton guuid grp
180
  serial <- arbitrary
181
  cluster <- resize 8 arbitrary
182
  let c = ConfigData version cluster contnodes contgroups continsts serial
183
  return c
184

    
185
-- * Test properties
186

    
187
-- | Tests that fillDict behaves correctly
188
prop_fillDict :: [(Int, Int)] -> [(Int, Int)] -> Property
189
prop_fillDict defaults custom =
190
  let d_map = Map.fromList defaults
191
      d_keys = map fst defaults
192
      c_map = Map.fromList custom
193
      c_keys = map fst custom
194
  in conjoin [ printTestCase "Empty custom filling"
195
               (fillDict d_map Map.empty [] == d_map)
196
             , printTestCase "Empty defaults filling"
197
               (fillDict Map.empty c_map [] == c_map)
198
             , printTestCase "Delete all keys"
199
               (fillDict d_map c_map (d_keys++c_keys) == Map.empty)
200
             ]
201

    
202
-- | Test that the serialisation of 'DiskLogicalId', which is
203
-- implemented manually, is idempotent. Since we don't have a
204
-- standalone JSON instance for DiskLogicalId (it's a data type that
205
-- expands over two fields in a JSObject), we test this by actially
206
-- testing entire Disk serialisations. So this tests two things at
207
-- once, basically.
208
prop_Disk_serialisation :: Disk -> Property
209
prop_Disk_serialisation = testSerialisation
210

    
211
-- | Check that node serialisation is idempotent.
212
prop_Node_serialisation :: Node -> Property
213
prop_Node_serialisation = testSerialisation
214

    
215
-- | Check that instance serialisation is idempotent.
216
prop_Inst_serialisation :: Instance -> Property
217
prop_Inst_serialisation = testSerialisation
218

    
219
-- | Check config serialisation.
220
prop_Config_serialisation :: Property
221
prop_Config_serialisation =
222
  forAll (choose (0, maxNodes `div` 4) >>= genEmptyCluster) testSerialisation
223

    
224
testSuite "Objects"
225
  [ 'prop_fillDict
226
  , 'prop_Disk_serialisation
227
  , 'prop_Inst_serialisation
228
  , 'prop_Node_serialisation
229
  , 'prop_Config_serialisation
230
  ]