~ubuntu-branches/ubuntu/trusty/twisted/trusty

« back to all changes in this revision

Viewing changes to twisted/python/test/test_utilpy3.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 13:30:20 UTC
  • mfrom: (44.2.1 sid)
  • Revision ID: package-import@ubuntu.com-20130620133020-p316m1joldnubeio
Tags: 13.0.0-1ubuntu1
* Merge with Debian; remaining changes:
  - Keep the preliminary python3 support, but don't enable it.
  - Try to use plain pygtkcompat and fall back to gi.pygtkcompat, to
    avoid a DeprecationWarning, and a crash.
  - Use new io_add_watch api on new versions of pygobject.
  - Point html documentation to the generated api docs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) Twisted Matrix Laboratories.
2
 
# See LICENSE for details.
3
 
 
4
 
"""
5
 
Tests for the subset of L{twisted.python.util} which has been ported to Python 3.
6
 
"""
7
 
 
8
 
from __future__ import division, absolute_import
9
 
 
10
 
import sys, errno, warnings
11
 
 
12
 
from twisted.trial.unittest import SynchronousTestCase as TestCase
13
 
 
14
 
from twisted.python import _utilpy3 as util
15
 
 
16
 
 
17
 
class Record(util.FancyEqMixin):
18
 
    """
19
 
    Trivial user of L{FancyEqMixin} used by tests.
20
 
    """
21
 
    compareAttributes = ('a', 'b')
22
 
 
23
 
    def __init__(self, a, b):
24
 
        self.a = a
25
 
        self.b = b
26
 
 
27
 
 
28
 
 
29
 
class DifferentRecord(util.FancyEqMixin):
30
 
    """
31
 
    Trivial user of L{FancyEqMixin} which is not related to L{Record}.
32
 
    """
33
 
    compareAttributes = ('a', 'b')
34
 
 
35
 
    def __init__(self, a, b):
36
 
        self.a = a
37
 
        self.b = b
38
 
 
39
 
 
40
 
 
41
 
class DerivedRecord(Record):
42
 
    """
43
 
    A class with an inheritance relationship to L{Record}.
44
 
    """
45
 
 
46
 
 
47
 
 
48
 
class EqualToEverything(object):
49
 
    """
50
 
    A class the instances of which consider themselves equal to everything.
51
 
    """
52
 
    def __eq__(self, other):
53
 
        return True
54
 
 
55
 
 
56
 
    def __ne__(self, other):
57
 
        return False
58
 
 
59
 
 
60
 
 
61
 
class EqualToNothing(object):
62
 
    """
63
 
    A class the instances of which consider themselves equal to nothing.
64
 
    """
65
 
    def __eq__(self, other):
66
 
        return False
67
 
 
68
 
 
69
 
    def __ne__(self, other):
70
 
        return True
71
 
 
72
 
 
73
 
 
74
 
class EqualityTests(TestCase):
75
 
    """
76
 
    Tests for L{FancyEqMixin}.
77
 
    """
78
 
    def test_identity(self):
79
 
        """
80
 
        Instances of a class which mixes in L{FancyEqMixin} but which
81
 
        defines no comparison attributes compare by identity.
82
 
        """
83
 
        class Empty(util.FancyEqMixin):
84
 
            pass
85
 
 
86
 
        self.assertFalse(Empty() == Empty())
87
 
        self.assertTrue(Empty() != Empty())
88
 
        empty = Empty()
89
 
        self.assertTrue(empty == empty)
90
 
        self.assertFalse(empty != empty)
91
 
 
92
 
 
93
 
    def test_equality(self):
94
 
        """
95
 
        Instances of a class which mixes in L{FancyEqMixin} should compare
96
 
        equal if all of their attributes compare equal.  They should not
97
 
        compare equal if any of their attributes do not compare equal.
98
 
        """
99
 
        self.assertTrue(Record(1, 2) == Record(1, 2))
100
 
        self.assertFalse(Record(1, 2) == Record(1, 3))
101
 
        self.assertFalse(Record(1, 2) == Record(2, 2))
