~divmod-dev/divmod.org/trunk

« back to all changes in this revision

Viewing changes to Epsilon/epsilon/test/test_structlike.py

  • Committer: Jean-Paul Calderone
  • Date: 2014-06-29 20:33:04 UTC
  • mfrom: (2749.1.1 remove-epsilon-1325289)
  • Revision ID: exarkun@twistedmatrix.com-20140629203304-gdkmbwl1suei4m97
mergeĀ lp:~exarkun/divmod.org/remove-epsilon-1325289

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
"""
3
 
Tests for L{epsilon.structlike}.
4
 
"""
5
 
 
6
 
import threading
7
 
 
8
 
from twisted.trial import unittest
9
 
from twisted.internet.threads import deferToThread
10
 
from twisted.internet.defer import gatherResults
11
 
from epsilon.structlike import record
12
 
 
13
 
 
14
 
class MyRecord(record('something somethingElse')):
15
 
    """
16
 
    A sample record subclass.
17
 
    """
18
 
 
19
 
 
20
 
 
21
 
class StructLike(unittest.TestCase):
22
 
    def _testme(self, TestStruct):
23
 
        x = TestStruct()
24
 
        self.assertEquals(x.x, 1)
25
 
        self.assertEquals(x.y, 2)
26
 
        self.assertEquals(x.z, 3)
27
 
 
28
 
        y = TestStruct('3', '2', '1')
29
 
        self.assertEquals(y.x, '3')
30
 
        self.assertEquals(y.y, '2')
31
 
        self.assertEquals(y.z, '1')
32
 
 
33
 
        z = TestStruct(z='z', x='x', y='y')
34
 
        self.assertEquals(z.x, 'x')
35
 
        self.assertEquals(z.y, 'y')
36
 
        self.assertEquals(z.z, 'z')
37
 
 
38
 
        a = TestStruct('abc')
39
 
        self.assertEquals(a.x, 'abc')
40
 
        self.assertEquals(a.y, 2)
41
 
        self.assertEquals(a.z, 3)
42
 
 
43
 
        b = TestStruct(y='123')
44
 
        self.assertEquals(b.x, 1)
45
 
        self.assertEquals(b.y, '123')
46
 
        self.assertEquals(b.z, 3)
47
 
 
48
 
    def testWithPositional(self):
49
 
        self._testme(record('x y z', x=1, y=2, z=3))
50
 
 
51
 
    def testWithPositionalSubclass(self):
52
 
        class RecordSubclass(record('x y z', x=1, y=2, z=3)):
53
 
            pass
54
 
        self._testme(RecordSubclass)
55
 
 
56
 
    def testWithoutPositional(self):
57
 
        self._testme(record(x=1, y=2, z=3))
58
 
 
59
 
    def testWithoutPositionalSubclass(self):
60
 
        class RecordSubclass(record(x=1, y=2, z=3)):
61
 
            pass
62
 
        self._testme(RecordSubclass)
63
 
 
64
 
    def testBreakRecord(self):
65
 
        self.assertRaises(TypeError, record)
66
 
        self.assertRaises(TypeError, record, 'a b c', a=1, c=2)
67
 
        self.assertRaises(TypeError, record, 'a b', c=2)
68
 
        self.assertRaises(TypeError, record, 'a b', a=1)
69
 
 
70
 
    def testUndeclared(self):
71
 
        R = record('a')
72
 
        r = R(1)
73
 
        r.foo = 2
74
 
        self.assertEquals(r.foo, 2)
75
 
 
76
 
    def testCreateWithNoValuesAndNoDefaults(self):
77
 
        R = record('x')
78
 
        self.assertRaises(TypeError, R)
79
 
 
80
 
    def testUnknownArgs(self):
81
 
        """
82
 
        Test that passing in unknown keyword and / or positional arguments to a
83
 
        record's initializer causes TypeError to be raised.
84
 
        """
85
 
        R = record('x')
86
 
        self.assertRaises(TypeError, R, x=5, y=6)
87
 
        self.assertRaises(TypeError, R, 5, 6)
88
 
 
89
 
 
90
 
    def test_typeStringRepresentation(self):
