Statistics
| Branch: | Tag: | Revision:

root / test / py / testutils.py @ 5ce621ab

History | View | Annotate | Download (6.6 kB)

1 c9c4f19e Michael Hanselmann
#
2 c9c4f19e Michael Hanselmann
#
3 c9c4f19e Michael Hanselmann
4 c9c4f19e Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 c9c4f19e Michael Hanselmann
#
6 c9c4f19e Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 c9c4f19e Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 c9c4f19e Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 c9c4f19e Michael Hanselmann
# (at your option) any later version.
10 c9c4f19e Michael Hanselmann
#
11 c9c4f19e Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 c9c4f19e Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 c9c4f19e Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 c9c4f19e Michael Hanselmann
# General Public License for more details.
15 c9c4f19e Michael Hanselmann
#
16 c9c4f19e Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 c9c4f19e Michael Hanselmann
# along with this program; if not, write to the Free Software
18 c9c4f19e Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 c9c4f19e Michael Hanselmann
# 02110-1301, USA.
20 c9c4f19e Michael Hanselmann
21 c9c4f19e Michael Hanselmann
22 c9c4f19e Michael Hanselmann
"""Utilities for unit testing"""
23 c9c4f19e Michael Hanselmann
24 149a5439 Iustin Pop
import os
25 43983a88 Michael Hanselmann
import sys
26 9b977740 Guido Trotter
import stat
27 51596eb2 Iustin Pop
import tempfile
28 c9c4f19e Michael Hanselmann
import unittest
29 25231ec5 Michael Hanselmann
import logging
30 c9c4f19e Michael Hanselmann
31 149a5439 Iustin Pop
from ganeti import utils
32 149a5439 Iustin Pop
33 c9c4f19e Michael Hanselmann
34 3f991867 Michael Hanselmann
def GetSourceDir():
35 3f991867 Michael Hanselmann
  return os.environ.get("TOP_SRCDIR", ".")
36 3f991867 Michael Hanselmann
37 3f991867 Michael Hanselmann
38 00ef625c Michael Hanselmann
def TestDataFilename(name):
39 00ef625c Michael Hanselmann
  """Returns the filename of a given test data file.
40 00ef625c Michael Hanselmann

41 00ef625c Michael Hanselmann
  @type name: str
42 00ef625c Michael Hanselmann
  @param name: the 'base' of the file name, as present in
43 00ef625c Michael Hanselmann
      the test/data directory
44 00ef625c Michael Hanselmann
  @rtype: str
45 00ef625c Michael Hanselmann
  @return: the full path to the filename, such that it can
46 00ef625c Michael Hanselmann
      be used in 'make distcheck' rules
47 00ef625c Michael Hanselmann

48 00ef625c Michael Hanselmann
  """
49 00ef625c Michael Hanselmann
  return "%s/test/data/%s" % (GetSourceDir(), name)
50 00ef625c Michael Hanselmann
51 00ef625c Michael Hanselmann
52 00ef625c Michael Hanselmann
def ReadTestData(name):
53 00ef625c Michael Hanselmann
  """Returns the content of a test data file.
54 00ef625c Michael Hanselmann

55 00ef625c Michael Hanselmann
  This is just a very simple wrapper over utils.ReadFile with the
56 00ef625c Michael Hanselmann
  proper test file name.
57 00ef625c Michael Hanselmann

58 00ef625c Michael Hanselmann
  """
59 00ef625c Michael Hanselmann
  return utils.ReadFile(TestDataFilename(name))
60 00ef625c Michael Hanselmann
61 00ef625c Michael Hanselmann
62 913138f4 Michael Hanselmann
def _SetupLogging(verbose):
63 913138f4 Michael Hanselmann
  """Setupup logging infrastructure.
64 913138f4 Michael Hanselmann

65 913138f4 Michael Hanselmann
  """
66 913138f4 Michael Hanselmann
  fmt = logging.Formatter("%(asctime)s: %(threadName)s"
67 913138f4 Michael Hanselmann
                          " %(levelname)s %(message)s")
68 913138f4 Michael Hanselmann
69 913138f4 Michael Hanselmann
  if verbose:
70 913138f4 Michael Hanselmann
    handler = logging.StreamHandler()
71 913138f4 Michael Hanselmann
  else:
72 913138f4 Michael Hanselmann
    handler = logging.FileHandler(os.devnull, "a")