102
 
        self.assertFalse(Record(1, 2) == Record(3, 4))
103
 
 
104
 
 
105
 
    def test_unequality(self):
106
 
        """
107
 
        Unequality between instances of a particular L{record} should be
108
 
        defined as the negation of equality.
109
 
        """
110
 
        self.assertFalse(Record(1, 2) != Record(1, 2))
111
 
        self.assertTrue(Record(1, 2) != Record(1, 3))
112
 
        self.assertTrue(Record(1, 2) != Record(2, 2))
113
 
        self.assertTrue(Record(1, 2) != Record(3, 4))
114
 
 
115
 
 
116
 
    def test_differentClassesEquality(self):
117
 
        """
118
 
        Instances of different classes which mix in L{FancyEqMixin} should not
119
 
        compare equal.
120
 
        """
121
 
        self.assertFalse(Record(1, 2) == DifferentRecord(1, 2))
122
 
 
123
 
 
124
 
    def test_differentClassesInequality(self):
125
 
        """
126
 
        Instances of different classes which mix in L{FancyEqMixin} should
127
 
        compare unequal.
128
 
        """
129
 
        self.assertTrue(Record(1, 2) != DifferentRecord(1, 2))
130
 
 
131
 
 
132
 
    def test_inheritedClassesEquality(self):
133
 
        """
134
 
        An instance of a class which derives from a class which mixes in
135
 
        L{FancyEqMixin} should compare equal to an instance of the base class
136
 
        if and only if all of their attributes compare equal.
137
 
        """
138
 
        self.assertTrue(Record(1, 2) == DerivedRecord(1, 2))
139
 
        self.assertFalse(Record(1, 2) == DerivedRecord(1, 3))
140
 
        self.assertFalse(Record(1, 2) == DerivedRecord(2, 2))
141
 
        self.assertFalse(Record(1, 2) == DerivedRecord(3, 4))
142
 
 
143
 
 
144
 
    def test_inheritedClassesInequality(self):
145
 
        """
146
 
        An instance of a class which derives from a class which mixes in
147
 
        L{FancyEqMixin} should compare unequal to an instance of the base
148
 
        class if any of their attributes compare unequal.
149
 
        """
150
 
        self.assertFalse(Record(1, 2) != DerivedRecord(1, 2))
151
 
        self.assertTrue(Record(1, 2) != DerivedRecord(1, 3))
152
 
        self.assertTrue(Record(1, 2) != DerivedRecord(2, 2))
153
 
        self.assertTrue(Record(1, 2) != DerivedRecord(3, 4))
154
 
 
155
 
 
156
 
    def test_rightHandArgumentImplementsEquality(self):
157
 
        """
158
 
        The right-hand argument to the equality operator is given a chance
159
 
        to determine the result of the operation if it is of a type
160
 
        unrelated to the L{FancyEqMixin}-based instance on the left-hand
161
 
        side.
162
 
        """
163
 
        self.assertTrue(Record(1, 2) == EqualToEverything())
164
 
        self.assertFalse(Record(1, 2) == EqualToNothing())
165
 
 
166
 
 
167
 
    def test_rightHandArgumentImplementsUnequality(self):
168
 
        """
169
 
        The right-hand argument to the non-equality operator is given a
170
 
        chance to determine the result of the operation if it is of a type
171
 
        unrelated to the L{FancyEqMixin}-based instance on the left-hand
172
 
        side.
173
 
        """
174
 
        self.assertFalse(Record(1, 2) != EqualToEverything())
175
 
        self.assertTrue(Record(1, 2) != EqualToNothing())
176
 
 
177
 
 
178
 
 
179
 
class UnsignedIDTests(TestCase):
180
 
    """
181
 
    Tests for L{util.unsignedID} and L{util.setIDFunction}.
182
 
    """
183
 
 
184
 
    def setUp(self):
185
 
        """
186
 
        Save the value of L{util._idFunction} and arrange for it to be restored
187
 
        after the test runs.
188
 
        """
