Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / OpCodes.hs @ 5ce621ab

History | View | Annotate | Download (25.7 kB)

1 aed2325f Iustin Pop
{-# LANGUAGE TemplateHaskell #-}
2 aed2325f Iustin Pop
{-# OPTIONS_GHC -fno-warn-orphans #-}
3 aed2325f Iustin Pop
4 aed2325f Iustin Pop
{-| Unittests for ganeti-htools.
5 aed2325f Iustin Pop
6 aed2325f Iustin Pop
-}
7 aed2325f Iustin Pop
8 aed2325f Iustin Pop
{-
9 aed2325f Iustin Pop
10 72747d91 Iustin Pop
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
11 aed2325f Iustin Pop
12 aed2325f Iustin Pop
This program is free software; you can redistribute it and/or modify
13 aed2325f Iustin Pop
it under the terms of the GNU General Public License as published by
14 aed2325f Iustin Pop
the Free Software Foundation; either version 2 of the License, or
15 aed2325f Iustin Pop
(at your option) any later version.
16 aed2325f Iustin Pop
17 aed2325f Iustin Pop
This program is distributed in the hope that it will be useful, but
18 aed2325f Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
19 aed2325f Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 aed2325f Iustin Pop
General Public License for more details.
21 aed2325f Iustin Pop
22 aed2325f Iustin Pop
You should have received a copy of the GNU General Public License
23 aed2325f Iustin Pop
along with this program; if not, write to the Free Software
24 aed2325f Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 aed2325f Iustin Pop
02110-1301, USA.
26 aed2325f Iustin Pop
27 aed2325f Iustin Pop
-}
28 aed2325f Iustin Pop
29 aed2325f Iustin Pop
module Test.Ganeti.OpCodes
30 aed2325f Iustin Pop
  ( testOpCodes
31 aed2325f Iustin Pop
  , OpCodes.OpCode(..)
32 aed2325f Iustin Pop
  ) where
33 aed2325f Iustin Pop
34 f56013fd Iustin Pop
import Test.HUnit as HUnit
35 f56013fd Iustin Pop
import Test.QuickCheck as QuickCheck
36 aed2325f Iustin Pop
37 aed2325f Iustin Pop
import Control.Applicative
38 dc4b5c42 Iustin Pop
import Control.Monad
39 dc4b5c42 Iustin Pop
import Data.Char
40 aed2325f Iustin Pop
import Data.List
41 c66f09f5 Iustin Pop
import qualified Data.Map as Map
42 aed2325f Iustin Pop
import qualified Text.JSON as J
43 8d239fa4 Iustin Pop
import Text.Printf (printf)
44 aed2325f Iustin Pop
45 aed2325f Iustin Pop
import Test.Ganeti.TestHelper
46 aed2325f Iustin Pop
import Test.Ganeti.TestCommon
47 c7d249d0 Iustin Pop
import Test.Ganeti.Types ()
48 6e94b75c Jose A. Lopes
import Test.Ganeti.Query.Language ()
49 aed2325f Iustin Pop
50 f56013fd Iustin Pop
import Ganeti.BasicTypes
51 aed2325f Iustin Pop
import qualified Ganeti.Constants as C
52 aed2325f Iustin Pop
import qualified Ganeti.OpCodes as OpCodes
53 c7d249d0 Iustin Pop
import Ganeti.Types
54 c7d249d0 Iustin Pop
import Ganeti.OpParams
55 c66f09f5 Iustin Pop
import Ganeti.JSON
56 aed2325f Iustin Pop
57 5b11f8db Iustin Pop
{-# ANN module "HLint: ignore Use camelCase" #-}
58 5b11f8db Iustin Pop
59 aed2325f Iustin Pop
-- * Arbitrary instances
60 aed2325f Iustin Pop
61 de36f091 Jose A. Lopes
instance (Ord k, Arbitrary k, Arbitrary a) => Arbitrary (Map.Map k a) where
62 de36f091 Jose A. Lopes
  arbitrary = Map.fromList <$> arbitrary
63 367c4241 Dato Simó
64 6e94b75c Jose A. Lopes
arbitraryOpTagsGet :: Gen OpCodes.OpCode
65 6e94b75c Jose A. Lopes
arbitraryOpTagsGet = do
66 6e94b75c Jose A. Lopes
  kind <- arbitrary
67 6e94b75c Jose A. Lopes
  OpCodes.OpTagsSet kind <$> arbitrary <*> genOpCodesTagName kind
68 6e94b75c Jose A. Lopes
69 6e94b75c Jose A. Lopes
arbitraryOpTagsSet :: Gen OpCodes.OpCode
70 6e94b75c Jose A. Lopes
arbitraryOpTagsSet = do
71 6e94b75c Jose A. Lopes
  kind <- arbitrary
72 6e94b75c Jose A. Lopes
  OpCodes.OpTagsSet kind <$> genTags <*> genOpCodesTagName kind
73 6e94b75c Jose A. Lopes
74 6e94b75c Jose A. Lopes
arbitraryOpTagsDel :: Gen OpCodes.OpCode
75 6e94b75c Jose A. Lopes
arbitraryOpTagsDel = do
76 6e94b75c Jose A. Lopes
  kind <- arbitrary
77 6e94b75c Jose A. Lopes
  OpCodes.OpTagsDel kind <$> genTags <*> genOpCodesTagName kind
78 6e94b75c Jose A. Lopes
79 7022db83 Iustin Pop
$(genArbitrary ''OpCodes.ReplaceDisksMode)
80 aed2325f Iustin Pop
81 6d558717 Iustin Pop
$(genArbitrary ''DiskAccess)
82 6d558717 Iustin Pop
83 aed2325f Iustin Pop
instance Arbitrary OpCodes.DiskIndex where
84 aed2325f Iustin Pop
  arbitrary = choose (0, C.maxDisks - 1) >>= OpCodes.mkDiskIndex
85 aed2325f Iustin Pop
86 5ef4fbb1 Iustin Pop
instance Arbitrary INicParams where
87 5006418e Iustin Pop
  arbitrary = INicParams <$> genMaybe genNameNE <*> genMaybe genName <*>
88 6e94b75c Jose A. Lopes
              genMaybe genNameNE <*> genMaybe genNameNE <*>
89 6e94b75c Jose A. Lopes
              genMaybe genNameNE <*> genMaybe genNameNE <*>
90 6e94b75c Jose A. Lopes
              genMaybe genNameNE
91 c66f09f5 Iustin Pop
92 6d558717 Iustin Pop
instance Arbitrary IDiskParams where
93 6d558717 Iustin Pop
  arbitrary = IDiskParams <$> arbitrary <*> arbitrary <*>
94 5006418e Iustin Pop
              genMaybe genNameNE <*> genMaybe genNameNE <*>
95 4e4433e8 Christos Stavrakakis
              genMaybe genNameNE <*> genMaybe genNameNE
96 6d558717 Iustin Pop
97 c2d3219b Iustin Pop
instance Arbitrary RecreateDisksInfo where
98 c2d3219b Iustin Pop
  arbitrary = oneof [ pure RecreateDisksAll
99 c2d3219b Iustin Pop
                    , RecreateDisksIndices <$> arbitrary
100 c2d3219b Iustin Pop
                    , RecreateDisksParams <$> arbitrary
101 c2d3219b Iustin Pop
                    ]
102 c2d3219b Iustin Pop
103 c2d3219b Iustin Pop
instance Arbitrary DdmOldChanges where
104 c2d3219b Iustin Pop
  arbitrary = oneof [ DdmOldIndex <$> arbitrary
105 c2d3219b Iustin Pop
                    , DdmOldMod   <$> arbitrary
106 c2d3219b Iustin Pop
                    ]
107 c2d3219b Iustin Pop
108 c2d3219b Iustin Pop
instance (Arbitrary a) => Arbitrary (SetParamsMods a) where
109 c2d3219b Iustin Pop
  arbitrary = oneof [ pure SetParamsEmpty
110 c2d3219b Iustin Pop
                    , SetParamsDeprecated <$> arbitrary
111 c2d3219b Iustin Pop
                    , SetParamsNew        <$> arbitrary
112 c2d3219b Iustin Pop
                    ]
113 c2d3219b Iustin Pop
114 398e9066 Iustin Pop
instance Arbitrary ExportTarget where
115 398e9066 Iustin Pop
  arbitrary = oneof [ ExportTargetLocal <$> genNodeNameNE
116 398e9066 Iustin Pop
                    , ExportTargetRemote <$> pure []
117 398e9066 Iustin Pop
                    ]
118 398e9066 Iustin Pop
119 aed2325f Iustin Pop
instance Arbitrary OpCodes.OpCode where
120 aed2325f Iustin Pop
  arbitrary = do
121 aed2325f Iustin Pop
    op_id <- elements OpCodes.allOpIDs
122 aed2325f Iustin Pop
    case op_id of
123 aed2325f Iustin Pop
      "OP_TEST_DELAY" ->
124 7d421386 Iustin Pop
        OpCodes.OpTestDelay <$> arbitrary <*> arbitrary <*>
125 1c3231aa Thomas Thrainer
          genNodeNamesNE <*> return Nothing <*> arbitrary
126 aed2325f Iustin Pop
      "OP_INSTANCE_REPLACE_DISKS" ->
127 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceReplaceDisks <$> genFQDN <*> return Nothing <*>
128 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*> genDiskIndices <*>
129 1c3231aa Thomas Thrainer
          genMaybe genNodeNameNE <*> return Nothing <*> genMaybe genNameNE
130 aed2325f Iustin Pop
      "OP_INSTANCE_FAILOVER" ->
131 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceFailover <$> genFQDN <*> return Nothing <*>
132 da4a52a3 Thomas Thrainer
        arbitrary <*> arbitrary <*> genMaybe genNodeNameNE <*>
133 1ca326c8 Thomas Thrainer
        return Nothing <*> arbitrary <*> arbitrary <*> genMaybe genNameNE
134 aed2325f Iustin Pop
      "OP_INSTANCE_MIGRATE" ->
135 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceMigrate <$> genFQDN <*> return Nothing <*>
136 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> genMaybe genNodeNameNE <*>
137 da4a52a3 Thomas Thrainer
          return Nothing <*> arbitrary <*> arbitrary <*> arbitrary <*>
138 da4a52a3 Thomas Thrainer
          genMaybe genNameNE <*> arbitrary
139 a451dae2 Iustin Pop
      "OP_TAGS_GET" ->
140 6e94b75c Jose A. Lopes
        arbitraryOpTagsGet
141 a451dae2 Iustin Pop
      "OP_TAGS_SEARCH" ->
142 a451dae2 Iustin Pop
        OpCodes.OpTagsSearch <$> genNameNE
143 3bebda52 Dato Simó
      "OP_TAGS_SET" ->
144 6e94b75c Jose A. Lopes
        arbitraryOpTagsSet
145 3bebda52 Dato Simó
      "OP_TAGS_DEL" ->
146 6e94b75c Jose A. Lopes
        arbitraryOpTagsDel
147 c66f09f5 Iustin Pop
      "OP_CLUSTER_POST_INIT" -> pure OpCodes.OpClusterPostInit
148 c66f09f5 Iustin Pop
      "OP_CLUSTER_DESTROY" -> pure OpCodes.OpClusterDestroy
149 c66f09f5 Iustin Pop
      "OP_CLUSTER_QUERY" -> pure OpCodes.OpClusterQuery
150 c66f09f5 Iustin Pop
      "OP_CLUSTER_VERIFY" ->
151 c66f09f5 Iustin Pop
        OpCodes.OpClusterVerify <$> arbitrary <*> arbitrary <*>
152 4651c69f Jose A. Lopes
          genListSet Nothing <*> genListSet Nothing <*> arbitrary <*>
153 5006418e Iustin Pop
          genMaybe genNameNE
154 c66f09f5 Iustin Pop
      "OP_CLUSTER_VERIFY_CONFIG" ->
155 c66f09f5 Iustin Pop
        OpCodes.OpClusterVerifyConfig <$> arbitrary <*> arbitrary <*>
156 4651c69f Jose A. Lopes
          genListSet Nothing <*> arbitrary
157 c66f09f5 Iustin Pop
      "OP_CLUSTER_VERIFY_GROUP" ->
158 5ef4fbb1 Iustin Pop
        OpCodes.OpClusterVerifyGroup <$> genNameNE <*> arbitrary <*>
159 4651c69f Jose A. Lopes
          arbitrary <*> genListSet Nothing <*> genListSet Nothing <*> arbitrary
160 c66f09f5 Iustin Pop
      "OP_CLUSTER_VERIFY_DISKS" -> pure OpCodes.OpClusterVerifyDisks
161 c66f09f5 Iustin Pop
      "OP_GROUP_VERIFY_DISKS" ->
162 5ef4fbb1 Iustin Pop
        OpCodes.OpGroupVerifyDisks <$> genNameNE
163 c66f09f5 Iustin Pop
      "OP_CLUSTER_REPAIR_DISK_SIZES" ->
164 5006418e Iustin Pop
        OpCodes.OpClusterRepairDiskSizes <$> genNodeNamesNE
165 c66f09f5 Iustin Pop
      "OP_CLUSTER_CONFIG_QUERY" ->
166 5ef4fbb1 Iustin Pop
        OpCodes.OpClusterConfigQuery <$> genFieldsNE
167 c66f09f5 Iustin Pop
      "OP_CLUSTER_RENAME" ->
168 5006418e Iustin Pop
        OpCodes.OpClusterRename <$> genNameNE
169 c66f09f5 Iustin Pop
      "OP_CLUSTER_SET_PARAMS" ->
170 e5c92cfb Klaus Aehlig
        OpCodes.OpClusterSetParams <$> arbitrary <*> emptyMUD <*> emptyMUD <*>
171 6e94b75c Jose A. Lopes
          arbitrary <*> genMaybe arbitrary <*>
172 5006418e Iustin Pop
          genMaybe genEmptyContainer <*> emptyMUD <*>
173 5006418e Iustin Pop
          genMaybe genEmptyContainer <*> genMaybe genEmptyContainer <*>
174 5006418e Iustin Pop
          genMaybe genEmptyContainer <*> genMaybe arbitrary <*>
175 c66f09f5 Iustin Pop
          arbitrary <*> arbitrary <*> arbitrary <*>
176 c66f09f5 Iustin Pop
          arbitrary <*> arbitrary <*> arbitrary <*>
177 c66f09f5 Iustin Pop
          emptyMUD <*> emptyMUD <*> arbitrary <*>
178 67fc4de7 Iustin Pop
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
179 3039e2dc Helga Velroyen
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
180 5ce621ab Helga Velroyen
          genMaybe genName <*>
181 5ce621ab Helga Velroyen
          genMaybe genName
182 c66f09f5 Iustin Pop
      "OP_CLUSTER_REDIST_CONF" -> pure OpCodes.OpClusterRedistConf
183 c66f09f5 Iustin Pop
      "OP_CLUSTER_ACTIVATE_MASTER_IP" ->
184 c66f09f5 Iustin Pop
        pure OpCodes.OpClusterActivateMasterIp
185 c66f09f5 Iustin Pop
      "OP_CLUSTER_DEACTIVATE_MASTER_IP" ->
186 c66f09f5 Iustin Pop
        pure OpCodes.OpClusterDeactivateMasterIp
187 c66f09f5 Iustin Pop
      "OP_QUERY" ->
188 6e94b75c Jose A. Lopes
        OpCodes.OpQuery <$> arbitrary <*> arbitrary <*> arbitrary <*>
189 6e94b75c Jose A. Lopes
        pure Nothing
190 c66f09f5 Iustin Pop
      "OP_QUERY_FIELDS" ->
191 c66f09f5 Iustin Pop
        OpCodes.OpQueryFields <$> arbitrary <*> arbitrary
192 c66f09f5 Iustin Pop
      "OP_OOB_COMMAND" ->
193 1c3231aa Thomas Thrainer
        OpCodes.OpOobCommand <$> genNodeNamesNE <*> return Nothing <*>
194 1c3231aa Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*>
195 1c3231aa Thomas Thrainer
          (arbitrary `suchThat` (>0))
196 1c3231aa Thomas Thrainer
      "OP_NODE_REMOVE" ->
197 1c3231aa Thomas Thrainer
        OpCodes.OpNodeRemove <$> genNodeNameNE <*> return Nothing
198 c66f09f5 Iustin Pop
      "OP_NODE_ADD" ->
199 5ef4fbb1 Iustin Pop
        OpCodes.OpNodeAdd <$> genNodeNameNE <*> emptyMUD <*> emptyMUD <*>
200 5cbf7832 Jose A. Lopes
          genMaybe genNameNE <*> genMaybe genNameNE <*> arbitrary <*>
201 5006418e Iustin Pop
          genMaybe genNameNE <*> arbitrary <*> arbitrary <*> emptyMUD
202 c66f09f5 Iustin Pop
      "OP_NODE_QUERY" ->
203 3131adc7 Iustin Pop
        OpCodes.OpNodeQuery <$> genFieldsNE <*> genNamesNE <*> arbitrary
204 c66f09f5 Iustin Pop
      "OP_NODE_QUERYVOLS" ->
205 c66f09f5 Iustin Pop
        OpCodes.OpNodeQueryvols <$> arbitrary <*> genNodeNamesNE
206 c66f09f5 Iustin Pop
      "OP_NODE_QUERY_STORAGE" ->
207 c66f09f5 Iustin Pop
        OpCodes.OpNodeQueryStorage <$> arbitrary <*> arbitrary <*>
208 6e94b75c Jose A. Lopes
          genNodeNamesNE <*> genMaybe genNameNE
209 c66f09f5 Iustin Pop
      "OP_NODE_MODIFY_STORAGE" ->
210 1c3231aa Thomas Thrainer
        OpCodes.OpNodeModifyStorage <$> genNodeNameNE <*> return Nothing <*>
211 6e94b75c Jose A. Lopes
          arbitrary <*> genMaybe genNameNE <*> pure emptyJSObject
212 c66f09f5 Iustin Pop
      "OP_REPAIR_NODE_STORAGE" ->
213 1c3231aa Thomas Thrainer
        OpCodes.OpRepairNodeStorage <$> genNodeNameNE <*> return Nothing <*>
214 6e94b75c Jose A. Lopes
          arbitrary <*> genMaybe genNameNE <*> arbitrary
215 c66f09f5 Iustin Pop
      "OP_NODE_SET_PARAMS" ->
216 1c3231aa Thomas Thrainer
        OpCodes.OpNodeSetParams <$> genNodeNameNE <*> return Nothing <*>
217 1c3231aa Thomas Thrainer
          arbitrary <*> emptyMUD <*> emptyMUD <*> arbitrary <*> arbitrary <*>
218 1c3231aa Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
219 1c3231aa Thomas Thrainer
          genMaybe genNameNE <*> emptyMUD <*> arbitrary
220 c66f09f5 Iustin Pop
      "OP_NODE_POWERCYCLE" ->
221 1c3231aa Thomas Thrainer
        OpCodes.OpNodePowercycle <$> genNodeNameNE <*> return Nothing <*>
222 1c3231aa Thomas Thrainer
          arbitrary
223 c66f09f5 Iustin Pop
      "OP_NODE_MIGRATE" ->
224 1c3231aa Thomas Thrainer
        OpCodes.OpNodeMigrate <$> genNodeNameNE <*> return Nothing <*>
225 1c3231aa Thomas Thrainer
          arbitrary <*> arbitrary <*> genMaybe genNodeNameNE <*>
226 1c3231aa Thomas Thrainer
          return Nothing <*> arbitrary <*> arbitrary <*> genMaybe genNameNE
227 c66f09f5 Iustin Pop
      "OP_NODE_EVACUATE" ->
228 c66f09f5 Iustin Pop
        OpCodes.OpNodeEvacuate <$> arbitrary <*> genNodeNameNE <*>
229 1c3231aa Thomas Thrainer
          return Nothing <*> genMaybe genNodeNameNE <*> return Nothing <*>
230 1c3231aa Thomas Thrainer
          genMaybe genNameNE <*> arbitrary
231 6d558717 Iustin Pop
      "OP_INSTANCE_CREATE" ->
232 5006418e Iustin Pop
        OpCodes.OpInstanceCreate <$> genFQDN <*> arbitrary <*>
233 6d558717 Iustin Pop
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
234 6e94b75c Jose A. Lopes
          pure emptyJSObject <*> arbitrary <*> arbitrary <*> arbitrary <*>
235 6e94b75c Jose A. Lopes
          genMaybe genNameNE <*> pure emptyJSObject <*> arbitrary <*>
236 6e94b75c Jose A. Lopes
          genMaybe genNameNE <*> arbitrary <*> arbitrary <*> arbitrary <*>
237 6e94b75c Jose A. Lopes
          arbitrary <*> arbitrary <*> arbitrary <*> pure emptyJSObject <*>
238 6e94b75c Jose A. Lopes
          genMaybe genNameNE <*> genMaybe genNodeNameNE <*> return Nothing <*>
239 6e94b75c Jose A. Lopes
          genMaybe genNodeNameNE <*> return Nothing <*> genMaybe (pure []) <*>
240 6e94b75c Jose A. Lopes
          genMaybe genNodeNameNE <*> arbitrary <*> genMaybe genNodeNameNE <*>
241 6e94b75c Jose A. Lopes
          return Nothing <*> genMaybe genNodeNameNE <*> genMaybe genNameNE <*>
242 6e94b75c Jose A. Lopes
          arbitrary <*> (genTags >>= mapM mkNonEmpty)
243 c2d3219b Iustin Pop
      "OP_INSTANCE_MULTI_ALLOC" ->
244 6e94b75c Jose A. Lopes
        OpCodes.OpInstanceMultiAlloc <$> arbitrary <*> genMaybe genNameNE <*>
245 6e94b75c Jose A. Lopes
        pure []
246 c2d3219b Iustin Pop
      "OP_INSTANCE_REINSTALL" ->
247 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceReinstall <$> genFQDN <*> return Nothing <*>
248 da4a52a3 Thomas Thrainer
          arbitrary <*> genMaybe genNameNE <*> genMaybe (pure emptyJSObject)
249 c2d3219b Iustin Pop
      "OP_INSTANCE_REMOVE" ->
250 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceRemove <$> genFQDN <*> return Nothing <*>
251 c2d3219b Iustin Pop
          arbitrary <*> arbitrary
252 da4a52a3 Thomas Thrainer
      "OP_INSTANCE_RENAME" ->
253 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceRename <$> genFQDN <*> return Nothing <*>
254 da4a52a3 Thomas Thrainer
          genNodeNameNE <*> arbitrary <*> arbitrary
255 c2d3219b Iustin Pop
      "OP_INSTANCE_STARTUP" ->
256 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceStartup <$> genFQDN <*> return Nothing <*>
257 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> pure emptyJSObject <*>
258 da4a52a3 Thomas Thrainer
          pure emptyJSObject <*> arbitrary <*> arbitrary
259 c2d3219b Iustin Pop
      "OP_INSTANCE_SHUTDOWN" ->
260 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceShutdown <$> genFQDN <*> return Nothing <*>
261 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
262 c2d3219b Iustin Pop
      "OP_INSTANCE_REBOOT" ->
263 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceReboot <$> genFQDN <*> return Nothing <*>
264 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary
265 c2d3219b Iustin Pop
      "OP_INSTANCE_MOVE" ->
266 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceMove <$> genFQDN <*> return Nothing <*>
267 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> genNodeNameNE <*> return Nothing <*>
268 da4a52a3 Thomas Thrainer
          arbitrary
269 da4a52a3 Thomas Thrainer
      "OP_INSTANCE_CONSOLE" -> OpCodes.OpInstanceConsole <$> genFQDN <*>
270 da4a52a3 Thomas Thrainer
          return Nothing
271 c2d3219b Iustin Pop
      "OP_INSTANCE_ACTIVATE_DISKS" ->
272 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceActivateDisks <$> genFQDN <*> return Nothing <*>
273 c2d3219b Iustin Pop
          arbitrary <*> arbitrary
274 c2d3219b Iustin Pop
      "OP_INSTANCE_DEACTIVATE_DISKS" ->
275 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceDeactivateDisks <$> genFQDN <*> return Nothing <*>
276 da4a52a3 Thomas Thrainer
          arbitrary
277 c2d3219b Iustin Pop
      "OP_INSTANCE_RECREATE_DISKS" ->
278 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceRecreateDisks <$> genFQDN <*> return Nothing <*>
279 da4a52a3 Thomas Thrainer
          arbitrary <*> genNodeNamesNE <*> return Nothing <*>
280 da4a52a3 Thomas Thrainer
          genMaybe genNameNE
281 1cd563e2 Iustin Pop
      "OP_INSTANCE_QUERY" ->
282 6e94b75c Jose A. Lopes
        OpCodes.OpInstanceQuery <$> genFieldsNE <*> arbitrary <*> genNamesNE
283 c2d3219b Iustin Pop
      "OP_INSTANCE_QUERY_DATA" ->
284 c2d3219b Iustin Pop
        OpCodes.OpInstanceQueryData <$> arbitrary <*>
285 c2d3219b Iustin Pop
          genNodeNamesNE <*> arbitrary
286 c2d3219b Iustin Pop
      "OP_INSTANCE_SET_PARAMS" ->
287 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceSetParams <$> genFQDN <*> return Nothing <*>
288 c2d3219b Iustin Pop
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
289 da4a52a3 Thomas Thrainer
          arbitrary <*> pure emptyJSObject <*> arbitrary <*>
290 da4a52a3 Thomas Thrainer
          pure emptyJSObject <*> arbitrary <*> genMaybe genNodeNameNE <*>
291 da4a52a3 Thomas Thrainer
          return Nothing <*> genMaybe genNodeNameNE <*> return Nothing <*>
292 d2204b1a Klaus Aehlig
          genMaybe genNameNE <*> pure emptyJSObject <*> arbitrary <*>
293 d2204b1a Klaus Aehlig
          arbitrary <*> arbitrary
294 c2d3219b Iustin Pop
      "OP_INSTANCE_GROW_DISK" ->
295 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceGrowDisk <$> genFQDN <*> return Nothing <*>
296 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
297 c2d3219b Iustin Pop
      "OP_INSTANCE_CHANGE_GROUP" ->
298 da4a52a3 Thomas Thrainer
        OpCodes.OpInstanceChangeGroup <$> genFQDN <*> return Nothing <*>
299 da4a52a3 Thomas Thrainer
          arbitrary <*> genMaybe genNameNE <*>
300 da4a52a3 Thomas Thrainer
          genMaybe (resize maxNodes (listOf genNameNE))
301 398e9066 Iustin Pop
      "OP_GROUP_ADD" ->
302 398e9066 Iustin Pop
        OpCodes.OpGroupAdd <$> genNameNE <*> arbitrary <*>
303 5006418e Iustin Pop
          emptyMUD <*> genMaybe genEmptyContainer <*>
304 398e9066 Iustin Pop
          emptyMUD <*> emptyMUD <*> emptyMUD
305 398e9066 Iustin Pop
      "OP_GROUP_ASSIGN_NODES" ->
306 398e9066 Iustin Pop
        OpCodes.OpGroupAssignNodes <$> genNameNE <*> arbitrary <*>
307 1c3231aa Thomas Thrainer
          genNodeNamesNE <*> return Nothing
308 398e9066 Iustin Pop
      "OP_GROUP_QUERY" ->
309 398e9066 Iustin Pop
        OpCodes.OpGroupQuery <$> genFieldsNE <*> genNamesNE
310 398e9066 Iustin Pop
      "OP_GROUP_SET_PARAMS" ->
311 398e9066 Iustin Pop
        OpCodes.OpGroupSetParams <$> genNameNE <*> arbitrary <*>
312 5006418e Iustin Pop
          emptyMUD <*> genMaybe genEmptyContainer <*>
313 398e9066 Iustin Pop
          emptyMUD <*> emptyMUD <*> emptyMUD
314 398e9066 Iustin Pop
      "OP_GROUP_REMOVE" ->
315 398e9066 Iustin Pop
        OpCodes.OpGroupRemove <$> genNameNE
316 398e9066 Iustin Pop
      "OP_GROUP_RENAME" ->
317 398e9066 Iustin Pop
        OpCodes.OpGroupRename <$> genNameNE <*> genNameNE
318 398e9066 Iustin Pop
      "OP_GROUP_EVACUATE" ->
319 398e9066 Iustin Pop
        OpCodes.OpGroupEvacuate <$> genNameNE <*> arbitrary <*>
320 5006418e Iustin Pop
          genMaybe genNameNE <*> genMaybe genNamesNE
321 398e9066 Iustin Pop
      "OP_OS_DIAGNOSE" ->
322 398e9066 Iustin Pop
        OpCodes.OpOsDiagnose <$> genFieldsNE <*> genNamesNE
323 b954f097 Constantinos Venetsanopoulos
      "OP_EXT_STORAGE_DIAGNOSE" ->
324 b954f097 Constantinos Venetsanopoulos
        OpCodes.OpOsDiagnose <$> genFieldsNE <*> genNamesNE
325 398e9066 Iustin Pop
      "OP_BACKUP_QUERY" ->
326 398e9066 Iustin Pop
        OpCodes.OpBackupQuery <$> arbitrary <*> genNodeNamesNE
327 398e9066 Iustin Pop
      "OP_BACKUP_PREPARE" ->
328 da4a52a3 Thomas Thrainer
        OpCodes.OpBackupPrepare <$> genFQDN <*> return Nothing <*> arbitrary
329 398e9066 Iustin Pop
      "OP_BACKUP_EXPORT" ->
330 da4a52a3 Thomas Thrainer
        OpCodes.OpBackupExport <$> genFQDN <*> return Nothing <*>
331 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> return Nothing <*> arbitrary <*>
332 da4a52a3 Thomas Thrainer
          arbitrary <*> arbitrary <*> arbitrary <*> genMaybe (pure []) <*>
333 1c3231aa Thomas Thrainer
          genMaybe genNameNE
334 398e9066 Iustin Pop
      "OP_BACKUP_REMOVE" ->
335 da4a52a3 Thomas Thrainer
        OpCodes.OpBackupRemove <$> genFQDN <*> return Nothing
336 a3f02317 Iustin Pop
      "OP_TEST_ALLOCATOR" ->
337 a3f02317 Iustin Pop
        OpCodes.OpTestAllocator <$> arbitrary <*> arbitrary <*>
338 6e94b75c Jose A. Lopes
          genNameNE <*> genMaybe (pure []) <*> genMaybe (pure []) <*>
339 5006418e Iustin Pop
          arbitrary <*> genMaybe genNameNE <*>
340 a3f02317 Iustin Pop
          (genTags >>= mapM mkNonEmpty) <*>
341 5006418e Iustin Pop
          arbitrary <*> arbitrary <*> genMaybe genNameNE <*>
342 5006418e Iustin Pop
          arbitrary <*> genMaybe genNodeNamesNE <*> arbitrary <*>
343 5006418e Iustin Pop
          genMaybe genNamesNE <*> arbitrary <*> arbitrary
344 a3f02317 Iustin Pop
      "OP_TEST_JQUEUE" ->
345 a3f02317 Iustin Pop
        OpCodes.OpTestJqueue <$> arbitrary <*> arbitrary <*>
346 5006418e Iustin Pop
          resize 20 (listOf genFQDN) <*> arbitrary
347 a3f02317 Iustin Pop
      "OP_TEST_DUMMY" ->
348 a3f02317 Iustin Pop
        OpCodes.OpTestDummy <$> pure J.JSNull <*> pure J.JSNull <*>
349 a3f02317 Iustin Pop
          pure J.JSNull <*> pure J.JSNull
350 8d239fa4 Iustin Pop
      "OP_NETWORK_ADD" ->
351 6e94b75c Jose A. Lopes
        OpCodes.OpNetworkAdd <$> genNameNE <*> genIPv4Network <*>
352 6e94b75c Jose A. Lopes
          genMaybe genIPv4Address <*> pure Nothing <*> pure Nothing <*>
353 6e94b75c Jose A. Lopes
          genMaybe genMacPrefix <*> genMaybe (listOf genIPv4Address) <*>
354 1dbceab9 Iustin Pop
          arbitrary <*> (genTags >>= mapM mkNonEmpty)
355 8d239fa4 Iustin Pop
      "OP_NETWORK_REMOVE" ->
356 8d239fa4 Iustin Pop
        OpCodes.OpNetworkRemove <$> genNameNE <*> arbitrary
357 8d239fa4 Iustin Pop
      "OP_NETWORK_SET_PARAMS" ->
358 5cfa6c37 Dimitris Aragiorgis
        OpCodes.OpNetworkSetParams <$> genNameNE <*>
359 6e94b75c Jose A. Lopes
          genMaybe genIPv4Address <*> pure Nothing <*> pure Nothing <*>
360 6e94b75c Jose A. Lopes
          genMaybe genMacPrefix <*> genMaybe (listOf genIPv4Address) <*>
361 6e94b75c Jose A. Lopes
          genMaybe (listOf genIPv4Address)
362 8d239fa4 Iustin Pop
      "OP_NETWORK_CONNECT" ->
363 8d239fa4 Iustin Pop
        OpCodes.OpNetworkConnect <$> genNameNE <*> genNameNE <*>
364 8d239fa4 Iustin Pop
          arbitrary <*> genNameNE <*> arbitrary
365 8d239fa4 Iustin Pop
      "OP_NETWORK_DISCONNECT" ->
366 0ae4b355 Helga Velroyen
        OpCodes.OpNetworkDisconnect <$> genNameNE <*> genNameNE
367 8d239fa4 Iustin Pop
      "OP_NETWORK_QUERY" ->
368 6e94b75c Jose A. Lopes
        OpCodes.OpNetworkQuery <$> genFieldsNE <*> arbitrary <*> genNamesNE
369 1cd563e2 Iustin Pop
      "OP_RESTRICTED_COMMAND" ->
370 1cd563e2 Iustin Pop
        OpCodes.OpRestrictedCommand <$> arbitrary <*> genNodeNamesNE <*>
371 1c3231aa Thomas Thrainer
          return Nothing <*> genNameNE
372 c66f09f5 Iustin Pop
      _ -> fail $ "Undefined arbitrary for opcode " ++ op_id
373 aed2325f Iustin Pop
374 516a0e94 Michele Tartara
-- | Generates one element of a reason trail
375 516a0e94 Michele Tartara
genReasonElem :: Gen ReasonElem
376 516a0e94 Michele Tartara
genReasonElem = (,,) <$> genFQDN <*> genFQDN <*> arbitrary
377 516a0e94 Michele Tartara
378 516a0e94 Michele Tartara
-- | Generates a reason trail
379 516a0e94 Michele Tartara
genReasonTrail :: Gen ReasonTrail
380 516a0e94 Michele Tartara
genReasonTrail = do
381 516a0e94 Michele Tartara
  size <- choose (0, 10)
382 516a0e94 Michele Tartara
  vectorOf size genReasonElem
383 516a0e94 Michele Tartara
384 4a826364 Iustin Pop
instance Arbitrary OpCodes.CommonOpParams where
385 4a826364 Iustin Pop
  arbitrary = OpCodes.CommonOpParams <$> arbitrary <*> arbitrary <*>
386 516a0e94 Michele Tartara
                arbitrary <*> resize 5 arbitrary <*> genMaybe genName <*>
387 516a0e94 Michele Tartara
                genReasonTrail
388 4a826364 Iustin Pop
389 c7d249d0 Iustin Pop
-- * Helper functions
390 c7d249d0 Iustin Pop
391 c66f09f5 Iustin Pop
-- | Empty JSObject.
392 c66f09f5 Iustin Pop
emptyJSObject :: J.JSObject J.JSValue
393 c66f09f5 Iustin Pop
emptyJSObject = J.toJSObject []
394 c66f09f5 Iustin Pop
395 c66f09f5 Iustin Pop
-- | Empty maybe unchecked dictionary.
396 c66f09f5 Iustin Pop
emptyMUD :: Gen (Maybe (J.JSObject J.JSValue))
397 5006418e Iustin Pop
emptyMUD = genMaybe $ pure emptyJSObject
398 c66f09f5 Iustin Pop
399 c66f09f5 Iustin Pop
-- | Generates an empty container.
400 c66f09f5 Iustin Pop
genEmptyContainer :: (Ord a) => Gen (GenericContainer a b)
401 c66f09f5 Iustin Pop
genEmptyContainer = pure . GenericContainer $ Map.fromList []
402 c66f09f5 Iustin Pop
403 c7d249d0 Iustin Pop
-- | Generates list of disk indices.
404 c7d249d0 Iustin Pop
genDiskIndices :: Gen [DiskIndex]
405 c7d249d0 Iustin Pop
genDiskIndices = do
406 c7d249d0 Iustin Pop
  cnt <- choose (0, C.maxDisks)
407 df8578fb Iustin Pop
  genUniquesList cnt arbitrary
408 c7d249d0 Iustin Pop
409 c7d249d0 Iustin Pop
-- | Generates a list of node names.
410 c7d249d0 Iustin Pop
genNodeNames :: Gen [String]
411 5006418e Iustin Pop
genNodeNames = resize maxNodes (listOf genFQDN)
412 c7d249d0 Iustin Pop
413 c66f09f5 Iustin Pop
-- | Generates a list of node names in non-empty string type.
414 c66f09f5 Iustin Pop
genNodeNamesNE :: Gen [NonEmptyString]
415 417ab39c Iustin Pop
genNodeNamesNE = genNodeNames >>= mapM mkNonEmpty
416 c66f09f5 Iustin Pop
417 c7d249d0 Iustin Pop
-- | Gets a node name in non-empty type.
418 c7d249d0 Iustin Pop
genNodeNameNE :: Gen NonEmptyString
419 5006418e Iustin Pop
genNodeNameNE = genFQDN >>= mkNonEmpty
420 c7d249d0 Iustin Pop
421 5ef4fbb1 Iustin Pop
-- | Gets a name (non-fqdn) in non-empty type.
422 5ef4fbb1 Iustin Pop
genNameNE :: Gen NonEmptyString
423 5006418e Iustin Pop
genNameNE = genName >>= mkNonEmpty
424 5ef4fbb1 Iustin Pop
425 398e9066 Iustin Pop
-- | Gets a list of names (non-fqdn) in non-empty type.
426 398e9066 Iustin Pop
genNamesNE :: Gen [NonEmptyString]
427 398e9066 Iustin Pop
genNamesNE = resize maxNodes (listOf genNameNE)
428 398e9066 Iustin Pop
429 5ef4fbb1 Iustin Pop
-- | Returns a list of non-empty fields.
430 5ef4fbb1 Iustin Pop
genFieldsNE :: Gen [NonEmptyString]
431 5006418e Iustin Pop
genFieldsNE = genFields >>= mapM mkNonEmpty
432 5ef4fbb1 Iustin Pop
433 8d239fa4 Iustin Pop
-- | Generate a 3-byte MAC prefix.
434 8d239fa4 Iustin Pop
genMacPrefix :: Gen NonEmptyString
435 8d239fa4 Iustin Pop
genMacPrefix = do
436 8d239fa4 Iustin Pop
  octets <- vectorOf 3 $ choose (0::Int, 255)
437 8d239fa4 Iustin Pop
  mkNonEmpty . intercalate ":" $ map (printf "%02x") octets
438 8d239fa4 Iustin Pop
439 4a826364 Iustin Pop
-- | Arbitrary instance for MetaOpCode, defined here due to TH ordering.
440 4a826364 Iustin Pop
$(genArbitrary ''OpCodes.MetaOpCode)
441 4a826364 Iustin Pop
442 f56013fd Iustin Pop
-- | Small helper to check for a failed JSON deserialisation
443 f56013fd Iustin Pop
isJsonError :: J.Result a -> Bool
444 f56013fd Iustin Pop
isJsonError (J.Error _) = True
445 f56013fd Iustin Pop
isJsonError _           = False
446 f56013fd Iustin Pop
447 aed2325f Iustin Pop
-- * Test cases
448 aed2325f Iustin Pop
449 aed2325f Iustin Pop
-- | Check that opcode serialization is idempotent.
450 20bc5360 Iustin Pop
prop_serialization :: OpCodes.OpCode -> Property
451 63b068c1 Iustin Pop
prop_serialization = testSerialisation
452 aed2325f Iustin Pop
453 aed2325f Iustin Pop
-- | Check that Python and Haskell defined the same opcode list.
454 20bc5360 Iustin Pop
case_AllDefined :: HUnit.Assertion
455 20bc5360 Iustin Pop
case_AllDefined = do
456 d31193c3 Jose A. Lopes
  py_stdout <-
457 d31193c3 Jose A. Lopes
     runPython "from ganeti import opcodes\n\
458 d31193c3 Jose A. Lopes
               \from ganeti import serializer\n\
459 d31193c3 Jose A. Lopes
               \import sys\n\
460 6e94b75c Jose A. Lopes
               \print serializer.Dump([opid for opid in opcodes.OP_MAPPING])\n"
461 6e94b75c Jose A. Lopes
               ""
462 d31193c3 Jose A. Lopes
     >>= checkPythonResult
463 d31193c3 Jose A. Lopes
  py_ops <- case J.decode py_stdout::J.Result [String] of
464 d31193c3 Jose A. Lopes
               J.Ok ops -> return ops
465 d31193c3 Jose A. Lopes
               J.Error msg ->
466 d31193c3 Jose A. Lopes
                 HUnit.assertFailure ("Unable to decode opcode names: " ++ msg)
467 d31193c3 Jose A. Lopes
                 -- this already raised an expection, but we need it
468 d31193c3 Jose A. Lopes
                 -- for proper types
469 d31193c3 Jose A. Lopes
                 >> fail "Unable to decode opcode names"
470 d31193c3 Jose A. Lopes
  let hs_ops = sort OpCodes.allOpIDs
471 9b773665 Iustin Pop
      extra_py = py_ops \\ hs_ops
472 aed2325f Iustin Pop
      extra_hs = hs_ops \\ py_ops
473 9b773665 Iustin Pop
  HUnit.assertBool ("Missing OpCodes from the Haskell code:\n" ++
474 9b773665 Iustin Pop
                    unlines extra_py) (null extra_py)
475 aed2325f Iustin Pop
  HUnit.assertBool ("Extra OpCodes in the Haskell code code:\n" ++
476 aed2325f Iustin Pop
                    unlines extra_hs) (null extra_hs)
477 aed2325f Iustin Pop
478 aed2325f Iustin Pop
-- | Custom HUnit test case that forks a Python process and checks
479 aed2325f Iustin Pop
-- correspondence between Haskell-generated OpCodes and their Python
480 aed2325f Iustin Pop
-- decoded, validated and re-encoded version.
481 aed2325f Iustin Pop
--
482 aed2325f Iustin Pop
-- Note that we have a strange beast here: since launching Python is
483 aed2325f Iustin Pop
-- expensive, we don't do this via a usual QuickProperty, since that's
484 aed2325f Iustin Pop
-- slow (I've tested it, and it's indeed quite slow). Rather, we use a
485 aed2325f Iustin Pop
-- single HUnit assertion, and in it we manually use QuickCheck to
486 aed2325f Iustin Pop
-- generate 500 opcodes times the number of defined opcodes, which
487 aed2325f Iustin Pop
-- then we pass in bulk to Python. The drawbacks to this method are
488 aed2325f Iustin Pop
-- two fold: we cannot control the number of generated opcodes, since
489 aed2325f Iustin Pop
-- HUnit assertions don't get access to the test options, and for the
490 aed2325f Iustin Pop
-- same reason we can't run a repeatable seed. We should probably find
491 aed2325f Iustin Pop
-- a better way to do this, for example by having a
492 aed2325f Iustin Pop
-- separately-launched Python process (if not running the tests would
493 aed2325f Iustin Pop
-- be skipped).
494 d1ac695f Iustin Pop
case_py_compat_types :: HUnit.Assertion
495 d1ac695f Iustin Pop
case_py_compat_types = do
496 086ad4cf Iustin Pop
  let num_opcodes = length OpCodes.allOpIDs * 100
497 72747d91 Iustin Pop
  opcodes <- genSample (vectorOf num_opcodes
498 72747d91 Iustin Pop
                                   (arbitrary::Gen OpCodes.MetaOpCode))
499 72747d91 Iustin Pop
  let with_sum = map (\o -> (OpCodes.opSummary $
500 ad1c1e41 Iustin Pop
                             OpCodes.metaOpCode o, o)) opcodes
501 aed2325f Iustin Pop
      serialized = J.encode opcodes
502 dc4b5c42 Iustin Pop
  -- check for non-ASCII fields, usually due to 'arbitrary :: String'
503 dc4b5c42 Iustin Pop
  mapM_ (\op -> when (any (not . isAscii) (J.encode op)) .
504 dc4b5c42 Iustin Pop
                HUnit.assertFailure $
505 dc4b5c42 Iustin Pop
                  "OpCode has non-ASCII fields: " ++ show op
506 dc4b5c42 Iustin Pop
        ) opcodes
507 aed2325f Iustin Pop
  py_stdout <-
508 aed2325f Iustin Pop
     runPython "from ganeti import opcodes\n\
509 aed2325f Iustin Pop
               \from ganeti import serializer\n\
510 6e94b75c Jose A. Lopes
               \import sys\n\
511 aed2325f Iustin Pop
               \op_data = serializer.Load(sys.stdin.read())\n\
512 aed2325f Iustin Pop
               \decoded = [opcodes.OpCode.LoadOpCode(o) for o in op_data]\n\
513 aed2325f Iustin Pop
               \for op in decoded:\n\
514 aed2325f Iustin Pop
               \  op.Validate(True)\n\
515 ad1c1e41 Iustin Pop
               \encoded = [(op.Summary(), op.__getstate__())\n\
516 ad1c1e41 Iustin Pop
               \           for op in decoded]\n\
517 aed2325f Iustin Pop
               \print serializer.Dump(encoded)" serialized
518 aed2325f Iustin Pop
     >>= checkPythonResult
519 ad1c1e41 Iustin Pop
  let deserialised =
520 ad1c1e41 Iustin Pop
        J.decode py_stdout::J.Result [(String, OpCodes.MetaOpCode)]
521 aed2325f Iustin Pop
  decoded <- case deserialised of
522 aed2325f Iustin Pop
               J.Ok ops -> return ops
523 aed2325f Iustin Pop
               J.Error msg ->
524 aed2325f Iustin Pop
                 HUnit.assertFailure ("Unable to decode opcodes: " ++ msg)
525 aed2325f Iustin Pop
                 -- this already raised an expection, but we need it
526 aed2325f Iustin Pop
                 -- for proper types
527 aed2325f Iustin Pop
                 >> fail "Unable to decode opcodes"
528 aed2325f Iustin Pop
  HUnit.assertEqual "Mismatch in number of returned opcodes"
529 ad1c1e41 Iustin Pop
    (length decoded) (length with_sum)
530 aed2325f Iustin Pop
  mapM_ (uncurry (HUnit.assertEqual "Different result after encoding/decoding")
531 ad1c1e41 Iustin Pop
        ) $ zip decoded with_sum
532 aed2325f Iustin Pop
533 d1ac695f Iustin Pop
-- | Custom HUnit test case that forks a Python process and checks
534 d1ac695f Iustin Pop
-- correspondence between Haskell OpCodes fields and their Python
535 d1ac695f Iustin Pop
-- equivalent.
536 d1ac695f Iustin Pop
case_py_compat_fields :: HUnit.Assertion
537 d1ac695f Iustin Pop
case_py_compat_fields = do
538 d1ac695f Iustin Pop
  let hs_fields = sort $ map (\op_id -> (op_id, OpCodes.allOpFields op_id))
539 d1ac695f Iustin Pop
                         OpCodes.allOpIDs
540 d1ac695f Iustin Pop
  py_stdout <-
541 d1ac695f Iustin Pop
     runPython "from ganeti import opcodes\n\
542 d1ac695f Iustin Pop
               \import sys\n\
543 d1ac695f Iustin Pop
               \from ganeti import serializer\n\
544 d1ac695f Iustin Pop
               \fields = [(k, sorted([p[0] for p in v.OP_PARAMS]))\n\
545 d1ac695f Iustin Pop
               \           for k, v in opcodes.OP_MAPPING.items()]\n\
546 d1ac695f Iustin Pop
               \print serializer.Dump(fields)" ""
547 d1ac695f Iustin Pop
     >>= checkPythonResult
548 d1ac695f Iustin Pop
  let deserialised = J.decode py_stdout::J.Result [(String, [String])]
549 d1ac695f Iustin Pop
  py_fields <- case deserialised of
550 d1ac695f Iustin Pop
                 J.Ok v -> return $ sort v
551 d1ac695f Iustin Pop
                 J.Error msg ->
552 d1ac695f Iustin Pop
                   HUnit.assertFailure ("Unable to decode op fields: " ++ msg)
553 d1ac695f Iustin Pop
                   -- this already raised an expection, but we need it
554 d1ac695f Iustin Pop
                   -- for proper types
555 d1ac695f Iustin Pop
                   >> fail "Unable to decode op fields"
556 d1ac695f Iustin Pop
  HUnit.assertEqual "Mismatch in number of returned opcodes"
557 d1ac695f Iustin Pop
    (length hs_fields) (length py_fields)
558 d1ac695f Iustin Pop
  HUnit.assertEqual "Mismatch in defined OP_IDs"
559 d1ac695f Iustin Pop
    (map fst hs_fields) (map fst py_fields)
560 d1ac695f Iustin Pop
  mapM_ (\((py_id, py_flds), (hs_id, hs_flds)) -> do
561 d1ac695f Iustin Pop
           HUnit.assertEqual "Mismatch in OP_ID" py_id hs_id
562 d1ac695f Iustin Pop
           HUnit.assertEqual ("Mismatch in fields for " ++ hs_id)
563 d1ac695f Iustin Pop
             py_flds hs_flds
564 d1ac695f Iustin Pop
        ) $ zip py_fields hs_fields
565 d1ac695f Iustin Pop
566 4a826364 Iustin Pop
-- | Checks that setOpComment works correctly.
567 4a826364 Iustin Pop
prop_setOpComment :: OpCodes.MetaOpCode -> String -> Property
568 4a826364 Iustin Pop
prop_setOpComment op comment =
569 4a826364 Iustin Pop
  let (OpCodes.MetaOpCode common _) = OpCodes.setOpComment comment op
570 4a826364 Iustin Pop
  in OpCodes.opComment common ==? Just comment
571 4a826364 Iustin Pop
572 f56013fd Iustin Pop
-- | Tests wrong (negative) disk index.
573 f56013fd Iustin Pop
prop_mkDiskIndex_fail :: QuickCheck.Positive Int -> Property
574 f56013fd Iustin Pop
prop_mkDiskIndex_fail (Positive i) =
575 f56013fd Iustin Pop
  case mkDiskIndex (negate i) of
576 f56013fd Iustin Pop
    Bad msg -> printTestCase "error message " $
577 f56013fd Iustin Pop
               "Invalid value" `isPrefixOf` msg
578 f56013fd Iustin Pop
    Ok v -> failTest $ "Succeeded to build disk index '" ++ show v ++
579 f56013fd Iustin Pop
                       "' from negative value " ++ show (negate i)
580 f56013fd Iustin Pop
581 f56013fd Iustin Pop
-- | Tests a few invalid 'readRecreateDisks' cases.
582 f56013fd Iustin Pop
case_readRecreateDisks_fail :: Assertion
583 f56013fd Iustin Pop
case_readRecreateDisks_fail = do
584 f56013fd Iustin Pop
  assertBool "null" $
585 f56013fd Iustin Pop
    isJsonError (J.readJSON J.JSNull::J.Result RecreateDisksInfo)
586 f56013fd Iustin Pop
  assertBool "string" $
587 f56013fd Iustin Pop
    isJsonError (J.readJSON (J.showJSON "abc")::J.Result RecreateDisksInfo)
588 f56013fd Iustin Pop
589 f56013fd Iustin Pop
-- | Tests a few invalid 'readDdmOldChanges' cases.
590 f56013fd Iustin Pop
case_readDdmOldChanges_fail :: Assertion
591 f56013fd Iustin Pop
case_readDdmOldChanges_fail = do
592 f56013fd Iustin Pop
  assertBool "null" $
593 f56013fd Iustin Pop
    isJsonError (J.readJSON J.JSNull::J.Result DdmOldChanges)
594 f56013fd Iustin Pop
  assertBool "string" $
595 f56013fd Iustin Pop
    isJsonError (J.readJSON (J.showJSON "abc")::J.Result DdmOldChanges)
596 f56013fd Iustin Pop
597 f56013fd Iustin Pop
-- | Tests a few invalid 'readExportTarget' cases.
598 f56013fd Iustin Pop
case_readExportTarget_fail :: Assertion
599 f56013fd Iustin Pop
case_readExportTarget_fail = do
600 f56013fd Iustin Pop
  assertBool "null" $
601 f56013fd Iustin Pop
    isJsonError (J.readJSON J.JSNull::J.Result ExportTarget)
602 f56013fd Iustin Pop
  assertBool "int" $
603 f56013fd Iustin Pop
    isJsonError (J.readJSON (J.showJSON (5::Int))::J.Result ExportTarget)
604 f56013fd Iustin Pop
605 aed2325f Iustin Pop
testSuite "OpCodes"
606 20bc5360 Iustin Pop
            [ 'prop_serialization
607 20bc5360 Iustin Pop
            , 'case_AllDefined
608 d1ac695f Iustin Pop
            , 'case_py_compat_types
609 d1ac695f Iustin Pop
            , 'case_py_compat_fields
610 4a826364 Iustin Pop
            , 'prop_setOpComment
611 f56013fd Iustin Pop
            , 'prop_mkDiskIndex_fail
612 f56013fd Iustin Pop
            , 'case_readRecreateDisks_fail
613 f56013fd Iustin Pop
            , 'case_readDdmOldChanges_fail
614 f56013fd Iustin Pop
            , 'case_readExportTarget_fail
615 aed2325f Iustin Pop
            ]