Revision 305e174c htools/Ganeti/HTools/QC.hs

b/htools/Ganeti/HTools/QC.hs
48 48
  , testJSON
49 49
  , testLuxi
50 50
  , testSsconf
51
  , testRpc
52 51
  , testQlang
53
  , testConfd
54 52
  ) where
55 53

  
56 54
import qualified Test.HUnit as HUnit
......
87 85
import qualified Ganeti.Luxi as Luxi
88 86
import qualified Ganeti.Objects as Objects
89 87
import qualified Ganeti.OpCodes as OpCodes
90
import qualified Ganeti.Rpc as Rpc
91 88
import qualified Ganeti.Query.Language as Qlang
92 89
import qualified Ganeti.Runtime as Runtime
93 90
import qualified Ganeti.Ssconf as Ssconf
......
281 278
  n <- choose (1, 32)
282 279
  vectorOf n getName
283 280

  
284
-- | Defines a tag type.
285
newtype TagChar = TagChar { tagGetChar :: Char }
286

  
287
-- | All valid tag chars. This doesn't need to match _exactly_
288
-- Ganeti's own tag regex, just enough for it to be close.
289
tagChar :: [Char]
290
tagChar = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ ".+*/:@-"
291

  
292
instance Arbitrary TagChar where
293
  arbitrary = do
294
    c <- elements tagChar
295
    return (TagChar c)
296

  
297
-- | Generates a tag
298
genTag :: Gen [TagChar]
299
genTag = do
300
  -- the correct value would be C.maxTagLen, but that's way too
301
  -- verbose in unittests, and at the moment I don't see any possible
302
  -- bugs with longer tags and the way we use tags in htools
303
  n <- choose (1, 10)
304
  vector n
305

  
306
-- | Generates a list of tags (correctly upper bounded).
307
genTags :: Gen [String]
308
genTags = do
309
  -- the correct value would be C.maxTagsPerObj, but per the comment
310
  -- in genTag, we don't use tags enough in htools to warrant testing
311
  -- such big values
312
  n <- choose (0, 10::Int)
313
  tags <- mapM (const genTag) [1..n]
314
  return $ map (map tagGetChar) tags
315

  
316 281
instance Arbitrary Types.InstanceStatus where
317 282
    arbitrary = elements [minBound..maxBound]
318 283

  
......
489 454
                         , Types.iPolicySpindleRatio = spindle_ratio
490 455
                         }
491 456

  
492
instance Arbitrary Objects.Hypervisor where
493
  arbitrary = elements [minBound..maxBound]
494

  
495
instance Arbitrary Objects.PartialNDParams where
496
  arbitrary = Objects.PartialNDParams <$> arbitrary <*> arbitrary
497

  
498
instance Arbitrary Objects.Node where
499
  arbitrary = Objects.Node <$> getFQDN <*> getFQDN <*> getFQDN
500
              <*> arbitrary <*> arbitrary <*> arbitrary <*> getFQDN
501
              <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
502
              <*> arbitrary <*> arbitrary <*> getFQDN <*> arbitrary
503
              <*> (Set.fromList <$> genTags)
504

  
505
instance Arbitrary Rpc.RpcCallAllInstancesInfo where
506
  arbitrary = Rpc.RpcCallAllInstancesInfo <$> arbitrary
507

  
508
instance Arbitrary Rpc.RpcCallInstanceList where
509
  arbitrary = Rpc.RpcCallInstanceList <$> arbitrary
510

  
511
instance Arbitrary Rpc.RpcCallNodeInfo where
512
  arbitrary = Rpc.RpcCallNodeInfo <$> arbitrary <*> arbitrary
513

  
514 457
-- | Custom 'Qlang.Filter' generator (top-level), which enforces a
515 458
-- (sane) limit on the depth of the generated filters.
516 459
genFilter :: Gen (Qlang.Filter Qlang.FilterField)
......
1976 1919
  [ 'prop_Ssconf_filename
1977 1920
  ]
1978 1921

  
1979
-- * Rpc tests
1980

  
1981
-- | Monadic check that, for an offline node and a call that does not
1982
-- offline nodes, we get a OfflineNodeError response.
1983
-- FIXME: We need a way of generalizing this, running it for
1984
-- every call manually will soon get problematic
1985
prop_Rpc_noffl_request_allinstinfo :: Rpc.RpcCallAllInstancesInfo -> Property
1986
prop_Rpc_noffl_request_allinstinfo call =
1987
  forAll (arbitrary `suchThat` Objects.nodeOffline) $ \node -> monadicIO $ do
1988
      res <- run $ Rpc.executeRpcCall [node] call
1989
      stop $ res ==? [(node, Left (Rpc.OfflineNodeError node))]
1990

  
1991
prop_Rpc_noffl_request_instlist :: Rpc.RpcCallInstanceList -> Property
1992
prop_Rpc_noffl_request_instlist call =
1993
  forAll (arbitrary `suchThat` Objects.nodeOffline) $ \node -> monadicIO $ do
1994
      res <- run $ Rpc.executeRpcCall [node] call
1995
      stop $ res ==? [(node, Left (Rpc.OfflineNodeError node))]
1996

  
1997
prop_Rpc_noffl_request_nodeinfo :: Rpc.RpcCallNodeInfo -> Property
1998
prop_Rpc_noffl_request_nodeinfo call =
1999
  forAll (arbitrary `suchThat` Objects.nodeOffline) $ \node -> monadicIO $ do
2000
      res <- run $ Rpc.executeRpcCall [node] call
2001
      stop $ res ==? [(node, Left (Rpc.OfflineNodeError node))]
2002

  
2003
testSuite "Rpc"
2004
  [ 'prop_Rpc_noffl_request_allinstinfo
2005
  , 'prop_Rpc_noffl_request_instlist
2006
  , 'prop_Rpc_noffl_request_nodeinfo
2007
  ]
2008

  
2009 1922
-- * Qlang tests
2010 1923

  
2011 1924
-- | Tests that serialisation/deserialisation of filters is

Also available in: Unified diff