189
 
        self.addCleanup(setattr, util, '_idFunction', util._idFunction)
190
 
 
191
 
 
192
 
    def test_setIDFunction(self):
193
 
        """
194
 
        L{util.setIDFunction} returns the last value passed to it.
195
 
        """
196
 
        value = object()
197
 
        previous = util.setIDFunction(value)
198
 
        result = util.setIDFunction(previous)
199
 
        self.assertIdentical(value, result)
200
 
 
201
 
 
202
 
    def test_unsignedID(self):
203
 
        """
204
 
        L{util.unsignedID} uses the function passed to L{util.setIDFunction} to
205
 
        determine the unique integer id of an object and then adjusts it to be
206
 
        positive if necessary.
207
 
        """
208
 
        foo = object()
209
 
        bar = object()
210
 
 
211
 
        # A fake object identity mapping
212
 
        objects = {foo: 17, bar: -73}
213
 
        def fakeId(obj):
214
 
            return objects[obj]
215
 
 
216
 
        util.setIDFunction(fakeId)
217
 
 
218
 
        self.assertEqual(util.unsignedID(foo), 17)
219
 
        self.assertEqual(util.unsignedID(bar), (sys.maxsize + 1) * 2 - 73)
220
 
 
221
 
 
222
 
    def test_defaultIDFunction(self):
223
 
        """
224
 
        L{util.unsignedID} uses the built in L{id} by default.
225
 
        """
226
 
        obj = object()
227
 
        idValue = id(obj)
228
 
        if idValue < 0:
229
 
            idValue += (sys.maxsize + 1) * 2
230
 
 
231
 
        self.assertEqual(util.unsignedID(obj), idValue)
232
 
 
233
 
 
234
 
 
235
 
class UntilConcludesTests(TestCase):
236
 
    """
237
 
    Tests for L{untilConcludes}, an C{EINTR} helper.
238
 
    """
239
 
    def test_uninterruptably(self):
240
 
        """
241
 
        L{untilConcludes} calls the function passed to it until the function
242
 
        does not raise either L{OSError} or L{IOError} with C{errno} of
243
 
        C{EINTR}.  It otherwise completes with the same result as the function
244
 
        passed to it.
245
 
        """
246
 
        def f(a, b):
247
 
            self.calls += 1
248
 
            exc = self.exceptions.pop()
249
 
            if exc is not None:
250
 
                raise exc(errno.EINTR, "Interrupted system call!")
251
 
            return a + b
252
 
 
253
 
        self.exceptions = [None]
254
 
        self.calls = 0
255
 
        self.assertEqual(util.untilConcludes(f, 1, 2), 3)
256
 
        self.assertEqual(self.calls, 1)
257
 
 
258
 
        self.exceptions = [None, OSError, IOError]
259
 
        self.calls = 0
260
 
        self.assertEqual(util.untilConcludes(f, 2, 3), 5)
261
 
        self.assertEqual(self.calls, 3)
262
 
 
263
 
 
264
 
 
265
 
class SuppressedWarningsTests(TestCase):
266
 
    """
267
 
    Tests for L{util.runWithWarningsSuppressed}.
268
 
    """
269
 
    runWithWarningsSuppressed = staticmethod(util.runWithWarningsSuppressed)
270
 
 
271
 
    def test_runWithWarningsSuppressedFiltered(self):
272
 
        """
273
 
        Warnings from the function called by C{runWithWarningsSuppressed} are
274
 
        suppressed if they match the passed in filter.
275
 
        """
276
 
        filters = [(("ignore", ".*foo.*"), {}),
277
 
                   (("ignore", ".*bar.*"), {})]
278
 
        self.runWithWarningsSuppressed(filters, warnings.warn, "ignore foo")
279
 
        self.runWithWarningsSuppressed(filters, warnings.warn, "ignore bar")
280
 
        self.assertEqual([], self.flushWarnings())
281
 
 
282
 
 
283
 
    def test_runWithWarningsSuppressedUnfiltered(self):
