]> git.mxchange.org Git - quix0rs-apt-p2p.git/blob - test_airhook.py
bug fixes, more tests, looking solid now
[quix0rs-apt-p2p.git] / test_airhook.py
1 import unittest
2 from airhook import *
3 from random import uniform as rand
4
5 if __name__ =="__main__":
6         tests = unittest.defaultTestLoader.loadTestsFromNames(['test_airhook'])
7         result = unittest.TextTestRunner().run(tests)
8
9
10
11 def test_createStartPacket():
12         flags = 0 | FLAG_AIRHOOK | FLAG_SESSION 
13         packet = chr(flags) + "\xff" + "\x00\x00" + pack("!L", long(rand(0, 2**32)))
14         return packet
15
16 def test_createReply(session, observed, obseq, seq):
17         flags = 0 | FLAG_AIRHOOK | FLAG_SESSION | FLAG_OBSERVED
18         packet = chr(flags) + pack("!H", seq)[1] + pack("!H", obseq + 1) + pack("!L", session) + pack("!L", observed)
19         return packet
20
21
22 def pscope(msg, noisy=0):
23         # packet scope
24         str = ""
25         p = AirhookPacket(msg)
26         str += "oseq: %s  seq: %s " %  (p.oseq, p.seq)
27         if noisy:
28                 str += "packet: %s  \n" % (`p.datagram`)
29         flags = p.flags
30         str += "flags: "
31         if flags & FLAG_SESSION:
32                 str += "FLAG_SESSION "
33         if flags & FLAG_OBSERVED:
34                 str += "FLAG_OBSERVED "
35         if flags & FLAG_MISSED:
36                 str += "FLAG_MISSED "
37         if flags & FLAG_NEXT:
38                 str += "FLAG_NEXT "
39         str += "\n"
40         
41         if p.observed != None:
42                 str += "OBSERVED: %s\n" % p.observed
43         if p.session != None:
44                 str += "SESSION: %s\n" % p.session
45         if p.next != None:
46                 str += "NEXT: %s\n" % p.next
47         if p.missed:
48                 if noisy:
49                         str += "MISSED: " + `p.missed`
50                 else:
51                         str += "MISSED: " + `len(p.missed)`
52                 str += "\n"
53         if p.msgs:
54                 if noisy:
55                         str += "MSGS: " + `p.msgs` + "\n"
56                 else:
57                         str += "MSGS: <%s> " % len(p.msgs)
58                 str += "\n"
59         return str
60                         
61 # testing function
62 def swap(a, dir="", noisy=0):
63         msg = ""
64         while not msg:
65                 a.transport.seek(0)
66                 msg= a.transport.read()
67                 a.transport = StringIO()
68                 if not msg:
69                         a.sendNext()
70         if noisy:
71                                 print 6*dir + " " + pscope(msg)
72         return msg
73         
74
75 class UstrTests(unittest.TestCase):
76         def u(self, seq):
77                 return ustr("%s%s" % (pack("!H", seq), 'foobar'))
78                 
79         def testLT(self):
80                 self.failUnless(self.u(0) < self.u(1))
81                 self.failUnless(self.u(1) < self.u(2))
82                 self.failUnless(self.u(2**16 - 1) < self.u(0))
83                 self.failUnless(self.u(2**16 - 1) < self.u(1))
84                 
85                 self.failIf(self.u(1) < self.u(0))
86                 self.failIf(self.u(2) < self.u(1))
87                 self.failIf(self.u(0) < self.u(2**16 - 1))
88                 self.failIf(self.u(1) < self.u(2**16 - 1))
89                 
90         def testLTE(self):
91                 self.failUnless(self.u(0) <= self.u(1))
92                 self.failUnless(self.u(1) <= self.u(2))
93                 self.failUnless(self.u(2) <= self.u(2))
94                 self.failUnless(self.u(2**16 - 1) <= self.u(0))
95                 self.failUnless(self.u(2**16 - 1) <= self.u(1))
96                 self.failUnless(self.u(2**16 - 1) <= self.u(2**16))
97
98                 self.failIf(self.u(1) <= self.u(0))
99                 self.failIf(self.u(2) <= self.u(1))
100                 self.failIf(self.u(0) <= self.u(2**16 - 1))
101                 self.failIf(self.u(1) <= self.u(2**16 - 1))
102                 
103         def testGT(self):
104                 self.failUnless(self.u(1) > self.u(0))
105                 self.failUnless(self.u(2) > self.u(1))
106                 self.failUnless(self.u(0) > self.u(2**16 - 1))
107                 self.failUnless(self.u(1) > self.u(2**16 - 1))
108
109                 self.failIf(self.u(0) > self.u(1))
110                 self.failIf(self.u(1) > self.u(2))
111                 self.failIf(self.u(2**16 - 1) > self.u(0))
112                 self.failIf(self.u(2**16 - 1) > self.u(1))
113
114         def testGTE(self):
115                 self.failUnless(self.u(1) >= self.u(0))
116                 self.failUnless(self.u(2) >= self.u(1))
117                 self.failUnless(self.u(2) >= self.u(2))
118                 self.failUnless(self.u(0) >= self.u(0))
119                 self.failUnless(self.u(1) >= self.u(1))
120                 self.failUnless(self.u(2**16 - 1) >= self.u(2**16 - 1))
121
122                 self.failIf(self.u(0) >= self.u(1))
123                 self.failIf(self.u(1) >= self.u(2))
124                 self.failIf(self.u(2**16 - 1) >= self.u(0))
125                 self.failIf(self.u(2**16 - 1) >= self.u(1))
126                 
127         def testEQ(self):
128                 self.failUnless(self.u(0) == self.u(0))
129                 self.failUnless(self.u(1) == self.u(1))
130                 self.failUnless(self.u(2**16 - 1) == self.u(2**16-1))
131         
132                 self.failIf(self.u(0) == self.u(1))
133                 self.failIf(self.u(1) == self.u(0))
134                 self.failIf(self.u(2**16 - 1) == self.u(0))
135
136         def testNEQ(self):
137                 self.failUnless(self.u(1) != self.u(0))
138                 self.failUnless(self.u(2) != self.u(1))
139                 self.failIf(self.u(2) != self.u(2))
140                 self.failIf(self.u(0) != self.u(0))
141                 self.failIf(self.u(1) != self.u(1))
142                 self.failIf(self.u(2**16 - 1) != self.u(2**16 - 1))
143
144
145 class SimpleTest(unittest.TestCase):
146         def setUp(self):
147                 self.noisy = 0
148                 self.a = AirhookConnection(StringIO(), (None, 'localhost', 4040), None)
149                 self.b = AirhookConnection(StringIO(), (None, 'localhost', 4040), None)
150         def testReallySimple(self):
151                 # connect to eachother and send a few packets, observe sequence incrementing
152                 a = self.a
153                 b = self.b
154                 self.assertEqual(a.state, pending)
155                 self.assertEqual(b.state, pending)
156                 self.assertEqual(a.outSeq, 0)
157                 self.assertEqual(b.outSeq, 0)
158                 self.assertEqual(a.obSeq, 0)
159                 self.assertEqual(b.obSeq, 0)
160
161                 msg = swap(a, '>', self.noisy)          
162                 self.assertEqual(a.state, sent)
163                 self.assertEqual(a.outSeq, 1)
164                 self.assertEqual(a.obSeq, 0)
165
166                 b.datagramReceived(msg)
167                 self.assertEqual(b.state, sent)
168                 self.assertEqual(b.inSeq, 0)
169                 self.assertEqual(b.obSeq, 0)
170                 msg = swap(b, '<', self.noisy)          
171                 self.assertEqual(b.outSeq, 1)
172
173                 a.datagramReceived(msg)
174                 self.assertEqual(a.state, confirmed)
175                 self.assertEqual(a.obSeq, 0)
176                 self.assertEqual(a.inSeq, 0)
177                 msg = swap(a, '>', self.noisy)          
178                 self.assertEqual(a.outSeq, 2)
179
180                 b.datagramReceived(msg)
181                 self.assertEqual(b.state, confirmed)
182                 self.assertEqual(b.obSeq, 0)
183                 self.assertEqual(b.inSeq, 1)
184                 msg = swap(b, '<', self.noisy)          
185                 self.assertEqual(b.outSeq, 2)
186
187                 a.datagramReceived(msg)
188                 self.assertEqual(a.outSeq, 2)
189                 self.assertEqual(a.inSeq, 1)
190                 self.assertEqual(a.obSeq, 1)
191
192 class BasicTests(unittest.TestCase):
193         def setUp(self):
194                 self.noisy = 0
195                 self.a = AirhookConnection(StringIO(), (None, 'localhost', 4040), None)
196                 self.b = AirhookConnection(StringIO(), (None, 'localhost', 4040), None)
197         def testSimple(self):
198                 a = self.a
199                 b = self.b
200                 
201                 TESTMSG = "Howdy, Y'All!"
202                 a.omsgq.append(TESTMSG)
203                 a.sendNext()
204                 msg = swap(a, '>', self.noisy)
205                 
206                 b.datagramReceived(msg)
207                 msg = swap(b, '<', self.noisy)
208                 a.datagramReceived(msg)
209                 msg = swap(a, '>', self.noisy)
210                 b.datagramReceived(msg)
211                 
212                 self.assertEqual(b.inMsg, 1)
213                 self.assertEqual(len(b.imsgq), 1)
214                 self.assertEqual(b.imsgq[0], TESTMSG)
215                 
216                 msg = swap(b, '<', self.noisy)
217                 
218                 a.datagramReceived(msg)
219                 msg = swap(a, '>', self.noisy)
220                 b.datagramReceived(msg)
221                 
222         def testLostFirst(self):
223                 a = self.a
224                 b = self.b
225                 
226                 TESTMSG = "Howdy, Y'All!"
227                 TESTMSG2 = "Yee Haw"
228                 
229                 a.omsgq.append(TESTMSG)
230                 msg = swap(a, '>', self.noisy)
231                 b.datagramReceived(msg)
232                 msg = swap(b, '<', self.noisy)
233                 self.assertEqual(b.state, sent)
234                 a.datagramReceived(msg)
235                 msg = swap(a, '>', self.noisy)
236
237                 del(msg) # dropping first message
238                 
239                 a.omsgq.append(TESTMSG2)
240                 msg = swap(a, '>', self.noisy)
241         
242                 b.datagramReceived(msg)
243                 self.assertEqual(b.state, confirmed)
244                 self.assertEqual(len(b.imsgq), 1)
245                 self.assertEqual(b.imsgq[0], TESTMSG2)
246                 self.assertEqual(b.weMissed, [(1, 0)])
247                 msg = swap(b, '<', self.noisy)
248                 
249                 a.datagramReceived(msg)
250                                                                 
251                 msg = swap(a, '>', self.noisy)
252                 
253                 b.datagramReceived(msg)
254                 self.assertEqual(len(b.imsgq), 2)
255                 b.imsgq.sort()
256                 l = [TESTMSG2, TESTMSG]
257                 l.sort()
258                 self.assertEqual(b.imsgq,l)
259                 
260                 msg = swap(b, '<', self.noisy)
261                 
262                 a.datagramReceived(msg)
263                 msg = swap(a, '>', self.noisy)
264                 b.datagramReceived(msg)
265                 
266                 msg = swap(b, '<', self.noisy)
267                 a.datagramReceived(msg)
268                 msg = swap(a, '>', self.noisy)
269                 b.datagramReceived(msg)
270
271                 msg = swap(b, '<', self.noisy)
272                 a.datagramReceived(msg)
273                 msg = swap(a, '>', self.noisy)
274
275                 self.assertEqual(len(b.imsgq), 2)
276                 b.imsgq.sort()
277                 l = [TESTMSG2, TESTMSG]
278                 l.sort()
279                 self.assertEqual(b.imsgq,l)
280
281         def testLostSecond(self):
282                 a = self.a
283                 b = self.b
284                 
285                 TESTMSG = "Howdy, Y'All!"
286                 TESTMSG2 = "Yee Haw"
287                 
288                 a.omsgq.append(TESTMSG)
289                 msg = swap(a, '>', self.noisy)
290                 b.datagramReceived(msg)
291                 msg = swap(b, '<', self.noisy)
292                 self.assertEqual(b.state, sent)
293                 a.datagramReceived(msg)
294                 msg = swap(a, '>', self.noisy)
295
296                 a.omsgq.append(TESTMSG2)
297                 msg2 = swap(a, '>', self.noisy)
298                 del(msg2) # dropping second message
299
300                 assert(a.outMsgs[1] != None)
301
302                 b.datagramReceived(msg)
303                 self.assertEqual(b.state, confirmed)
304                 self.assertEqual(len(b.imsgq), 1)
305                 self.assertEqual(b.imsgq[0], TESTMSG)
306                 self.assertEqual(b.inMsg, 1)
307                 self.assertEqual(b.weMissed, [])
308                 msg = swap(b, '<', self.noisy)
309                 
310                 a.datagramReceived(msg)
311                 assert(a.outMsgs[1] != None)
312                 msg = swap(a, '>', self.noisy)
313
314                 b.datagramReceived(msg)
315                 self.assertEqual(b.state, confirmed)
316                 self.assertEqual(len(b.imsgq), 1)
317                 self.assertEqual(b.imsgq[0], TESTMSG)
318                 self.assertEqual(b.weMissed, [(2, 1)])
319                 msg = swap(b, '<', self.noisy)
320
321                 a.datagramReceived(msg)
322                 msg = swap(a, '>', self.noisy)
323
324                 b.datagramReceived(msg)
325                 self.assertEqual(len(b.imsgq), 2)
326                 b.imsgq.sort()
327                 l = [TESTMSG2, TESTMSG]
328                 l.sort()
329                 self.assertEqual(b.imsgq,l)
330                 
331                 msg = swap(b, '<', self.noisy)
332
333                 a.datagramReceived(msg)
334                 msg = swap(a, '>', self.noisy)
335
336                 b.datagramReceived(msg)
337                 
338                 msg = swap(b, '<', self.noisy)
339
340                 a.datagramReceived(msg)
341                 msg = swap(a, '>', self.noisy)
342
343                 b.datagramReceived(msg)
344
345                 msg = swap(b, '<', self.noisy)
346
347                 a.datagramReceived(msg)
348
349
350                 msg = swap(a, '>', self.noisy)
351
352                 self.assertEqual(len(b.imsgq), 2)
353                 b.imsgq.sort()
354                 l = [TESTMSG2, TESTMSG]
355                 l.sort()
356                 self.assertEqual(b.imsgq,l)
357
358         def testDoubleDouble(self):
359                 a = self.a
360                 b = self.b
361                 
362                 TESTMSGA = "Howdy, Y'All!"
363                 TESTMSGB = "Yee Haw"
364                 TESTMSGC = "FOO BAR"
365                 TESTMSGD = "WING WANG"
366                 
367                 a.omsgq.append(TESTMSGA)
368                 a.omsgq.append(TESTMSGB)
369
370                 b.omsgq.append(TESTMSGC)
371                 b.omsgq.append(TESTMSGD)
372                 
373                 
374                 msg = swap(a, '>', self.noisy)
375                         
376
377                 b.datagramReceived(msg)
378                 self.assertEqual(b.state, sent)
379                 
380                 msg = swap(b, '<', self.noisy)
381                 a.datagramReceived(msg)
382
383                 msg = swap(a, '>', self.noisy)
384
385                 b.datagramReceived(msg)
386                 self.assertEqual(len(b.imsgq), 2)
387                 l = [TESTMSGA, TESTMSGB]
388                 l.sort();b.imsgq.sort()
389                 self.assertEqual(b.imsgq, l)
390                 self.assertEqual(b.inMsg, 2)
391
392                 msg = swap(b, '<', self.noisy)
393                 a.datagramReceived(msg)
394                 
395                 self.assertEqual(len(a.imsgq), 2)
396                 l = [TESTMSGC, TESTMSGD]
397                 l.sort();a.imsgq.sort()
398                 self.assertEqual(a.imsgq, l)
399                 self.assertEqual(a.inMsg, 2)
400
401         def testDoubleDoubleProb(self, prob=0.25):
402                 a = self.a
403                 b = self.b
404                 TESTMSGA = "Howdy, Y'All!"
405                 TESTMSGB = "Yee Haw"
406                 TESTMSGC = "FOO BAR"
407                 TESTMSGD = "WING WANG"
408                 
409                 a.omsgq.append(TESTMSGA)
410                 a.omsgq.append(TESTMSGB)
411
412                 b.omsgq.append(TESTMSGC)
413                 b.omsgq.append(TESTMSGD)
414                 
415                 while a.state != confirmed or b.state != confirmed or ord(msga[0]) & FLAG_NEXT or ord(msgb[0]) & FLAG_NEXT :
416                         msga = swap(a, '>', self.noisy)
417         
418                         if rand(0,1) < prob:
419                                 b.datagramReceived(msga)
420                         
421                         msgb = swap(b, '<', self.noisy)
422
423                         if rand(0,1) < prob:
424                                 a.datagramReceived(msgb)
425
426                 self.assertEqual(a.state, confirmed)
427                 self.assertEqual(b.state, confirmed)
428                 self.assertEqual(len(b.imsgq), 2)
429                 l = [TESTMSGA, TESTMSGB]
430                 l.sort();b.imsgq.sort()
431                 self.assertEqual(b.imsgq, l)
432                                 
433                 self.assertEqual(len(a.imsgq), 2)
434                 l = [TESTMSGC, TESTMSGD]
435                 l.sort();a.imsgq.sort()
436                 self.assertEqual(a.imsgq, l)
437
438         def testOneWayBlast(self, num = 2**12):
439                 a = self.a
440                 b = self.b
441                 import sha
442                 
443                 
444                 for i in xrange(num):
445                         a.omsgq.append(sha.sha(`i`).digest())
446                 msga = swap(a, '>', self.noisy)
447                 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):
448                         b.datagramReceived(msga)
449                         msgb = swap(b, '<', self.noisy)
450
451                         a.datagramReceived(msgb)
452                         msga = swap(a, '>', self.noisy)
453
454                 self.assertEqual(len(b.imsgq), num)
455                 
456         def testTwoWayBlast(self, num = 2**12, prob=0.5):
457                 a = self.a
458                 b = self.b
459                 import sha
460                 
461                 
462                 for i in xrange(num):
463                         a.omsgq.append(sha.sha('a' + `i`).digest())
464                         b.omsgq.append(sha.sha('b' + `i`).digest())
465                         
466                 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):
467                         if rand(0,1) < prob:
468                                 msga = swap(a, '>', self.noisy)
469                                 b.datagramReceived(msga)
470                         else:
471                                 msga = swap(a, '>', 0)
472                         if rand(0,1) < prob:
473                                 msgb = swap(b, '<', self.noisy)
474                                 a.datagramReceived(msgb)
475                         else:
476                                 msgb = swap(b, '<', 0)
477                                         
478
479
480                 self.assertEqual(len(a.imsgq), num)
481                 self.assertEqual(len(b.imsgq), num)
482                 
483         def testLimitMessageNumbers(self):
484                 a = self.a
485                 b = self.b
486                 import sha
487
488                 msg = swap(a, noisy=self.noisy)
489                 b.datagramReceived(msg)
490
491                 msg = swap(b, noisy=self.noisy)
492                 a.datagramReceived(msg)
493                 
494                 
495                 for i in range(5000):
496                         a.omsgq.append(sha.sha('a' + 'i').digest())
497                 
498                 for i in range(5000 / 255):
499                         msg = swap(a, noisy=self.noisy)
500                         self.assertEqual(a.obSeq, 0)
501                 self.assertEqual(a.next, 255)
502                 self.assertEqual(a.outMsgNums[(a.outSeq-1) % 256], 254)
503
504 class OrderedTests(unittest.TestCase):
505         def setUp(self):
506                 self.noisy = 0
507                 class queuer:
508                         def __init__(self):
509                                 self.msg = ""
510                         def dataCameIn(self, host, port, data):
511                                 self.msg+= data
512                 self.A = queuer()
513                 self.B = queuer()
514                 self.a = OrderedConnection(StringIO(), (None, 'localhost', 4040), self.A)
515                 self.b = OrderedConnection(StringIO(), (None, 'localhost', 4040), self.B)
516
517         def testOrderedSimple(self, num = 2**18, prob=1.0):
518                 f = open('/dev/urandom', 'r')
519                 a = self.a
520                 b = self.b
521                 A = self.A
522                 B = self.B
523
524                 MSGA = f.read(num)
525                 MSGB = f.read(num)
526                 self.a.sendSomeData(MSGA)
527                 self.b.sendSomeData(MSGB)
528                 
529                 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):
530                         if rand(0,1) < prob:
531                                 msga = swap(a, '>', self.noisy)
532                                 b.datagramReceived(msga)
533                         else:
534                                 msga = swap(a, '>', 0)
535                         if rand(0,1) < prob:
536                                 msgb = swap(b, '<', self.noisy)
537                                 a.datagramReceived(msgb)
538                         else:
539                                 msgb = swap(b, '<', 0)
540                 self.assertEqual(len(self.A.msg), len(MSGB))
541                 self.assertEqual(len(self.B.msg), len(MSGA))
542                 self.assertEqual(self.A.msg, MSGB)
543                 self.assertEqual(self.B.msg, MSGA)
544
545         def testOrderedLossy(self, num = 2**18, prob=0.5):
546                 self.testOrderedSimple(num, prob)