Revision e969a81f test/py/cmdlib/testsupport/cmdlib_testcase.py

b/test/py/cmdlib/testsupport/cmdlib_testcase.py
22 22
"""Main module of the cmdlib test framework"""
23 23

  
24 24

  
25
import inspect
26
import re
27
import traceback
28

  
25 29
from cmdlib.testsupport.config_mock import ConfigMock
26
from cmdlib.testsupport.iallocator_mock import CreateIAllocatorMock
30
from cmdlib.testsupport.iallocator_mock import patchIAllocator
27 31
from cmdlib.testsupport.lock_manager_mock import LockManagerMock
28 32
from cmdlib.testsupport.processor_mock import ProcessorMock
29 33
from cmdlib.testsupport.rpc_runner_mock import CreateRpcRunnerMock
30 34

  
35
from ganeti import errors
36
from ganeti import opcodes
37

  
31 38
import testutils
32 39

  
33 40

  
......
50 57
    * C{cfg}: @see L{ConfigMock}
51 58
    * C{glm}: @see L{LockManagerMock}
52 59
    * C{rpc}: @see L{CreateRpcRunnerMock}
53
    * C{iallocator}: @see L{CreateIAllocatorMock}
60
    * C{iallocator_cls}: @see L{patchIAllocator}
54 61
    * C{mcpu}: @see L{ProcessorMock}
55 62

  
56 63
  """
64

  
65
  REMOVE = object()
66

  
57 67
  def setUp(self):
58 68
    super(CmdlibTestCase, self).setUp()
69
    self._iallocator_patcher = None
70

  
71
    self.ResetMocks()
72

  
73
  def _StopPatchers(self):
74
    if self._iallocator_patcher is not None:
75
      self._iallocator_patcher.stop()
76
      self._iallocator_patcher = None
77

  
78
  def tearDown(self):
79
    super(CmdlibTestCase, self).tearDown()
59 80

  
81
    self._StopPatchers()
82

  
83
  def _GetTestModule(self):
84
    module = inspect.getsourcefile(self.__class__).split("/")[-1]
85
    suffix = "_unittest.py"
86
    assert module.endswith(suffix), "Naming convention for cmdlib test" \
87
                                    " modules is: <module>%s (found '%s')"\
88
                                    % (suffix, module)
89
    return module[:-len(suffix)]
90

  
91
  def ResetMocks(self):
92
    """Resets all mocks back to their initial state.
93

  
94
    This is useful if you want to execute more than one opcode in a single
95
    test.
96

  
97
    """
60 98
    self.cfg = ConfigMock()
61 99
    self.glm = LockManagerMock()
62 100
    self.rpc = CreateRpcRunnerMock()
63
    self.iallocator = CreateIAllocatorMock()
101

  
102
    self._StopPatchers()
103
    try:
104
      self._iallocator_patcher = patchIAllocator(self._GetTestModule())
105
      self.iallocator_cls = self._iallocator_patcher.start()
106
    except ImportError:
107
      # this test module does not use iallocator, no patching performed
108
      self._iallocator_patcher = None
109

  
64 110
    ctx = GanetiContextMock(self.cfg, self.glm, self.rpc)
65 111
    self.mcpu = ProcessorMock(ctx)
66 112

  
67
  def tearDown(self):
68
    super(CmdlibTestCase, self).tearDown()
69

  
70 113
  def ExecOpCode(self, opcode):
71 114
    """Executes the given opcode.
72 115

  
73 116
    @param opcode: the opcode to execute
74 117
    @return: the result of the LU's C{Exec} method
118

  
75 119
    """
76 120
    self.glm.AddLocksFromConfig(self.cfg)
77 121

  
78 122
    return self.mcpu.ExecOpCodeAndRecordOutput(opcode)
79 123

  
124
  def ExecOpCodeExpectException(self, opcode,
125
                                expected_exception,
126
                                expected_regex=None):
127
    """Executes the given opcode and expects an exception.
128

  
129
    @param opcode: @see L{ExecOpCode}
130
    @type expected_exception: class
131
    @param expected_exception: the exception which must be raised
132
    @type expected_regex: string
133
    @param expected_regex: if not C{None}, a regular expression which must be
134
          present in the string representation of the exception
135

  
136
    """
137
    try:
138
      self.ExecOpCode(opcode)
139
    except expected_exception, e:
140
      if expected_regex is not None:
141
        assert re.search(expected_regex, str(e)) is not None, \
142
                "Caught exception '%s' did not match '%s'" % \
143
                  (str(e), expected_regex)
144
    except Exception, e:
145
      tb = traceback.format_exc()
146
      raise AssertionError("%s\n(See original exception above)\n"
147
                           "Expected exception '%s' was not raised,"
148
                           " got '%s' of class '%s' instead." %
149
                           (tb, expected_exception, e, e.__class__))
150
    else:
151
      raise AssertionError("Expected exception '%s' was not raised" %
152
                           expected_exception)
153

  
154
  def ExecOpCodeExpectOpPrereqError(self, opcode, expected_regex=None):
155
    """Executes the given opcode and expects a L{errors.OpPrereqError}
156

  
157
    @see L{ExecOpCodeExpectException}
158

  
159
    """
160
    self.ExecOpCodeExpectException(opcode, errors.OpPrereqError, expected_regex)
161

  
162
  def ExecOpCodeExpectOpExecError(self, opcode, expected_regex=None):
163
    """Executes the given opcode and expects a L{errors.OpExecError}
164

  
165
    @see L{ExecOpCodeExpectException}
166

  
167
    """
168
    self.ExecOpCodeExpectException(opcode, errors.OpExecError, expected_regex)
169

  
80 170
  def assertLogContainsMessage(self, expected_msg):
81 171
    """Shortcut for L{ProcessorMock.assertLogContainsMessage}
82 172

  
......
89 179
    """
90 180
    self.mcpu.assertLogContainsRegex(expected_regex)
91 181

  
182
  def CopyOpCode(self, opcode, **kwargs):
183
    """Creates a copy of the given opcode and applies modifications to it
184

  
185
    @type opcode: opcode.OpCode
186
    @param opcode: the opcode to copy
187
    @type kwargs: dict
188
    @param kwargs: dictionary of fields to overwrite in the copy. The special
189
          value L{REMOVE} can be used to remove fields from the copy.
190
    @return: a copy of the given opcode
191

  
192
    """
193
    state = opcode.__getstate__()
194

  
195
    for key, value in kwargs.items():
196
      if value == self.REMOVE:
197
        del state[key]
198
      else:
199
        state[key] = value
200

  
201
    return opcodes.OpCode.LoadOpCode(state)

Also available in: Unified diff