Merge lp:~thekorn/zeitgeist/fix-634740-634744-testrunner-improvements into lp:zeitgeist/0.1
- fix-634740-634744-testrunner-improvements
- Merge into 0.8-python
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 1602 | ||||||||
Proposed branch: | lp:~thekorn/zeitgeist/fix-634740-634744-testrunner-improvements | ||||||||
Merge into: | lp:zeitgeist/0.1 | ||||||||
Diff against target: |
607 lines (+293/-76) 9 files modified
bug_testrunner.py (+10/-0) test/blacklist-test.py (+3/-1) test/engine-extension-test.py (+26/-18) test/engine-test.py (+6/-4) test/loggers-datasources-recent-test.py (+16/-4) test/remote-test.py (+36/-9) test/run-all-tests.py (+98/-27) test/sql-test.py (+7/-1) test/testutils.py (+91/-12) |
||||||||
To merge this branch: | bzr merge lp:~thekorn/zeitgeist/fix-634740-634744-testrunner-improvements | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Siegfried Gevatter | Approve | ||
Seif Lotfy | Needs Fixing | ||
Review via email: mp+36134@code.launchpad.net |
Commit message
Description of the change
* Make sure to run all tests using its own temporary ZEITGEIST_
* `make check` (or `test/run-
- 1599. By Markus Korn
-
merged recent changes from lp:zeitgeist
Seif Lotfy (seif) wrote : | # |
Seif Lotfy (seif) : | # |
Seif Lotfy (seif) wrote : | # |
Here is the full output when running test/run-
-------
seif@Wumbo:
[dix] Could not init font path element /usr/share/
5 XSELINUXs still allocated at reset
SCREEN: 0 objects of 68 bytes = 0 total bytes 0 private allocs
DEVICE: 4 objects of 16 bytes = 64 total bytes 0 private allocs
CLIENT: 0 objects of 152 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 16 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 72 bytes, 0 allocs
4 DEVICEs still allocated at reset
DEVICE: 4 objects of 16 bytes = 64 total bytes 0 private allocs
CLIENT: 0 objects of 152 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 16 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 72 bytes, 0 allocs
1 PIXMAPs still allocated at reset
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 1 objects, 8 bytes, 0 allocs
[dix] Could not init font path element /usr/share/
Doctest: test-engine-
test_mime_none (mimetypes-
test_mime_regex (mimetypes-
test_textplain (mimetypes-
test_scheme_file (mimetypes-
test_scheme_none (mimetypes-
testDeleteHook (engine-
testGetHook (engine-
testInsertHook (engine-
testCreateEngine (engine-
for now we raise a ValueError if someone wants to search ... ok
testInTimeRange (datamodel-
testNegationCom
testNegationFields (datamodel-
testNegationTem
testNegationWil
testNewForValues1 (datamodel-
testNewForValues2 (datamodel-
testSimple (datamodel-
testTemplateFil
testTemplateMat
testTemplatePar
Markus Korn (thekorn) wrote : | # |
> It still fails with the blacklist-test.py! I had to quit zeitgeist manually
> for the tests to succeed. Here is my print out.
>
>
> seif@Wumbo:
> EEEE
[...]
Please note, the private/temporary DBus bus only works if you run the whole testsuite, by running `make check` or `test/run-
I did not want to fire-up one temporary bus for each testcase, because I think this operation is too expensive (time consuming). And unfortunatly python2.5's unittest module does not have a way for module-wide setUp/tearDown methods.
- 1600. By Markus Korn
-
merged recent changes from lp:zeitgeist and resolved conflicts
- 1601. By Markus Korn
-
replaced spaces by tabs
- 1602. By Markus Korn
-
* print some information to stderr about the running private dbus bus
* add 'ignore_errors' option to DBusPrivateMessageBus. {run(), quit()}
failures in these methods should never cause the actual tests to fail,
as a fallback the old way (using the users session bus) will be used - 1603. By Markus Korn
-
be more verbose in RuntimeError in case the zeitgeist-daemon fails to start in the testsuite
- 1604. By Markus Korn
-
* try to be more verbose in the testcases in case of zeitgeist-daemon
failures - 1605. By Markus Korn
-
added missing lazy import
- 1606. By Markus Korn
-
be even more verbose
- 1607. By Markus Korn
-
* test/run-
all-tests. py: it is now possible to select which tests to run,
that's a first step to clean up the testsuite - 1608. By Markus Korn
-
small fix to make all tests runable
- 1609. By Markus Korn
-
also filter doctests based on pattern
- 1610. By Markus Korn
-
added a test script for seif's issue
- 1611. By Markus Korn
-
added some debug statement
Siegfried Gevatter (rainct) wrote : | # |
Merged, good work.
Preview Diff
1 | === added file 'bug_testrunner.py' |
2 | --- bug_testrunner.py 1970-01-01 00:00:00 +0000 |
3 | +++ bug_testrunner.py 2010-09-23 11:07:07 +0000 |
4 | @@ -0,0 +1,10 @@ |
5 | +import os |
6 | +import glob |
7 | +from subprocess import Popen |
8 | + |
9 | +tests = map(lambda x: os.path.basename(x).rsplit(".", 1)[0], glob.glob("test/*.rst")) |
10 | +tests += map(lambda x: os.path.basename(x).rsplit(".", 1)[0], glob.glob("test/*-test.py")) |
11 | + |
12 | +for test in tests: |
13 | + print "*****************", test |
14 | + Popen(["test/run-all-tests.py", test, "blacklist-test"]).wait() |
15 | |
16 | === modified file 'test/blacklist-test.py' |
17 | --- test/blacklist-test.py 2010-04-26 19:42:07 +0000 |
18 | +++ test/blacklist-test.py 2010-09-23 11:07:07 +0000 |
19 | @@ -5,7 +5,6 @@ |
20 | import sys |
21 | import os |
22 | import unittest |
23 | -import dbus |
24 | |
25 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
26 | from zeitgeist.client import ZeitgeistDBusInterface |
27 | @@ -19,6 +18,9 @@ |
28 | self.blacklist = None |
29 | |
30 | def setUp(self): |
31 | + # lazy import to get a chance to use the private bus |
32 | + import dbus |
33 | + |
34 | # We set up the connection lazily in order to wait for the |
35 | # engine to come up |
36 | super(BlacklistTest, self).setUp() |
37 | |
38 | === modified file 'test/engine-extension-test.py' |
39 | --- test/engine-extension-test.py 2010-08-02 10:13:12 +0000 |
40 | +++ test/engine-extension-test.py 2010-09-23 11:07:07 +0000 |
41 | @@ -7,30 +7,23 @@ |
42 | import weakref |
43 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
44 | |
45 | -import _zeitgeist.engine |
46 | -from _zeitgeist.engine import constants |
47 | -from _zeitgeist.engine import get_engine |
48 | -from _zeitgeist.engine.extension import Extension |
49 | - |
50 | import unittest |
51 | from testutils import import_events |
52 | |
53 | -class _Extension1(Extension): |
54 | - PUBLIC_METHODS = ["return_hallo", "return_engine"] |
55 | - |
56 | - def return_hallo(self): |
57 | - return "Hallo" |
58 | - |
59 | - def return_boo(self): |
60 | - return "boo" |
61 | - |
62 | - def return_engine(self): |
63 | - return self.engine |
64 | - |
65 | +Extension = None |
66 | |
67 | class _engineTestClass(unittest.TestCase): |
68 | |
69 | def setUp (self): |
70 | + global Extension |
71 | + |
72 | + from _zeitgeist.engine import constants |
73 | + from _zeitgeist.engine import get_engine |
74 | + |
75 | + if Extension is None: |
76 | + from _zeitgeist.engine.extension import Extension as _Extension |
77 | + Extension = _Extension |
78 | + |
79 | constants.DATABASE_FILE = ":memory:" |
80 | self.save_default_ext = os.environ.get("ZEITGEIST_DEFAULT_EXTENSIONS") |
81 | self.save_extra_ext = os.environ.get("ZEITGEIST_EXTRA_EXTENSIONS") |
82 | @@ -39,6 +32,7 @@ |
83 | self.engine = get_engine() |
84 | |
85 | def tearDown (self): |
86 | + import _zeitgeist.engine |
87 | if self.save_default_ext is not None: |
88 | os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = self.save_default_ext |
89 | else: |
90 | @@ -54,13 +48,27 @@ |
91 | class TestExtensions(_engineTestClass): |
92 | |
93 | def testCreateEngine(self): |
94 | - engine = get_engine() |
95 | + |
96 | + class _Extension1(Extension): |
97 | + PUBLIC_METHODS = ["return_hallo", "return_engine"] |
98 | + |
99 | + def return_hallo(self): |
100 | + return "Hallo" |
101 | + |
102 | + def return_boo(self): |
103 | + return "boo" |
104 | + |
105 | + def return_engine(self): |
106 | + return self.engine |
107 | + |
108 | + engine = self.engine |
109 | self.assertEqual(len(engine.extensions), 0) |
110 | self.assertRaises(AttributeError, engine.extensions.__getattr__, "return_hallo") |
111 | engine.extensions.load(_Extension1) |
112 | self.assertEqual(engine.extensions.return_hallo(), "Hallo") |
113 | self.assertRaises(AttributeError, engine.extensions.__getattr__, "return_boo") |
114 | self.assertEqual(engine.extensions.return_engine(), weakref.proxy(engine)) |
115 | + |
116 | |
117 | class TestExtensionHooks(_engineTestClass): |
118 | |
119 | |
120 | === modified file 'test/engine-test.py' |
121 | --- test/engine-test.py 2010-09-19 09:24:40 +0000 |
122 | +++ test/engine-test.py 2010-09-23 11:07:07 +0000 |
123 | @@ -6,10 +6,6 @@ |
124 | import os |
125 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
126 | |
127 | -import _zeitgeist.engine |
128 | -from _zeitgeist.engine import constants |
129 | -from _zeitgeist.engine import get_engine |
130 | -from _zeitgeist.engine.sql import WhereClause |
131 | from zeitgeist.datamodel import * |
132 | from testutils import import_events |
133 | |
134 | @@ -41,6 +37,9 @@ |
135 | class _engineTestClass(unittest.TestCase): |
136 | |
137 | def setUp (self): |
138 | + from _zeitgeist.engine import constants |
139 | + from _zeitgeist.engine import get_engine |
140 | + |
141 | self.save_default_ext = os.environ.get("ZEITGEIST_DEFAULT_EXTENSIONS") |
142 | self.save_extra_ext = os.environ.get("ZEITGEIST_EXTRA_EXTENSIONS") |
143 | os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = "" |
144 | @@ -58,6 +57,7 @@ |
145 | self.engine = get_engine() |
146 | |
147 | def tearDown (self): |
148 | + import _zeitgeist.engine |
149 | if self.save_default_ext is not None: |
150 | os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = self.save_default_ext |
151 | else: |
152 | @@ -935,6 +935,8 @@ |
153 | self.assertEquals(5, len(ids)) |
154 | |
155 | def testWildcardOptimization(self): |
156 | + from _zeitgeist.engine.sql import WhereClause |
157 | + |
158 | cursor = self.engine._cursor |
159 | strings = [ |
160 | (u"hällö, I'm gürmen - åge drikker øl - ☠ bug",), |
161 | |
162 | === modified file 'test/loggers-datasources-recent-test.py' |
163 | --- test/loggers-datasources-recent-test.py 2009-11-30 07:57:58 +0000 |
164 | +++ test/loggers-datasources-recent-test.py 2010-09-23 11:07:07 +0000 |
165 | @@ -7,16 +7,28 @@ |
166 | import unittest |
167 | |
168 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
169 | -from _zeitgeist.loggers.datasources.recent import SimpleMatch, MimeTypeSet |
170 | - |
171 | -class SimpleMatchTest(unittest.TestCase): |
172 | + |
173 | +SimpleMatch = None |
174 | +MimeTypeSet = None |
175 | + |
176 | +class BaseTestCase(unittest.TestCase): |
177 | + |
178 | + def setUp(self): |
179 | + global SimpleMatch |
180 | + global MimeTypeSet |
181 | + if None in (SimpleMatch, MimeTypeSet): |
182 | + from _zeitgeist.loggers.datasources.recent import SimpleMatch as _SM, MimeTypeSet as _MTS |
183 | + SimpleMatch = _SM |
184 | + MimeTypeSet = _MTS |
185 | + |
186 | +class SimpleMatchTest(BaseTestCase): |
187 | |
188 | def testmatch(self): |
189 | self.assertTrue(SimpleMatch("boo/*").match("boo/bar")) |
190 | self.assertTrue(SimpleMatch("boo/bar.*").match("boo/bar.foo")) |
191 | self.assertFalse(SimpleMatch("boo/bar.*").match("boo/barfoo")) |
192 | |
193 | -class MimeTypeSetTest(unittest.TestCase): |
194 | +class MimeTypeSetTest(BaseTestCase): |
195 | |
196 | def testinit(self): |
197 | self.assertEquals(repr(MimeTypeSet("boo", "bar", "foo")), "MimeTypeSet('bar', 'boo', 'foo')") |
198 | |
199 | === modified file 'test/remote-test.py' |
200 | --- test/remote-test.py 2010-09-15 14:20:21 +0000 |
201 | +++ test/remote-test.py 2010-09-23 11:07:07 +0000 |
202 | @@ -6,6 +6,8 @@ |
203 | import logging |
204 | import signal |
205 | import time |
206 | +import tempfile |
207 | +import shutil |
208 | from subprocess import Popen, PIPE |
209 | |
210 | # DBus setup |
211 | @@ -18,7 +20,6 @@ |
212 | from zeitgeist.client import ZeitgeistDBusInterface, ZeitgeistClient |
213 | from zeitgeist.datamodel import (Event, Subject, Interpretation, Manifestation, |
214 | TimeRange, StorageState) |
215 | -from _zeitgeist.engine.remote import RemoteInterface |
216 | |
217 | import testutils |
218 | from testutils import parse_events |
219 | @@ -322,9 +323,31 @@ |
220 | |
221 | class ZeitgeistRemoteInterfaceTest(unittest.TestCase): |
222 | |
223 | + def setUp(self): |
224 | + from _zeitgeist import engine |
225 | + from _zeitgeist.engine import sql, constants |
226 | + engine._engine = None |
227 | + sql.unset_cursor() |
228 | + self.saved_data = { |
229 | + "datapath": constants.DATA_PATH, |
230 | + "database": constants.DATABASE_FILE, |
231 | + "extensions": constants.USER_EXTENSION_PATH, |
232 | + } |
233 | + constants.DATA_PATH = tempfile.mkdtemp(prefix="zeitgeist.datapath.") |
234 | + constants.DATABASE_FILE = ":memory:" |
235 | + constants.USER_EXTENSION_PATH = os.path.join(constants.DATA_PATH, "extensions") |
236 | + |
237 | + def tearDown(self): |
238 | + from _zeitgeist.engine import constants |
239 | + shutil.rmtree(constants.DATA_PATH) |
240 | + constants.DATA_PATH = self.saved_data["datapath"] |
241 | + constants.DATABASE_FILE = self.saved_data["database"] |
242 | + constants.USER_EXTENSION_PATH = self.saved_data["extensions"] |
243 | + |
244 | def testQuit(self): |
245 | """calling Quit() on the remote interface should shutdown the |
246 | engine in a clean way""" |
247 | + from _zeitgeist.engine.remote import RemoteInterface |
248 | interface = RemoteInterface() |
249 | self.assertEquals(interface._engine.is_closed(), False) |
250 | interface.Quit() |
251 | @@ -332,17 +355,21 @@ |
252 | |
253 | class ZeitgeistDaemonTest(unittest.TestCase): |
254 | |
255 | + def setUp(self): |
256 | + self.env = os.environ.copy() |
257 | + self.datapath = tempfile.mkdtemp(prefix="zeitgeist.datapath.") |
258 | + self.env.update({ |
259 | + "ZEITGEIST_DATABASE_PATH": ":memory:", |
260 | + "ZEITGEIST_DATA_PATH": self.datapath, |
261 | + }) |
262 | + |
263 | + def tearDown(self): |
264 | + shutil.rmtree(self.datapath) |
265 | + |
266 | def testSIGHUP(self): |
267 | """sending a SIGHUP signal to a running deamon instance results |
268 | in a clean shutdown""" |
269 | - daemon = Popen( |
270 | - ["./zeitgeist-daemon.py", "--no-datahub"], stderr=PIPE, stdout=PIPE |
271 | - ) |
272 | - # give the daemon some time to wake up |
273 | - time.sleep(3) |
274 | - err = daemon.poll() |
275 | - if err: |
276 | - raise RuntimeError("Could not start daemon, got err=%i" % err) |
277 | + daemon = testutils.RemoteTestCase._safe_start_daemon(env=self.env) |
278 | os.kill(daemon.pid, signal.SIGHUP) |
279 | err = daemon.wait() |
280 | self.assertEqual(err, 0) |
281 | |
282 | === modified file 'test/run-all-tests.py' |
283 | --- test/run-all-tests.py 2010-09-02 14:33:04 +0000 |
284 | +++ test/run-all-tests.py 2010-09-23 11:07:07 +0000 |
285 | @@ -6,36 +6,107 @@ |
286 | import doctest |
287 | import logging |
288 | import sys |
289 | +import tempfile |
290 | +import shutil |
291 | |
292 | from optparse import OptionParser |
293 | -parser = OptionParser() |
294 | -parser.add_option("-v", action="count", dest="verbosity") |
295 | -(options, args) = parser.parse_args() |
296 | - |
297 | -if options.verbosity: |
298 | - # do more fine grained stuff later |
299 | - # redirect all debugging output to stderr |
300 | - logging.basicConfig(stream=sys.stderr) |
301 | -else: |
302 | - logging.basicConfig(filename="/dev/null") |
303 | |
304 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
305 | |
306 | # Find the test/ directory |
307 | -testdir = os.path.dirname(os.path.abspath(__file__)) |
308 | -doctests = glob.glob(os.path.join(testdir, "*.rst")) |
309 | - |
310 | -# Create a test suite to run all tests |
311 | -# first, add all doctests |
312 | -arguments = {"module_relative": False, "globs": {"sys": sys}} |
313 | -suite = doctest.DocFileSuite(*doctests, **arguments) |
314 | - |
315 | -# Add all of the tests from each file that ends with "-test.py" |
316 | -for fname in os.listdir(testdir): |
317 | - if fname.endswith("-test.py"): |
318 | - fname = os.path.basename(fname)[:-3] # Get the filename and chop off ".py" |
319 | - module = __import__(fname) |
320 | - suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(module)) |
321 | - |
322 | -# Run all of the tests |
323 | -unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(suite) |
324 | +TESTDIR = os.path.dirname(os.path.abspath(__file__)) |
325 | +DOCTESTS = glob.glob(os.path.join(TESTDIR, "*.rst")) |
326 | + |
327 | +def doctest_setup(test): |
328 | + test._datapath = tempfile.mkdtemp(prefix="zeitgeist.datapath.") |
329 | + test._env = os.environ.copy() |
330 | + os.environ.update({ |
331 | + "ZEITGEIST_DATABASE_PATH": ":memory:", |
332 | + "ZEITGEIST_DATA_PATH": test._datapath |
333 | + }) |
334 | + |
335 | +def doctest_teardown(test): |
336 | + shutil.rmtree(test._datapath) |
337 | + os.environ = test._env |
338 | + |
339 | +def iter_tests(suite): |
340 | + for test in suite: |
341 | + if isinstance(test, unittest.TestSuite): |
342 | + for t in iter_tests(test): |
343 | + yield t |
344 | + else: |
345 | + yield test |
346 | + |
347 | +def get_test_name(test): |
348 | + return ".".join((test.__class__.__module__, test.__class__.__name__, test._testMethodName)) |
349 | + |
350 | +def load_tests(module, pattern): |
351 | + suite = unittest.defaultTestLoader.loadTestsFromModule(module) |
352 | + for test in iter_tests(suite): |
353 | + name = get_test_name(test) |
354 | + if pattern is not None: |
355 | + for p in pattern: |
356 | + if name.startswith(p): |
357 | + yield test |
358 | + break |
359 | + else: |
360 | + yield test |
361 | + |
362 | +def check_name(filename, pattern): |
363 | + if pattern is None: |
364 | + return True |
365 | + for p in pattern: |
366 | + if os.path.basename(filename).startswith(p): |
367 | + return True |
368 | + return False |
369 | + |
370 | +def compile_suite(pattern=None): |
371 | + # Create a test suite to run all tests |
372 | + |
373 | + # first, add all doctests |
374 | + arguments = { |
375 | + "module_relative": False, |
376 | + "globs": {"sys": sys}, |
377 | + "setUp": doctest_setup, |
378 | + "tearDown": doctest_teardown, |
379 | + } |
380 | + doctests = filter(lambda x: check_name(str(x), pattern), DOCTESTS) |
381 | + suite = doctest.DocFileSuite(*doctests, **arguments) |
382 | + |
383 | + # Add all of the tests from each file that ends with "-test.py" |
384 | + for fname in os.listdir(TESTDIR): |
385 | + if fname.endswith("-test.py"): |
386 | + fname = os.path.basename(fname)[:-3] # Get the filename and chop off ".py" |
387 | + module = __import__(fname) |
388 | + tests = list(load_tests(module, pattern)) |
389 | + suite.addTests(tests) |
390 | + return suite |
391 | + |
392 | +if __name__ == "__main__": |
393 | + parser = OptionParser() |
394 | + parser.add_option("-v", action="count", dest="verbosity") |
395 | + (options, args) = parser.parse_args() |
396 | + |
397 | + if options.verbosity: |
398 | + # do more fine grained stuff later |
399 | + # redirect all debugging output to stderr |
400 | + logging.basicConfig(stream=sys.stderr) |
401 | + else: |
402 | + logging.basicConfig(filename="/dev/null") |
403 | + |
404 | + from testutils import DBusPrivateMessageBus |
405 | + bus = DBusPrivateMessageBus() |
406 | + err = bus.run(ignore_errors=True) |
407 | + if err: |
408 | + print >> sys.stderr, "*** Failed to setup private bus, error was: %s" %err |
409 | + else: |
410 | + print >> sys.stderr, "*** Testsuite is running using a private dbus bus" |
411 | + config = bus.dbus_config.copy() |
412 | + config.update({"DISPLAY": bus.DISPLAY, "pid.Xvfb": bus.display.pid}) |
413 | + print >> sys.stderr, "*** Configuration: %s" %config |
414 | + try: |
415 | + suite = compile_suite(args or None) |
416 | + # Run all of the tests |
417 | + unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(suite) |
418 | + finally: |
419 | + bus.quit(ignore_errors=True) |
420 | |
421 | === modified file 'test/sql-test.py' |
422 | --- test/sql-test.py 2010-09-19 11:49:41 +0000 |
423 | +++ test/sql-test.py 2010-09-23 11:07:07 +0000 |
424 | @@ -23,10 +23,16 @@ |
425 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) |
426 | |
427 | import unittest |
428 | -from _zeitgeist.engine.sql import * |
429 | +WhereClause = None |
430 | |
431 | class SQLTest (unittest.TestCase): |
432 | |
433 | + def setUp(self): |
434 | + global WhereClause |
435 | + if WhereClause is None: |
436 | + from _zeitgeist.engine.sql import WhereClause as _WhereClause |
437 | + WhereClause = _WhereClause |
438 | + |
439 | def testFlat (self): |
440 | where = WhereClause(WhereClause.AND) |
441 | where.add ("foo = %s", 10) |
442 | |
443 | === modified file 'test/testutils.py' |
444 | --- test/testutils.py 2010-07-22 09:52:53 +0000 |
445 | +++ test/testutils.py 2010-09-23 11:07:07 +0000 |
446 | @@ -3,6 +3,7 @@ |
447 | # Zeitgeist |
448 | # |
449 | # Copyright © 2009 Mikkel Kamstrup Erlandsen <mikkel.kamstrup@gmail.com> |
450 | +# Copyright © 2009-2010 Markus Korn <thekorn@gmx.de> |
451 | # |
452 | # This program is free software: you can redistribute it and/or modify |
453 | # it under the terms of the GNU Lesser General Public License as published by |
454 | @@ -22,6 +23,8 @@ |
455 | import time |
456 | import sys |
457 | import signal |
458 | +import tempfile |
459 | +import shutil |
460 | from subprocess import Popen, PIPE |
461 | |
462 | # DBus setup |
463 | @@ -41,8 +44,6 @@ |
464 | # maybe the user is using python < 2.6 |
465 | import simplejson as json |
466 | |
467 | -from zeitgeist.datamodel import Event, Subject |
468 | - |
469 | def dict2event(d): |
470 | ev = Event() |
471 | ev[0][Event.Id] = d.get("id", "").encode("UTF-8") |
472 | @@ -74,7 +75,7 @@ |
473 | """ |
474 | Load a collection of JSON event definitions into 'engine'. Fx: |
475 | |
476 | - import_events("test/data/single_event.js", self.engine) |
477 | + import_events("test/data/single_event.js", self.engine) |
478 | """ |
479 | events = parse_events(path) |
480 | |
481 | @@ -86,21 +87,50 @@ |
482 | remote Zeitgeist process |
483 | """ |
484 | |
485 | + @staticmethod |
486 | + def _get_pid(matching_string): |
487 | + p1 = Popen(["ps", "aux"], stdout=PIPE, stderr=PIPE) |
488 | + p2 = Popen(["grep", matching_string], stdin=p1.stdout, stderr=PIPE, stdout=PIPE) |
489 | + return p2.communicate()[0] |
490 | + |
491 | + @staticmethod |
492 | + def _safe_start_subprocess(cmd, env, timeout=1, error_callback=None): |
493 | + """ starts `cmd` in a subprocess and check after `timeout` |
494 | + if everything goes well""" |
495 | + process = Popen(cmd, stderr=PIPE, stdout=PIPE, env=env) |
496 | + # give the process some time to wake up |
497 | + time.sleep(timeout) |
498 | + error = process.poll() |
499 | + if error: |
500 | + cmd = " ".join(cmd) |
501 | + error = "'%s' exits with error %i." %(cmd, error) |
502 | + if error_callback: |
503 | + error += " *** %s" %error_callback(*process.communicate()) |
504 | + raise RuntimeError(error) |
505 | + return process |
506 | + |
507 | + @staticmethod |
508 | + def _safe_start_daemon(env=None, timeout=1): |
509 | + if env is None: |
510 | + env = os.environ.copy() |
511 | + |
512 | + def error_callback(stdout, stderr): |
513 | + if "--replace" in stderr: |
514 | + return "%r | %s" %(stderr, RemoteTestCase._get_pid("zeitgeist-daemon").replace("\n", "|")) |
515 | + else: |
516 | + return stderr |
517 | + |
518 | + return RemoteTestCase._safe_start_subprocess( |
519 | + ("./zeitgeist-daemon.py", "--no-datahub"), env, timeout, error_callback |
520 | + ) |
521 | + |
522 | def __init__(self, methodName): |
523 | super(RemoteTestCase, self).__init__(methodName) |
524 | self.daemon = None |
525 | self.client = None |
526 | |
527 | def spawn_daemon(self): |
528 | - os.environ.update({"ZEITGEIST_DATABASE_PATH": ":memory:"}) |
529 | - self.daemon = Popen( |
530 | - ["./zeitgeist-daemon.py", "--no-datahub"], stderr=sys.stderr, stdout=sys.stderr |
531 | - ) |
532 | - # give the daemon some time to wake up |
533 | - time.sleep(3) |
534 | - err = self.daemon.poll() |
535 | - if err: |
536 | - raise RuntimeError("Could not start daemon, got err=%i" % err) |
537 | + self.daemon = self._safe_start_daemon(env=self.env) |
538 | |
539 | def kill_daemon(self): |
540 | os.kill(self.daemon.pid, signal.SIGKILL) |
541 | @@ -109,6 +139,12 @@ |
542 | def setUp(self): |
543 | assert self.daemon is None |
544 | assert self.client is None |
545 | + self.env = os.environ.copy() |
546 | + self.datapath = tempfile.mkdtemp(prefix="zeitgeist.datapath.") |
547 | + self.env.update({ |
548 | + "ZEITGEIST_DATABASE_PATH": ":memory:", |
549 | + "ZEITGEIST_DATA_PATH": self.datapath, |
550 | + }) |
551 | self.spawn_daemon() |
552 | |
553 | # hack to clear the state of the interface |
554 | @@ -119,6 +155,7 @@ |
555 | assert self.daemon is not None |
556 | assert self.client is not None |
557 | self.kill_daemon() |
558 | + shutil.rmtree(self.datapath) |
559 | |
560 | def insertEventsAndWait(self, events): |
561 | """ |
562 | @@ -220,3 +257,45 @@ |
563 | num_events=num_events, result_type=result_type) |
564 | mainloop.run() |
565 | return result |
566 | + |
567 | +class DBusPrivateMessageBus(object): |
568 | + DISPLAY = ":27" |
569 | + |
570 | + def _run(self): |
571 | + os.environ.update({"DISPLAY": self.DISPLAY}) |
572 | + self.display = Popen(["Xvfb", self.DISPLAY, "-screen", "0", "1024x768x8"]) |
573 | + # give the display some time to wake up |
574 | + time.sleep(1) |
575 | + err = self.display.poll() |
576 | + if err: |
577 | + raise RuntimeError("Could not start Xvfb on display %s, got err=%i" %(self.DISPLAY, err)) |
578 | + dbus = Popen(["dbus-launch"], stdout=PIPE) |
579 | + time.sleep(1) |
580 | + self.dbus_config = dict(l.split("=", 1) for l in dbus.communicate()[0].split("\n") if l) |
581 | + os.environ.update(self.dbus_config) |
582 | + |
583 | + def run(self, ignore_errors=False): |
584 | + try: |
585 | + return self._run() |
586 | + except Exception, e: |
587 | + if ignore_errors: |
588 | + return e |
589 | + raise |
590 | + |
591 | + def _quit(self): |
592 | + os.kill(self.display.pid, signal.SIGKILL) |
593 | + self.display.wait() |
594 | + pid = int(self.dbus_config["DBUS_SESSION_BUS_PID"]) |
595 | + os.kill(pid, signal.SIGKILL) |
596 | + try: |
597 | + os.waitpid(pid, 0) |
598 | + except OSError: |
599 | + pass |
600 | + |
601 | + def quit(self, ignore_errors=False): |
602 | + try: |
603 | + return self._quit() |
604 | + except Exception, e: |
605 | + if ignore_errors: |
606 | + return e |
607 | + raise |
It still fails with the blacklist-test.py! I had to quit zeitgeist manually for the tests to succeed. Here is my print out.
seif@Wumbo: ~/Projects/ xxx/zeitgeist$ test/blacklist- test.py ======= ======= ======= ======= ======= ======= ======= ======= ======= _.BlacklistTest ) ------- ------- ------- ------- ------- ------- ------- ------- ------- -test.py" , line 24, in setUp BlacklistTest, self).setUp() seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 118, in setUp spawn_daemon( ) seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 103, in spawn_daemon
EEEE
=======
ERROR: testApplyBlacklist (__main_
-------
Traceback (most recent call last):
File "test/blacklist
super(
File "/home/
self.
File "/home/
raise RuntimeError("Could not start daemon, got err=%i" % err)
RuntimeError: Could not start daemon, got err=1
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= ingClientDBusIn terface (__main_ _.BlacklistTest ) ------- ------- ------- ------- ------- ------- ------- ------- ------- -test.py" , line 24, in setUp BlacklistTest, self).setUp() seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 118, in setUp spawn_daemon( ) seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 103, in spawn_daemon
ERROR: testBlacklistUs
-------
Traceback (most recent call last):
File "test/blacklist
super(
File "/home/
self.
File "/home/
raise RuntimeError("Could not start daemon, got err=%i" % err)
RuntimeError: Could not start daemon, got err=1
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= _.BlacklistTest ) ------- ------- ------- ------- ------- ------- ------- ------- ------- -test.py" , line 24, in setUp BlacklistTest, self).setUp() seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 118, in setUp spawn_daemon( ) seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 103, in spawn_daemon
ERROR: testClear (__main_
-------
Traceback (most recent call last):
File "test/blacklist
super(
File "/home/
self.
File "/home/
raise RuntimeError("Could not start daemon, got err=%i" % err)
RuntimeError: Could not start daemon, got err=1
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= _.BlacklistTest ) ------- ------- ------- ------- ------- ------- ------- ------- ------- -test.py" , line 24, in setUp BlacklistTest, self).setUp() seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 118, in setUp spawn_daemon( ) seif/Projects/ xxx/zeitgeist/ test/testutils. py", line 103, in spawn_daemon
ERROR: testSetOne (__main_
-------
Traceback (most recent call last):
File "test/blacklist
super(
File "/home/
self.
File "/home/
raise RuntimeError("Could not start daemon, got err=%i" % err)
RuntimeError: Could not start daemon, got err=1
------- ------- ------- ------- ------- ------- ------- ------- ------- -------
Ran 4 tests in 4.014s
FAILED (errors=4)