Statistics
| Branch: | Tag: | Revision:

root / test / py / testutils.py @ 2fe9deec

History | View | Annotate | Download (6.5 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 c6a65efb Michael Hanselmann
import types
31 c9c4f19e Michael Hanselmann
32 149a5439 Iustin Pop
from ganeti import utils
33 149a5439 Iustin Pop
34 c9c4f19e Michael Hanselmann
35 3f991867 Michael Hanselmann
def GetSourceDir():
36 3f991867 Michael Hanselmann
  return os.environ.get("TOP_SRCDIR", ".")
37 3f991867 Michael Hanselmann
38 3f991867 Michael Hanselmann
39 00ef625c Michael Hanselmann
def TestDataFilename(name):
40 00ef625c Michael Hanselmann
  """Returns the filename of a given test data file.
41 00ef625c Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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