73 913138f4 Michael Hanselmann
74 913138f4 Michael Hanselmann
  handler.setLevel(logging.NOTSET)
75 913138f4 Michael Hanselmann
  handler.setFormatter(fmt)
76 913138f4 Michael Hanselmann
77 913138f4 Michael Hanselmann
  root_logger = logging.getLogger("")
78 913138f4 Michael Hanselmann
  root_logger.setLevel(logging.NOTSET)
79 913138f4 Michael Hanselmann
  root_logger.addHandler(handler)
80 913138f4 Michael Hanselmann
81 913138f4 Michael Hanselmann
82 25231ec5 Michael Hanselmann
class GanetiTestProgram(unittest.TestProgram):
83 25231ec5 Michael Hanselmann
  def runTests(self):
84 913138f4 Michael Hanselmann
    """Runs all tests.
85 25231ec5 Michael Hanselmann

86 25231ec5 Michael Hanselmann
    """
87 913138f4 Michael Hanselmann
    _SetupLogging("LOGTOSTDERR" in os.environ)
88 43983a88 Michael Hanselmann
89 43983a88 Michael Hanselmann
    sys.stderr.write("Running %s\n" % self.progName)
90 43983a88 Michael Hanselmann
    sys.stderr.flush()
91 43983a88 Michael Hanselmann
92 a9b144cb Michael Hanselmann
    # Ensure assertions will be evaluated
93 a9b144cb Michael Hanselmann
    if not __debug__:
94 a9b144cb Michael Hanselmann
      raise Exception("Not running in debug mode, assertions would not be"
95 a9b144cb Michael Hanselmann
                      " evaluated")
96 a9b144cb Michael Hanselmann
97 a9b144cb Michael Hanselmann
    # Check again, this time with a real assertion
98 a9b144cb Michael Hanselmann
    try:
99 a9b144cb Michael Hanselmann
      assert False
100 a9b144cb Michael Hanselmann
    except AssertionError:
101 a9b144cb Michael Hanselmann
      pass
102 a9b144cb Michael Hanselmann
    else:
103 a9b144cb Michael Hanselmann
      raise Exception("Assertion not evaluated")
104 a9b144cb Michael Hanselmann
105 25231ec5 Michael Hanselmann
    return unittest.TestProgram.runTests(self)
106 25231ec5 Michael Hanselmann
107 25231ec5 Michael Hanselmann
108 c9c4f19e Michael Hanselmann
class GanetiTestCase(unittest.TestCase):
109 51596eb2 Iustin Pop
  """Helper class for unittesting.
110 51596eb2 Iustin Pop

111 51596eb2 Iustin Pop
  This class defines a few utility functions that help in building
112 51596eb2 Iustin Pop
  unittests. Child classes must call the parent setup and cleanup.
113 51596eb2 Iustin Pop

114 51596eb2 Iustin Pop
  """
115 51596eb2 Iustin Pop
  def setUp(self):
116 51596eb2 Iustin Pop
    self._temp_files = []
117 51596eb2 Iustin Pop
118 51596eb2 Iustin Pop
  def tearDown(self):
119 51596eb2 Iustin Pop
    while self._temp_files:
120 51596eb2 Iustin Pop
      try:
121 51596eb2 Iustin Pop
        utils.RemoveFile(self._temp_files.pop())
122 bd39b6bb Thomas Thrainer
      except EnvironmentError:
123 51596eb2 Iustin Pop
        pass
124 51596eb2 Iustin Pop
125 149a5439 Iustin Pop
  def assertFileContent(self, file_name, expected_content):
126 9b977740 Guido Trotter
    """Checks that the content of a file is what we expect.
127 149a5439 Iustin Pop

128 149a5439 Iustin Pop
    @type file_name: str
129 149a5439 Iustin Pop
    @param file_name: the file whose contents we should check
130 149a5439 Iustin Pop
    @type expected_content: str
131 149a5439 Iustin Pop
    @param expected_content: the content we expect
132 149a5439 Iustin Pop

133 149a5439 Iustin Pop
    """
134 149a5439 Iustin Pop
    actual_content = utils.ReadFile(file_name)
135 149a5439 Iustin Pop
    self.assertEqual(actual_content, expected_content)
136 149a5439 Iustin Pop
137 9b977740 Guido Trotter
  def assertFileMode(self, file_name, expected_mode):
