Statistics
| Branch: | Tag: | Revision:

root / test / py / testutils.py @ 595149d5

History | View | Annotate | Download (6.7 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 c6a65efb Michael Hanselmann
    # The following piece of code is a backport from Python 2.6. Python 2.4/2.5
107 c6a65efb Michael Hanselmann
    # only accept class instances as test runners. Being able to pass classes
108 c6a65efb Michael Hanselmann
    # reduces the amount of code necessary for using a custom test runner.
109 c6a65efb Michael Hanselmann
    # 2.6 and above should use their own code, however.
110 c6a65efb Michael Hanselmann
    if (self.testRunner and sys.hexversion < 0x2060000 and
111 c6a65efb Michael Hanselmann
        isinstance(self.testRunner, (type, types.ClassType))):
112 c6a65efb Michael Hanselmann
      try:
113 c6a65efb Michael Hanselmann
        self.testRunner = self.testRunner(verbosity=self.verbosity)
114 c6a65efb Michael Hanselmann
      except TypeError:
115 c6a65efb Michael Hanselmann
        # didn't accept the verbosity argument
116 c6a65efb Michael Hanselmann
        self.testRunner = self.testRunner()
117 c6a65efb Michael Hanselmann
118 25231ec5 Michael Hanselmann
    return unittest.TestProgram.runTests(self)
119 25231ec5 Michael Hanselmann
120 25231ec5 Michael Hanselmann
121 c9c4f19e Michael Hanselmann
class GanetiTestCase(unittest.TestCase):
122 51596eb2 Iustin Pop
  """Helper class for unittesting.
123 51596eb2 Iustin Pop

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

127 51596eb2 Iustin Pop
  """
128 51596eb2 Iustin Pop
  def setUp(self):
129 51596eb2 Iustin Pop
    self._temp_files = []
130 51596eb2 Iustin Pop
131 51596eb2 Iustin Pop
  def tearDown(self):
132 51596eb2 Iustin Pop
    while self._temp_files:
133 51596eb2 Iustin Pop
      try:
134 51596eb2 Iustin Pop
        utils.RemoveFile(self._temp_files.pop())
135 51596eb2 Iustin Pop
      except EnvironmentError, err:
136 51596eb2 Iustin Pop
        pass
137 51596eb2 Iustin Pop
138 149a5439 Iustin Pop
  def assertFileContent(self, file_name, expected_content):
139 9b977740 Guido Trotter
    """Checks that the content of a file is what we expect.
140 149a5439 Iustin Pop

141 149a5439 Iustin Pop
    @type file_name: str
142 149a5439 Iustin Pop
    @param file_name: the file whose contents we should check
143 149a5439 Iustin Pop
    @type expected_content: str
144 149a5439 Iustin Pop
    @param expected_content: the content we expect
145 149a5439 Iustin Pop

146 149a5439 Iustin Pop
    """
147 149a5439 Iustin Pop
    actual_content = utils.ReadFile(file_name)
148 149a5439 Iustin Pop
    self.assertEqual(actual_content, expected_content)
149 149a5439 Iustin Pop
150 9b977740 Guido Trotter
  def assertFileMode(self, file_name, expected_mode):
151 9b977740 Guido Trotter
    """Checks that the mode of a file is what we expect.
152 9b977740 Guido Trotter

153 9b977740 Guido Trotter
    @type file_name: str
154 9b977740 Guido Trotter
    @param file_name: the file whose contents we should check
155 9b977740 Guido Trotter
    @type expected_mode: int
156 9b977740 Guido Trotter
    @param expected_mode: the mode we expect
157 9b977740 Guido Trotter

158 9b977740 Guido Trotter
    """
159 9b977740 Guido Trotter
    st = os.stat(file_name)
160 9b977740 Guido Trotter
    actual_mode = stat.S_IMODE(st.st_mode)
161 9b977740 Guido Trotter
    self.assertEqual(actual_mode, expected_mode)
162 9b977740 Guido Trotter
163 0d20cc42 Bernardo Dal Seno
  def assertFileUid(self, file_name, expected_uid):
164 0d20cc42 Bernardo Dal Seno
    """Checks that the user 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_uid: int
169 0d20cc42 Bernardo Dal Seno
    @param expected_uid: the user 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_uid = st.st_uid
174 0d20cc42 Bernardo Dal Seno
    self.assertEqual(actual_uid, expected_uid)
175 0d20cc42 Bernardo Dal Seno
176 0d20cc42 Bernardo Dal Seno
  def assertFileGid(self, file_name, expected_gid):
177 0d20cc42 Bernardo Dal Seno
    """Checks that the group id of a file is what we expect.
178 0d20cc42 Bernardo Dal Seno

179 0d20cc42 Bernardo Dal Seno
    @type file_name: str
180 0d20cc42 Bernardo Dal Seno
    @param file_name: the file whose contents we should check
181 0d20cc42 Bernardo Dal Seno
    @type expected_gid: int
182 0d20cc42 Bernardo Dal Seno
    @param expected_gid: the group id we expect
183 0d20cc42 Bernardo Dal Seno

184 0d20cc42 Bernardo Dal Seno
    """
185 0d20cc42 Bernardo Dal Seno
    st = os.stat(file_name)
186 0d20cc42 Bernardo Dal Seno
    actual_gid = st.st_gid
187 0d20cc42 Bernardo Dal Seno
    self.assertEqual(actual_gid, expected_gid)
188 0d20cc42 Bernardo Dal Seno
189 d357f531 Michael Hanselmann
  def assertEqualValues(self, first, second, msg=None):
190 d357f531 Michael Hanselmann
    """Compares two values whether they're equal.
191 d357f531 Michael Hanselmann

192 d357f531 Michael Hanselmann
    Tuples are automatically converted to lists before comparing.
193 d357f531 Michael Hanselmann

194 d357f531 Michael Hanselmann
    """
195 d357f531 Michael Hanselmann
    return self.assertEqual(UnifyValueType(first),
196 d357f531 Michael Hanselmann
                            UnifyValueType(second),
197 d357f531 Michael Hanselmann
                            msg=msg)
198 d357f531 Michael Hanselmann
199 51596eb2 Iustin Pop
  def _CreateTempFile(self):
200 51596eb2 Iustin Pop
    """Creates a temporary file and adds it to the internal cleanup list.
201 51596eb2 Iustin Pop

202 51596eb2 Iustin Pop
    This method simplifies the creation and cleanup of temporary files
203 51596eb2 Iustin Pop
    during tests.
204 51596eb2 Iustin Pop

205 51596eb2 Iustin Pop
    """
206 51596eb2 Iustin Pop
    fh, fname = tempfile.mkstemp(prefix="ganeti-test", suffix=".tmp")
207 51596eb2 Iustin Pop
    os.close(fh)
208 51596eb2 Iustin Pop
    self._temp_files.append(fname)
209 51596eb2 Iustin Pop
    return fname
210 d357f531 Michael Hanselmann
211 d357f531 Michael Hanselmann
212 d357f531 Michael Hanselmann
def UnifyValueType(data):
213 d357f531 Michael Hanselmann
  """Converts all tuples into lists.
214 d357f531 Michael Hanselmann

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

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

231 ebfb2f46 Michael Hanselmann
  """
232 ebfb2f46 Michael Hanselmann
  def __init__(self, fn):
233 ebfb2f46 Michael Hanselmann
    """Initializes this class.
234 ebfb2f46 Michael Hanselmann

235 ebfb2f46 Michael Hanselmann
    @type fn: Callable
236 ebfb2f46 Michael Hanselmann

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

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

251 ebfb2f46 Michael Hanselmann
    @rtype: number
252 ebfb2f46 Michael Hanselmann

253 ebfb2f46 Michael Hanselmann
    """
254 ebfb2f46 Michael Hanselmann
    return self._count