Merge lp:~lifeless/bzr/test-speed into lp:~bzr/bzr/trunk-old
- test-speed
- Merge into trunk-old
Proposed by
Robert Collins
Status: | Merged |
---|---|
Merge reported by: | Robert Collins |
Merged at revision: | not available |
Proposed branch: | lp:~lifeless/bzr/test-speed |
Merge into: | lp:~bzr/bzr/trunk-old |
Diff against target: | 1320 lines |
To merge this branch: | bzr merge lp:~lifeless/bzr/test-speed |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincent Ladeuil | Approve | ||
Review via email: mp+10590@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote : | # |
Revision history for this message
Vincent Ladeuil (vila) wrote : | # |
Nice work and a particular kudo for the clarification comments.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bzrlib/tests/__init__.py' |
2 | --- bzrlib/tests/__init__.py 2009-08-20 05:05:59 +0000 |
3 | +++ bzrlib/tests/__init__.py 2009-08-24 06:35:12 +0000 |
4 | @@ -3207,6 +3207,7 @@ |
5 | starting_with=None, |
6 | runner_class=None, |
7 | suite_decorators=None, |
8 | + stream=None, |
9 | ): |
10 | """Run the whole test suite under the enhanced runner""" |
11 | # XXX: Very ugly way to do this... |
12 | @@ -3230,9 +3231,14 @@ |
13 | else: |
14 | keep_only = load_test_id_list(load_list) |
15 | if test_suite_factory is None: |
16 | + # Reduce loading time by loading modules based on the starting_with |
17 | + # patterns. |
18 | suite = test_suite(keep_only, starting_with) |
19 | else: |
20 | suite = test_suite_factory() |
21 | + if starting_with: |
22 | + # But always filter as requested. |
23 | + suite = filter_suite_by_id_startswith(suite, starting_with) |
24 | return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern, |
25 | stop_on_failure=stop_on_failure, |
26 | transport=transport, |
27 | @@ -3245,6 +3251,7 @@ |
28 | strict=strict, |
29 | runner_class=runner_class, |
30 | suite_decorators=suite_decorators, |
31 | + stream=stream, |
32 | ) |
33 | finally: |
34 | default_transport = old_transport |
35 | @@ -3683,9 +3690,6 @@ |
36 | reload(sys) |
37 | sys.setdefaultencoding(default_encoding) |
38 | |
39 | - if starting_with: |
40 | - suite = filter_suite_by_id_startswith(suite, starting_with) |
41 | - |
42 | if keep_only is not None: |
43 | # Now that the referred modules have loaded their tests, keep only the |
44 | # requested ones. |
45 | |
46 | === modified file 'bzrlib/tests/blackbox/test_selftest.py' |
47 | --- bzrlib/tests/blackbox/test_selftest.py 2009-07-10 07:14:02 +0000 |
48 | +++ bzrlib/tests/blackbox/test_selftest.py 2009-08-24 06:35:13 +0000 |
49 | @@ -16,474 +16,111 @@ |
50 | |
51 | """UI tests for the test framework.""" |
52 | |
53 | -from cStringIO import StringIO |
54 | -import os |
55 | -import re |
56 | -import signal |
57 | -import sys |
58 | -import unittest |
59 | - |
60 | -import bzrlib |
61 | +import bzrlib.transport |
62 | from bzrlib import ( |
63 | - osutils, |
64 | + benchmarks, |
65 | + tests, |
66 | ) |
67 | from bzrlib.errors import ParamikoNotPresent |
68 | from bzrlib.tests import ( |
69 | SubUnitFeature, |
70 | TestCase, |
71 | TestCaseInTempDir, |
72 | - TestCaseWithMemoryTransport, |
73 | - TestCaseWithTransport, |
74 | - TestUIFactory, |
75 | TestSkipped, |
76 | ) |
77 | -from bzrlib.tests.blackbox import ExternalBase |
78 | - |
79 | - |
80 | -class TestOptions(TestCase): |
81 | - |
82 | - current_test = None |
83 | + |
84 | + |
85 | +class SelfTestPatch: |
86 | + |
87 | + def get_params_passed_to_core(self, cmdline): |
88 | + params = [] |
89 | + def selftest(*args, **kwargs): |
90 | + """Capture the arguments selftest was run with.""" |
91 | + params.append((args, kwargs)) |
92 | + return True |
93 | + # Yes this prevents using threads to run the test suite in parallel, |
94 | + # however we don't have a clean dependency injector for commands, |
95 | + # and even if we did - we'd still be testing that the glue is wired |
96 | + # up correctly. XXX: TODO: Solve this testing problem. |
97 | + original_selftest = tests.selftest |
98 | + tests.selftest = selftest |
99 | + try: |
100 | + self.run_bzr(cmdline) |
101 | + return params[0] |
102 | + finally: |
103 | + tests.selftest = original_selftest |
104 | + |
105 | + |
106 | +class TestOptionsWritingToDisk(TestCaseInTempDir, SelfTestPatch): |
107 | + |
108 | + def test_benchmark_runs_benchmark_tests(self): |
109 | + """selftest --benchmark should change the suite factory.""" |
110 | + params = self.get_params_passed_to_core('selftest --benchmark') |
111 | + self.assertEqual(benchmarks.test_suite, |
112 | + params[1]['test_suite_factory']) |
113 | + self.assertNotEqual(None, params[1]['bench_history']) |
114 | + benchfile = open(".perf_history", "rt") |
115 | + try: |
116 | + lines = benchfile.readlines() |
117 | + finally: |
118 | + benchfile.close() |
119 | + # Because we don't run the actual test code no output is made to the |
120 | + # file. |
121 | + self.assertEqual(0, len(lines)) |
122 | + |
123 | + |
124 | +class TestOptions(TestCase, SelfTestPatch): |
125 | + |
126 | + def test_load_list(self): |
127 | + params = self.get_params_passed_to_core('selftest --load-list foo') |
128 | + self.assertEqual('foo', params[1]['load_list']) |
129 | |
130 | def test_transport_set_to_sftp(self): |
131 | - # test the --transport option has taken effect from within the |
132 | - # test_transport test |
133 | + # Test that we can pass a transport to the selftest core - sftp |
134 | + # version. |
135 | try: |
136 | import bzrlib.transport.sftp |
137 | except ParamikoNotPresent: |
138 | raise TestSkipped("Paramiko not present") |
139 | - if TestOptions.current_test != "test_transport_set_to_sftp": |
140 | - return |
141 | + params = self.get_params_passed_to_core('selftest --transport=sftp') |
142 | self.assertEqual(bzrlib.transport.sftp.SFTPAbsoluteServer, |
143 | - bzrlib.tests.default_transport) |
144 | + params[1]["transport"]) |
145 | |
146 | def test_transport_set_to_memory(self): |
147 | - # test the --transport option has taken effect from within the |
148 | - # test_transport test |
149 | + # Test that we can pass a transport to the selftest core - memory |
150 | + # version. |
151 | import bzrlib.transport.memory |
152 | - if TestOptions.current_test != "test_transport_set_to_memory": |
153 | - return |
154 | + params = self.get_params_passed_to_core('selftest --transport=memory') |
155 | self.assertEqual(bzrlib.transport.memory.MemoryServer, |
156 | - bzrlib.tests.default_transport) |
157 | - |
158 | - def test_transport(self): |
159 | - # test that --transport=sftp works |
160 | - try: |
161 | - import bzrlib.transport.sftp |
162 | - except ParamikoNotPresent: |
163 | - raise TestSkipped("Paramiko not present") |
164 | - old_transport = bzrlib.tests.default_transport |
165 | - old_root = TestCaseWithMemoryTransport.TEST_ROOT |
166 | - TestCaseWithMemoryTransport.TEST_ROOT = None |
167 | - try: |
168 | - TestOptions.current_test = "test_transport_set_to_sftp" |
169 | - stdout = self.run_bzr( |
170 | - 'selftest --transport=sftp test_transport_set_to_sftp')[0] |
171 | - self.assertContainsRe(stdout, 'Ran 1 test') |
172 | - self.assertEqual(old_transport, bzrlib.tests.default_transport) |
173 | - |
174 | - TestOptions.current_test = "test_transport_set_to_memory" |
175 | - stdout = self.run_bzr( |
176 | - 'selftest --transport=memory test_transport_set_to_memory')[0] |
177 | - self.assertContainsRe(stdout, 'Ran 1 test') |
178 | - self.assertEqual(old_transport, bzrlib.tests.default_transport) |
179 | - finally: |
180 | - bzrlib.tests.default_transport = old_transport |
181 | - TestOptions.current_test = None |
182 | - TestCaseWithMemoryTransport.TEST_ROOT = old_root |
183 | + params[1]["transport"]) |
184 | + |
185 | + def test_parameters_passed_to_core(self): |
186 | + params = self.get_params_passed_to_core('selftest --list-only') |
187 | + self.assertTrue("list_only" in params[1]) |
188 | + params = self.get_params_passed_to_core('selftest --list-only selftest') |
189 | + self.assertTrue("list_only" in params[1]) |
190 | + params = self.get_params_passed_to_core(['selftest', '--list-only', |
191 | + '--exclude', 'selftest']) |
192 | + self.assertTrue("list_only" in params[1]) |
193 | + params = self.get_params_passed_to_core(['selftest', '--list-only', |
194 | + 'selftest', '--randomize', 'now']) |
195 | + self.assertSubset(["list_only", "random_seed"], params[1]) |
196 | + |
197 | + def test_starting_with(self): |
198 | + params = self.get_params_passed_to_core('selftest --starting-with foo') |
199 | + self.assertEqual(['foo'], params[1]['starting_with']) |
200 | + |
201 | + def test_starting_with_multiple_argument(self): |
202 | + params = self.get_params_passed_to_core( |
203 | + 'selftest --starting-with foo --starting-with bar') |
204 | + self.assertEqual(['foo', 'bar'], params[1]['starting_with']) |
205 | |
206 | def test_subunit(self): |
207 | - """Passing --subunit results in subunit output.""" |
208 | self.requireFeature(SubUnitFeature) |
209 | - from subunit import ProtocolTestCase |
210 | - stdout = self.run_bzr( |
211 | - 'selftest --subunit --no-plugins ' |
212 | - 'tests.test_selftest.SelftestTests.test_import_tests')[0] |
213 | - stream = StringIO(str(stdout)) |
214 | - test = ProtocolTestCase(stream) |
215 | - result = unittest.TestResult() |
216 | - test.run(result) |
217 | - self.assertEqual(1, result.testsRun) |
218 | - |
219 | - |
220 | -class TestRunBzr(ExternalBase): |
221 | - |
222 | - def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None, |
223 | - working_dir=None): |
224 | - """Override _run_bzr_core to test how it is invoked by run_bzr. |
225 | - |
226 | - Attempts to run bzr from inside this class don't actually run it. |
227 | - |
228 | - We test how run_bzr actually invokes bzr in another location. |
229 | - Here we only need to test that it is run_bzr passes the right |
230 | - parameters to run_bzr. |
231 | - """ |
232 | - self.argv = list(argv) |
233 | - self.retcode = retcode |
234 | - self.encoding = encoding |
235 | - self.stdin = stdin |
236 | - self.working_dir = working_dir |
237 | - return '', '' |
238 | - |
239 | - def test_encoding(self): |
240 | - """Test that run_bzr passes encoding to _run_bzr_core""" |
241 | - self.run_bzr('foo bar') |
242 | - self.assertEqual(None, self.encoding) |
243 | - self.assertEqual(['foo', 'bar'], self.argv) |
244 | - |
245 | - self.run_bzr('foo bar', encoding='baz') |
246 | - self.assertEqual('baz', self.encoding) |
247 | - self.assertEqual(['foo', 'bar'], self.argv) |
248 | - |
249 | - def test_retcode(self): |
250 | - """Test that run_bzr passes retcode to _run_bzr_core""" |
251 | - # Default is retcode == 0 |
252 | - self.run_bzr('foo bar') |
253 | - self.assertEqual(0, self.retcode) |
254 | - self.assertEqual(['foo', 'bar'], self.argv) |
255 | - |
256 | - self.run_bzr('foo bar', retcode=1) |
257 | - self.assertEqual(1, self.retcode) |
258 | - self.assertEqual(['foo', 'bar'], self.argv) |
259 | - |
260 | - self.run_bzr('foo bar', retcode=None) |
261 | - self.assertEqual(None, self.retcode) |
262 | - self.assertEqual(['foo', 'bar'], self.argv) |
263 | - |
264 | - self.run_bzr(['foo', 'bar'], retcode=3) |
265 | - self.assertEqual(3, self.retcode) |
266 | - self.assertEqual(['foo', 'bar'], self.argv) |
267 | - |
268 | - def test_stdin(self): |
269 | - # test that the stdin keyword to run_bzr is passed through to |
270 | - # _run_bzr_core as-is. We do this by overriding |
271 | - # _run_bzr_core in this class, and then calling run_bzr, |
272 | - # which is a convenience function for _run_bzr_core, so |
273 | - # should invoke it. |
274 | - self.run_bzr('foo bar', stdin='gam') |
275 | - self.assertEqual('gam', self.stdin) |
276 | - self.assertEqual(['foo', 'bar'], self.argv) |
277 | - |
278 | - self.run_bzr('foo bar', stdin='zippy') |
279 | - self.assertEqual('zippy', self.stdin) |
280 | - self.assertEqual(['foo', 'bar'], self.argv) |
281 | - |
282 | - def test_working_dir(self): |
283 | - """Test that run_bzr passes working_dir to _run_bzr_core""" |
284 | - self.run_bzr('foo bar') |
285 | - self.assertEqual(None, self.working_dir) |
286 | - self.assertEqual(['foo', 'bar'], self.argv) |
287 | - |
288 | - self.run_bzr('foo bar', working_dir='baz') |
289 | - self.assertEqual('baz', self.working_dir) |
290 | - self.assertEqual(['foo', 'bar'], self.argv) |
291 | - |
292 | - def test_reject_extra_keyword_arguments(self): |
293 | - self.assertRaises(TypeError, self.run_bzr, "foo bar", |
294 | - error_regex=['error message']) |
295 | - |
296 | - |
297 | -class TestBenchmarkTests(TestCaseWithTransport): |
298 | - |
299 | - def test_benchmark_runs_benchmark_tests(self): |
300 | - """bzr selftest --benchmark should not run the default test suite.""" |
301 | - # We test this by passing a regression test name to --benchmark, which |
302 | - # should result in 0 tests run. |
303 | - old_root = TestCaseWithMemoryTransport.TEST_ROOT |
304 | - try: |
305 | - TestCaseWithMemoryTransport.TEST_ROOT = None |
306 | - out, err = self.run_bzr('selftest --benchmark' |
307 | - ' per_workingtree') |
308 | - finally: |
309 | - TestCaseWithMemoryTransport.TEST_ROOT = old_root |
310 | - self.assertContainsRe(out, 'Ran 0 tests.*\n\nOK') |
311 | - self.assertContainsRe(out, 'tests passed\n') |
312 | - benchfile = open(".perf_history", "rt") |
313 | - try: |
314 | - lines = benchfile.readlines() |
315 | - finally: |
316 | - benchfile.close() |
317 | - self.assertEqual(1, len(lines)) |
318 | - self.assertContainsRe(lines[0], "--date [0-9.]+") |
319 | - |
320 | - |
321 | -class TestRunBzrCaptured(ExternalBase): |
322 | - |
323 | - def apply_redirected(self, stdin=None, stdout=None, stderr=None, |
324 | - a_callable=None, *args, **kwargs): |
325 | - self.stdin = stdin |
326 | - self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None) |
327 | - self.factory = bzrlib.ui.ui_factory |
328 | - self.working_dir = osutils.getcwd() |
329 | - stdout.write('foo\n') |
330 | - stderr.write('bar\n') |
331 | - return 0 |
332 | - |
333 | - def test_stdin(self): |
334 | - # test that the stdin keyword to _run_bzr_core is passed through to |
335 | - # apply_redirected as a StringIO. We do this by overriding |
336 | - # apply_redirected in this class, and then calling _run_bzr_core, |
337 | - # which calls apply_redirected. |
338 | - self.run_bzr(['foo', 'bar'], stdin='gam') |
339 | - self.assertEqual('gam', self.stdin.read()) |
340 | - self.assertTrue(self.stdin is self.factory_stdin) |
341 | - self.run_bzr(['foo', 'bar'], stdin='zippy') |
342 | - self.assertEqual('zippy', self.stdin.read()) |
343 | - self.assertTrue(self.stdin is self.factory_stdin) |
344 | - |
345 | - def test_ui_factory(self): |
346 | - # each invocation of self.run_bzr should get its |
347 | - # own UI factory, which is an instance of TestUIFactory, |
348 | - # with stdin, stdout and stderr attached to the stdin, |
349 | - # stdout and stderr of the invoked run_bzr |
350 | - current_factory = bzrlib.ui.ui_factory |
351 | - self.run_bzr(['foo']) |
352 | - self.failIf(current_factory is self.factory) |
353 | - self.assertNotEqual(sys.stdout, self.factory.stdout) |
354 | - self.assertNotEqual(sys.stderr, self.factory.stderr) |
355 | - self.assertEqual('foo\n', self.factory.stdout.getvalue()) |
356 | - self.assertEqual('bar\n', self.factory.stderr.getvalue()) |
357 | - self.assertIsInstance(self.factory, TestUIFactory) |
358 | - |
359 | - def test_working_dir(self): |
360 | - self.build_tree(['one/', 'two/']) |
361 | - cwd = osutils.getcwd() |
362 | - |
363 | - # Default is to work in the current directory |
364 | - self.run_bzr(['foo', 'bar']) |
365 | - self.assertEqual(cwd, self.working_dir) |
366 | - |
367 | - self.run_bzr(['foo', 'bar'], working_dir=None) |
368 | - self.assertEqual(cwd, self.working_dir) |
369 | - |
370 | - # The function should be run in the alternative directory |
371 | - # but afterwards the current working dir shouldn't be changed |
372 | - self.run_bzr(['foo', 'bar'], working_dir='one') |
373 | - self.assertNotEqual(cwd, self.working_dir) |
374 | - self.assertEndsWith(self.working_dir, 'one') |
375 | - self.assertEqual(cwd, osutils.getcwd()) |
376 | - |
377 | - self.run_bzr(['foo', 'bar'], working_dir='two') |
378 | - self.assertNotEqual(cwd, self.working_dir) |
379 | - self.assertEndsWith(self.working_dir, 'two') |
380 | - self.assertEqual(cwd, osutils.getcwd()) |
381 | - |
382 | - |
383 | -class TestRunBzrSubprocess(TestCaseWithTransport): |
384 | - |
385 | - def test_run_bzr_subprocess(self): |
386 | - """The run_bzr_helper_external command behaves nicely.""" |
387 | - result = self.run_bzr_subprocess('--version') |
388 | - result = self.run_bzr_subprocess(['--version']) |
389 | - result = self.run_bzr_subprocess('--version', retcode=None) |
390 | - self.assertContainsRe(result[0], 'is free software') |
391 | - self.assertRaises(AssertionError, self.run_bzr_subprocess, |
392 | - '--versionn') |
393 | - result = self.run_bzr_subprocess('--versionn', retcode=3) |
394 | - result = self.run_bzr_subprocess('--versionn', retcode=None) |
395 | - self.assertContainsRe(result[1], 'unknown command') |
396 | - err = self.run_bzr_subprocess(['merge', '--merge-type', |
397 | - 'magic merge'], retcode=3)[1] |
398 | - self.assertContainsRe(err, 'Bad value "magic merge" for option' |
399 | - ' "merge-type"') |
400 | - |
401 | - def test_run_bzr_subprocess_env(self): |
402 | - """run_bzr_subprocess can set environment variables in the child only. |
403 | - |
404 | - These changes should not change the running process, only the child. |
405 | - """ |
406 | - # The test suite should unset this variable |
407 | - self.assertEqual(None, os.environ.get('BZR_EMAIL')) |
408 | - out, err = self.run_bzr_subprocess('whoami', env_changes={ |
409 | - 'BZR_EMAIL':'Joe Foo <joe@foo.com>' |
410 | - }, universal_newlines=True) |
411 | - self.assertEqual('', err) |
412 | - self.assertEqual('Joe Foo <joe@foo.com>\n', out) |
413 | - # And it should not be modified |
414 | - self.assertEqual(None, os.environ.get('BZR_EMAIL')) |
415 | - |
416 | - # Do it again with a different address, just to make sure |
417 | - # it is actually changing |
418 | - out, err = self.run_bzr_subprocess('whoami', env_changes={ |
419 | - 'BZR_EMAIL':'Barry <bar@foo.com>' |
420 | - }, universal_newlines=True) |
421 | - self.assertEqual('', err) |
422 | - self.assertEqual('Barry <bar@foo.com>\n', out) |
423 | - self.assertEqual(None, os.environ.get('BZR_EMAIL')) |
424 | - |
425 | - def test_run_bzr_subprocess_env_del(self): |
426 | - """run_bzr_subprocess can remove environment variables too.""" |
427 | - # Create a random email, so we are sure this won't collide |
428 | - rand_bzr_email = 'John Doe <jdoe@%s.com>' % (osutils.rand_chars(20),) |
429 | - rand_email = 'Jane Doe <jdoe@%s.com>' % (osutils.rand_chars(20),) |
430 | - os.environ['BZR_EMAIL'] = rand_bzr_email |
431 | - os.environ['EMAIL'] = rand_email |
432 | - try: |
433 | - # By default, the child will inherit the current env setting |
434 | - out, err = self.run_bzr_subprocess('whoami', universal_newlines=True) |
435 | - self.assertEqual('', err) |
436 | - self.assertEqual(rand_bzr_email + '\n', out) |
437 | - |
438 | - # Now that BZR_EMAIL is not set, it should fall back to EMAIL |
439 | - out, err = self.run_bzr_subprocess('whoami', |
440 | - env_changes={'BZR_EMAIL':None}, |
441 | - universal_newlines=True) |
442 | - self.assertEqual('', err) |
443 | - self.assertEqual(rand_email + '\n', out) |
444 | - |
445 | - # This switches back to the default email guessing logic |
446 | - # Which shouldn't match either of the above addresses |
447 | - out, err = self.run_bzr_subprocess('whoami', |
448 | - env_changes={'BZR_EMAIL':None, 'EMAIL':None}, |
449 | - universal_newlines=True) |
450 | - |
451 | - self.assertEqual('', err) |
452 | - self.assertNotEqual(rand_bzr_email + '\n', out) |
453 | - self.assertNotEqual(rand_email + '\n', out) |
454 | - finally: |
455 | - # TestCase cleans up BZR_EMAIL, and EMAIL at startup |
456 | - del os.environ['BZR_EMAIL'] |
457 | - del os.environ['EMAIL'] |
458 | - |
459 | - def test_run_bzr_subprocess_env_del_missing(self): |
460 | - """run_bzr_subprocess won't fail if deleting a nonexistant env var""" |
461 | - self.failIf('NON_EXISTANT_ENV_VAR' in os.environ) |
462 | - out, err = self.run_bzr_subprocess('rocks', |
463 | - env_changes={'NON_EXISTANT_ENV_VAR':None}, |
464 | - universal_newlines=True) |
465 | - self.assertEqual('It sure does!\n', out) |
466 | - self.assertEqual('', err) |
467 | - |
468 | - def test_run_bzr_subprocess_working_dir(self): |
469 | - """Test that we can specify the working dir for the child""" |
470 | - cwd = osutils.getcwd() |
471 | - |
472 | - self.make_branch_and_tree('.') |
473 | - self.make_branch_and_tree('one') |
474 | - self.make_branch_and_tree('two') |
475 | - |
476 | - def get_root(**kwargs): |
477 | - """Spawn a process to get the 'root' of the tree. |
478 | - |
479 | - You can pass in arbitrary new arguments. This just makes |
480 | - sure that the returned path doesn't have trailing whitespace. |
481 | - """ |
482 | - return self.run_bzr_subprocess('root', **kwargs)[0].rstrip() |
483 | - |
484 | - self.assertEqual(cwd, get_root()) |
485 | - self.assertEqual(cwd, get_root(working_dir=None)) |
486 | - # Has our path changed? |
487 | - self.assertEqual(cwd, osutils.getcwd()) |
488 | - |
489 | - dir1 = get_root(working_dir='one') |
490 | - self.assertEndsWith(dir1, 'one') |
491 | - self.assertEqual(cwd, osutils.getcwd()) |
492 | - |
493 | - dir2 = get_root(working_dir='two') |
494 | - self.assertEndsWith(dir2, 'two') |
495 | - self.assertEqual(cwd, osutils.getcwd()) |
496 | - |
497 | - |
498 | -class _DontSpawnProcess(Exception): |
499 | - """A simple exception which just allows us to skip unnecessary steps""" |
500 | - |
501 | - |
502 | -class TestRunBzrSubprocessCommands(TestCaseWithTransport): |
503 | - |
504 | - def _popen(self, *args, **kwargs): |
505 | - """Record the command that is run, so that we can ensure it is correct""" |
506 | - self._popen_args = args |
507 | - self._popen_kwargs = kwargs |
508 | - raise _DontSpawnProcess() |
509 | - |
510 | - def test_run_bzr_subprocess_no_plugins(self): |
511 | - self.assertRaises(_DontSpawnProcess, self.run_bzr_subprocess, '') |
512 | - command = self._popen_args[0] |
513 | - self.assertEqual(sys.executable, command[0]) |
514 | - self.assertEqual(self.get_bzr_path(), command[1]) |
515 | - self.assertEqual(['--no-plugins'], command[2:]) |
516 | - |
517 | - def test_allow_plugins(self): |
518 | - self.assertRaises(_DontSpawnProcess, |
519 | - self.run_bzr_subprocess, '', allow_plugins=True) |
520 | - command = self._popen_args[0] |
521 | - self.assertEqual([], command[2:]) |
522 | - |
523 | - |
524 | -class TestBzrSubprocess(TestCaseWithTransport): |
525 | - |
526 | - def test_start_and_stop_bzr_subprocess(self): |
527 | - """We can start and perform other test actions while that process is |
528 | - still alive. |
529 | - """ |
530 | - process = self.start_bzr_subprocess(['--version']) |
531 | - result = self.finish_bzr_subprocess(process) |
532 | - self.assertContainsRe(result[0], 'is free software') |
533 | - self.assertEqual('', result[1]) |
534 | - |
535 | - def test_start_and_stop_bzr_subprocess_with_error(self): |
536 | - """finish_bzr_subprocess allows specification of the desired exit code. |
537 | - """ |
538 | - process = self.start_bzr_subprocess(['--versionn']) |
539 | - result = self.finish_bzr_subprocess(process, retcode=3) |
540 | - self.assertEqual('', result[0]) |
541 | - self.assertContainsRe(result[1], 'unknown command') |
542 | - |
543 | - def test_start_and_stop_bzr_subprocess_ignoring_retcode(self): |
544 | - """finish_bzr_subprocess allows the exit code to be ignored.""" |
545 | - process = self.start_bzr_subprocess(['--versionn']) |
546 | - result = self.finish_bzr_subprocess(process, retcode=None) |
547 | - self.assertEqual('', result[0]) |
548 | - self.assertContainsRe(result[1], 'unknown command') |
549 | - |
550 | - def test_start_and_stop_bzr_subprocess_with_unexpected_retcode(self): |
551 | - """finish_bzr_subprocess raises self.failureException if the retcode is |
552 | - not the expected one. |
553 | - """ |
554 | - process = self.start_bzr_subprocess(['--versionn']) |
555 | - self.assertRaises(self.failureException, self.finish_bzr_subprocess, |
556 | - process) |
557 | - |
558 | - def test_start_and_stop_bzr_subprocess_send_signal(self): |
559 | - """finish_bzr_subprocess raises self.failureException if the retcode is |
560 | - not the expected one. |
561 | - """ |
562 | - process = self.start_bzr_subprocess(['wait-until-signalled'], |
563 | - skip_if_plan_to_signal=True) |
564 | - self.assertEqual('running\n', process.stdout.readline()) |
565 | - result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT, |
566 | - retcode=3) |
567 | - self.assertEqual('', result[0]) |
568 | - self.assertEqual('bzr: interrupted\n', result[1]) |
569 | - |
570 | - def test_start_and_stop_working_dir(self): |
571 | - cwd = osutils.getcwd() |
572 | - |
573 | - self.make_branch_and_tree('one') |
574 | - |
575 | - process = self.start_bzr_subprocess(['root'], working_dir='one') |
576 | - result = self.finish_bzr_subprocess(process, universal_newlines=True) |
577 | - self.assertEndsWith(result[0], 'one\n') |
578 | - self.assertEqual('', result[1]) |
579 | - |
580 | - |
581 | -class TestRunBzrError(ExternalBase): |
582 | - |
583 | - def test_run_bzr_error(self): |
584 | - # retcode=0 is specially needed here because run_bzr_error expects |
585 | - # an error (oddly enough) but we want to test the case of not |
586 | - # actually getting one |
587 | - out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=0) |
588 | - self.assertEqual(out, 'It sure does!\n') |
589 | - # now test actually getting an error |
590 | - out, err = self.run_bzr_error( |
591 | - ["bzr: ERROR: foobarbaz is not versioned"], |
592 | - ['file-id', 'foobarbaz']) |
593 | - |
594 | - |
595 | -class TestSelftestListOnly(TestCase): |
596 | - |
597 | - @staticmethod |
598 | - def _parse_test_list(lines, newlines_in_header=0): |
599 | + params = self.get_params_passed_to_core('selftest --subunit') |
600 | + self.assertEqual(tests.SubUnitBzrRunner, params[1]['runner_class']) |
601 | + |
602 | + def _parse_test_list(self, lines, newlines_in_header=0): |
603 | "Parse a list of lines into a tuple of 3 lists (header,body,footer)." |
604 | in_header = newlines_in_header != 0 |
605 | in_footer = False |
606 | @@ -512,92 +149,26 @@ |
607 | return (header,body,footer) |
608 | |
609 | def test_list_only(self): |
610 | - # check that bzr selftest --list-only works correctly |
611 | - out,err = self.run_bzr('selftest selftest --list-only') |
612 | - (header,body,footer) = self._parse_test_list(out.splitlines()) |
613 | - num_tests = len(body) |
614 | - self.assertLength(0, header) |
615 | - self.assertLength(0, footer) |
616 | - self.assertEqual('', err) |
617 | - |
618 | - def test_list_only_filtered(self): |
619 | - # check that a filtered --list-only works, both include and exclude |
620 | - out_all,err_all = self.run_bzr('selftest --list-only') |
621 | - tests_all = self._parse_test_list(out_all.splitlines())[1] |
622 | - out_incl,err_incl = self.run_bzr('selftest --list-only selftest') |
623 | - tests_incl = self._parse_test_list(out_incl.splitlines())[1] |
624 | - self.assertSubset(tests_incl, tests_all) |
625 | - out_excl,err_excl = self.run_bzr(['selftest', '--list-only', |
626 | - '--exclude', 'selftest']) |
627 | - tests_excl = self._parse_test_list(out_excl.splitlines())[1] |
628 | - self.assertSubset(tests_excl, tests_all) |
629 | - set_incl = set(tests_incl) |
630 | - set_excl = set(tests_excl) |
631 | - intersection = set_incl.intersection(set_excl) |
632 | - self.assertEquals(0, len(intersection)) |
633 | - self.assertEquals(len(tests_all), len(tests_incl) + len(tests_excl)) |
634 | - |
635 | - def test_list_only_random(self): |
636 | - # check that --randomize works correctly |
637 | - out_all,err_all = self.run_bzr('selftest --list-only selftest') |
638 | - tests_all = self._parse_test_list(out_all.splitlines())[1] |
639 | - # XXX: It looks like there are some orders for generating tests that |
640 | - # fail as of 20070504 - maybe because of import order dependencies. |
641 | - # So unfortunately this will rarely intermittently fail at the moment. |
642 | - # -- mbp 20070504 |
643 | - out_rand,err_rand = self.run_bzr(['selftest', '--list-only', |
644 | - 'selftest', '--randomize', 'now']) |
645 | - (header_rand,tests_rand,dummy) = self._parse_test_list( |
646 | - out_rand.splitlines(), 1) |
647 | - # XXX: The following line asserts that the randomized order is not the |
648 | - # same as the default order. It is just possible that they'll get |
649 | - # randomized into the same order and this will falsely fail, but |
650 | - # that's very unlikely in practice because there are thousands of |
651 | - # tests. |
652 | - self.assertNotEqual(tests_all, tests_rand) |
653 | - self.assertEqual(sorted(tests_all), sorted(tests_rand)) |
654 | - # Check that the seed can be reused to get the exact same order |
655 | - seed_re = re.compile('Randomizing test order using seed (\w+)') |
656 | - match_obj = seed_re.search(header_rand[-1]) |
657 | - seed = match_obj.group(1) |
658 | - out_rand2,err_rand2 = self.run_bzr(['selftest', '--list-only', |
659 | - 'selftest', '--randomize', seed]) |
660 | - (header_rand2,tests_rand2,dummy) = self._parse_test_list( |
661 | - out_rand2.splitlines(), 1) |
662 | - self.assertEqual(tests_rand, tests_rand2) |
663 | - |
664 | - |
665 | -class TestSelftestWithIdList(TestCaseInTempDir): |
666 | - |
667 | - def test_load_list(self): |
668 | - # We don't want to call selftest for the whole suite, so we start with |
669 | - # a reduced list. |
670 | - test_list_fname = 'test.list' |
671 | - fl = open(test_list_fname, 'wt') |
672 | - fl.write('%s\n' % self.id()) |
673 | - fl.close() |
674 | - out, err = self.run_bzr( |
675 | - ['selftest', '--load-list', test_list_fname, '--list']) |
676 | - self.assertContainsRe(out, "TestSelftestWithIdList") |
677 | - self.assertLength(1, out.splitlines()) |
678 | - |
679 | - def test_load_unknown(self): |
680 | - out, err = self.run_bzr('selftest --load-list I_do_not_exist ', |
681 | - retcode=3) |
682 | - |
683 | - |
684 | -class TestSelftestStartingWith(TestCase): |
685 | - |
686 | - def test_starting_with_single_argument(self): |
687 | - out, err = self.run_bzr( |
688 | - ['selftest', '--starting-with', self.id(), '--list']) |
689 | - self.assertContainsRe(out, self.id()) |
690 | - |
691 | - def test_starting_with_multiple_argument(self): |
692 | - out, err = self.run_bzr( |
693 | - ['selftest', |
694 | - '--starting-with', self.id(), |
695 | - '--starting-with', 'bzrlib.tests.test_sampler', |
696 | - '--list']) |
697 | - self.assertContainsRe(out, self.id()) |
698 | - self.assertContainsRe(out, 'bzrlib.tests.test_sampler') |
699 | + # check that bzr selftest --list-only outputs no ui noise |
700 | + def selftest(*args, **kwargs): |
701 | + """Capture the arguments selftest was run with.""" |
702 | + return True |
703 | + def outputs_nothing(cmdline): |
704 | + out,err = self.run_bzr(cmdline) |
705 | + (header,body,footer) = self._parse_test_list(out.splitlines()) |
706 | + num_tests = len(body) |
707 | + self.assertLength(0, header) |
708 | + self.assertLength(0, footer) |
709 | + self.assertEqual('', err) |
710 | + # Yes this prevents using threads to run the test suite in parallel, |
711 | + # however we don't have a clean dependency injector for commands, |
712 | + # and even if we did - we'd still be testing that the glue is wired |
713 | + # up correctly. XXX: TODO: Solve this testing problem. |
714 | + original_selftest = tests.selftest |
715 | + tests.selftest = selftest |
716 | + try: |
717 | + outputs_nothing('selftest --list-only') |
718 | + outputs_nothing('selftest --list-only selftest') |
719 | + outputs_nothing(['selftest', '--list-only', '--exclude', 'selftest']) |
720 | + finally: |
721 | + tests.selftest = original_selftest |
722 | |
723 | === modified file 'bzrlib/tests/test_selftest.py' |
724 | --- bzrlib/tests/test_selftest.py 2009-08-17 03:47:03 +0000 |
725 | +++ bzrlib/tests/test_selftest.py 2009-08-24 06:35:12 +0000 |
726 | @@ -18,6 +18,7 @@ |
727 | |
728 | from cStringIO import StringIO |
729 | import os |
730 | +import signal |
731 | import sys |
732 | import time |
733 | import unittest |
734 | @@ -50,6 +51,7 @@ |
735 | deprecated_method, |
736 | ) |
737 | from bzrlib.tests import ( |
738 | + SubUnitFeature, |
739 | test_lsprof, |
740 | test_sftp_transport, |
741 | TestUtil, |
742 | @@ -1745,7 +1747,7 @@ |
743 | |
744 | def test_make_tree_for_sftp_branch(self): |
745 | """Transports backed by local directories create local trees.""" |
746 | - |
747 | + # NB: This is arguably a bug in the definition of make_branch_and_tree. |
748 | tree = self.make_branch_and_tree('t1') |
749 | base = tree.bzrdir.root_transport.base |
750 | self.failIf(base.startswith('sftp'), |
751 | @@ -1756,7 +1758,24 @@ |
752 | tree.branch.repository.bzrdir.root_transport) |
753 | |
754 | |
755 | -class TestSelftest(tests.TestCase): |
756 | +class SelfTestHelper: |
757 | + |
758 | + def run_selftest(self, **kwargs): |
759 | + """Run selftest returning its output.""" |
760 | + output = StringIO() |
761 | + old_transport = bzrlib.tests.default_transport |
762 | + old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT |
763 | + tests.TestCaseWithMemoryTransport.TEST_ROOT = None |
764 | + try: |
765 | + self.assertEqual(True, tests.selftest(stream=output, **kwargs)) |
766 | + finally: |
767 | + bzrlib.tests.default_transport = old_transport |
768 | + tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root |
769 | + output.seek(0) |
770 | + return output |
771 | + |
772 | + |
773 | +class TestSelftest(tests.TestCase, SelfTestHelper): |
774 | """Tests of bzrlib.tests.selftest.""" |
775 | |
776 | def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self): |
777 | @@ -1770,6 +1789,511 @@ |
778 | test_suite_factory=factory) |
779 | self.assertEqual([True], factory_called) |
780 | |
781 | + def factory(self): |
782 | + """A test suite factory.""" |
783 | + class Test(tests.TestCase): |
784 | + def a(self): |
785 | + pass |
786 | + def b(self): |
787 | + pass |
788 | + def c(self): |
789 | + pass |
790 | + return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")]) |
791 | + |
792 | + def test_list_only(self): |
793 | + output = self.run_selftest(test_suite_factory=self.factory, |
794 | + list_only=True) |
795 | + self.assertEqual(3, len(output.readlines())) |
796 | + |
797 | + def test_list_only_filtered(self): |
798 | + output = self.run_selftest(test_suite_factory=self.factory, |
799 | + list_only=True, pattern="Test.b") |
800 | + self.assertEndsWith(output.getvalue(), "Test.b\n") |
801 | + self.assertLength(1, output.readlines()) |
802 | + |
803 | + def test_list_only_excludes(self): |
804 | + output = self.run_selftest(test_suite_factory=self.factory, |
805 | + list_only=True, exclude_pattern="Test.b") |
806 | + self.assertNotContainsRe("Test.b", output.getvalue()) |
807 | + self.assertLength(2, output.readlines()) |
808 | + |
809 | + def test_random(self): |
810 | + # test randomising by listing a number of tests. |
811 | + output_123 = self.run_selftest(test_suite_factory=self.factory, |
812 | + list_only=True, random_seed="123") |
813 | + output_234 = self.run_selftest(test_suite_factory=self.factory, |
814 | + list_only=True, random_seed="234") |
815 | + self.assertNotEqual(output_123, output_234) |
816 | + # "Randominzing test order..\n\n |
817 | + self.assertLength(5, output_123.readlines()) |
818 | + self.assertLength(5, output_234.readlines()) |
819 | + |
820 | + def test_random_reuse_is_same_order(self): |
821 | + # test randomising by listing a number of tests. |
822 | + expected = self.run_selftest(test_suite_factory=self.factory, |
823 | + list_only=True, random_seed="123") |
824 | + repeated = self.run_selftest(test_suite_factory=self.factory, |
825 | + list_only=True, random_seed="123") |
826 | + self.assertEqual(expected.getvalue(), repeated.getvalue()) |
827 | + |
828 | + def test_runner_class(self): |
829 | + self.requireFeature(SubUnitFeature) |
830 | + from subunit import ProtocolTestCase |
831 | + stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner, |
832 | + test_suite_factory=self.factory) |
833 | + test = ProtocolTestCase(stream) |
834 | + result = unittest.TestResult() |
835 | + test.run(result) |
836 | + self.assertEqual(3, result.testsRun) |
837 | + |
838 | + def test_starting_with_single_argument(self): |
839 | + output = self.run_selftest(test_suite_factory=self.factory, |
840 | + starting_with=['bzrlib.tests.test_selftest.Test.a'], |
841 | + list_only=True) |
842 | + self.assertEqual('bzrlib.tests.test_selftest.Test.a\n', |
843 | + output.getvalue()) |
844 | + |
845 | + def test_starting_with_multiple_argument(self): |
846 | + output = self.run_selftest(test_suite_factory=self.factory, |
847 | + starting_with=['bzrlib.tests.test_selftest.Test.a', |
848 | + 'bzrlib.tests.test_selftest.Test.b'], |
849 | + list_only=True) |
850 | + self.assertEqual('bzrlib.tests.test_selftest.Test.a\n' |
851 | + 'bzrlib.tests.test_selftest.Test.b\n', |
852 | + output.getvalue()) |
853 | + |
854 | + def check_transport_set(self, transport_server): |
855 | + captured_transport = [] |
856 | + def seen_transport(a_transport): |
857 | + captured_transport.append(a_transport) |
858 | + class Capture(tests.TestCase): |
859 | + def a(self): |
860 | + seen_transport(bzrlib.tests.default_transport) |
861 | + def factory(): |
862 | + return TestUtil.TestSuite([Capture("a")]) |
863 | + self.run_selftest(transport=transport_server, test_suite_factory=factory) |
864 | + self.assertEqual(transport_server, captured_transport[0]) |
865 | + |
866 | + def test_transport_sftp(self): |
867 | + try: |
868 | + import bzrlib.transport.sftp |
869 | + except ParamikoNotPresent: |
870 | + raise TestSkipped("Paramiko not present") |
871 | + self.check_transport_set(bzrlib.transport.sftp.SFTPAbsoluteServer) |
872 | + |
873 | + def test_transport_memory(self): |
874 | + self.check_transport_set(bzrlib.transport.memory.MemoryServer) |
875 | + |
876 | + |
877 | +class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper): |
878 | + # Does IO: reads test.list |
879 | + |
880 | + def test_load_list(self): |
881 | + # Provide a list with one test - this test. |
882 | + test_id_line = '%s\n' % self.id() |
883 | + self.build_tree_contents([('test.list', test_id_line)]) |
884 | + # And generate a list of the tests in the suite. |
885 | + stream = self.run_selftest(load_list='test.list', list_only=True) |
886 | + self.assertEqual(test_id_line, stream.getvalue()) |
887 | + |
888 | + def test_load_unknown(self): |
889 | + # Provide a list with one test - this test. |
890 | + # And generate a list of the tests in the suite. |
891 | + err = self.assertRaises(errors.NoSuchFile, self.run_selftest, |
892 | + load_list='missing file name', list_only=True) |
893 | + |
894 | + |
895 | +class TestRunBzr(tests.TestCase): |
896 | + |
897 | + out = '' |
898 | + err = '' |
899 | + |
900 | + def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None, |
901 | + working_dir=None): |
902 | + """Override _run_bzr_core to test how it is invoked by run_bzr. |
903 | + |
904 | + Attempts to run bzr from inside this class don't actually run it. |
905 | + |
906 | + We test how run_bzr actually invokes bzr in another location. |
907 | + Here we only need to test that it is run_bzr passes the right |
908 | + parameters to run_bzr. |
909 | + """ |
910 | + self.argv = list(argv) |
911 | + self.retcode = retcode |
912 | + self.encoding = encoding |
913 | + self.stdin = stdin |
914 | + self.working_dir = working_dir |
915 | + return self.out, self.err |
916 | + |
917 | + def test_run_bzr_error(self): |
918 | + self.out = "It sure does!\n" |
919 | + out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34) |
920 | + self.assertEqual(['rocks'], self.argv) |
921 | + self.assertEqual(34, self.retcode) |
922 | + self.assertEqual(out, 'It sure does!\n') |
923 | + |
924 | + def test_run_bzr_error_regexes(self): |
925 | + self.out = '' |
926 | + self.err = "bzr: ERROR: foobarbaz is not versioned" |
927 | + out, err = self.run_bzr_error( |
928 | + ["bzr: ERROR: foobarbaz is not versioned"], |
929 | + ['file-id', 'foobarbaz']) |
930 | + |
931 | + def test_encoding(self): |
932 | + """Test that run_bzr passes encoding to _run_bzr_core""" |
933 | + self.run_bzr('foo bar') |
934 | + self.assertEqual(None, self.encoding) |
935 | + self.assertEqual(['foo', 'bar'], self.argv) |
936 | + |
937 | + self.run_bzr('foo bar', encoding='baz') |
938 | + self.assertEqual('baz', self.encoding) |
939 | + self.assertEqual(['foo', 'bar'], self.argv) |
940 | + |
941 | + def test_retcode(self): |
942 | + """Test that run_bzr passes retcode to _run_bzr_core""" |
943 | + # Default is retcode == 0 |
944 | + self.run_bzr('foo bar') |
945 | + self.assertEqual(0, self.retcode) |
946 | + self.assertEqual(['foo', 'bar'], self.argv) |
947 | + |
948 | + self.run_bzr('foo bar', retcode=1) |
949 | + self.assertEqual(1, self.retcode) |
950 | + self.assertEqual(['foo', 'bar'], self.argv) |
951 | + |
952 | + self.run_bzr('foo bar', retcode=None) |
953 | + self.assertEqual(None, self.retcode) |
954 | + self.assertEqual(['foo', 'bar'], self.argv) |
955 | + |
956 | + self.run_bzr(['foo', 'bar'], retcode=3) |
957 | + self.assertEqual(3, self.retcode) |
958 | + self.assertEqual(['foo', 'bar'], self.argv) |
959 | + |
960 | + def test_stdin(self): |
961 | + # test that the stdin keyword to run_bzr is passed through to |
962 | + # _run_bzr_core as-is. We do this by overriding |
963 | + # _run_bzr_core in this class, and then calling run_bzr, |
964 | + # which is a convenience function for _run_bzr_core, so |
965 | + # should invoke it. |
966 | + self.run_bzr('foo bar', stdin='gam') |
967 | + self.assertEqual('gam', self.stdin) |
968 | + self.assertEqual(['foo', 'bar'], self.argv) |
969 | + |
970 | + self.run_bzr('foo bar', stdin='zippy') |
971 | + self.assertEqual('zippy', self.stdin) |
972 | + self.assertEqual(['foo', 'bar'], self.argv) |
973 | + |
974 | + def test_working_dir(self): |
975 | + """Test that run_bzr passes working_dir to _run_bzr_core""" |
976 | + self.run_bzr('foo bar') |
977 | + self.assertEqual(None, self.working_dir) |
978 | + self.assertEqual(['foo', 'bar'], self.argv) |
979 | + |
980 | + self.run_bzr('foo bar', working_dir='baz') |
981 | + self.assertEqual('baz', self.working_dir) |
982 | + self.assertEqual(['foo', 'bar'], self.argv) |
983 | + |
984 | + def test_reject_extra_keyword_arguments(self): |
985 | + self.assertRaises(TypeError, self.run_bzr, "foo bar", |
986 | + error_regex=['error message']) |
987 | + |
988 | + |
989 | +class TestRunBzrCaptured(tests.TestCaseWithTransport): |
990 | + # Does IO when testing the working_dir parameter. |
991 | + |
992 | + def apply_redirected(self, stdin=None, stdout=None, stderr=None, |
993 | + a_callable=None, *args, **kwargs): |
994 | + self.stdin = stdin |
995 | + self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None) |
996 | + self.factory = bzrlib.ui.ui_factory |
997 | + self.working_dir = osutils.getcwd() |
998 | + stdout.write('foo\n') |
999 | + stderr.write('bar\n') |
1000 | + return 0 |
1001 | + |
1002 | + def test_stdin(self): |
1003 | + # test that the stdin keyword to _run_bzr_core is passed through to |
1004 | + # apply_redirected as a StringIO. We do this by overriding |
1005 | + # apply_redirected in this class, and then calling _run_bzr_core, |
1006 | + # which calls apply_redirected. |
1007 | + self.run_bzr(['foo', 'bar'], stdin='gam') |
1008 | + self.assertEqual('gam', self.stdin.read()) |
1009 | + self.assertTrue(self.stdin is self.factory_stdin) |
1010 | + self.run_bzr(['foo', 'bar'], stdin='zippy') |
1011 | + self.assertEqual('zippy', self.stdin.read()) |
1012 | + self.assertTrue(self.stdin is self.factory_stdin) |
1013 | + |
1014 | + def test_ui_factory(self): |
1015 | + # each invocation of self.run_bzr should get its |
1016 | + # own UI factory, which is an instance of TestUIFactory, |
1017 | + # with stdin, stdout and stderr attached to the stdin, |
1018 | + # stdout and stderr of the invoked run_bzr |
1019 | + current_factory = bzrlib.ui.ui_factory |
1020 | + self.run_bzr(['foo']) |
1021 | + self.failIf(current_factory is self.factory) |
1022 | + self.assertNotEqual(sys.stdout, self.factory.stdout) |
1023 | + self.assertNotEqual(sys.stderr, self.factory.stderr) |
1024 | + self.assertEqual('foo\n', self.factory.stdout.getvalue()) |
1025 | + self.assertEqual('bar\n', self.factory.stderr.getvalue()) |
1026 | + self.assertIsInstance(self.factory, tests.TestUIFactory) |
1027 | + |
1028 | + def test_working_dir(self): |
1029 | + self.build_tree(['one/', 'two/']) |
1030 | + cwd = osutils.getcwd() |
1031 | + |
1032 | + # Default is to work in the current directory |
1033 | + self.run_bzr(['foo', 'bar']) |
1034 | + self.assertEqual(cwd, self.working_dir) |
1035 | + |
1036 | + self.run_bzr(['foo', 'bar'], working_dir=None) |
1037 | + self.assertEqual(cwd, self.working_dir) |
1038 | + |
1039 | + # The function should be run in the alternative directory |
1040 | + # but afterwards the current working dir shouldn't be changed |
1041 | + self.run_bzr(['foo', 'bar'], working_dir='one') |
1042 | + self.assertNotEqual(cwd, self.working_dir) |
1043 | + self.assertEndsWith(self.working_dir, 'one') |
1044 | + self.assertEqual(cwd, osutils.getcwd()) |
1045 | + |
1046 | + self.run_bzr(['foo', 'bar'], working_dir='two') |
1047 | + self.assertNotEqual(cwd, self.working_dir) |
1048 | + self.assertEndsWith(self.working_dir, 'two') |
1049 | + self.assertEqual(cwd, osutils.getcwd()) |
1050 | + |
1051 | + |
1052 | +class StubProcess(object): |
1053 | + """A stub process for testing run_bzr_subprocess.""" |
1054 | + |
1055 | + def __init__(self, out="", err="", retcode=0): |
1056 | + self.out = out |
1057 | + self.err = err |
1058 | + self.returncode = retcode |
1059 | + |
1060 | + def communicate(self): |
1061 | + return self.out, self.err |
1062 | + |
1063 | + |
1064 | +class TestRunBzrSubprocess(tests.TestCaseWithTransport): |
1065 | + |
1066 | + def setUp(self): |
1067 | + tests.TestCaseWithTransport.setUp(self) |
1068 | + self.subprocess_calls = [] |
1069 | + |
1070 | + def start_bzr_subprocess(self, process_args, env_changes=None, |
1071 | + skip_if_plan_to_signal=False, |
1072 | + working_dir=None, |
1073 | + allow_plugins=False): |
1074 | + """capture what run_bzr_subprocess tries to do.""" |
1075 | + self.subprocess_calls.append({'process_args':process_args, |
1076 | + 'env_changes':env_changes, |
1077 | + 'skip_if_plan_to_signal':skip_if_plan_to_signal, |
1078 | + 'working_dir':working_dir, 'allow_plugins':allow_plugins}) |
1079 | + return self.next_subprocess |
1080 | + |
1081 | + def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs): |
1082 | + """Run run_bzr_subprocess with args and kwargs using a stubbed process. |
1083 | + |
1084 | + Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess |
1085 | + that will return static results. This assertion method populates those |
1086 | + results and also checks the arguments run_bzr_subprocess generates. |
1087 | + """ |
1088 | + self.next_subprocess = process |
1089 | + try: |
1090 | + result = self.run_bzr_subprocess(*args, **kwargs) |
1091 | + except: |
1092 | + self.next_subprocess = None |
1093 | + for key, expected in expected_args.iteritems(): |
1094 | + self.assertEqual(expected, self.subprocess_calls[-1][key]) |
1095 | + raise |
1096 | + else: |
1097 | + self.next_subprocess = None |
1098 | + for key, expected in expected_args.iteritems(): |
1099 | + self.assertEqual(expected, self.subprocess_calls[-1][key]) |
1100 | + return result |
1101 | + |
1102 | + def test_run_bzr_subprocess(self): |
1103 | + """The run_bzr_helper_external command behaves nicely.""" |
1104 | + self.assertRunBzrSubprocess({'process_args':['--version']}, |
1105 | + StubProcess(), '--version') |
1106 | + self.assertRunBzrSubprocess({'process_args':['--version']}, |
1107 | + StubProcess(), ['--version']) |
1108 | + # retcode=None disables retcode checking |
1109 | + result = self.assertRunBzrSubprocess({}, |
1110 | + StubProcess(retcode=3), '--version', retcode=None) |
1111 | + result = self.assertRunBzrSubprocess({}, |
1112 | + StubProcess(out="is free software"), '--version') |
1113 | + self.assertContainsRe(result[0], 'is free software') |
1114 | + # Running a subcommand that is missing errors |
1115 | + self.assertRaises(AssertionError, self.assertRunBzrSubprocess, |
1116 | + {'process_args':['--versionn']}, StubProcess(retcode=3), |
1117 | + '--versionn') |
1118 | + # Unless it is told to expect the error from the subprocess |
1119 | + result = self.assertRunBzrSubprocess({}, |
1120 | + StubProcess(retcode=3), '--versionn', retcode=3) |
1121 | + # Or to ignore retcode checking |
1122 | + result = self.assertRunBzrSubprocess({}, |
1123 | + StubProcess(err="unknown command", retcode=3), '--versionn', |
1124 | + retcode=None) |
1125 | + self.assertContainsRe(result[1], 'unknown command') |
1126 | + |
1127 | + def test_env_change_passes_through(self): |
1128 | + self.assertRunBzrSubprocess( |
1129 | + {'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}}, |
1130 | + StubProcess(), '', |
1131 | + env_changes={'new':'value', 'changed':'newvalue', 'deleted':None}) |
1132 | + |
1133 | + def test_no_working_dir_passed_as_None(self): |
1134 | + self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '') |
1135 | + |
1136 | + def test_no_working_dir_passed_through(self): |
1137 | + self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '', |
1138 | + working_dir='dir') |
1139 | + |
1140 | + def test_run_bzr_subprocess_no_plugins(self): |
1141 | + self.assertRunBzrSubprocess({'allow_plugins': False}, |
1142 | + StubProcess(), '') |
1143 | + |
1144 | + def test_allow_plugins(self): |
1145 | + self.assertRunBzrSubprocess({'allow_plugins': True}, |
1146 | + StubProcess(), '', allow_plugins=True) |
1147 | + |
1148 | + |
1149 | +class _DontSpawnProcess(Exception): |
1150 | + """A simple exception which just allows us to skip unnecessary steps""" |
1151 | + |
1152 | + |
1153 | +class TestStartBzrSubProcess(tests.TestCase): |
1154 | + |
1155 | + def check_popen_state(self): |
1156 | + """Replace to make assertions when popen is called.""" |
1157 | + |
1158 | + def _popen(self, *args, **kwargs): |
1159 | + """Record the command that is run, so that we can ensure it is correct""" |
1160 | + self.check_popen_state() |
1161 | + self._popen_args = args |
1162 | + self._popen_kwargs = kwargs |
1163 | + raise _DontSpawnProcess() |
1164 | + |
1165 | + def test_run_bzr_subprocess_no_plugins(self): |
1166 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, []) |
1167 | + command = self._popen_args[0] |
1168 | + self.assertEqual(sys.executable, command[0]) |
1169 | + self.assertEqual(self.get_bzr_path(), command[1]) |
1170 | + self.assertEqual(['--no-plugins'], command[2:]) |
1171 | + |
1172 | + def test_allow_plugins(self): |
1173 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [], |
1174 | + allow_plugins=True) |
1175 | + command = self._popen_args[0] |
1176 | + self.assertEqual([], command[2:]) |
1177 | + |
1178 | + def test_set_env(self): |
1179 | + self.failIf('EXISTANT_ENV_VAR' in os.environ) |
1180 | + # set in the child |
1181 | + def check_environment(): |
1182 | + self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR']) |
1183 | + self.check_popen_state = check_environment |
1184 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [], |
1185 | + env_changes={'EXISTANT_ENV_VAR':'set variable'}) |
1186 | + # not set in theparent |
1187 | + self.assertFalse('EXISTANT_ENV_VAR' in os.environ) |
1188 | + |
1189 | + def test_run_bzr_subprocess_env_del(self): |
1190 | + """run_bzr_subprocess can remove environment variables too.""" |
1191 | + self.failIf('EXISTANT_ENV_VAR' in os.environ) |
1192 | + def check_environment(): |
1193 | + self.assertFalse('EXISTANT_ENV_VAR' in os.environ) |
1194 | + os.environ['EXISTANT_ENV_VAR'] = 'set variable' |
1195 | + self.check_popen_state = check_environment |
1196 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [], |
1197 | + env_changes={'EXISTANT_ENV_VAR':None}) |
1198 | + # Still set in parent |
1199 | + self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR']) |
1200 | + del os.environ['EXISTANT_ENV_VAR'] |
1201 | + |
1202 | + def test_env_del_missing(self): |
1203 | + self.failIf('NON_EXISTANT_ENV_VAR' in os.environ) |
1204 | + def check_environment(): |
1205 | + self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ) |
1206 | + self.check_popen_state = check_environment |
1207 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [], |
1208 | + env_changes={'NON_EXISTANT_ENV_VAR':None}) |
1209 | + |
1210 | + def test_working_dir(self): |
1211 | + """Test that we can specify the working dir for the child""" |
1212 | + orig_getcwd = osutils.getcwd |
1213 | + orig_chdir = os.chdir |
1214 | + chdirs = [] |
1215 | + def chdir(path): |
1216 | + chdirs.append(path) |
1217 | + os.chdir = chdir |
1218 | + try: |
1219 | + def getcwd(): |
1220 | + return 'current' |
1221 | + osutils.getcwd = getcwd |
1222 | + try: |
1223 | + self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [], |
1224 | + working_dir='foo') |
1225 | + finally: |
1226 | + osutils.getcwd = orig_getcwd |
1227 | + finally: |
1228 | + os.chdir = orig_chdir |
1229 | + self.assertEqual(['foo', 'current'], chdirs) |
1230 | + |
1231 | + |
1232 | +class TestBzrSubprocess(tests.TestCaseWithTransport): |
1233 | + |
1234 | + def test_start_and_stop_bzr_subprocess(self): |
1235 | + """We can start and perform other test actions while that process is |
1236 | + still alive. |
1237 | + """ |
1238 | + process = self.start_bzr_subprocess(['--version']) |
1239 | + result = self.finish_bzr_subprocess(process) |
1240 | + self.assertContainsRe(result[0], 'is free software') |
1241 | + self.assertEqual('', result[1]) |
1242 | + |
1243 | + def test_start_and_stop_bzr_subprocess_with_error(self): |
1244 | + """finish_bzr_subprocess allows specification of the desired exit code. |
1245 | + """ |
1246 | + process = self.start_bzr_subprocess(['--versionn']) |
1247 | + result = self.finish_bzr_subprocess(process, retcode=3) |
1248 | + self.assertEqual('', result[0]) |
1249 | + self.assertContainsRe(result[1], 'unknown command') |
1250 | + |
1251 | + def test_start_and_stop_bzr_subprocess_ignoring_retcode(self): |
1252 | + """finish_bzr_subprocess allows the exit code to be ignored.""" |
1253 | + process = self.start_bzr_subprocess(['--versionn']) |
1254 | + result = self.finish_bzr_subprocess(process, retcode=None) |
1255 | + self.assertEqual('', result[0]) |
1256 | + self.assertContainsRe(result[1], 'unknown command') |
1257 | + |
1258 | + def test_start_and_stop_bzr_subprocess_with_unexpected_retcode(self): |
1259 | + """finish_bzr_subprocess raises self.failureException if the retcode is |
1260 | + not the expected one. |
1261 | + """ |
1262 | + process = self.start_bzr_subprocess(['--versionn']) |
1263 | + self.assertRaises(self.failureException, self.finish_bzr_subprocess, |
1264 | + process) |
1265 | + |
1266 | + def test_start_and_stop_bzr_subprocess_send_signal(self): |
1267 | + """finish_bzr_subprocess raises self.failureException if the retcode is |
1268 | + not the expected one. |
1269 | + """ |
1270 | + process = self.start_bzr_subprocess(['wait-until-signalled'], |
1271 | + skip_if_plan_to_signal=True) |
1272 | + self.assertEqual('running\n', process.stdout.readline()) |
1273 | + result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT, |
1274 | + retcode=3) |
1275 | + self.assertEqual('', result[0]) |
1276 | + self.assertEqual('bzr: interrupted\n', result[1]) |
1277 | + |
1278 | + def test_start_and_stop_working_dir(self): |
1279 | + cwd = osutils.getcwd() |
1280 | + self.make_branch_and_tree('one') |
1281 | + process = self.start_bzr_subprocess(['root'], working_dir='one') |
1282 | + result = self.finish_bzr_subprocess(process, universal_newlines=True) |
1283 | + self.assertEndsWith(result[0], 'one\n') |
1284 | + self.assertEqual('', result[1]) |
1285 | + |
1286 | |
1287 | class TestKnownFailure(tests.TestCase): |
1288 | |
1289 | @@ -1840,8 +2364,8 @@ |
1290 | tests.TestCase.setUp(self) |
1291 | self.suite = TestUtil.TestSuite() |
1292 | self.loader = TestUtil.TestLoader() |
1293 | - self.suite.addTest(self.loader.loadTestsFromModuleNames([ |
1294 | - 'bzrlib.tests.test_selftest'])) |
1295 | + self.suite.addTest(self.loader.loadTestsFromModule( |
1296 | + sys.modules['bzrlib.tests.test_selftest'])) |
1297 | self.all_names = _test_ids(self.suite) |
1298 | |
1299 | def test_condition_id_re(self): |
1300 | @@ -2158,8 +2682,8 @@ |
1301 | class TestTestSuite(tests.TestCase): |
1302 | |
1303 | def test_test_suite(self): |
1304 | - # This test is slow, so we do a single test with one test in each |
1305 | - # category |
1306 | + # This test is slow - it loads the entire test suite to operate, so we |
1307 | + # do a single test with one test in each category |
1308 | test_list = [ |
1309 | # testmod_names |
1310 | 'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch', |
1311 | @@ -2175,6 +2699,9 @@ |
1312 | self.assertEquals(test_list, _test_ids(suite)) |
1313 | |
1314 | def test_test_suite_list_and_start(self): |
1315 | + # We cannot test this at the same time as the main load, because we want |
1316 | + # to know that starting_with == None works. So a second full load is |
1317 | + # incurred. |
1318 | test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite'] |
1319 | suite = tests.test_suite(test_list, |
1320 | ['bzrlib.tests.test_selftest.TestTestSuite']) |
This finishes the thread I started tugging on this morning.
It does two basic things: tests.blackbox. test_selftest
- moves tests that are not for the bzr selftest command line out of
bzrlib.
- where possiblestops invoking child processes to test how we call such
processes, instead extending the existing idioms for intercepting
such calls to test how the calls are setup.
This saves another 50% of test time in 'test_selftest' tests over my
patch earlier today.
-Rob
--