/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_lazy_import.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Test the lazy_import functionality."""
18
18
 
 
19
import linecache
19
20
import os
 
21
import re
20
22
import sys
21
23
 
22
24
from bzrlib import (
24
26
    lazy_import,
25
27
    osutils,
26
28
    )
27
 
from bzrlib.tests import TestCase, TestCaseInTempDir
 
29
from bzrlib.tests import (
 
30
    TestCase,
 
31
    TestCaseInTempDir,
 
32
    )
28
33
 
29
34
 
30
35
class InstrumentedReplacer(lazy_import.ScopeReplacer):
262
267
        InstrumentedReplacer(scope=globals(), name='test_class2',
263
268
                             factory=factory)
264
269
 
265
 
        self.failIf(test_class2 is TestClass)
 
270
        self.assertFalse(test_class2 is TestClass)
266
271
        obj = test_class2()
267
272
        self.assertIs(test_class2, TestClass)
268
273
        self.assertIsInstance(obj, TestClass)
295
300
        InstrumentedReplacer(scope=globals(), name='test_func1',
296
301
                             factory=factory)
297
302
 
298
 
        self.failIf(test_func1 is func)
 
303
        self.assertFalse(test_func1 is func)
299
304
        val = test_func1(1, 2, c='3')
300
305
        self.assertIs(test_func1, func)
301
306
 
1164
1169
                          ('_import', 'root8'),
1165
1170
                          ('import', self.root_name, []),
1166
1171
                         ], self.actions)
 
1172
 
 
1173
 
 
1174
class TestScopeReplacerReentrance(TestCase):
 
1175
    """The ScopeReplacer should be reentrant.
 
1176
 
 
1177
    Invoking a replacer while an invocation was already on-going leads to a
 
1178
    race to see which invocation will be the first to delete the _factory and
 
1179
    _scope attributes.  The loosing caller used to see AttributeErrors (bug
 
1180
    702914).
 
1181
 
 
1182
    These tests set up a tracer that stops at the moment just before one of
 
1183
    the attributes is being deleted and starts another call to the
 
1184
    functionality in question (__call__, __getattribute__, __setattr_) in
 
1185
    order win the race, setting up the originall caller to loose.
 
1186
    """
 
1187
 
 
1188
    def tracer(self, frame, event, arg):
 
1189
        # Grab the name of the file that contains the code being executed.
 
1190
        filename = frame.f_globals["__file__"]
 
1191
        # Convert ".pyc" and ".pyo" file names to their ".py" equivalent.
 
1192
        filename = re.sub(r'\.py[co]$', '.py', filename)
 
1193
        # If we're executing a line of code from the right module...
 
1194
        if event == 'line' and 'lazy_import.py' in filename:
 
1195
            line = linecache.getline(filename, frame.f_lineno)
 
1196
            # ...and the line of code is the one we're looking for...
 
1197
            if 'del self._factory' in line:
 
1198
                # We don't need to trace any more.
 
1199
                sys.settrace(None)
 
1200
                # Run another racer.  This one will "win" the race, deleting
 
1201
                # the attributes.  When the first racer resumes it will loose
 
1202
                # the race, generating an AttributeError.
 
1203
                self.racer()
 
1204
        return self.tracer
 
1205
 
 
1206
    def run_race(self, racer):
 
1207
        self.racer = racer
 
1208
        sys.settrace(self.tracer)
 
1209
        self.racer() # Should not raise an AttributeError
 
1210
        # Make sure the tracer actually found the code it was looking for.  If
 
1211
        # not, maybe the code was refactored in such a way that these tests
 
1212
        # aren't needed any more.
 
1213
        self.assertEqual(None, sys.gettrace())
 
1214
 
 
1215
    def test_call(self):
 
1216
        def factory(*args):
 
1217
            return factory
 
1218
        replacer = lazy_import.ScopeReplacer({}, factory, 'name')
 
1219
        self.run_race(replacer)
 
1220
 
 
1221
    def test_setattr(self):
 
1222
        class Replaced:
 
1223
            pass
 
1224
 
 
1225
        def factory(*args):
 
1226
            return Replaced()
 
1227
 
 
1228
        replacer = lazy_import.ScopeReplacer({}, factory, 'name')
 
1229
 
 
1230
        def racer():
 
1231
            replacer.foo = 42
 
1232
 
 
1233
        self.run_race(racer)
 
1234
 
 
1235
    def test_getattribute(self):
 
1236
        class Replaced:
 
1237
            foo = 'bar'
 
1238
 
 
1239
        def factory(*args):
 
1240
            return Replaced()
 
1241
 
 
1242
        replacer = lazy_import.ScopeReplacer({}, factory, 'name')
 
1243
 
 
1244
        def racer():
 
1245
            replacer.foo
 
1246
 
 
1247
        self.run_race(racer)