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