138 9b977740 Guido Trotter
    """Checks that the mode of a file is what we expect.
139 9b977740 Guido Trotter

140 9b977740 Guido Trotter
    @type file_name: str
141 9b977740 Guido Trotter
    @param file_name: the file whose contents we should check
142 9b977740 Guido Trotter
    @type expected_mode: int
143 9b977740 Guido Trotter
    @param expected_mode: the mode we expect
144 9b977740 Guido Trotter

145 9b977740 Guido Trotter
    """
146 9b977740 Guido Trotter
    st = os.stat(file_name)
147 9b977740 Guido Trotter
    actual_mode = stat.S_IMODE(st.st_mode)
148 9b977740 Guido Trotter
    self.assertEqual(actual_mode, expected_mode)
149 9b977740 Guido Trotter
150 0d20cc42 Bernardo Dal Seno
  def assertFileUid(self, file_name, expected_uid):
151 0d20cc42 Bernardo Dal Seno
    """Checks that the user id of a file is what we expect.
152 0d20cc42 Bernardo Dal Seno

153 0d20cc42 Bernardo Dal Seno
    @type file_name: str
154 0d20cc42 Bernardo Dal Seno
    @param file_name: the file whose contents we should check
155 0d20cc42 Bernardo Dal Seno
    @type expected_uid: int
156 0d20cc42 Bernardo Dal Seno
    @param expected_uid: the user id we expect
157 0d20cc42 Bernardo Dal Seno

158 0d20cc42 Bernardo Dal Seno
    """
159 0d20cc42 Bernardo Dal Seno
    st = os.stat(file_name)
160 0d20cc42 Bernardo Dal Seno
    actual_uid = st.st_uid
161 0d20cc42 Bernardo Dal Seno
    self.assertEqual(actual_uid, expected_uid)
162 0d20cc42 Bernardo Dal Seno
163 0d20cc42 Bernardo Dal Seno
  def assertFileGid(self, file_name, expected_gid):
164 0d20cc42 Bernardo Dal Seno
    """Checks that the group id of a file is what we expect.
165 0d20cc42 Bernardo Dal Seno

166 0d20cc42 Bernardo Dal Seno
    @type file_name: str
167 0d20cc42 Bernardo Dal Seno
    @param file_name: the file whose contents we should check
168 0d20cc42 Bernardo Dal Seno
    @type expected_gid: int
169 0d20cc42 Bernardo Dal Seno
    @param expected_gid: the group id we expect
170 0d20cc42 Bernardo Dal Seno

171 0d20cc42 Bernardo Dal Seno
    """
172 0d20cc42 Bernardo Dal Seno
    st = os.stat(file_name)
173 0d20cc42 Bernardo Dal Seno
    actual_gid = st.st_gid
174 0d20cc42 Bernardo Dal Seno
    self.assertEqual(actual_gid, expected_gid)
175 0d20cc42 Bernardo Dal Seno
176 d357f531 Michael Hanselmann
  def assertEqualValues(self, first, second, msg=None):
177 d357f531 Michael Hanselmann
    """Compares two values whether they're equal.
178 d357f531 Michael Hanselmann

179 d357f531 Michael Hanselmann
    Tuples are automatically converted to lists before comparing.
180 d357f531 Michael Hanselmann

181 d357f531 Michael Hanselmann
    """
182 d357f531 Michael Hanselmann
    return self.assertEqual(UnifyValueType(first),
183 d357f531 Michael Hanselmann
                            UnifyValueType(second),
184 d357f531 Michael Hanselmann
                            msg=msg)
185 d357f531 Michael Hanselmann
186 51596eb2 Iustin Pop
  def _CreateTempFile(self):
187 51596eb2 Iustin Pop
    """Creates a temporary file and adds it to the internal cleanup list.
188 51596eb2 Iustin Pop

189 51596eb2 Iustin Pop
    This method simplifies the creation and cleanup of temporary files
190 51596eb2 Iustin Pop
    during tests.
191 51596eb2 Iustin Pop

192 51596eb2 Iustin Pop
    """
193 51596eb2 Iustin Pop
    fh, fname = tempfile.mkstemp(prefix="ganeti-test", suffix=".tmp")
194 51596eb2 Iustin Pop
    os.close(fh)
