Merge lp:~exarkun/divmod.org/pop3-timeouts into lp:divmod.org

Proposed by Jean-Paul Calderone
Status: Merged
Approved by: Tristan Seligmann
Approved revision: 2695
Merged at revision: 2693
Proposed branch: lp:~exarkun/divmod.org/pop3-timeouts
Merge into: lp:divmod.org
Diff against target: 144 lines (+75/-18)
2 files modified
Quotient/xquotient/grabber.py (+5/-3)
Quotient/xquotient/test/test_grabber.py (+70/-15)
To merge this branch: bzr merge lp:~exarkun/divmod.org/pop3-timeouts
Reviewer Review Type Date Requested Status
Tristan Seligmann Approve
Review via email: mp+105489@code.launchpad.net

Description of the change

Branch does a couple things:

  - Adds a check to `setStatus` to not bother doing anything if `grabber` has already been discarded
  - Shuffles things around a bit in `timeoutConnection` so the timeout is actually reflected in the status.

To post a comment you must log in.
Revision history for this message
Tristan Seligmann (mithrandi) wrote :

I haven't actually tested the code, but the diff looks reasonable.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Quotient/xquotient/grabber.py'
2--- Quotient/xquotient/grabber.py 2012-04-28 14:23:40 +0000
3+++ Quotient/xquotient/grabber.py 2012-05-11 14:12:27 +0000
4@@ -409,10 +409,11 @@
5 Disassociate the protocol object from the POP3Grabber and drop the
6 connection.
7 """
8+ msg = u"Timed out waiting for server response."
9 addr, peer = self.transport.getHost(), self.transport.getPeer()
10 log.msg("POP3GrabberProtocol/%s->%s timed out" % (addr, peer))
11- self.transientFailure(failure.Failure(
12- error.TimeoutError("Timed out waiting for server response.")))
13+ self.setStatus(msg)
14+ self.transientFailure(failure.Failure(error.TimeoutError(msg)))
15 self.stoppedRunning()
16 self.transport.loseConnection()
17
18@@ -593,7 +594,8 @@
19
20
21 def setStatus(self, msg, success=True):
22- self._transact(self.grabber.status.setStatus, msg, success)
23+ if self.grabber is not None:
24+ self._transact(self.grabber.status.setStatus, msg, success)
25
26
27 def shouldRetrieve(self, uidList):
28
29=== modified file 'Quotient/xquotient/test/test_grabber.py'
30--- Quotient/xquotient/test/test_grabber.py 2012-04-28 14:23:40 +0000
31+++ Quotient/xquotient/test/test_grabber.py 2012-05-11 14:12:27 +0000
32@@ -7,6 +7,8 @@
33 from twisted.internet import defer, error
34 from twisted.mail import pop3
35 from twisted.cred import error as ecred
36+from twisted.test.proto_helpers import StringTransport
37+from twisted.python.failure import Failure
38
39 from epsilon import structlike, extime
40
41@@ -364,35 +366,88 @@
42 """
43 Tests for L{xquotient.grabber.ControlledPOP3GrabberProtocol}.
44 """
45+ def setUp(self):
46+ """
47+ Create a grabber in a user store.
48+ """
49+ self.siteStore = store.Store()
50+ self.subStore = substore.SubStore.createNew(self.siteStore, ['grabber'])
51+ self.userStore = self.subStore.open()
52+ self.scheduler = iaxiom.IScheduler(self.userStore)
53+
54+ self.grabberItem = grabber.POP3Grabber(
55+ store=self.userStore, username=u"alice", domain=u"example.com",
56+ password=u"secret", running=True,
57+ config=grabber.GrabberConfiguration(store=self.userStore))
58+ self.grabberItem.scheduled = extime.Time()
59+ self.scheduler.schedule(self.grabberItem, self.grabberItem.scheduled)
60+
61+
62 def test_stoppedRunningWithGrabber(self):
63 """
64 When L{ControlledPOP3GrabberProtocol.stoppedRunning} is called after a
65 transient failure, and the protocol instance has an associated grabber,
66 that grabber is rescheduled to run immediately.
67 """
68- siteStore = store.Store()
69- subStore = substore.SubStore.createNew(siteStore, ['grabber'])
70- userStore = subStore.open()
71- scheduler = iaxiom.IScheduler(userStore)
72-
73- grabberItem = grabber.POP3Grabber(
74- store=userStore, username=u"alice", domain=u"example.com",
75- password=u"secret", running=True,
76- config=grabber.GrabberConfiguration(store=userStore))
77- grabberItem.scheduled = extime.Time()
78- scheduler.schedule(grabberItem, grabberItem.scheduled)
79-
80- factory = grabber.POP3GrabberFactory(grabberItem, False)
81+ factory = grabber.POP3GrabberFactory(self.grabberItem, False)
82 protocol = factory.buildProtocol(None)
83 protocol.transientFailure(None)
84 protocol.stoppedRunning()
85- self.assertEqual(False, grabberItem.running)
86+ self.assertEqual(False, self.grabberItem.running)
87
88- scheduled = list(scheduler.scheduledTimes(grabberItem))
89+ scheduled = list(self.scheduler.scheduledTimes(self.grabberItem))
90 self.assertEqual(1, len(scheduled))
91 self.assertTrue(scheduled[0] <= extime.Time())
92
93
94+ def test_stoppedRunningAfterTimeout(self):
95+ """
96+ When L{ControlledPOP3GrabberProtocol} times out the connection
97+ due to inactivity, the controlling grabber's status is set to
98+ reflect this.
99+ """
100+ factory = grabber.POP3GrabberFactory(self.grabberItem, False)
101+ protocol = factory.buildProtocol(None)
102+ protocol.makeConnection(StringTransport())
103+ protocol.timeoutConnection()
104+ protocol.connectionLost(Failure(error.ConnectionLost("Simulated")))
105+
106+ self.assertEqual(
107+ self.grabberItem.status.message,
108+ u"Timed out waiting for server response.")
109+
110+
111+ def test_stoppedRunningAfterListTimeout(self):
112+ """
113+ When L{ControlledPOP3GrabberProtocol} times out the connection
114+ due to inactivity while waiting for a response to a I{UIDL}
115+ (list UIDs) command, the controlling grabber's status is set
116+ to reflect this.
117+ """
118+ factory = grabber.POP3GrabberFactory(self.grabberItem, False)
119+ protocol = factory.buildProtocol(None)
120+ protocol.allowInsecureLogin = True
121+ protocol.makeConnection(StringTransport())
122+ # Server greeting
123+ protocol.dataReceived("+OK Hello\r\n")
124+ # CAPA response
125+ protocol.dataReceived("+OK\r\nUSER\r\nUIDL\r\n.\r\n")
126+ # USER response
127+ protocol.dataReceived("+OK\r\n")
128+ # PASS response
129+ protocol.dataReceived("+OK\r\n")
130+ # Sanity check, we should have gotten to sending the UIDL
131+ self.assertTrue(
132+ protocol.transport.value().endswith("\r\nUIDL\r\n"),
133+ "Failed to get to UIDL: %r" % (protocol.transport.value(),))
134+
135+ protocol.timeoutConnection()
136+ protocol.connectionLost(Failure(error.ConnectionLost("Simulated")))
137+ self.assertEqual(
138+ self.grabberItem.status.message,
139+ u"Timed out waiting for server response.")
140+
141+
142
143 class GrabberConfigurationTestCase(unittest.TestCase):
144 """

Subscribers

People subscribed via source and target branches