284
 
        """
285
 
        Warnings from the function called by C{runWithWarningsSuppressed} are
286
 
        not suppressed if they do not match the passed in filter.
287
 
        """
288
 
        filters = [(("ignore", ".*foo.*"), {}),
289
 
                   (("ignore", ".*bar.*"), {})]
290
 
        self.runWithWarningsSuppressed(filters, warnings.warn, "don't ignore")
291
 
        self.assertEqual(
292
 
            ["don't ignore"], [w['message'] for w in self.flushWarnings()])
293
 
 
294
 
 
295
 
    def test_passThrough(self):
296
 
        """
297
 
        C{runWithWarningsSuppressed} returns the result of the function it
298
 
        called.
299
 
        """
300
 
        self.assertEqual(self.runWithWarningsSuppressed([], lambda: 4), 4)
301
 
 
302
 
 
303
 
    def test_noSideEffects(self):
304
 
        """
305
 
        Once C{runWithWarningsSuppressed} has returned, it no longer
306
 
        suppresses warnings.
307
 
        """
308
 
        filters = [(("ignore", ".*foo.*"), {}),
309
 
                   (("ignore", ".*bar.*"), {})]
310
 
        self.runWithWarningsSuppressed(filters, lambda: None)
311
 
        warnings.warn("ignore foo")
312
 
        self.assertEqual(
313
 
            ["ignore foo"], [w['message'] for w in self.flushWarnings()])
314
 
 
315
 
 
316
 
 
317
 
class FancyStrMixinTests(TestCase):
318
 
    """
319
 
    Tests for L{util.FancyStrMixin}.
320
 
    """
321
 
 
322
 
    def test_sequenceOfStrings(self):
323
 
        """
324
 
        If C{showAttributes} is set to a sequence of strings, C{__str__}
325
 
        renders using those by looking them up as attributes on the object.
326
 
        """
327
 
        class Foo(util.FancyStrMixin):
328
 
            showAttributes = ("first", "second")
329
 
            first = 1
330
 
            second = "hello"
331
 
        self.assertEqual(str(Foo()), "<Foo first=1 second='hello'>")
332
 
 
333
 
 
334
 
    def test_formatter(self):
335
 
        """
336
 
        If C{showAttributes} has an item that is a 2-tuple, C{__str__} renders
337
 
        the first item in the tuple as a key and the result of calling the
338
 
        second item with the value of the attribute named by the first item as
339
 
        the value.
340
 
        """
341
 
        class Foo(util.FancyStrMixin):
342
 
            showAttributes = (
343
 
                "first",
344
 
                ("second", lambda value: repr(value[::-1])))
345
 
            first = "hello"
346
 
            second = "world"
347
 
        self.assertEqual("<Foo first='hello' second='dlrow'>", str(Foo()))
348
 
 
349
 
 
350
 
    def test_override(self):
351
 
        """
352
 
        If C{showAttributes} has an item that is a 3-tuple, C{__str__} renders
353
 
        the second item in the tuple as a key, and the contents of the
354
 
        attribute named in the first item are rendered as the value. The value
355
 
        is formatted using the third item in the tuple.
356
 
        """
357
 
        class Foo(util.FancyStrMixin):
358
 
            showAttributes = ("first", ("second", "2nd", "%.1f"))
359
 
            first = 1
360
 
            second = 2.111
361
 
        self.assertEqual(str(Foo()), "<Foo first=1 2nd=2.1>")
362
 
 
363
 
 
364
 
    def test_fancybasename(self):
365
 
        """
366
 
        If C{fancybasename} is present, C{__str__} uses it instead of the class name.
367
 
        """
368
 
        class Foo(util.FancyStrMixin):
369
 
            fancybasename = "Bar"
370
 
        self.assertEqual(str(Foo()), "<Bar>")
371
 
 
372
 
 
373
 
    def test_repr(self):
374
 
        """
375
 
        C{__repr__} outputs the same content as C{__str__}.
376
 
        """
377
 
        class Foo(util.FancyStrMixin):
378
 
            showAttributes = ("first", "second")
379
 
            first = 1
380
 
            second = "hello"
