LGTM, thanks for the extensive test!

On Tue, May 17, 2016 at 12:15 PM, 'Brian Foley' via ganeti-devel <
[email protected]> wrote:

> Improve mocks and add a unit test to test this case.
>
> Signed-off-by: Brian Foley <[email protected]>
> ---
>  lib/mcpu.py                     |  4 +--
>  test/py/ganeti.mcpu_unittest.py | 35 +++++++++++++++++++++++
>  test/py/mocks.py                | 61
> +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 98 insertions(+), 2 deletions(-)
>
> diff --git a/lib/mcpu.py b/lib/mcpu.py
> index 689b89c..2255cec 100644
> --- a/lib/mcpu.py
> +++ b/lib/mcpu.py
> @@ -538,9 +538,9 @@ class Processor(object):
>        try:
>          result = self._ExecLU(lu)
>        except errors.OpPrereqError, err:
> -        (_, ecode) = err.args
> -        if ecode != errors.ECODE_TEMP_NORES:
> +        if len(err.args) < 2 or err.args[1] != errors.ECODE_TEMP_NORES:
>            raise
> +
>          logging.debug("Temporarily out of resources; will retry
> internally")
>          try:
>            lu.PrepareRetry(self.Log)
> diff --git a/test/py/ganeti.mcpu_unittest.py b/test/py/
> ganeti.mcpu_unittest.py
> index 18fabd8..796c2ba 100755
> --- a/test/py/ganeti.mcpu_unittest.py
> +++ b/test/py/ganeti.mcpu_unittest.py
> @@ -33,12 +33,16 @@
>
>  import unittest
>  import itertools
> +import mocks
> +from cmdlib.testsupport.rpc_runner_mock import CreateRpcRunnerMock
>
>  from ganeti import compat
>  from ganeti import mcpu
>  from ganeti import opcodes
>  from ganeti import cmdlib
>  from ganeti import locking
> +from ganeti import ht
> +from ganeti import errors
>  from ganeti import constants
>  from ganeti.constants import \
>      LOCK_ATTEMPTS_TIMEOUT, \
> @@ -175,6 +179,37 @@ class TestProcessResult(unittest.TestCase):
>      self.assertEqual(op2.comment, "foobar")
>      self.assertEqual(op2.debug_level, 3)
>
> +class TestExecLU(unittest.TestCase):
> +  class OpTest(opcodes.OpCode):
> +    OP_DSC_FIELD = "data"
> +    OP_PARAMS = [
> +      ("data", ht.NoDefault, ht.TString, None),
> +    ]
> +
> +  def setUp(self):
> +    self.ctx = mocks.FakeContext()
> +    self.cfg = self.ctx.GetConfig("ec_id")
> +    self.rpc = CreateRpcRunnerMock()
> +    self.proc = mcpu.Processor(self.ctx, "ec_id", enable_locks = False)
> +    self.op = self.OpTest()
> +    self.calc_timeout = lambda: 42
> +
> +  def testRunLU(self):
> +    lu = mocks.FakeLU(self.proc, self.op, self.cfg, self.rpc, None)
> +    self.proc._ExecLU(lu)
> +
> +  def testRunLUWithPrereqError(self):
> +    prereq = errors.OpPrereqError(self.op, errors.ECODE_INVAL)
> +    lu = mocks.FakeLU(self.proc, self.op, self.cfg, self.rpc, prereq)
> +    self.assertRaises(errors.OpPrereqError, self.proc._LockAndExecLU,
> +        lu, locking.LEVEL_CLUSTER, self.calc_timeout)
> +
> +  def testRunLUWithPrereqErrorMissingECode(self):
> +    prereq = errors.OpPrereqError(self.op)
> +    lu = mocks.FakeLU(self.proc, self.op, self.cfg, self.rpc, prereq)
> +    self.assertRaises(errors.OpPrereqError, self.proc._LockAndExecLU,
> +        lu, locking.LEVEL_CLUSTER, self.calc_timeout)
> +
>
>  if __name__ == "__main__":
>    testutils.GanetiTestProgram()
> diff --git a/test/py/mocks.py b/test/py/mocks.py
> index 649b032..406caca 100644
> --- a/test/py/mocks.py
> +++ b/test/py/mocks.py
> @@ -33,6 +33,7 @@
>
>  import os
>
> +from ganeti import locking
>  from ganeti import netutils
>
>
> @@ -47,6 +48,11 @@ FAKE_CLUSTER_KEY =
> ("AAAAB3NzaC1yc2EAAAABIwAAAQEAsuGLw70et3eApJ/ZEJkAVZogIrm"
>
>  class FakeConfig(object):
>    """Fake configuration object"""
> +  def __init__(self):
> +    self.write_count = 0
> +
> +  def OutDate(self):
> +    pass
>
>    def IsCluster(self):
>      return True
> @@ -112,6 +118,14 @@ class FakeContext(object):
>      self.cfg = FakeConfig()
>      self.glm = FakeGLM()
>
> +  def GetConfig(self, ec_id):
> +    return self.cfg
> +
> +  def GetRpc(self, cfg):
> +    return None
> +
> +  def GetWConfdContext(self, _ec_id):
> +    return (None, None, None)
>
>  class FakeGetentResolver(object):
>    """Fake runtime.GetentResolver"""
> @@ -139,3 +153,50 @@ class FakeGetentResolver(object):
>
>    def LookupGid(self, gid):
>      return "group%s" % gid
> +
> +class FakeLU(object):
> +  HPATH = "fake-lu"
> +  HTYPE = None
> +
> +  def __init__(self, processor, op, cfg, rpc_runner, prereq_err):
> +    self.proc = processor
> +    self.cfg = cfg
> +    self.op  = op
> +    self.rpc = rpc_runner
> +    self.prereq_err = prereq_err
> +
> +    self.needed_locks = {}
> +    self.opportunistic_locks = dict.fromkeys(locking.LEVELS, False)
> +    self.dont_collate_locks = dict.fromkeys(locking.LEVELS, False)
> +    self.add_locks = {}
> +
> +    self.LogWarning = processor.LogWarning
> +
> +  def CheckArguments(self):
> +    pass
> +
> +  def ExpandNames(self):
> +    pass
> +
> +  def DeclareLocks(self, level):
> +    pass
> +
> +  def CheckPrereq(self):
> +    if self.prereq_err:
> +      raise self.prereq_err
> +    pass
> +
> +  def Exec(self, feedback_fn):
> +    pass
> +
> +  def BuildHooksNodes(self):
> +    return ([], [])
> +
> +  def BuildHooksEnv(self):
> +    return {}
> +
> +  def PreparePostHookNodes(self, post_hook_node_uuids):
> +    return []
> +
> +  def HooksCallBack(self, phase, hook_results, feedback_fn, lu_result):
> +    return lu_result
> --
> 2.8.0.rc3.226.g39d4020
>
>

Reply via email to