1 # Written by Nicolas Neubauer, Arno Bakker
\r
2 # see LICENSE.txt for license information
\r
4 # Test case for BuddyCast overlay version 12 (and 8). To be integrated into
\r
5 # test_buddycast_msg.py
\r
7 # Very sensitive to the order in which things are put into DB,
\r
8 # so not a robust test
\r
18 from random import randint,shuffle
\r
19 from traceback import print_exc
\r
20 from types import StringType, ListType, DictType
\r
21 from threading import Thread
\r
22 from time import sleep
\r
23 from M2Crypto import Rand,EC
\r
26 from BaseLib.Test.test_as_server import TestAsServer
\r
27 from olconn import OLConnection
\r
28 from BaseLib.__init__ import LIBRARYNAME
\r
29 from BaseLib.Core.BitTornado.bencode import bencode,bdecode
\r
30 from BaseLib.Core.BitTornado.BT1.MessageID import *
\r
32 from BaseLib.Core.CacheDB.CacheDBHandler import BarterCastDBHandler
\r
34 from BaseLib.Core.BuddyCast.buddycast import BuddyCastFactory, BuddyCastCore
\r
36 from BaseLib.Core.Overlay.SecureOverlay import OLPROTO_VER_FIRST, OLPROTO_VER_SECOND, OLPROTO_VER_THIRD, OLPROTO_VER_FOURTH, OLPROTO_VER_FIFTH, OLPROTO_VER_SIXTH, OLPROTO_VER_SEVENTH, OLPROTO_VER_EIGHTH, OLPROTO_VER_ELEVENTH, OLPROTO_VER_CURRENT, OLPROTO_VER_LOWEST
\r
37 from BaseLib.Core.simpledefs import *
\r
39 from BaseLib.Core.CacheDB.SqliteCacheDBHandler import *
\r
40 from BaseLib.Core.CacheDB.sqlitecachedb import CURRENT_MAIN_DB_VERSION
\r
46 class TestBuddyCastMsg8Plus(TestAsServer):
\r
48 Testing BuddyCast 5 / overlay protocol v12+v8 interactions:
\r
49 swarm size info exchange.
\r
53 """ override TestAsServer """
\r
54 TestAsServer.setUp(self)
\r
55 Rand.load_file('randpool.dat', -1)
\r
57 def setUpPreSession(self):
\r
58 """ override TestAsServer """
\r
59 TestAsServer.setUpPreSession(self)
\r
61 self.config.set_buddycast(True)
\r
62 BuddyCastCore.TESTASSERVER = True
\r
63 self.config.set_start_recommender(True)
\r
64 self.config.set_bartercast(True)
\r
66 # Arno, 2010-02-02: Install empty superpeers.txt so no interference from
\r
68 self.config.set_crawler(False)
\r
70 # Write superpeers.txt
\r
71 self.install_path = tempfile.mkdtemp()
\r
72 spdir = os.path.join(self.install_path, LIBRARYNAME, 'Core')
\r
75 statsdir = os.path.join(self.install_path, LIBRARYNAME, 'Core', 'Statistics')
\r
76 os.makedirs(statsdir)
\r
78 superpeerfilename = os.path.join(spdir, 'superpeer.txt')
\r
79 print >> sys.stderr,"test: writing empty superpeers to",superpeerfilename
\r
80 f = open(superpeerfilename, "w")
\r
84 self.config.set_install_dir(self.install_path)
\r
87 srcfiles.append(os.path.join(LIBRARYNAME,"schema_sdb_v"+str(CURRENT_MAIN_DB_VERSION)+".sql"))
\r
88 for srcfile in srcfiles:
\r
89 sfn = os.path.join('..','..',srcfile)
\r
90 dfn = os.path.join(self.install_path,srcfile)
\r
91 print >>sys.stderr,"test: copying",sfn,dfn
\r
92 shutil.copyfile(sfn,dfn)
\r
96 def setUpPostSession(self):
\r
97 """ override TestAsServer """
\r
98 TestAsServer.setUpPostSession(self)
\r
100 self.mypermid = str(self.my_keypair.pub().get_der())
\r
101 self.hispermid = str(self.his_keypair.pub().get_der())
\r
102 self.myhash = sha(self.mypermid).digest()
\r
104 self.buddycast = BuddyCastFactory.getInstance(superpeer=True)
\r
105 self.buddycast.olthread_register(True)
\r
107 # arg0 = sys.argv[0].lower()
\r
108 # if arg0.endswith('.exe'):
\r
109 # installdir = os.path.abspath(os.path.dirname(sys.argv[0]))
\r
111 # installdir = os.getcwd()
\r
112 # self.utility = Utility(installdir)
\r
115 # wait for buddycast to have completed on run cycle,
\r
116 # seems to create problems otherwise
\r
117 while not self.buddycast.ranonce:
\r
120 def tearDown(self):
\r
121 """ override TestAsServer """
\r
122 TestAsServer.tearDown(self)
\r
124 os.remove('randpool.dat')
\r
129 def singtest_all_olproto_ver_current(self):
\r
130 self._test_all(OLPROTO_VER_CURRENT)
\r
132 def singtest_all_olproto_ver_11(self):
\r
135 def singtest_all_olproto_ver_8(self):
\r
138 def _test_all(self,myoversion):
\r
140 I want to start a Tribler client once and then connect to
\r
141 it many times. So there must be only one test method
\r
142 to prevent setUp() from creating a new client every time.
\r
144 The code is constructed so unittest will show the name of the
\r
145 (sub)test where the error occured in the traceback it prints.
\r
147 # Arno, 2010-02-03: clicklog 1,2,3 must be run consecutively
\r
148 # create_mypref() must be called after clicklog 1,2,3
\r
149 self.subtest_good_buddycast_clicklog(1,myoversion)
\r
150 self.subtest_good_buddycast_clicklog(2,myoversion)
\r
151 self.subtest_good_buddycast_clicklog(3,myoversion)
\r
152 self.subtest_terms(myoversion)
\r
153 self.subtest_create_mypref()
\r
154 self.subtest_create_bc(myoversion)
\r
157 def get_good_clicklog_msg(self,n,myoversion=8):
\r
163 # reranking strategy
\r
165 # number of seeders
\r
166 # number of leechers
\r
168 # number of sources seen'
\r
169 prec = ["hash1hash1hash1hash1", ["linux","ubuntu"], 1, 2]
\r
170 if myoversion >= 11:
\r
171 prec += [400, 500, 1000, 50]
\r
172 preferences = [prec]
\r
173 if myoversion >= 11:
\r
174 prec = ['hash0hash0hash0hash0', 300, 800, 5000, 30]
\r
175 collected_torrents = [prec]
\r
177 collected_torrents = ['hash0hash0hash0hash0']
\r
180 prec = ["hash2hash2hash2hash2", ["linux", "ubuntu"], 2, 2]
\r
181 if myoversion >= 11:
\r
182 prec += [600, 700,20000,60]
\r
183 preferences = [prec]
\r
184 if myoversion >= 11:
\r
185 prec = ['hash2hash2hash2hash2', 500, 200, 70000, 8000]
\r
186 collected_torrents = [prec]
\r
188 collected_torrents = ["hash2hash2hash2hash2"]
\r
190 prec = ["hash3hash3hash3hash3", ["linux","redhat"], 5 ,2 ]
\r
191 if myoversion >= 11:
\r
192 prec += [800, 900, 30000, 70]
\r
193 preferences = [prec]
\r
194 if myoversion >= 11:
\r
195 prec = ['hash3hash3hash3hash3', 700, 200, 45000, 75]
\r
196 collected_torrents = [prec]
\r
198 collected_torrents = ['hash3hash3hash3hash3']
\r
202 'preferences': preferences,
\r
204 'permid': self.mypermid,
\r
205 'ip': '127.0.0.1', #'130.149.146.117',
\r
206 'taste buddies': [],
\r
208 'random peers': [],
\r
209 'collected torrents': collected_torrents,
\r
212 'port': self.hisport,
\r
218 def subtest_good_buddycast_clicklog(self, i, myoversion):
\r
219 """sends two buddy cast messages containing clicklog data,
\r
220 then checks in the DB to find out whether the correct
\r
223 This in fact checks quite a lot of things.
\r
224 For example, the messages always contain terms [1,2]
\r
227 print >>sys.stderr,"\ntest: subtest_good_buddycast_clicklog",i,"selversion",myoversion
\r
229 s = OLConnection(self.my_keypair,'localhost',self.hisport,myoversion=myoversion)
\r
231 prefmsg = self.get_good_clicklog_msg(i,myoversion)
\r
233 print >>sys.stderr,myoversion,`prefmsg`
\r
235 msg = self.create_payload(prefmsg)
\r
239 print >>sys.stderr,"test: reply message %s:%s" % (getMessageName(resp[0]), resp[1:])
\r
241 print >>sys.stderr,"no reply message"
\r
242 self.assert_(len(resp) > 0)
\r
244 #if we have survived this, check if the content of the remote database is correct
\r
245 search_db = self.session.open_dbhandler(NTFY_SEARCH)
\r
246 term_db = self.session.open_dbhandler(NTFY_TERM)
\r
247 pref_db = self.session.open_dbhandler(NTFY_PREFERENCES)
\r
248 torrent_db = self.session.open_dbhandler(NTFY_TORRENTS)
\r
251 while not torrent_id:
\r
252 hash = prefmsg['preferences'][0][0]
\r
253 print >> sys.stderr, "hash: %s, bin2str: %s" % (hash, bin2str(hash))
\r
254 torrent_data = torrent_db.getTorrentID(hash)
\r
255 print >> sys.stderr, "Torrent data for torrent %s: %s" % (prefmsg['preferences'][0][0], torrent_data)
\r
256 torrent_id = torrent_data
\r
258 print >> sys.stderr, "torrent not yet saved, waiting..."
\r
262 # self.getAll("rowid, peer_id, torrent_id, click_position,reranking_strategy", order_by="peer_id, torrent_id")
\r
263 real_prefs = pref_db.getAllEntries()
\r
264 print >>sys.stderr,"test: getAllEntries returned",real_prefs
\r
266 my_peer_id = real_prefs[0][1]
\r
267 real_terms = term_db.getAllEntries()
\r
268 real_search = search_db.getAllEntries()
\r
272 wanted_prefs = [[1,my_peer_id,1,1,2]]
\r
273 wanted_terms = [[1,u'linux'], [2,u'ubuntu']]
\r
274 wanted_search = [[1,my_peer_id,'?',1,0],
\r
275 [2,my_peer_id,'?',2,1]]
\r
277 # Arno, 2010-02-04: Nicolas assumed the collected torrent for i=1
\r
278 # wouldn't be stored in DB?
\r
279 wanted_prefs = [[1,my_peer_id,'?',1,2],[2,my_peer_id,torrent_id,2,2]]
\r
280 wanted_terms = [[1,u'linux'], [2,u'ubuntu']]
\r
281 wanted_search = [[1,my_peer_id,'?',1,0],
\r
282 [2,my_peer_id,'?',2,1],
\r
283 [3,my_peer_id,'?',1,0],
\r
284 [4,my_peer_id,'?',2,1]]
\r
287 wanted_prefs = [[1,my_peer_id,'?',1,2],[2,my_peer_id,'?',2,2],[3,my_peer_id,torrent_id,5,2]]
\r
288 wanted_terms = [[1,u'linux'], [2,u'ubuntu'], [3, u'redhat']]
\r
289 wanted_search = [[1,my_peer_id,'?',1,0],
\r
290 [2,my_peer_id,'?',2,1],
\r
291 [3,my_peer_id,'?',1,0],
\r
292 [4,my_peer_id,'?',2,1],
\r
293 [5,my_peer_id,'?',1,0],
\r
294 [6,my_peer_id,'?',3,1]]
\r
298 print >> sys.stderr, "real_prefs: %s" % real_prefs
\r
299 print >> sys.stderr, "real_terms: %s" % real_terms
\r
300 print >> sys.stderr, "real_search: %s " % real_search
\r
302 print >> sys.stderr, "wanted_prefs: %s" % wanted_prefs
\r
303 print >> sys.stderr, "wanted_terms: %s" % wanted_terms
\r
304 print >> sys.stderr, "wanted_search: %s " % wanted_search
\r
306 self.assert_(self.lol_equals(real_search, wanted_search, "good buddycast %d: search" % i))
\r
307 self.assert_(self.lol_equals(real_terms, wanted_terms, "good buddycast %d: terms" % i))
\r
308 self.assert_(self.lol_equals(real_prefs, wanted_prefs, "good buddycast %d: prefs" % i))
\r
310 def subtest_terms(self,myoversion):
\r
311 """assumes clicklog message 1 and 2 have been sent and digested"""
\r
313 print >>sys.stderr,"\ntest: subtest_terms"
\r
315 term_db = self.session.open_dbhandler(NTFY_TERM)
\r
317 s = OLConnection(self.my_keypair,'localhost',self.hisport,myoversion=myoversion)
\r
318 msg = self.get_good_clicklog_msg(3,myoversion)
\r
319 msg = self.create_payload(msg)
\r
322 self.assert_(len(resp) > 0)
\r
324 termid = term_db.getTermID(u"linux")
\r
325 print >>sys.stderr, "TermID for Linux: %s" % termid
\r
326 #self.assert_(termid == 1)
\r
328 #self.assert_(term_db.getTerm(1)==bin2str(str(u"linux")))
\r
330 completedTerms = term_db.getTermsStartingWith("li")
\r
331 print >> sys.stderr, "terms starting with l: %s" % completedTerms
\r
332 self.assert_(len(completedTerms)==1)
\r
333 self.assert_(u'linux' in completedTerms)
\r
335 term_db.insertTerm("asd#")
\r
336 completedTerms = term_db.getTermsStartingWith("asd")
\r
337 print >> sys.stderr, "terms starting with asd: %s" % completedTerms
\r
338 self.assert_(len(completedTerms)==1)
\r
339 # Arno, 2010-02-03: Nicolas had 'asd' here, but I don't see any place
\r
340 # where the # should have been stripped.
\r
342 self.assert_(u'asd#' in completedTerms)
\r
347 def subtest_create_mypref(self):
\r
348 print >>sys.stderr,"\ntest: creating test MyPreference data"
\r
350 torrent_db = self.session.open_dbhandler(NTFY_TORRENTS)
\r
351 torrent_db.addInfohash('mhashmhashmhashmhash')
\r
352 torrent_id = torrent_db.getTorrentID('mhashmhashmhashmhash')
\r
353 mypref_db = self.session.open_dbhandler(NTFY_MYPREFERENCES)
\r
354 search_db = self.session.open_dbhandler(NTFY_SEARCH)
\r
356 mypref_db.addMyPreference('mhashmhashmhashmhash', {'destination_path':''}, commit=True)
\r
358 'click_position': 1,
\r
359 'reranking_strategy': 2,
\r
360 'keywords': ['linux', 'fedora']
\r
362 mypref_db.addClicklogToMyPreference('mhashmhashmhashmhash', clicklog_data, commit=True)
\r
364 # self.getAll("torrent_id, click_position, reranking_strategy", order_by="torrent_id")
\r
365 allEntries = mypref_db.getAllEntries()
\r
366 print >> sys.stderr, "all mypref entries: %s" % allEntries
\r
367 self.assert_(len(allEntries)==1)
\r
368 # (torrent_id, click_pos, rerank_strategy)
\r
369 mypref_wanted = [['?',1,2]]
\r
370 self.assert_(self.lol_equals(allEntries, mypref_wanted, "create mypref all"))
\r
372 # self.getAll("rowid, peer_id, torrent_id, term_id, term_order ", order_by="rowid")
\r
373 real_search = search_db.getAllOwnEntries()
\r
374 wanted_search = [[7,0,torrent_id,1,0],
\r
375 [8,0,torrent_id,5,1]] # is now 5 for some reason
\r
376 self.assert_(self.lol_equals(real_search, wanted_search, "create mypref allown"))
\r
379 def subtest_create_bc(self,myoversion):
\r
380 print >>sys.stderr,"\ntest: creating test create_bc"
\r
382 torrent_db = self.session.open_dbhandler(NTFY_TORRENTS)
\r
383 torrent_db._db.update("Torrent", status_id=1)
\r
384 pref_db = self.session.open_dbhandler(NTFY_MYPREFERENCES)
\r
386 msg = self.buddycast.buddycast_core.createBuddyCastMessage(0, myoversion, target_ip="127.0.0.1", target_port=80)
\r
387 print >> sys.stderr, "created bc pref: %s" % msg
\r
389 wantpref = ['mhashmhashmhashmhash',['linux','fedora'],1,2]
\r
390 if myoversion >= OLPROTO_VER_ELEVENTH:
\r
391 wantpref += [-1,-1,-1,-1]
\r
392 wantprefs = [wantpref]
\r
394 self.assert_(msg['preferences']==wantprefs)
\r
398 def lol_equals(self, lol1, lol2, msg):
\r
400 for (l1, l2) in zip(lol1, lol2):
\r
401 for (e1, e2) in zip(l1, l2):
\r
402 if e1=='?' or e2=='?':
\r
405 print >> sys.stderr, "%s != %s!" % (e1, e2)
\r
409 print >> sys.stderr, "%s: lol != lol:\nreal %s\nwanted %s" % (msg, lol1, lol2)
\r
413 def create_payload(self,r):
\r
414 return BUDDYCAST+bencode(r)
\r
418 suite = unittest.TestSuite()
\r
419 # We should run the tests in a separate Python interpreter to prevent
\r
420 # problems with our singleton classes, e.g. PeerDB, etc.
\r
421 if len(sys.argv) != 2:
\r
422 print "Usage: python test_buddycast_msg8plus.py <method name>"
\r
424 suite.addTest(TestBuddyCastMsg8Plus(sys.argv[1]))
\r
429 unittest.main(defaultTest='test_suite',argv=[sys.argv[0]])
\r
431 if __name__ == "__main__":
\r