Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / OpCodes.hs @ 8d459129

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