381
 
        obj = Foo()
382
 
        self.assertEqual(str(obj), repr(obj))
383
 
 
384
 
 
385
 
 
386
 
class NameToLabelTests(TestCase):
387
 
    """
388
 
    Tests for L{nameToLabel}.
389
 
    """
390
 
 
391
 
    def test_nameToLabel(self):
392
 
        """
393
 
        Test the various kinds of inputs L{nameToLabel} supports.
394
 
        """
395
 
        nameData = [
396
 
            ('f', 'F'),
397
 
            ('fo', 'Fo'),
398
 
            ('foo', 'Foo'),
399
 
            ('fooBar', 'Foo Bar'),
400
 
            ('fooBarBaz', 'Foo Bar Baz'),
401
 
            ]
402
 
        for inp, out in nameData:
403
 
            got = util.nameToLabel(inp)
404
 
            self.assertEqual(
405
 
                got, out,
406
 
                "nameToLabel(%r) == %r != %r" % (inp, got, out))
407
 
 
408
 
 
409
 
 
410
 
class InsensitiveDictTest(TestCase):
411
 
    """
412
 
    Tests for L{util.InsensitiveDict}.
413
 
    """
414
 
 
415
 
    def test_preserve(self):
416
 
        """
417
 
        L{util.InsensitiveDict} preserves the case of keys if constructed with
418
 
        C{preserve=True}.
419
 
        """
420
 
        dct = util.InsensitiveDict({'Foo':'bar', 1:2, 'fnz':{1:2}}, preserve=1)
421
 
        self.assertEqual(dct['fnz'], {1:2})
422
 
        self.assertEqual(dct['foo'], 'bar')
423
 
        self.assertEqual(dct.copy(), dct)
424
 
        self.assertEqual(dct['foo'], dct.get('Foo'))
425
 
        self.assertIn(1, dct)
426
 
        self.assertIn('foo', dct)
427
 
        # Make eval() work, urrrrgh:
428
 
        InsensitiveDict = util.InsensitiveDict
429
 
        self.assertEqual(eval(repr(dct)), dct)
430
 
        keys=['Foo', 'fnz', 1]
431
 
        for x in keys:
432
 
            self.assertIn(x, dct.keys())
433
 
            self.assertIn((x, dct[x]), dct.items())
434
 
        self.assertEqual(len(keys), len(dct))
435
 
        del dct[1]
436
 
        del dct['foo']
437
 
        self.assertEqual(dct.keys(), ['fnz'])
438
 
 
439
 
 
440
 
    def test_noPreserve(self):
441
 
        """
442
 
        L{util.InsensitiveDict} does not preserves the case of keys if
443
 
        constructed with C{preserve=False}.
444
 
        """
445
 
        dct = util.InsensitiveDict({'Foo':'bar', 1:2, 'fnz':{1:2}}, preserve=0)
446
 
        keys=['foo', 'fnz', 1]
447
 
        for x in keys:
448
 
            self.assertIn(x, dct.keys())
449
 
            self.assertIn((x, dct[x]), dct.items())
450
 
        self.assertEqual(len(keys), len(dct))
451
 
        del dct[1]
452
 
        del dct['foo']
453
 
        self.assertEqual(dct.keys(), ['fnz'])
454
 
 
455
 
 
456
 
    def test_unicode(self):
457
 
        """
458
 
        Unicode keys are case insensitive.
459
 
        """
460
 
        d = util.InsensitiveDict(preserve=False)
461
 
        d[u"Foo"] = 1
462
 
        self.assertEqual(d[u"FOO"], 1)
463
 
        self.assertEqual(d.keys(), [u"foo"])
464
 
 
465
 
 
466
 
    def test_bytes(self):
467
 
        """
468
 
        Bytes keys are case insensitive.
469
 
        """
470
 
        d = util.InsensitiveDict(preserve=False)
471
 
        d[b"Foo"] = 1
472
 
        self.assertEqual(d[b"FOO"], 1)
473
 
        self.assertEqual(d.keys(), [b"foo"])