Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / OpCodes.hs @ d31193c3

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