~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/__init__.py

Merge from mpool.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
import unittest
28
28
import time
29
29
 
 
30
from logging import debug, warning, error
 
31
 
30
32
import bzrlib.commands
31
33
import bzrlib.trace
32
 
import bzrlib.fetch
33
34
import bzrlib.osutils as osutils
34
35
from bzrlib.selftest import TestUtil
35
36
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
36
37
from bzrlib.selftest.treeshape import build_tree_contents
 
38
from bzrlib.errors import BzrError
37
39
 
38
40
MODULES_TO_TEST = []
39
41
MODULES_TO_DOCTEST = []
40
42
 
41
 
from logging import debug, warning, error
42
43
 
43
44
 
44
45
class EarlyStoppingTestResultAdapter(object):
222
223
        """
223
224
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
224
225
        self._log_file = os.fdopen(fileno, 'w+')
225
 
        hdlr = logging.StreamHandler(self._log_file)
226
 
        hdlr.setLevel(logging.DEBUG)
227
 
        hdlr.setFormatter(logging.Formatter('%(levelname)8s  %(message)s'))
228
 
        logging.getLogger('').addHandler(hdlr)
229
 
        logging.getLogger('').setLevel(logging.DEBUG)
230
 
        self._log_hdlr = hdlr
 
226
        bzrlib.trace.enable_test_log(self._log_file)
231
227
        debug('opened log file %s', name)
232
228
        self._log_file_name = name
233
229
        self.addCleanup(self._finishLogFile)
237
233
 
238
234
        Read contents into memory, close, and delete.
239
235
        """
 
236
        bzrlib.trace.disable_test_log()
240
237
        self._log_file.seek(0)
241
238
        self._log_contents = self._log_file.read()
242
239
        self._log_file.close()
255
252
        self._cleanups.append(callable)
256
253
 
257
254
    def _cleanEnvironment(self):
258
 
        self.oldenv = os.environ.get('HOME', None)
259
 
        os.environ['HOME'] = os.getcwd()
260
 
        self.bzr_email = os.environ.get('BZREMAIL')
261
 
        if self.bzr_email is not None:
262
 
            del os.environ['BZREMAIL']
263
 
        self.email = os.environ.get('EMAIL')
264
 
        if self.email is not None:
265
 
            del os.environ['EMAIL']
 
255
        new_env = {
 
256
            'HOME': os.getcwd(),
 
257
            'APPDATA': os.getcwd(),
 
258
            'BZREMAIL': None,
 
259
            'EMAIL': None,
 
260
        }
 
261
        self.__old_env = {}
266
262
        self.addCleanup(self._restoreEnvironment)
 
263
        for name, value in new_env.iteritems():
 
264
            self._captureVar(name, value)
 
265
 
 
266
 
 
267
    def _captureVar(self, name, newvalue):
 
268
        """Set an environment variable, preparing it to be reset when finished."""
 
269
        self.__old_env[name] = os.environ.get(name, None)
 
270
        if newvalue is None:
 
271
            if name in os.environ:
 
272
                del os.environ[name]
 
273
        else:
 
274
            os.environ[name] = newvalue
 
275
 
 
276
    @staticmethod
 
277
    def _restoreVar(name, value):
 
278
        if value is None:
 
279
            if name in os.environ:
 
280
                del os.environ[name]
 
281
        else:
 
282
            os.environ[name] = value
267
283
 
268
284
    def _restoreEnvironment(self):
269
 
        os.environ['HOME'] = self.oldenv
270
 
        if os.environ.get('BZREMAIL') is not None:
271
 
            del os.environ['BZREMAIL']
272
 
        if self.bzr_email is not None:
273
 
            os.environ['BZREMAIL'] = self.bzr_email
274
 
        if os.environ.get('EMAIL') is not None:
275
 
            del os.environ['EMAIL']
276
 
        if self.email is not None:
277
 
            os.environ['EMAIL'] = self.email
 
285
        for name, value in self.__old_env.iteritems():
 
286
            self._restoreVar(name, value)
278
287
 
279
288
    def tearDown(self):