91
 
        """
92
 
        'Record' types should have a name which provides information about the
93
 
        slots they contain.
94
 
        """
95
 
        R = record('xyz abc def')
96
 
        self.assertEquals(R.__name__, "Record<xyz abc def>")
97
 
 
98
 
 
99
 
    def test_instanceStringRepresentation(self):
100
 
        """
101
 
        'Record' instances should provide a string representation which
102
 
        provides information about the values contained in their slots.
103
 
        """
104
 
        obj = MyRecord(something=1, somethingElse=2)
105
 
        self.assertEquals(repr(obj), 'MyRecord(something=1, somethingElse=2)')
106
 
 
107
 
 
108
 
    def test_instanceStringRepresentationNesting(self):
109
 
        """
110
 
        Nested L{Record} instances should have nested string representations.
111
 
        """
112
 
        obj = MyRecord(something=1, somethingElse=2)
113
 
        objRepr = 'MyRecord(something=1, somethingElse=2)'
114
 
        self.assertEquals(
115
 
            repr(MyRecord(obj, obj)),
116
 
            'MyRecord(something=%s, somethingElse=%s)' % (objRepr, objRepr))
117
 
 
118
 
 
119
 
    def test_instanceStringRepresentationRecursion(self):
120
 
        """
121
 
        'Record' instances should provide a repr that displays 'ClassName(...)'
122
 
        when it would otherwise infinitely recurse.
123
 
        """
124
 
        obj = MyRecord(something=1, somethingElse=2)
125
 
        obj.somethingElse = obj
126
 
        self.assertEquals(
127
 
            repr(obj), 'MyRecord(something=1, somethingElse=MyRecord(...))')
128
 
 
129
 
 
130
 
    def test_instanceStringRepresentationUnhashableRecursion(self):
131
 
        """
132
 
        'Record' instances should display 'ClassName(...)' even for unhashable
133
 
        objects.
134
 
        """
135
 
        obj = MyRecord(something=1, somethingElse=[])
136
 
        obj.somethingElse.append(obj)
137
 
        self.assertEquals(
138
 
            repr(obj), 'MyRecord(something=1, somethingElse=[MyRecord(...)])')
139
 
 
140
 
 
141
 
    def test_threadLocality(self):
142
 
        """
143
 
        An 'Record' repr()'d in two separate threads at the same time should
144
 
        look the same (i.e. the repr state tracking for '...' should be
145
 
        thread-local).
146
 
        """
147
 
        class StickyRepr(object):
148
 
            """
149
 
            This has a __repr__ which will block until a separate thread
150
 
            notifies it that it should return.  We use this to create a race
151
 
            condition.
152
 
            """
153
 
            waited = False
154
 
            def __init__(self):
155
 
                self.set = threading.Event()
156
 
                self.wait = threading.Event()
157
 
            def __repr__(self):
158
 
                if not self.waited:
159
 
                    self.set.set()
160
 
                    self.wait.wait()
161
 
                return 'sticky'
162
 
        r = StickyRepr()
163
 
        mr = MyRecord(something=1, somethingElse=r)
164
 
        d = deferToThread(repr, mr)
165
 
        def otherRepr():
166
 
            # First we wait for the first thread doing a repr() to enter its
167
 
            # __repr__()...
168
 
            r.set.wait()
169
 
            # OK, now it's blocked.  Let's make sure that subsequent calls to
170
 
            # this repr() won't block.
171
 
            r.waited = True
172
 
            # Do it!  This is a concurrent repr().
173
 
            result = repr(mr)
174
 
            # Now we're done, wake up the other repr and let it complete.
175
 
            r.wait.set()
176
 
            return result
177
 
        d2 = deferToThread(otherRepr)
178
 
 
179
 
        def done((thread1repr, thread2repr)):
180
 
            knownGood = 'MyRecord(something=1, somethingElse=sticky)'
181
 
            # self.assertEquals(thread1repr, thread2repr)
182
 
            self.assertEquals(thread1repr, knownGood)
183
 
            self.assertEquals(thread2repr, knownGood)
184
 
        return gatherResults([d, d2]).addCallback(done)
185
 
 
186