source: ralphm-patches/addHandler-48.patch @ 47:f6d222b68f1c

Last change on this file since 47:f6d222b68f1c was 47:f6d222b68f1c, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Many new patches, upstreamed affiliations and worked on pubsub item.
Upstreamed pubsub_manage_affiliations

File size: 5.7 KB
RevLine 
[47]1# HG changeset patch
2# Parent bcf4497abc14816955c62dc9429a8d61f0cfe703
3Fix race condition and nesting errors when adding a new subprotocol handler.
4
5This fixes two related issues with adding a new subprotocol handler:
6
7 * Adding a handler when the stream is not yet initialized (authenticated)
8   does not cause `connectionMade` to be called.
9 * Adding a handler in `connectionMade`, `connectionInitialized`, or
10   `connectionLost` modifies the lists of handlers iterated over, causing
11   some methods being called too often.
12
13Author: ff, kandaurovoleg, ralphm.
14Fixes: #48.
15
16diff -r bcf4497abc14 wokkel/subprotocols.py
17--- a/wokkel/subprotocols.py    Mon Feb 28 20:40:04 2011 +0100
18+++ b/wokkel/subprotocols.py    Mon Feb 28 20:53:55 2011 +0100
19@@ -185,8 +185,9 @@
20 
21         # get protocol handler up to speed when a connection has already
22         # been established
23-        if self.xmlstream and self._initialized:
24+        if self.xmlstream:
25             handler.makeConnection(self.xmlstream)
26+        if self._initialized:
27             handler.connectionInitialized()
28 
29 
30@@ -210,7 +211,7 @@
31 
32         self.xmlstream = xs
33 
34-        for e in self:
35+        for e in list(self):
36             e.makeConnection(xs)
37 
38 
39@@ -229,7 +230,7 @@
40 
41         # Notify all child services which implement
42         # the IService interface
43-        for e in self:
44+        for e in list(self):
45             e.connectionInitialized()
46 
47 
48@@ -264,7 +265,7 @@
49 
50         # Notify all child services which implement
51         # the IService interface
52-        for e in self:
53+        for e in list(self):
54             e.connectionLost(reason)
55 
56 
57diff -r bcf4497abc14 wokkel/test/test_subprotocols.py
58--- a/wokkel/test/test_subprotocols.py  Mon Feb 28 20:40:04 2011 +0100
59+++ b/wokkel/test/test_subprotocols.py  Mon Feb 28 20:53:55 2011 +0100
60@@ -286,6 +286,49 @@
61         self.assertEquals(0, handler.doneLost)
62 
63 
64+    def test_addHandlerConnected(self):
65+        """
66+        Adding a handler when connected doesn't call connectionInitialized.
67+        """
68+        sm = self.streamManager
69+        xs = xmlstream.XmlStream(xmlstream.Authenticator())
70+        sm._connected(xs)
71+        handler = DummyXMPPHandler()
72+        handler.setHandlerParent(sm)
73+
74+        self.assertEquals(1, handler.doneMade)
75+        self.assertEquals(0, handler.doneInitialized)
76+        self.assertEquals(0, handler.doneLost)
77+
78+
79+    def test_addHandlerConnectedNested(self):
80+        """
81+        Adding a handler in connectionMade doesn't cause 2nd call.
82+        """
83+        class NestingHandler(DummyXMPPHandler):
84+            nestedHandler = None
85+
86+            def connectionMade(self):
87+                DummyXMPPHandler.connectionMade(self)
88+                self.nestedHandler = DummyXMPPHandler()
89+                self.nestedHandler.setHandlerParent(self.parent)
90+
91+        sm = self.streamManager
92+        xs = xmlstream.XmlStream(xmlstream.Authenticator())
93+        handler = NestingHandler()
94+        handler.setHandlerParent(sm)
95+        sm._connected(xs)
96+
97+        self.assertEquals(1, handler.doneMade)
98+        self.assertEquals(0, handler.doneInitialized)
99+        self.assertEquals(0, handler.doneLost)
100+
101+        self.assertEquals(1, handler.nestedHandler.doneMade)
102+        self.assertEquals(0, handler.nestedHandler.doneInitialized)
103+        self.assertEquals(0, handler.nestedHandler.doneLost)
104+
105+
106+
107     def test_addHandlerInitialized(self):
108         """
109         Test the addition of a protocol handler after the stream
110@@ -306,6 +349,64 @@
111         self.assertEquals(1, handler.doneInitialized)
112         self.assertEquals(0, handler.doneLost)
113 
114+
115+    def test_addHandlerInitializedNested(self):
116+        """
117+        Adding a handler in connectionInitialized doesn't cause 2nd call.
118+        """
119+        class NestingHandler(DummyXMPPHandler):
120+            nestedHandler = None
121+
122+            def connectionInitialized(self):
123+                DummyXMPPHandler.connectionInitialized(self)
124+                self.nestedHandler = DummyXMPPHandler()
125+                self.nestedHandler.setHandlerParent(self.parent)
126+
127+        sm = self.streamManager
128+        xs = xmlstream.XmlStream(xmlstream.Authenticator())
129+        handler = NestingHandler()
130+        handler.setHandlerParent(sm)
131+        sm._connected(xs)
132+        sm._authd(xs)
133+
134+        self.assertEquals(1, handler.doneMade)
135+        self.assertEquals(1, handler.doneInitialized)
136+        self.assertEquals(0, handler.doneLost)
137+
138+        self.assertEquals(1, handler.nestedHandler.doneMade)
139+        self.assertEquals(1, handler.nestedHandler.doneInitialized)
140+        self.assertEquals(0, handler.nestedHandler.doneLost)
141+
142+
143+    def test_addHandlerConnectionLostNested(self):
144+        """
145+        Adding a handler in connectionLost doesn't call connectionLost there.
146+        """
147+        class NestingHandler(DummyXMPPHandler):
148+            nestedHandler = None
149+
150+            def connectionLost(self, reason):
151+                DummyXMPPHandler.connectionLost(self, reason)
152+                self.nestedHandler = DummyXMPPHandler()
153+                self.nestedHandler.setHandlerParent(self.parent)
154+
155+        sm = self.streamManager
156+        xs = xmlstream.XmlStream(xmlstream.Authenticator())
157+        handler = NestingHandler()
158+        handler.setHandlerParent(sm)
159+        sm._connected(xs)
160+        sm._authd(xs)
161+        sm._disconnected(xs)
162+
163+        self.assertEquals(1, handler.doneMade)
164+        self.assertEquals(1, handler.doneInitialized)
165+        self.assertEquals(1, handler.doneLost)
166+
167+        self.assertEquals(0, handler.nestedHandler.doneMade)
168+        self.assertEquals(0, handler.nestedHandler.doneInitialized)
169+        self.assertEquals(0, handler.nestedHandler.doneLost)
170+
171+
172     def test_removeHandler(self):
173         """
174         Test removal of protocol handler.
Note: See TracBrowser for help on using the repository browser.