1 ## Copyright 2002-2003 Andrew Loewenstern, All Rights Reserved
2 # see LICENSE.txt for license information
6 from random import uniform as rand
7 from cStringIO import StringIO
10 if __name__ =="__main__":
11 tests = unittest.defaultTestLoader.loadTestsFromNames(['test_airhook'])
12 result = unittest.TextTestRunner().run(tests)
14 class Echo(protocol.Protocol):
15 def dataReceived(self, data):
16 self.transport.write(data)
18 class Noisy(protocol.Protocol):
19 def dataReceived(self, data):
22 class Receiver(protocol.Protocol):
25 def dataReceived(self, data):
28 class StreamReceiver(protocol.Protocol):
31 def dataReceived(self, data):
35 f = protocol.Factory(); f.protocol = Echo
36 return listenAirhookStream(port, f)
38 f = protocol.Factory(); f.protocol = Noisy
39 return listenAirhookStream(port, f)
40 def makeReceiver(port):
41 f = protocol.Factory(); f.protocol = Receiver
42 return listenAirhookStream(port, f)
43 def makeStreamReceiver(port):
44 f = protocol.Factory(); f.protocol = StreamReceiver
45 return listenAirhookStream(port, f)
50 def write(self, data, addr):
53 return self.s.seek(num)
57 def test_createStartPacket():
58 flags = 0 | FLAG_AIRHOOK | FLAG_SESSION
59 packet = chr(flags) + "\xff" + "\x00\x00" + pack("!L", long(rand(0, 2**32)))
62 def test_createReply(session, observed, obseq, seq):
63 flags = 0 | FLAG_AIRHOOK | FLAG_SESSION | FLAG_OBSERVED
64 packet = chr(flags) + pack("!H", seq)[1] + pack("!H", obseq + 1) + pack("!L", session) + pack("!L", observed)
67 def pscope(msg, noisy=0):
70 p = AirhookPacket(msg)
71 str += "oseq: %s seq: %s " % (p.oseq, p.seq)
73 str += "packet: %s \n" % (`p.datagram`)
76 if flags & FLAG_SESSION:
77 str += "FLAG_SESSION "
78 if flags & FLAG_OBSERVED:
79 str += "FLAG_OBSERVED "
80 if flags & FLAG_MISSED:
86 if p.observed != None:
87 str += "OBSERVED: %s\n" % p.observed
89 str += "SESSION: %s\n" % p.session
91 str += "NEXT: %s\n" % p.next
94 str += "MISSED: " + `p.missed`
96 str += "MISSED: " + `len(p.missed)`
100 str += "MSGS: " + `p.msgs` + "\n"
102 str += "MSGS: <%s> " % len(p.msgs)
107 def swap(a, dir="", noisy=0):
111 msg= a.transport.read()
112 a.transport = DummyTransport()
116 print 6*dir + " " + pscope(msg)
119 def runTillEmpty(a, b, prob=1.0, noisy=0):
122 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):
124 msga = swap(a, '>', noisy)
125 b.datagramReceived(msga)
127 msga = swap(a, '>', 0)
129 msgb = swap(b, '<', noisy)
130 a.datagramReceived(msgb)
132 msgb = swap(b, '<', 0)
134 class UstrTests(unittest.TestCase):
136 return ustr("%s%s" % (pack("!H", seq), 'foobar'))
139 self.failUnless(self.u(0) < self.u(1))
140 self.failUnless(self.u(1) < self.u(2))
141 self.failUnless(self.u(2**16 - 1) < self.u(0))
142 self.failUnless(self.u(2**16 - 1) < self.u(1))
144 self.failIf(self.u(1) < self.u(0))
145 self.failIf(self.u(2) < self.u(1))
146 self.failIf(self.u(0) < self.u(2**16 - 1))
147 self.failIf(self.u(1) < self.u(2**16 - 1))
150 self.failUnless(self.u(0) <= self.u(1))
151 self.failUnless(self.u(1) <= self.u(2))
152 self.failUnless(self.u(2) <= self.u(2))
153 self.failUnless(self.u(2**16 - 1) <= self.u(0))
154 self.failUnless(self.u(2**16 - 1) <= self.u(1))
155 self.failUnless(self.u(2**16 - 1) <= self.u(2**16))
157 self.failIf(self.u(1) <= self.u(0))
158 self.failIf(self.u(2) <= self.u(1))
159 self.failIf(self.u(0) <= self.u(2**16 - 1))
160 self.failIf(self.u(1) <= self.u(2**16 - 1))
163 self.failUnless(self.u(1) > self.u(0))
164 self.failUnless(self.u(2) > self.u(1))
165 self.failUnless(self.u(0) > self.u(2**16 - 1))
166 self.failUnless(self.u(1) > self.u(2**16 - 1))
168 self.failIf(self.u(0) > self.u(1))
169 self.failIf(self.u(1) > self.u(2))
170 self.failIf(self.u(2**16 - 1) > self.u(0))
171 self.failIf(self.u(2**16 - 1) > self.u(1))
174 self.failUnless(self.u(1) >= self.u(0))
175 self.failUnless(self.u(2) >= self.u(1))
176 self.failUnless(self.u(2) >= self.u(2))
177 self.failUnless(self.u(0) >= self.u(0))
178 self.failUnless(self.u(1) >= self.u(1))
179 self.failUnless(self.u(2**16 - 1) >= self.u(2**16 - 1))
181 self.failIf(self.u(0) >= self.u(1))
182 self.failIf(self.u(1) >= self.u(2))
183 self.failIf(self.u(2**16 - 1) >= self.u(0))
184 self.failIf(self.u(2**16 - 1) >= self.u(1))
187 self.failUnless(self.u(0) == self.u(0))
188 self.failUnless(self.u(1) == self.u(1))
189 self.failUnless(self.u(2**16 - 1) == self.u(2**16-1))
191 self.failIf(self.u(0) == self.u(1))
192 self.failIf(self.u(1) == self.u(0))
193 self.failIf(self.u(2**16 - 1) == self.u(0))
196 self.failUnless(self.u(1) != self.u(0))
197 self.failUnless(self.u(2) != self.u(1))
198 self.failIf(self.u(2) != self.u(2))
199 self.failIf(self.u(0) != self.u(0))
200 self.failIf(self.u(1) != self.u(1))
201 self.failIf(self.u(2**16 - 1) != self.u(2**16 - 1))
204 class SimpleTest(unittest.TestCase):
207 self.a = AirhookConnection()
208 self.a.makeConnection(DummyTransport())
209 self.a.addr = ('127.0.0.1', 4444)
210 self.b = AirhookConnection()
211 self.b.makeConnection(DummyTransport())
212 self.b.addr = ('127.0.0.1', 4444)
214 def testReallySimple(self):
215 # connect to eachother and send a few packets, observe sequence incrementing
218 self.assertEqual(a.state, pending)
219 self.assertEqual(b.state, pending)
220 self.assertEqual(a.outSeq, 0)
221 self.assertEqual(b.outSeq, 0)
222 self.assertEqual(a.obSeq, 0)
223 self.assertEqual(b.obSeq, 0)
225 msg = swap(a, '>', self.noisy)
226 self.assertEqual(a.state, sent)
227 self.assertEqual(a.outSeq, 1)
228 self.assertEqual(a.obSeq, 0)
230 b.datagramReceived(msg)
231 self.assertEqual(b.inSeq, 0)
232 self.assertEqual(b.obSeq, 0)
233 msg = swap(b, '<', self.noisy)
234 self.assertEqual(b.state, sent)
235 self.assertEqual(b.outSeq, 1)
237 a.datagramReceived(msg)
238 self.assertEqual(a.state, confirmed)
239 self.assertEqual(a.obSeq, 0)
240 self.assertEqual(a.inSeq, 0)
241 msg = swap(a, '>', self.noisy)
242 self.assertEqual(a.outSeq, 2)
244 b.datagramReceived(msg)
245 self.assertEqual(b.state, confirmed)
246 self.assertEqual(b.obSeq, 0)
247 self.assertEqual(b.inSeq, 1)
248 msg = swap(b, '<', self.noisy)
249 self.assertEqual(b.outSeq, 2)
251 a.datagramReceived(msg)
252 self.assertEqual(a.outSeq, 2)
253 self.assertEqual(a.inSeq, 1)
254 self.assertEqual(a.obSeq, 1)
256 class BasicTests(unittest.TestCase):
259 self.a = AirhookConnection()
260 self.a.makeConnection(DummyTransport())
261 self.a.addr = ('127.0.0.1', 4444)
262 self.b = AirhookConnection()
263 self.b.makeConnection(DummyTransport())
264 self.b.addr = ('127.0.0.1', 4444)
265 self.a.protocol = Receiver()
266 self.b.protocol = Receiver()
268 def testSimple(self):
272 TESTMSG = "Howdy, Y'All!"
273 a.omsgq.append(TESTMSG)
275 msg = swap(a, '>', self.noisy)
277 b.datagramReceived(msg)
278 msg = swap(b, '<', self.noisy)
279 a.datagramReceived(msg)
280 msg = swap(a, '>', self.noisy)
281 b.datagramReceived(msg)
283 self.assertEqual(b.inMsg, 1)
284 self.assertEqual(len(b.protocol.q), 1)
285 self.assertEqual(b.protocol.q[0], TESTMSG)
287 msg = swap(b, '<', self.noisy)
289 a.datagramReceived(msg)
290 msg = swap(a, '>', self.noisy)
291 b.datagramReceived(msg)
293 def testLostFirst(self):
297 TESTMSG = "Howdy, Y'All!"
300 a.omsgq.append(TESTMSG)
301 msg = swap(a, '>', self.noisy)
302 b.datagramReceived(msg)
303 msg = swap(b, '<', self.noisy)
304 self.assertEqual(b.state, sent)
305 a.datagramReceived(msg)
306 msg = swap(a, '>', self.noisy)
308 del(msg) # dropping first message
310 a.omsgq.append(TESTMSG2)
311 msg = swap(a, '>', self.noisy)
313 b.datagramReceived(msg)
314 self.assertEqual(b.state, confirmed)
315 self.assertEqual(len(b.protocol.q), 1)
316 self.assertEqual(b.protocol.q[0], TESTMSG2)
317 self.assertEqual(b.weMissed, [(1, 0)])
318 msg = swap(b, '<', self.noisy)
320 a.datagramReceived(msg)
322 msg = swap(a, '>', self.noisy)
324 b.datagramReceived(msg)
325 self.assertEqual(len(b.protocol.q), 2)
327 l = [TESTMSG2, TESTMSG]
329 self.assertEqual(b.protocol.q,l)
331 msg = swap(b, '<', self.noisy)
333 a.datagramReceived(msg)
334 msg = swap(a, '>', self.noisy)
335 b.datagramReceived(msg)
337 msg = swap(b, '<', self.noisy)
338 a.datagramReceived(msg)
339 msg = swap(a, '>', self.noisy)
340 b.datagramReceived(msg)
342 msg = swap(b, '<', self.noisy)
343 a.datagramReceived(msg)
344 msg = swap(a, '>', self.noisy)
346 self.assertEqual(len(b.protocol.q), 2)
348 l = [TESTMSG2, TESTMSG]
350 self.assertEqual(b.protocol.q,l)
352 def testLostSecond(self):
356 TESTMSG = "Howdy, Y'All!"
359 a.omsgq.append(TESTMSG)
360 msg = swap(a, '>', self.noisy)
361 b.datagramReceived(msg)
362 msg = swap(b, '<', self.noisy)
363 self.assertEqual(b.state, sent)
364 a.datagramReceived(msg)
365 msg = swap(a, '>', self.noisy)
367 a.omsgq.append(TESTMSG2)
368 msg2 = swap(a, '>', self.noisy)
369 del(msg2) # dropping second message
371 assert(a.outMsgs[1] != None)
373 b.datagramReceived(msg)
374 self.assertEqual(b.state, confirmed)
375 self.assertEqual(len(b.protocol.q), 1)
376 self.assertEqual(b.protocol.q[0], TESTMSG)
377 self.assertEqual(b.inMsg, 1)
378 self.assertEqual(b.weMissed, [])
379 msg = swap(b, '<', self.noisy)
381 a.datagramReceived(msg)
382 assert(a.outMsgs[1] != None)
383 msg = swap(a, '>', self.noisy)
385 b.datagramReceived(msg)
386 self.assertEqual(b.state, confirmed)
387 self.assertEqual(len(b.protocol.q), 1)
388 self.assertEqual(b.protocol.q[0], TESTMSG)
389 self.assertEqual(b.weMissed, [(2, 1)])
390 msg = swap(b, '<', self.noisy)
392 a.datagramReceived(msg)
393 msg = swap(a, '>', self.noisy)
395 b.datagramReceived(msg)
396 self.assertEqual(len(b.protocol.q), 2)
398 l = [TESTMSG2, TESTMSG]
400 self.assertEqual(b.protocol.q,l)
402 msg = swap(b, '<', self.noisy)
404 a.datagramReceived(msg)
405 msg = swap(a, '>', self.noisy)
407 b.datagramReceived(msg)
409 msg = swap(b, '<', self.noisy)
411 a.datagramReceived(msg)
412 msg = swap(a, '>', self.noisy)
414 b.datagramReceived(msg)
416 msg = swap(b, '<', self.noisy)
418 a.datagramReceived(msg)
421 msg = swap(a, '>', self.noisy)
423 self.assertEqual(len(b.protocol.q), 2)
425 l = [TESTMSG2, TESTMSG]
427 self.assertEqual(b.protocol.q,l)
429 def testDoubleDouble(self):
433 TESTMSGA = "Howdy, Y'All!"
436 TESTMSGD = "WING WANG"
438 a.omsgq.append(TESTMSGA)
439 a.omsgq.append(TESTMSGB)
441 b.omsgq.append(TESTMSGC)
442 b.omsgq.append(TESTMSGD)
445 msg = swap(a, '>', self.noisy)
448 b.datagramReceived(msg)
450 msg = swap(b, '<', self.noisy)
451 self.assertEqual(b.state, sent)
452 a.datagramReceived(msg)
454 msg = swap(a, '>', self.noisy)
456 b.datagramReceived(msg)
457 self.assertEqual(len(b.protocol.q), 2)
458 l = [TESTMSGA, TESTMSGB]
459 l.sort();b.protocol.q.sort()
460 self.assertEqual(b.protocol.q, l)
461 self.assertEqual(b.inMsg, 2)
463 msg = swap(b, '<', self.noisy)
464 a.datagramReceived(msg)
466 self.assertEqual(len(a.protocol.q), 2)
467 l = [TESTMSGC, TESTMSGD]
468 l.sort();a.protocol.q.sort()
469 self.assertEqual(a.protocol.q, l)
470 self.assertEqual(a.inMsg, 2)
472 def testDoubleDoubleProb(self, prob=0.25):
476 TESTMSGA = "Howdy, Y'All!"
479 TESTMSGD = "WING WANG"
481 a.omsgq.append(TESTMSGA)
482 a.omsgq.append(TESTMSGB)
484 b.omsgq.append(TESTMSGC)
485 b.omsgq.append(TESTMSGD)
487 runTillEmpty(a, b, prob, self.noisy)
489 self.assertEqual(a.state, confirmed)
490 self.assertEqual(b.state, confirmed)
491 self.assertEqual(len(b.protocol.q), 2)
492 l = [TESTMSGA, TESTMSGB]
493 l.sort();b.protocol.q.sort()
494 self.assertEqual(b.protocol.q, l)
496 self.assertEqual(len(a.protocol.q), 2)
497 l = [TESTMSGC, TESTMSGD]
498 l.sort();a.protocol.q.sort()
499 self.assertEqual(a.protocol.q, l)
501 def testOneWayBlast(self, num = 2**12):
508 for i in xrange(num):
509 a.omsgq.append(sha.sha(`i`).digest())
510 runTillEmpty(a, b, noisy=self.noisy)
512 self.assertEqual(len(b.protocol.q), num)
514 def testTwoWayBlast(self, num = 2**12, prob=0.5):
521 for i in xrange(num):
522 a.omsgq.append(sha.sha('a' + `i`).digest())
523 b.omsgq.append(sha.sha('b' + `i`).digest())
525 runTillEmpty(a, b, prob, self.noisy)
528 self.assertEqual(len(a.protocol.q), num)
529 self.assertEqual(len(b.protocol.q), num)
531 def testLimitMessageNumbers(self):
536 msg = swap(a, noisy=self.noisy)
537 b.datagramReceived(msg)
539 msg = swap(b, noisy=self.noisy)
540 a.datagramReceived(msg)
543 for i in range(5000):
544 a.omsgq.append(sha.sha('a' + 'i').digest())
546 for i in range(5000 / 255):
547 msg = swap(a, noisy=self.noisy)
548 self.assertEqual(a.obSeq, 0)
549 self.assertEqual(a.next, 255)
550 self.assertEqual(a.outMsgNums[(a.outSeq-1) % 256], 254)
552 def testConnectionReset(self):
553 self.testTwoWayBlast()
554 self.b.protocol.q = []
557 msg = swap(a, noisy=self.noisy)
558 b.datagramReceived(msg)
560 msg = swap(b, noisy=self.noisy)
561 a.datagramReceived(msg)
563 a.omsgq.append("TESTING")
564 msg = swap(a, noisy=self.noisy)
565 b.datagramReceived(msg)
567 msg = swap(b, noisy=self.noisy)
568 a.datagramReceived(msg)
570 self.assertEqual(b.protocol.q[0], "TESTING")
571 self.assertEqual(b.state, confirmed)
573 self.a = AirhookConnection()
574 self.a.makeConnection(DummyTransport())
575 self.a.addr = ('127.0.0.1', 4444)
578 a.omsgq.append("TESTING2")
579 msg = swap(a, noisy=self.noisy)
580 b.datagramReceived(msg)
582 msg = swap(b, noisy=self.noisy)
583 a.datagramReceived(msg)
585 self.assertEqual(len(b.protocol.q), 1)
586 msg = swap(a, noisy=self.noisy)
587 b.datagramReceived(msg)
589 msg = swap(b, noisy=self.noisy)
590 a.datagramReceived(msg)
592 self.assertEqual(len(b.protocol.q), 2)
593 self.assertEqual(b.protocol.q[1], "TESTING2")
595 def testRecipientReset(self):
596 self.testTwoWayBlast()
597 self.b.protocol.q = []
601 msg = swap(a, noisy=self.noisy)
602 b.datagramReceived(msg)
604 msg = swap(b, noisy=self.noisy)
605 a.datagramReceived(msg)
607 a.omsgq.append("TESTING")
608 msg = swap(a, noisy=self.noisy)
609 b.datagramReceived(msg)
611 msg = swap(b, noisy=self.noisy)
612 a.datagramReceived(msg)
614 self.assertEqual(b.protocol.q[0], "TESTING")
615 self.assertEqual(b.state, confirmed)
617 self.b = AirhookConnection()
618 self.b.makeConnection(DummyTransport())
619 self.b.protocol = Receiver()
620 self.b.addr = ('127.0.0.1', 4444)
623 msg = swap(a, noisy=self.noisy)
624 b.datagramReceived(msg)
626 msg = swap(b, noisy=self.noisy)
627 a.datagramReceived(msg)
629 a.omsgq.append("TESTING2")
630 self.assertEqual(len(b.protocol.q), 0)
631 msg = swap(a, noisy=self.noisy)
632 b.datagramReceived(msg)
634 msg = swap(b, noisy=self.noisy)
635 a.datagramReceived(msg)
637 msg = swap(a, noisy=self.noisy)
638 b.datagramReceived(msg)
640 msg = swap(b, noisy=self.noisy)
641 a.datagramReceived(msg)
643 self.assertEqual(len(b.protocol.q), 1)
644 self.assertEqual(b.protocol.q[0], "TESTING2")
647 class StreamTests(unittest.TestCase):
650 self.a = StreamConnection()
651 self.a.makeConnection(DummyTransport())
652 self.a.addr = ('127.0.0.1', 4444)
653 self.b = StreamConnection()
654 self.b.makeConnection(DummyTransport())
655 self.b.addr = ('127.0.0.1', 4444)
656 self.a.protocol = StreamReceiver()
657 self.b.protocol = StreamReceiver()
659 def testStreamSimple(self, num = 2**12, prob=1.0):
660 f = open('/dev/urandom', 'r')
669 runTillEmpty(a, b, prob, self.noisy)
671 self.assertEqual(len(a.protocol.buf), len(MSGB))
672 self.assertEqual(len(b.protocol.buf), len(MSGA))
673 self.assertEqual(a.protocol.buf, MSGB)
674 self.assertEqual(b.protocol.buf, MSGA)
676 def testStreamLossy(self, num = 2**12, prob=0.5):
677 self.testStreamSimple(num, prob)
679 class SimpleReactor(unittest.TestCase):
682 self.a = makeReceiver(2020)
683 self.b = makeReceiver(2021)
684 self.ac = self.a.connectionForAddr(('127.0.0.1', 2021))
685 self.bc = self.b.connectionForAddr(('127.0.0.1', 2020))
686 self.ac.noisy = self.noisy
687 self.bc.noisy = self.noisy
688 def testSimple(self):
689 msg = "Testing 1, 2, 3"
694 self.assertEqual(self.bc.state, confirmed)
695 self.assertEqual(self.bc.protocol.q, [msg])
697 class SimpleReactorEcho(unittest.TestCase):
700 self.a = makeReceiver(2022)
701 self.b = makeEcho(2023)
702 self.ac = self.a.connectionForAddr(('127.0.0.1', 2023))
703 self.bc = self.b.connectionForAddr(('127.0.0.1', 2022))
704 def testSimple(self):
705 msg = "Testing 1, 2, 3"
711 self.assertEqual(self.ac.protocol.q, [msg])
715 self.assertEqual(self.ac.protocol.q, [msg])
718 class SimpleReactorStream(unittest.TestCase):
721 self.a = makeStreamReceiver(2024)
722 self.b = makeStreamReceiver(2025)
723 self.ac = self.a.connectionForAddr(('127.0.0.1', 2025))
724 self.bc = self.b.connectionForAddr(('127.0.0.1', 2024))
725 def testSimple(self):
726 msg = "Testing 1, 2, 3"
731 self.assertEqual(self.bc.protocol.buf, msg)
733 class SimpleReactorStreamBig(unittest.TestCase):
736 self.a = makeStreamReceiver(2026)
737 self.b = makeStreamReceiver(2027)
738 self.ac = self.a.connectionForAddr(('127.0.0.1', 2027))
739 self.bc = self.b.connectionForAddr(('127.0.0.1', 2026))
741 msg = open('/dev/urandom').read(4096)
750 self.assertEqual(self.bc.protocol.buf, msg)
752 class EchoReactorStreamBig(unittest.TestCase):
755 self.a = makeStreamReceiver(2028)
756 self.b = makeEcho(2029)
757 self.ac = self.a.connectionForAddr(('127.0.0.1', 2029))
759 msg = open('/dev/urandom').read(256)
766 self.assertEqual(self.ac.protocol.buf, msg)