genNameNE
_ -> fail $ "Undefined arbitrary for opcode " ++ op_id
+instance Arbitrary OpCodes.CommonOpParams where
+ arbitrary = OpCodes.CommonOpParams <$> arbitrary <*> arbitrary <*>
+ arbitrary <*> resize 5 arbitrary <*> genMaybe genName
+
-- * Helper functions
-- | Empty JSObject.
octets <- vectorOf 3 $ choose (0::Int, 255)
mkNonEmpty . intercalate ":" $ map (printf "%02x") octets
+-- | Arbitrary instance for MetaOpCode, defined here due to TH ordering.
+$(genArbitrary ''OpCodes.MetaOpCode)
+
-- * Test cases
-- | Check that opcode serialization is idempotent.
case_py_compat_types = do
let num_opcodes = length OpCodes.allOpIDs * 100
sample_opcodes <- sample' (vectorOf num_opcodes
- (arbitrary::Gen OpCodes.OpCode))
+ (arbitrary::Gen OpCodes.MetaOpCode))
let opcodes = head sample_opcodes
serialized = J.encode opcodes
-- check for non-ASCII fields, usually due to 'arbitrary :: String'
\encoded = [op.__getstate__() for op in decoded]\n\
\print serializer.Dump(encoded)" serialized
>>= checkPythonResult
- let deserialised = J.decode py_stdout::J.Result [OpCodes.OpCode]
+ let deserialised = J.decode py_stdout::J.Result [OpCodes.MetaOpCode]
decoded <- case deserialised of
J.Ok ops -> return ops
J.Error msg ->
py_flds hs_flds
) $ zip py_fields hs_fields
+-- | Checks that setOpComment works correctly.
+prop_setOpComment :: OpCodes.MetaOpCode -> String -> Property
+prop_setOpComment op comment =
+ let (OpCodes.MetaOpCode common _) = OpCodes.setOpComment comment op
+ in OpCodes.opComment common ==? Just comment
+
testSuite "OpCodes"
[ 'prop_serialization
, 'case_AllDefined
, 'case_py_compat_types
, 'case_py_compat_fields
+ , 'prop_setOpComment
]
, opID
, allOpIDs
, allOpFields
+ , CommonOpParams(..)
+ , defOpParams
+ , MetaOpCode(..)
+ , wrapOpCode
+ , setOpComment
) where
-import Text.JSON (readJSON, showJSON, JSON())
+import Text.JSON (readJSON, showJSON, JSON, JSValue, makeObj)
+import qualified Text.JSON
import Ganeti.THH
import Ganeti.OpParams
+import Ganeti.Types (OpSubmitPriority(..))
-- | OpCode representation.
--
instance JSON OpCode where
readJSON = loadOpCode
showJSON = saveOpCode
+
+-- | Generic\/common opcode parameters.
+$(buildObject "CommonOpParams" "op"
+ [ pDryRun
+ , pDebugLevel
+ , pOpPriority
+ , pDependencies
+ , pComment
+ ])
+
+-- | Default common parameter values.
+defOpParams :: CommonOpParams
+defOpParams =
+ CommonOpParams { opDryRun = Nothing
+ , opDebugLevel = Nothing
+ , opPriority = OpPrioNormal
+ , opDepends = Nothing
+ , opComment = Nothing
+ }
+
+-- | The top-level opcode type.
+data MetaOpCode = MetaOpCode CommonOpParams OpCode
+ deriving (Show, Eq)
+
+-- | JSON serialisation for 'MetaOpCode'.
+showMeta :: MetaOpCode -> JSValue
+showMeta (MetaOpCode params op) =
+ let objparams = toDictCommonOpParams params
+ objop = toDictOpCode op
+ in makeObj (objparams ++ objop)
+
+-- | JSON deserialisation for 'MetaOpCode'
+readMeta :: JSValue -> Text.JSON.Result MetaOpCode
+readMeta v = do
+ meta <- readJSON v
+ op <- readJSON v
+ return $ MetaOpCode meta op
+
+instance JSON MetaOpCode where
+ showJSON = showMeta
+ readJSON = readMeta
+
+-- | Wraps an 'OpCode' with the default parameters to build a
+-- 'MetaOpCode'.
+wrapOpCode :: OpCode -> MetaOpCode
+wrapOpCode = MetaOpCode defOpParams
+
+-- | Sets the comment on a meta opcode.
+setOpComment :: String -> MetaOpCode -> MetaOpCode
+setOpComment comment (MetaOpCode common op) =
+ MetaOpCode (common { opComment = Just comment}) op