Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / OpCodes.hs @ 41f2bf8d

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