aabaebc0befb924d406f3ca12b636c0050ea739e
[quix0rs-apt-p2p.git] / test_airhook.py
1 import unittest
2 from airhook import *
3 from random import uniform as rand
4 from cStringIO import StringIO
5
6
7 if __name__ =="__main__":
8     tests = unittest.defaultTestLoader.loadTestsFromNames(['test_airhook'])
9     result = unittest.TextTestRunner().run(tests)
10
11 class Echo(protocol.Protocol):
12     def dataReceived(self, data):
13         self.transport.write(data)
14         
15 class Noisy(protocol.Protocol):
16     def dataReceived(self, data):
17         print `data`
18
19 class Receiver(protocol.Protocol):
20     def __init__(self):
21         self.q = []
22     def dataReceived(self, data):
23         self.q.append(data)
24
25 class StreamReceiver(protocol.Protocol):
26     def __init__(self):
27         self.buf = ""
28     def dataReceived(self, data):
29         self.buf += data
30         
31 class EchoFactory(protocol.Factory):
32     def buildProtocol(self, addr):
33         return Echo()
34 class NoisyFactory(protocol.Factory):
35     def buildProtocol(self, addr):
36         return Noisy()
37 class ReceiverFactory(protocol.Factory):
38     def buildProtocol(self, addr):
39         return Receiver()
40 class StreamReceiverFactory(protocol.Factory):
41     def buildProtocol(self, addr):
42         return StreamReceiver()
43         
44 def makeEcho(port):
45     return listenAirhookStream(port, EchoFactory())
46 def makeNoisy(port):
47     return listenAirhookStream(port, NoisyFactory())
48 def makeReceiver(port):
49     return listenAirhookStream(port, ReceiverFactory())
50 def makeStreamReceiver(port):
51     return listenAirhookStream(port, StreamReceiverFactory())
52
53 class DummyTransport:
54     def __init__(self):
55         self.s = StringIO()
56     def write(self, data, addr):
57         self.s.write(data)
58     def seek(self, num):
59         return self.s.seek(num)
60     def read(self):
61         return self.s.read()
62         
63 def test_createStartPacket():
64     flags = 0 | FLAG_AIRHOOK | FLAG_SESSION 
65     packet = chr(flags) + "\xff" + "\x00\x00" + pack("!L", long(rand(0, 2**32)))
66     return packet
67
68 def test_createReply(session, observed, obseq, seq):
69     flags = 0 | FLAG_AIRHOOK | FLAG_SESSION | FLAG_OBSERVED
70     packet = chr(flags) + pack("!H", seq)[1] + pack("!H", obseq + 1) + pack("!L", session) + pack("!L", observed)
71     return packet
72
73 def pscope(msg, noisy=0):
74     # packet scope
75     str = ""
76     p = AirhookPacket(msg)
77     str += "oseq: %s  seq: %s " %  (p.oseq, p.seq)
78     if noisy:
79         str += "packet: %s  \n" % (`p.datagram`)
80     flags = p.flags
81     str += "flags: "
82     if flags & FLAG_SESSION:
83         str += "FLAG_SESSION "
84     if flags & FLAG_OBSERVED:
85         str += "FLAG_OBSERVED "
86     if flags & FLAG_MISSED:
87         str += "FLAG_MISSED "
88     if flags & FLAG_NEXT:
89         str += "FLAG_NEXT "
90     str += "\n"
91     
92     if p.observed != None:
93         str += "OBSERVED: %s\n" % p.observed
94     if p.session != None:
95         str += "SESSION: %s\n" % p.session
96     if p.next != None:
97         str += "NEXT: %s\n" % p.next
98     if p.missed:
99         if noisy:
100             str += "MISSED: " + `p.missed`
101         else:
102             str += "MISSED: " + `len(p.missed)`
103         str += "\n"
104     if p.msgs:
105         if noisy:
106             str += "MSGS: " + `p.msgs` + "\n"
107         else:
108             str += "MSGS: <%s> " % len(p.msgs)
109         str += "\n"
110     return str
111             
112 # testing function
113 def swap(a, dir="", noisy=0):
114     msg = ""
115     while not msg:
116         a.transport.seek(0)
117         msg= a.transport.read()
118         a.transport = DummyTransport()
119         if not msg:
120             a.sendNext()
121     if noisy:
122                 print 6*dir + " " + pscope(msg)
123     return msg
124     
125 def runTillEmpty(a, b, prob=1.0, noisy=0):
126     msga = ''
127     msgb = ''
128     while a.omsgq or b.omsgq or a.weMissed or b.weMissed or ord(msga[0]) & (FLAG_NEXT | FLAG_MISSED) or ord(msgb[0]) & (FLAG_NEXT | FLAG_MISSED):
129         if rand(0,1) < prob:
130             msga = swap(a, '>', noisy)
131             b.datagramReceived(msga)
132         else:
133             msga = swap(a, '>', 0)
134         if rand(0,1) < prob:
135             msgb = swap(b, '<', noisy)
136             a.datagramReceived(msgb)
137         else:
138             msgb = swap(b, '<', 0)
139
140 class UstrTests(unittest.TestCase):
141     def u(self, seq):
142         return ustr("%s%s" % (pack("!H", seq), 'foobar'))
143         
144     def testLT(self):
145         self.failUnless(self.u(0) < self.u(1))
146         self.failUnless(self.u(1) < self.u(2))
147         self.failUnless(self.u(2**16 - 1) < self.u(0))
148         self.failUnless(self.u(2**16 - 1) < self.u(1))
149         
150         self.failIf(self.u(1) < self.u(0))
151         self.failIf(self.u(2) < self.u(1))
152         self.failIf(self.u(0) < self.u(2**16 - 1))
153         self.failIf(self.u(1) < self.u(2**16 - 1))
154         
155     def testLTE(self):
156         self.failUnless(self.u(0) <= self.u(1))
157         self.failUnless(self.u(1) <= self.u(2))
158         self.failUnless(self.u(2) <= self.u(2))
159         self.failUnless(self.u(2**16 - 1) <= self.u(0))
160         self.failUnless(self.u(2**16 - 1) <= self.u(1))
161         self.failUnless(self.u(2**16 - 1) <= self.u(2**16))
162
163         self.failIf(self.u(1) <= self.u(0))
164         self.failIf(self.u(2) <= self.u(1))
165         self.failIf(self.u(0) <= self.u(2**16 - 1))
166         self.failIf(self.u(1) <= self.u(2**16 - 1))
167         
168     def testGT(self):
169         self.failUnless(self.u(1) > self.u(0))
170         self.failUnless(self.u(2) > self.u(1))
171         self.failUnless(self.u(0) > self.u(2**16 - 1))
172         self.failUnless(self.u(1) > self.u(2**16 - 1))
173
174         self.failIf(self.u(0) > self.u(1))
175         self.failIf(self.u(1) > self.u(2))
176         self.failIf(self.u(2**16 - 1) > self.u(0))
177         self.failIf(self.u(2**16 - 1) > self.u(1))
178
179     def testGTE(self):
180         self.failUnless(self.u(1) >= self.u(0))
181         self.failUnless(self.u(2) >= self.u(1))
182         self.failUnless(self.u(2) >= self.u(2))
183         self.failUnless(self.u(0) >= self.u(0))
184         self.failUnless(self.u(1) >= self.u(1))
185         self.failUnless(self.u(2**16 - 1) >= self.u(2**16 - 1))
186
187         self.failIf(self.u(0) >= self.u(1))
188         self.failIf(self.u(1) >= self.u(2))
189         self.failIf(self.u(2**16 - 1) >= self.u(0))
190         self.failIf(self.u(2**16 - 1) >= self.u(1))
191         
192     def testEQ(self):
193         self.failUnless(self.u(0) == self.u(0))
194         self.failUnless(self.u(1) == self.u(1))
195         self.failUnless(self.u(2**16 - 1) == self.u(2**16-1))
196     
197         self.failIf(self.u(0) == self.u(1))
198         self.failIf(self.u(1) == self.u(0))
199         self.failIf(self.u(2**16 - 1) == self.u(0))
200
201     def testNEQ(self):
202         self.failUnless(self.u(1) != self.u(0))
203         self.failUnless(self.u(2) != self.u(1))
204         self.failIf(self.u(2) != self.u(2))
205         self.failIf(self.u(0) != self.u(0))
206         self.failIf(self.u(1) != self.u(1))
207         self.failIf(self.u(2**16 - 1) != self.u(2**16 - 1))
208
209
210 class SimpleTest(unittest.TestCase):
211     def setUp(self):
212         self.noisy = 0
213         self.a = AirhookConnection()
214         self.a.makeConnection(DummyTransport())
215         self.a.addr = ('127.0.0.1', 4444)
216         self.b = AirhookConnection()
217         self.b.makeConnection(DummyTransport())
218         self.b.addr = ('127.0.0.1', 4444)
219
220     def testReallySimple(self):
221         # connect to eachother and send a few packets, observe sequence incrementing
222         a = self.a
223         b = self.b
224         self.assertEqual(a.state, pending)
225         self.assertEqual(b.state, pending)
226         self.assertEqual(a.outSeq, 0)
227         self.assertEqual(b.outSeq, 0)
228         self.assertEqual(a.obSeq, 0)
229         self.assertEqual(b.obSeq, 0)
230
231         msg = swap(a, '>', self.noisy)          
232         self.assertEqual(a.state, sent)
233         self.assertEqual(a.outSeq, 1)
234         self.assertEqual(a.obSeq, 0)
235
236         b.datagramReceived(msg)
237         self.assertEqual(b.state, sent)
238         self.assertEqual(b.inSeq, 0)
239         self.assertEqual(b.obSeq, 0)
240         msg = swap(b, '<', self.noisy)          
241         self.assertEqual(b.outSeq, 1)
242
243         a.datagramReceived(msg)
244         self.assertEqual(a.state, confirmed)
245         self.assertEqual(a.obSeq, 0)
246         self.assertEqual(a.inSeq, 0)
247         msg = swap(a, '>', self.noisy)          
248         self.assertEqual(a.outSeq, 2)
249
250         b.datagramReceived(msg)
251         self.assertEqual(b.state, confirmed)
252         self.assertEqual(b.obSeq, 0)
253         self.assertEqual(b.inSeq, 1)
254         msg = swap(b, '<', self.noisy)          
255         self.assertEqual(b.outSeq, 2)
256
257         a.datagramReceived(msg)
258         self.assertEqual(a.outSeq, 2)
259         self.assertEqual(a.inSeq, 1)
260         self.assertEqual(a.obSeq, 1)
261
262 class BasicTests(unittest.TestCase):
263     def setUp(self):
264         self.noisy = 0
265         self.a = AirhookConnection()
266         self.a.makeConnection(DummyTransport())
267         self.a.addr = ('127.0.0.1', 4444)
268         self.b = AirhookConnection()
269         self.b.makeConnection(DummyTransport())
270         self.b.addr = ('127.0.0.1', 4444)
271         self.a.protocol = Receiver()
272         self.b.protocol = Receiver()
273
274     def testSimple(self):
275         a = self.a
276         b = self.b
277         
278         TESTMSG = "Howdy, Y'All!"
279         a.omsgq.append(TESTMSG)
280         a.sendNext()
281         msg = swap(a, '>', self.noisy)
282         
283         b.datagramReceived(msg)
284         msg = swap(b, '<', self.noisy)
285         a.datagramReceived(msg)
286         msg = swap(a, '>', self.noisy)
287         b.datagramReceived(msg)
288         
289         self.assertEqual(b.inMsg, 1)
290         self.assertEqual(len(b.protocol.q), 1)
291         self.assertEqual(b.protocol.q[0], TESTMSG)
292         
293         msg = swap(b, '<', self.noisy)
294         
295         a.datagramReceived(msg)
296         msg = swap(a, '>', self.noisy)
297         b.datagramReceived(msg)
298         
299     def testLostFirst(self):
300         a = self.a
301         b = self.b
302         
303         TESTMSG = "Howdy, Y'All!"
304         TESTMSG2 = "Yee Haw"
305         
306         a.omsgq.append(TESTMSG)
307         msg = swap(a, '>', self.noisy)
308         b.datagramReceived(msg)
309         msg = swap(b, '<', self.noisy)
310         self.assertEqual(b.state, sent)
311         a.datagramReceived(msg)
312         msg = swap(a, '>', self.noisy)
313
314         del(msg) # dropping first message
315         
316         a.omsgq.append(TESTMSG2)
317         msg = swap(a, '>', self.noisy)
318     
319         b.datagramReceived(msg)
320         self.assertEqual(b.state, confirmed)
321         self.assertEqual(len(b.protocol.q), 1)
322         self.assertEqual(b.protocol.q[0], TESTMSG2)
323         self.assertEqual(b.weMissed, [(1, 0)])
324         msg = swap(b, '<', self.noisy)
325         
326         a.datagramReceived(msg)
327                                 
328         msg = swap(a, '>', self.noisy)
329         
330         b.datagramReceived(msg)
331         self.assertEqual(len(b.protocol.q), 2)
332         b.protocol.q.sort()
333         l = [TESTMSG2, TESTMSG]
334         l.sort()
335         self.assertEqual(b.protocol.q,l)
336         
337         msg = swap(b, '<', self.noisy)
338         
339         a.datagramReceived(msg)
340         msg = swap(a, '>', self.noisy)
341         b.datagramReceived(msg)
342         
343         msg = swap(b, '<', self.noisy)
344         a.datagramReceived(msg)
345         msg = swap(a, '>', self.noisy)
346         b.datagramReceived(msg)
347
348         msg = swap(b, '<', self.noisy)
349         a.datagramReceived(msg)
350         msg = swap(a, '>', self.noisy)
351
352         self.assertEqual(len(b.protocol.q), 2)
353         b.protocol.q.sort()
354         l = [TESTMSG2, TESTMSG]
355         l.sort()
356         self.assertEqual(b.protocol.q,l)
357
358     def testLostSecond(self):
359         a = self.a
360         b = self.b
361         
362         TESTMSG = "Howdy, Y'All!"
363         TESTMSG2 = "Yee Haw"
364         
365         a.omsgq.append(TESTMSG)
366         msg = swap(a, '>', self.noisy)
367         b.datagramReceived(msg)
368         msg = swap(b, '<', self.noisy)
369         self.assertEqual(b.state, sent)
370         a.datagramReceived(msg)
371         msg = swap(a, '>', self.noisy)
372
373         a.omsgq.append(TESTMSG2)
374         msg2 = swap(a, '>', self.noisy)
375         del(msg2) # dropping second message
376
377         assert(a.outMsgs[1] != None)
378
379         b.datagramReceived(msg)
380         self.assertEqual(b.state, confirmed)
381         self.assertEqual(len(b.protocol.q), 1)
382         self.assertEqual(b.protocol.q[0], TESTMSG)
383         self.assertEqual(b.inMsg, 1)
384         self.assertEqual(b.weMissed, [])
385         msg = swap(b, '<', self.noisy)
386         
387         a.datagramReceived(msg)
388         assert(a.outMsgs[1] != None)
389         msg = swap(a, '>', self.noisy)
390
391         b.datagramReceived(msg)
392         self.assertEqual(b.state, confirmed)
393         self.assertEqual(len(b.protocol.q), 1)
394         self.assertEqual(b.protocol.q[0], TESTMSG)
395         self.assertEqual(b.weMissed, [(2, 1)])
396         msg = swap(b, '<', self.noisy)
397
398         a.datagramReceived(msg)
399         msg = swap(a, '>', self.noisy)
400
401         b.datagramReceived(msg)
402         self.assertEqual(len(b.protocol.q), 2)
403         b.protocol.q.sort()
404         l = [TESTMSG2, TESTMSG]
405         l.sort()
406         self.assertEqual(b.protocol.q,l)
407         
408         msg = swap(b, '<', self.noisy)
409
410         a.datagramReceived(msg)
411         msg = swap(a, '>', self.noisy)
412
413         b.datagramReceived(msg)
414         
415         msg = swap(b, '<', self.noisy)
416
417         a.datagramReceived(msg)
418         msg = swap(a, '>', self.noisy)
419
420         b.datagramReceived(msg)
421
422         msg = swap(b, '<', self.noisy)
423
424         a.datagramReceived(msg)
425
426
427         msg = swap(a, '>', self.noisy)
428
429         self.assertEqual(len(b.protocol.q), 2)
430         b.protocol.q.sort()
431         l = [TESTMSG2, TESTMSG]
432         l.sort()
433         self.assertEqual(b.protocol.q,l)
434
435     def testDoubleDouble(self):
436         a = self.a
437         b = self.b
438         
439         TESTMSGA = "Howdy, Y'All!"
440         TESTMSGB = "Yee Haw"
441         TESTMSGC = "FOO BAR"
442         TESTMSGD = "WING WANG"
443         
444         a.omsgq.append(TESTMSGA)
445         a.omsgq.append(TESTMSGB)
446
447         b.omsgq.append(TESTMSGC)
448         b.omsgq.append(TESTMSGD)
449         
450         
451         msg = swap(a, '>', self.noisy)
452             
453
454         b.datagramReceived(msg)
455         self.assertEqual(b.state, sent)
456         
457         msg = swap(b, '<', self.noisy)
458         a.datagramReceived(msg)
459
460         msg = swap(a, '>', self.noisy)
461
462         b.datagramReceived(msg)
463         self.assertEqual(len(b.protocol.q), 2)
464         l = [TESTMSGA, TESTMSGB]
465         l.sort();b.protocol.q.sort()
466         self.assertEqual(b.protocol.q, l)
467         self.assertEqual(b.inMsg, 2)
468
469         msg = swap(b, '<', self.noisy)
470         a.datagramReceived(msg)
471         
472         self.assertEqual(len(a.protocol.q), 2)
473         l = [TESTMSGC, TESTMSGD]
474         l.sort();a.protocol.q.sort()
475         self.assertEqual(a.protocol.q, l)
476         self.assertEqual(a.inMsg, 2)
477
478     def testDoubleDoubleProb(self, prob=0.25):
479         a = self.a
480         b = self.b
481
482         TESTMSGA = "Howdy, Y'All!"
483         TESTMSGB = "Yee Haw"
484         TESTMSGC = "FOO BAR"
485         TESTMSGD = "WING WANG"
486         
487         a.omsgq.append(TESTMSGA)
488         a.omsgq.append(TESTMSGB)
489
490         b.omsgq.append(TESTMSGC)
491         b.omsgq.append(TESTMSGD)
492         
493         runTillEmpty(a, b, prob, self.noisy)
494         
495         self.assertEqual(a.state, confirmed)
496         self.assertEqual(b.state, confirmed)
497         self.assertEqual(len(b.protocol.q), 2)
498         l = [TESTMSGA, TESTMSGB]
499         l.sort();b.protocol.q.sort()
500         self.assertEqual(b.protocol.q, l)
501                 
502         self.assertEqual(len(a.protocol.q), 2)
503         l = [TESTMSGC, TESTMSGD]
504         l.sort();a.protocol.q.sort()
505         self.assertEqual(a.protocol.q, l)
506
507     def testOneWayBlast(self, num = 2**12):
508         a = self.a
509         b = self.b
510         
511         import sha
512         
513         
514         for i in xrange(num):
515             a.omsgq.append(sha.sha(`i`).digest())
516         runTillEmpty(a, b, noisy=self.noisy)
517
518         self.assertEqual(len(b.protocol.q), num)
519         
520     def testTwoWayBlast(self, num = 2**12, prob=0.5):
521         a = self.a
522         b = self.b
523
524         import sha
525         
526         
527         for i in xrange(num):
528             a.omsgq.append(sha.sha('a' + `i`).digest())
529             b.omsgq.append(sha.sha('b' + `i`).digest())
530             
531         runTillEmpty(a, b, prob, self.noisy)                    
532
533
534         self.assertEqual(len(a.protocol.q), num)
535         self.assertEqual(len(b.protocol.q), num)
536         
537     def testLimitMessageNumbers(self):
538         a = self.a
539         b = self.b
540         import sha
541
542         msg = swap(a, noisy=self.noisy)
543         b.datagramReceived(msg)
544
545         msg = swap(b, noisy=self.noisy)
546         a.datagramReceived(msg)
547         
548         
549         for i in range(5000):
550             a.omsgq.append(sha.sha('a' + 'i').digest())
551         
552         for i in range(5000 / 255):
553             msg = swap(a, noisy=self.noisy)
554             self.assertEqual(a.obSeq, 0)
555         self.assertEqual(a.next, 255)
556         self.assertEqual(a.outMsgNums[(a.outSeq-1) % 256], 254)
557
558 class StreamTests(unittest.TestCase):
559     def setUp(self):
560         self.noisy = 0
561         self.a = StreamConnection()
562         self.a.makeConnection(DummyTransport())
563         self.a.addr = ('127.0.0.1', 4444)
564         self.b = StreamConnection()
565         self.b.makeConnection(DummyTransport())
566         self.b.addr = ('127.0.0.1', 4444)
567         self.a.protocol = StreamReceiver()
568         self.b.protocol = StreamReceiver()
569
570     def testStreamSimple(self, num = 2**12, prob=1.0):
571         f = open('/dev/urandom', 'r')
572         a = self.a
573         b = self.b
574
575         MSGA = f.read(num)
576         MSGB = f.read(num)
577         self.a.write(MSGA)
578         self.b.write(MSGB)
579         
580         runTillEmpty(a, b, prob, self.noisy)
581                 
582         self.assertEqual(len(a.protocol.buf), len(MSGB))
583         self.assertEqual(len(b.protocol.buf), len(MSGA))
584         self.assertEqual(a.protocol.buf, MSGB)
585         self.assertEqual(b.protocol.buf, MSGA)
586
587     def testStreamLossy(self, num = 2**12, prob=0.5):
588         self.testStreamSimple(num, prob)
589
590 class SimpleReactor(unittest.TestCase):
591     def setUp(self):
592         self.noisy = 0
593         self.a = makeReceiver(2020)
594         self.b = makeReceiver(2021)
595         self.ac = self.a.connectionForAddr(('127.0.0.1', 2021))
596         self.bc = self.b.connectionForAddr(('127.0.0.1', 2020))
597     def testSimple(self):
598         msg = "Testing 1, 2, 3"
599         self.ac.write(msg)
600         reactor.iterate()
601         reactor.iterate()
602         reactor.iterate()
603         self.assertEqual(self.bc.protocol.q, [msg])
604
605 class SimpleReactorEcho(unittest.TestCase):
606     def setUp(self):
607         self.noisy = 0
608         self.a = makeReceiver(2022)
609         self.b = makeEcho(2023)
610         self.ac = self.a.connectionForAddr(('127.0.0.1', 2023))
611         self.bc = self.b.connectionForAddr(('127.0.0.1', 2022))
612     def testSimple(self):
613         msg = "Testing 1, 2, 3"
614         self.ac.write(msg)
615         reactor.iterate()
616         reactor.iterate()
617         reactor.iterate()
618         reactor.iterate()
619         self.assertEqual(self.ac.protocol.q, [msg])
620         reactor.iterate()
621         reactor.iterate()
622         reactor.iterate()
623         self.assertEqual(self.ac.protocol.q, [msg])
624
625
626 class SimpleReactorStream(unittest.TestCase):
627     def setUp(self):
628         self.noisy = 0
629         self.a = makeStreamReceiver(2024)
630         self.b = makeStreamReceiver(2025)
631         self.ac = self.a.connectionForAddr(('127.0.0.1', 2025))
632         self.bc = self.b.connectionForAddr(('127.0.0.1', 2024))
633     def testSimple(self):
634         msg = "Testing 1, 2, 3"
635         self.ac.write(msg)
636         reactor.iterate()
637         reactor.iterate()
638         reactor.iterate()
639         self.assertEqual(self.bc.protocol.buf, msg)
640         
641 class SimpleReactorStreamBig(unittest.TestCase):
642     def setUp(self):
643         self.noisy = 0
644         self.a = makeStreamReceiver(2026)
645         self.b = makeStreamReceiver(2027)
646         self.ac = self.a.connectionForAddr(('127.0.0.1', 2027))
647         self.bc = self.b.connectionForAddr(('127.0.0.1', 2026))
648     def testBig(self):
649         msg = open('/dev/urandom').read(4096)
650         self.ac.write(msg)
651         reactor.iterate()
652         reactor.iterate()
653         reactor.iterate()
654         reactor.iterate()
655         reactor.iterate()
656         reactor.iterate()
657         reactor.iterate()
658         self.assertEqual(self.bc.protocol.buf, msg)
659
660 class EchoReactorStreamBig(unittest.TestCase):
661     def setUp(self):
662         self.noisy = 0
663         self.a = makeStreamReceiver(2028)
664         self.b = makeEcho(2029)
665         self.ac = self.a.connectionForAddr(('127.0.0.1', 2028))
666         self.bc = self.b.connectionForAddr(('127.0.0.1', 2029))
667     def testBig(self):
668         msg = open('/dev/urandom').read(4096)
669         self.ac.write(msg)
670         reactor.iterate()
671         reactor.iterate()
672         reactor.iterate()
673         reactor.iterate()
674         reactor.iterate()
675         reactor.iterate()
676         reactor.iterate()
677         self.assertEqual(self.ac.protocol.buf, msg)
678
679