195 51596eb2 Iustin Pop
    self._temp_files.append(fname)
196 51596eb2 Iustin Pop
    return fname
197 d357f531 Michael Hanselmann
198 d357f531 Michael Hanselmann
199 74db37c0 Thomas Thrainer
def patch_object(*args, **kwargs):
200 74db37c0 Thomas Thrainer
  """Unified patch_object for various versions of Python Mock.
201 74db37c0 Thomas Thrainer

202 74db37c0 Thomas Thrainer
  Different Python Mock versions provide incompatible versions of patching an
203 74db37c0 Thomas Thrainer
  object. More recent versions use _patch_object, older ones used patch_object.
204 74db37c0 Thomas Thrainer
  This function unifies the different variations.
205 74db37c0 Thomas Thrainer

206 74db37c0 Thomas Thrainer
  """
207 74db37c0 Thomas Thrainer
  import mock
208 74db37c0 Thomas Thrainer
  try:
209 bd39b6bb Thomas Thrainer
    # pylint: disable=W0212
210 74db37c0 Thomas Thrainer
    return mock._patch_object(*args, **kwargs)
211 74db37c0 Thomas Thrainer
  except AttributeError:
212 bd39b6bb Thomas Thrainer
    # pylint: disable=E1101
213 74db37c0 Thomas Thrainer
    return mock.patch_object(*args, **kwargs)
214 74db37c0 Thomas Thrainer
215 74db37c0 Thomas Thrainer
216 d357f531 Michael Hanselmann
def UnifyValueType(data):
217 d357f531 Michael Hanselmann
  """Converts all tuples into lists.
218 d357f531 Michael Hanselmann

219 d357f531 Michael Hanselmann
  This is useful for unittests where an external library doesn't keep types.
220 d357f531 Michael Hanselmann

221 d357f531 Michael Hanselmann
  """
222 d357f531 Michael Hanselmann
  if isinstance(data, (tuple, list)):
223 d357f531 Michael Hanselmann
    return [UnifyValueType(i) for i in data]
224 d357f531 Michael Hanselmann
225 d357f531 Michael Hanselmann
  elif isinstance(data, dict):
226 d357f531 Michael Hanselmann
    return dict([(UnifyValueType(key), UnifyValueType(value))
227 d357f531 Michael Hanselmann
                 for (key, value) in data.iteritems()])
228 d357f531 Michael Hanselmann
229 d357f531 Michael Hanselmann
  return data
230 ebfb2f46 Michael Hanselmann
231 ebfb2f46 Michael Hanselmann
232 ebfb2f46 Michael Hanselmann
class CallCounter(object):
233 ebfb2f46 Michael Hanselmann
  """Utility class to count number of calls to a function/method.
234 ebfb2f46 Michael Hanselmann

235 ebfb2f46 Michael Hanselmann
  """
236 ebfb2f46 Michael Hanselmann
  def __init__(self, fn):
237 ebfb2f46 Michael Hanselmann
    """Initializes this class.
238 ebfb2f46 Michael Hanselmann

239 ebfb2f46 Michael Hanselmann
    @type fn: Callable
240 ebfb2f46 Michael Hanselmann

241 ebfb2f46 Michael Hanselmann
    """
242 ebfb2f46 Michael Hanselmann
    self._fn = fn
243 ebfb2f46 Michael Hanselmann
    self._count = 0
244 ebfb2f46 Michael Hanselmann
245 ebfb2f46 Michael Hanselmann
  def __call__(self, *args, **kwargs):
246 ebfb2f46 Michael Hanselmann
    """Calls wrapped function with given parameters.
247 ebfb2f46 Michael Hanselmann

248 ebfb2f46 Michael Hanselmann
    """
249 ebfb2f46 Michael Hanselmann
    self._count += 1
250 ebfb2f46 Michael Hanselmann
    return self._fn(*args, **kwargs)
251 ebfb2f46 Michael Hanselmann
252 ebfb2f46 Michael Hanselmann
  def Count(self):
253 ebfb2f46 Michael Hanselmann
    """Returns number of calls.
254 ebfb2f46 Michael Hanselmann

255 ebfb2f46 Michael Hanselmann
    @rtype: number
256 ebfb2f46 Michael Hanselmann

257 ebfb2f46 Michael Hanselmann
    """
258 ebfb2f46 Michael Hanselmann
    return self._count