source: wokkel/test/test_compat.py @ 198:7110457aff51

Last change on this file since 198:7110457aff51 was 165:76a61f5aa343, checked in by Ralph Meijer <ralphm@…>, 10 years ago

Cleanups leading up to Wokkel 0.7.0.

As we now depend on Twisted 10.0.0 or higher, the following classes and
interfaces were deprecated:

This also resolves all Pyflakes warnings, changes links for www.xmpp.org to
xmpp.org and fixes the copyright notice in LICENSE to include 2012.

  • Property exe set to *
File size: 15.7 KB
Line 
1# Copyright (c) Twisted Matrix Laboratories.
2# Copyright (c) Ralph Meijer.
3# See LICENSE for details.
4
5"""
6Tests for L{wokkel.compat}.
7"""
8
9from zope.interface import implements
10from twisted.internet import task
11from twisted.internet.interfaces import IReactorTime
12from twisted.trial import unittest
13from twisted.words.protocols.jabber import xmlstream
14
15from wokkel.compat import IQ
16from wokkel.compat import NamedConstant, Names, ValueConstant, Values
17
18class DeprecationTest(unittest.TestCase):
19    """
20    Deprecation tests for L{wokkel.compat}.
21    """
22
23    def lookForDeprecationWarning(self, testmethod, attributeName, newName):
24        """
25        Importing C{testmethod} emits a deprecation warning.
26        """
27        warningsShown = self.flushWarnings([testmethod])
28        self.assertEqual(len(warningsShown), 1)
29        self.assertIdentical(warningsShown[0]['category'], DeprecationWarning)
30        self.assertEqual(
31            warningsShown[0]['message'],
32            "wokkel.compat." + attributeName + " "
33            "was deprecated in Wokkel 0.7.0: Use " + newName + " instead.")
34
35
36    def test_bootstrapMixinTest(self):
37        """
38        L{compat.BootstrapMixin} is deprecated.
39        """
40        from wokkel.compat import BootstrapMixin
41        BootstrapMixin
42        self.lookForDeprecationWarning(
43                self.test_bootstrapMixinTest,
44                "BootstrapMixin",
45                "twisted.words.xish.xmlstream.BootstrapMixin")
46
47
48    def test_xmlStreamServerFactory(self):
49        """
50        L{compat.XmlStreamServerFactory} is deprecated.
51        """
52        from wokkel.compat import XmlStreamServerFactory
53        XmlStreamServerFactory
54        self.lookForDeprecationWarning(
55                self.test_xmlStreamServerFactory,
56                "XmlStreamServerFactory",
57                "twisted.words.protocols.jabber.xmlstream."
58                    "XmlStreamServerFactory")
59
60
61
62class FakeReactor(object):
63
64    implements(IReactorTime)
65    def __init__(self):
66        self.clock = task.Clock()
67        self.callLater = self.clock.callLater
68        self.getDelayedCalls = self.clock.getDelayedCalls
69
70
71
72class IQTest(unittest.TestCase):
73    """
74    Tests for L{IQ}.
75    """
76
77    def setUp(self):
78        self.reactor = FakeReactor()
79        self.clock = self.reactor.clock
80
81
82    def testRequestTimingOutEventDispatcher(self):
83        """
84        Test that an iq request with a defined timeout times out.
85        """
86        from twisted.words.xish import utility
87        output = []
88        xs = utility.EventDispatcher()
89        xs.send = output.append
90
91        self.iq = IQ(xs, reactor=self.reactor)
92        self.iq.timeout = 60
93        d = self.iq.send()
94        self.assertFailure(d, xmlstream.TimeoutError)
95
96        self.clock.pump([1, 60])
97        self.assertFalse(self.reactor.getDelayedCalls())
98        self.assertFalse(xs.iqDeferreds)
99        return d
100
101
102
103class NamedConstantTests(unittest.TestCase):
104    """
105    Tests for the L{twisted.python.constants.NamedConstant} class which is used
106    to represent individual values.
107    """
108    def setUp(self):
109        """
110        Create a dummy container into which constants can be placed.
111        """
112        class foo(Names):
113            pass
114        self.container = foo
115
116
117    def test_name(self):
118        """
119        The C{name} attribute of a L{NamedConstant} refers to the value passed
120        for the C{name} parameter to C{_realize}.
121        """
122        name = NamedConstant()
123        name._realize(self.container, "bar", None)
124        self.assertEqual("bar", name.name)
125
126
127    def test_representation(self):
128        """
129        The string representation of an instance of L{NamedConstant} includes
130        the container the instances belongs to as well as the instance's name.
131        """
132        name = NamedConstant()
133        name._realize(self.container, "bar", None)
134        self.assertEqual("<foo=bar>", repr(name))
135
136
137    def test_equality(self):
138        """
139        A L{NamedConstant} instance compares equal to itself.
140        """
141        name = NamedConstant()
142        name._realize(self.container, "bar", None)
143        self.assertTrue(name == name)
144        self.assertFalse(name != name)
145
146
147    def test_nonequality(self):
148        """
149        Two different L{NamedConstant} instances do not compare equal to each
150        other.
151        """
152        first = NamedConstant()
153        first._realize(self.container, "bar", None)
154        second = NamedConstant()
155        second._realize(self.container, "bar", None)
156        self.assertFalse(first == second)
157        self.assertTrue(first != second)
158
159
160    def test_hash(self):
161        """
162        Because two different L{NamedConstant} instances do not compare as equal
163        to each other, they also have different hashes to avoid collisions when
164        added to a C{dict} or C{set}.
165        """
166        first = NamedConstant()
167        first._realize(self.container, "bar", None)
168        second = NamedConstant()
169        second._realize(self.container, "bar", None)
170        self.assertNotEqual(hash(first), hash(second))
171
172
173
174class _ConstantsTestsMixin(object):
175    """
176    Mixin defining test helpers common to multiple types of constants
177    collections.
178    """
179    def _notInstantiableTest(self, name, cls):
180        """
181        Assert that an attempt to instantiate the constants class raises
182        C{TypeError}.
183
184        @param name: A C{str} giving the name of the constants collection.
185        @param cls: The constants class to test.
186        """
187        exc = self.assertRaises(TypeError, cls)
188        self.assertEqual(name + " may not be instantiated.", str(exc))
189
190
191
192class NamesTests(unittest.TestCase, _ConstantsTestsMixin):
193    """
194    Tests for L{twisted.python.constants.Names}, a base class for containers of
195    related constaints.
196    """
197    def setUp(self):
198        """
199        Create a fresh new L{Names} subclass for each unit test to use.  Since
200        L{Names} is stateful, re-using the same subclass across test methods
201        makes exercising all of the implementation code paths difficult.
202        """
203        class METHOD(Names):
204            """
205            A container for some named constants to use in unit tests for
206            L{Names}.
207            """
208            GET = NamedConstant()
209            PUT = NamedConstant()
210            POST = NamedConstant()
211            DELETE = NamedConstant()
212
213        self.METHOD = METHOD
214
215
216    def test_notInstantiable(self):
217        """
218        A subclass of L{Names} raises C{TypeError} if an attempt is made to
219        instantiate it.
220        """
221        self._notInstantiableTest("METHOD", self.METHOD)
222
223
224    def test_symbolicAttributes(self):
225        """
226        Each name associated with a L{NamedConstant} instance in the definition
227        of a L{Names} subclass is available as an attribute on the resulting
228        class.
229        """
230        self.assertTrue(hasattr(self.METHOD, "GET"))
231        self.assertTrue(hasattr(self.METHOD, "PUT"))
232        self.assertTrue(hasattr(self.METHOD, "POST"))
233        self.assertTrue(hasattr(self.METHOD, "DELETE"))
234
235
236    def test_withoutOtherAttributes(self):
237        """
238        As usual, names not defined in the class scope of a L{Names}
239        subclass are not available as attributes on the resulting class.
240        """
241        self.assertFalse(hasattr(self.METHOD, "foo"))
242
243
244    def test_representation(self):
245        """
246        The string representation of a constant on a L{Names} subclass includes
247        the name of the L{Names} subclass and the name of the constant itself.
248        """
249        self.assertEqual("<METHOD=GET>", repr(self.METHOD.GET))
250
251
252    def test_lookupByName(self):
253        """
254        Constants can be looked up by name using L{Names.lookupByName}.
255        """
256        method = self.METHOD.lookupByName("GET")
257        self.assertIdentical(self.METHOD.GET, method)
258
259
260    def test_notLookupMissingByName(self):
261        """
262        Names not defined with a L{NamedConstant} instance cannot be looked up
263        using L{Names.lookupByName}.
264        """
265        self.assertRaises(ValueError, self.METHOD.lookupByName, "lookupByName")
266        self.assertRaises(ValueError, self.METHOD.lookupByName, "__init__")
267        self.assertRaises(ValueError, self.METHOD.lookupByName, "foo")
268
269
270    def test_name(self):
271        """
272        The C{name} attribute of one of the named constants gives that
273        constant's name.
274        """
275        self.assertEqual("GET", self.METHOD.GET.name)
276
277
278    def test_attributeIdentity(self):
279        """
280        Repeated access of an attribute associated with a L{NamedConstant} value
281        in a L{Names} subclass results in the same object.
282        """
283        self.assertIdentical(self.METHOD.GET, self.METHOD.GET)
284
285
286    def test_iterconstants(self):
287        """
288        L{Names.iterconstants} returns an iterator over all of the constants
289        defined in the class, in the order they were defined.
290        """
291        constants = list(self.METHOD.iterconstants())
292        self.assertEqual(
293            [self.METHOD.GET, self.METHOD.PUT,
294             self.METHOD.POST, self.METHOD.DELETE],
295            constants)
296
297
298    def test_attributeIterconstantsIdentity(self):
299        """
300        The constants returned from L{Names.iterconstants} are identical to the
301        constants accessible using attributes.
302        """
303        constants = list(self.METHOD.iterconstants())
304        self.assertIdentical(self.METHOD.GET, constants[0])
305        self.assertIdentical(self.METHOD.PUT, constants[1])
306        self.assertIdentical(self.METHOD.POST, constants[2])
307        self.assertIdentical(self.METHOD.DELETE, constants[3])
308
309
310    def test_iterconstantsIdentity(self):
311        """
312        The constants returned from L{Names.iterconstants} are identical on each
313        call to that method.
314        """
315        constants = list(self.METHOD.iterconstants())
316        again = list(self.METHOD.iterconstants())
317        self.assertIdentical(again[0], constants[0])
318        self.assertIdentical(again[1], constants[1])
319        self.assertIdentical(again[2], constants[2])
320        self.assertIdentical(again[3], constants[3])
321
322
323    def test_initializedOnce(self):
324        """
325        L{Names._enumerants} is initialized once and its value re-used on
326        subsequent access.
327        """
328        first = self.METHOD._enumerants
329        self.METHOD.GET # Side-effects!
330        second = self.METHOD._enumerants
331        self.assertIdentical(first, second)
332
333
334
335class ValuesTests(unittest.TestCase, _ConstantsTestsMixin):
336    """
337    Tests for L{twisted.python.constants.Names}, a base class for containers of
338    related constaints with arbitrary values.
339    """
340    def setUp(self):
341        """
342        Create a fresh new L{Values} subclass for each unit test to use.  Since
343        L{Values} is stateful, re-using the same subclass across test methods
344        makes exercising all of the implementation code paths difficult.
345        """
346        class STATUS(Values):
347            OK = ValueConstant("200")
348            NOT_FOUND = ValueConstant("404")
349
350        self.STATUS = STATUS
351
352
353    def test_notInstantiable(self):
354        """
355        A subclass of L{Values} raises C{TypeError} if an attempt is made to
356        instantiate it.
357        """
358        self._notInstantiableTest("STATUS", self.STATUS)
359
360
361    def test_symbolicAttributes(self):
362        """
363        Each name associated with a L{ValueConstant} instance in the definition
364        of a L{Values} subclass is available as an attribute on the resulting
365        class.
366        """
367        self.assertTrue(hasattr(self.STATUS, "OK"))
368        self.assertTrue(hasattr(self.STATUS, "NOT_FOUND"))
369
370
371    def test_withoutOtherAttributes(self):
372        """
373        As usual, names not defined in the class scope of a L{Values}
374        subclass are not available as attributes on the resulting class.
375        """
376        self.assertFalse(hasattr(self.STATUS, "foo"))
377
378
379    def test_representation(self):
380        """
381        The string representation of a constant on a L{Values} subclass includes
382        the name of the L{Values} subclass and the name of the constant itself.
383        """
384        self.assertEqual("<STATUS=OK>", repr(self.STATUS.OK))
385
386
387    def test_lookupByName(self):
388        """
389        Constants can be looked up by name using L{Values.lookupByName}.
390        """
391        method = self.STATUS.lookupByName("OK")
392        self.assertIdentical(self.STATUS.OK, method)
393
394
395    def test_notLookupMissingByName(self):
396        """
397        Names not defined with a L{ValueConstant} instance cannot be looked up
398        using L{Values.lookupByName}.
399        """
400        self.assertRaises(ValueError, self.STATUS.lookupByName, "lookupByName")
401        self.assertRaises(ValueError, self.STATUS.lookupByName, "__init__")
402        self.assertRaises(ValueError, self.STATUS.lookupByName, "foo")
403
404
405    def test_lookupByValue(self):
406        """
407        Constants can be looked up by their associated value, defined by the
408        argument passed to L{ValueConstant}, using L{Values.lookupByValue}.
409        """
410        status = self.STATUS.lookupByValue("200")
411        self.assertIdentical(self.STATUS.OK, status)
412
413
414    def test_lookupDuplicateByValue(self):
415        """
416        If more than one constant is associated with a particular value,
417        L{Values.lookupByValue} returns whichever of them is defined first.
418        """
419        class TRANSPORT_MESSAGE(Values):
420            """
421            Message types supported by an SSH transport.
422            """
423            KEX_DH_GEX_REQUEST_OLD = ValueConstant(30)
424            KEXDH_INIT = ValueConstant(30)
425
426        self.assertIdentical(
427            TRANSPORT_MESSAGE.lookupByValue(30),
428            TRANSPORT_MESSAGE.KEX_DH_GEX_REQUEST_OLD)
429
430
431    def test_notLookupMissingByValue(self):
432        """
433        L{Values.lookupByValue} raises L{ValueError} when called with a value
434        with which no constant is associated.
435        """
436        self.assertRaises(ValueError, self.STATUS.lookupByValue, "OK")
437        self.assertRaises(ValueError, self.STATUS.lookupByValue, 200)
438        self.assertRaises(ValueError, self.STATUS.lookupByValue, "200.1")
439
440
441    def test_name(self):
442        """
443        The C{name} attribute of one of the constants gives that constant's
444        name.
445        """
446        self.assertEqual("OK", self.STATUS.OK.name)
447
448
449    def test_attributeIdentity(self):
450        """
451        Repeated access of an attribute associated with a L{ValueConstant} value
452        in a L{Values} subclass results in the same object.
453        """
454        self.assertIdentical(self.STATUS.OK, self.STATUS.OK)
455
456
457    def test_iterconstants(self):
458        """
459        L{Values.iterconstants} returns an iterator over all of the constants
460        defined in the class, in the order they were defined.
461        """
462        constants = list(self.STATUS.iterconstants())
463        self.assertEqual(
464            [self.STATUS.OK, self.STATUS.NOT_FOUND],
465            constants)
466
467
468    def test_attributeIterconstantsIdentity(self):
469        """
470        The constants returned from L{Values.iterconstants} are identical to the
471        constants accessible using attributes.
472        """
473        constants = list(self.STATUS.iterconstants())
474        self.assertIdentical(self.STATUS.OK, constants[0])
475        self.assertIdentical(self.STATUS.NOT_FOUND, constants[1])
476
477
478    def test_iterconstantsIdentity(self):
479        """
480        The constants returned from L{Values.iterconstants} are identical on
481        each call to that method.
482        """
483        constants = list(self.STATUS.iterconstants())
484        again = list(self.STATUS.iterconstants())
485        self.assertIdentical(again[0], constants[0])
486        self.assertIdentical(again[1], constants[1])
487
488
489    def test_initializedOnce(self):
490        """
491        L{Values._enumerants} is initialized once and its value re-used on
492        subsequent access.
493        """
494        first = self.STATUS._enumerants
495        self.STATUS.OK # Side-effects!
496        second = self.STATUS._enumerants
497        self.assertIdentical(first, second)
Note: See TracBrowser for help on using the repository browser.