280
 
        logging.getLogger('').removeHandler(self._log_hdlr)
281
 
        bzrlib.trace.enable_default_logging()
282
 
        logging.debug('%s teardown', self.id())
283
289
        self._runCleanups()
284
290
        unittest.TestCase.tearDown(self)
285
291
 
478
484
            os.chdir(_currentdir)
479
485
        self.addCleanup(_leaveDirectory)
480
486
        
481
 
    def build_tree(self, shape):
 
487
    def build_tree(self, shape, line_endings='native'):
482
488
        """Build a test tree according to a pattern.
483
489
 
484
490
        shape is a sequence of file specifications.  If the final
485
491
        character is '/', a directory is created.
486
492
 
487
493
        This doesn't add anything to a branch.
 
494
        :param line_endings: Either 'binary' or 'native'
 
495
                             in binary mode, exact contents are written
 
496
                             in native mode, the line endings match the
 
497
                             default platform endings.
488
498
        """
489
499
        # XXX: It's OK to just create them using forward slashes on windows?
490
500
        for name in shape:
492
502
            if name[-1] == '/':
493
503
                os.mkdir(name[:-1])
494
504
            else:
495
 
                f = file(name, 'wt')
 
505
                if line_endings == 'binary':
 
506
                    f = file(name, 'wb')
 
507
                elif line_endings == 'native':
 
508
                    f = file(name, 'wt')
 
509
                else:
 
510
                    raise BzrError('Invalid line ending request %r' % (line_endings,))
496
511
                print >>f, "contents of", name
497
512
                f.close()
498
513
 
512
527
class MetaTestLog(TestCase):
513
528
    def test_logging(self):
514
529
        """Test logs are captured when a test fails."""
515
 
        logging.info('an info message')
516
 
        warning('something looks dodgy...')
517
 
        logging.debug('hello, test is running')
 
530
        self.log('a test message')
 
531
        self.assertContainsRe(self._get_log(), 'a test message\n')
518
532
 
519
533
 
520
534
def filter_suite_by_re(suite, pattern):
527
541
 
528
542
 
529
543
def run_suite(suite, name='test', verbose=False, pattern=".*",
530
 
              stop_on_failure=False):
 
544
              stop_on_failure=False, keep_output=False):
531
545
    TestCaseInTempDir._TEST_NAME = name
532
546
    if verbose:
533
547
        verbosity = 2
543
557
    # This is still a little bogus, 
544
558
    # but only a little. Folk not using our testrunner will
545
559
    # have to delete their temp directories themselves.
546
 
    if result.wasSuccessful():
 
560
    if result.wasSuccessful() or not keep_output:
547
561
        if TestCaseInTempDir.TEST_ROOT is not None:
548
562
            shutil.rmtree(TestCaseInTempDir.TEST_ROOT) 
549
563
    else:
551
565
    return result.wasSuccessful()
552
566
 
553
567
 
554
 
def selftest(verbose=False, pattern=".*", stop_on_failure=True):
 
568
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
 
569
             keep_output=False):
555
570
    """Run the whole test suite under the enhanced runner"""
556
571
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
557
 
                     stop_on_failure=stop_on_failure)
 
572
                     stop_on_failure=stop_on_failure, keep_output=keep_output)
558
573
 
559
574
 
560
575
def test_suite():
565
580
 
566
581
    global MODULES_TO_TEST, MODULES_TO_DOCTEST
567
582
 
 
583
    # FIXME: If these fail to load, e.g. because of a syntax error, the
 
584
    # exception is hidden by unittest.  Sucks.  Should either fix that or
 
585
    # perhaps import them and pass them to unittest as modules.
568
586
    testmod_names = \
569
587
                  ['bzrlib.selftest.MetaTestLog',
570
588
                   'bzrlib.selftest.testapi',
613
631
                   'bzrlib.selftest.testnonascii',
614
632
                   'bzrlib.selftest.testreweave',
615
633
                   'bzrlib.selftest.testtsort',
 
634
                   'bzrlib.selftest.testtrace',
616
635
                   ]
617
636
 
618
637
    for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,