1 # Written by Andrea Reale
2 # see LICENSE.txt for license information
4 from __future__ import with_statement
5 from BaseLib.Test.test_as_server import TestAsServer
7 from Tribler import LIBRARYNAME
12 from BaseLib.Core.BitTornado.BT1.MessageID import GET_SUBS, SUBS
13 from BaseLib.Core.BitTornado.bencode import bencode, bdecode
14 from BaseLib.Core.Overlay.permid import generate_keypair
15 from BaseLib.Core.simpledefs import NTFY_RICH_METADATA
16 from BaseLib.Core.Subtitles.MetadataDomainObjects.MetadataDTO import MetadataDTO
17 from BaseLib.Core.Subtitles.MetadataDomainObjects.SubtitleInfo import SubtitleInfo
18 from traceback import print_exc
19 from BaseLib.Core.Subtitles.MetadataDomainObjects.Languages import LanguagesProvider
20 from BaseLib.Core.Utilities import utilities
21 from BaseLib.Core.Subtitles.SubtitlesHandler import SubtitlesHandler
22 import BaseLib.Core.Subtitles.SubtitlesHandler as SubUtils
23 from BaseLib.Test.olconn import OLConnection
24 from BaseLib.Core.BuddyCast.buddycast import BuddyCastCore
25 from BaseLib.Core.BuddyCast.channelcast import ChannelCastCore
26 from BaseLib.Core.BuddyCast.votecast import VoteCastCore
31 RES_DIR = os.path.join('.', 'subtitles_test_res')
33 class TestSubtitleMessages(TestAsServer):
35 def setUpPreSession(self):
36 """ override TestAsServer """
37 TestAsServer.setUpPreSession(self)
38 self.config.set_buddycast(True)
39 BuddyCastCore.TESTASSERVER = True
40 ChannelCastCore.TESTASSERVER = True
41 VoteCastCore.TESTASSERVER = True
42 self.config.set_start_recommender(True)
43 self.config.set_bartercast(True)
44 self.config.set_remote_query(True)
45 self.config.set_crawler(False)
46 self.config.set_torrent_collecting_dir(os.path.join(self.config_path, "tmp_torrent_collecting"))
48 self.collecting_dir = os.path.join(self.config_path, "temp_subtitles_collecting")
49 os.makedirs(self.collecting_dir)
50 self.config.set_subtitles_collecting(True)
51 self.config.set_subtitles_collecting_dir(self.collecting_dir)
55 # # Write superpeers.txt and DB schema
56 self.install_path = tempfile.mkdtemp()
57 spdir = os.path.join(self.install_path, LIBRARYNAME, 'Core')
60 statsdir = os.path.join(self.install_path, LIBRARYNAME, 'Core', 'Statistics')
63 superpeerfilename = os.path.join(spdir, 'superpeer.txt')
64 print >> sys.stderr,"test: writing empty superpeers to",superpeerfilename
65 f = open(superpeerfilename, "w")
69 self.config.set_install_dir(self.install_path)
72 srcfiles.append(os.path.join(LIBRARYNAME,"schema_sdb_v5.sql"))
73 for srcfile in srcfiles:
74 sfn = os.path.join('..','..',srcfile)
75 dfn = os.path.join(self.install_path,srcfile)
76 print >>sys.stderr,"test: copying",sfn,dfn
77 shutil.copyfile(sfn,dfn)
79 #copy subtitles files in the appropriate subtitles folder
80 self.src1 = os.path.join(RES_DIR,'fake.srt')
81 self.src2 = os.path.join(RES_DIR,'fake0.srt')
86 def setUpPostSession(self):
87 """ override TestAsServer """
88 TestAsServer.setUpPostSession(self)
90 self.mypermid = str(self.my_keypair.pub().get_der())
91 self.hispermid = str(self.his_keypair.pub().get_der())
93 self.another_keypair = generate_keypair()
94 self.anotherpermid = str(self.another_keypair.pub().get_der())
96 self.testInfohash = hashlib.sha1("yoman!").digest()
98 #copy subtitles in the collecting dir
99 nldName = SubUtils.getSubtitleFileRelativeName(self.anotherpermid, self.testInfohash, "nld")
100 engName = SubUtils.getSubtitleFileRelativeName(self.anotherpermid, self.testInfohash, "eng")
102 self.sub1 = os.path.join(self.collecting_dir, nldName)
103 self.sub2 = os.path.join(self.collecting_dir, engName)
105 shutil.copyfile(self.src1, self.sub1)
106 # Let's say that the receiving peer has only the nld subtitle
108 # shutil.copyfile(self.src2, self.sub2)
113 self.richMetadata_db = self.session.open_dbhandler(NTFY_RICH_METADATA)
116 self.mdto = MetadataDTO(self.anotherpermid, self.testInfohash)
117 subtitle1 = SubtitleInfo("nld", self.sub1)
118 subtitle1.computeChecksum()
119 subtitle2 = SubtitleInfo("eng", os.path.join(RES_DIR, "fake0.srt"))
120 subtitle2.computeChecksum()
121 self.mdto.addSubtitle(subtitle1)
122 self.mdto.addSubtitle(subtitle2)
124 self.mdto.sign(self.another_keypair)
126 self.richMetadata_db.insertMetadata(self.mdto)
130 #hisoermid has the nld subtitle but doesn't have the english one
131 self.richMetadata_db.updateSubtitlePath(self.mdto.channel,self.mdto.infohash,"eng",None)
138 TestAsServer.tearDown(self)
139 self.session.close_dbhandler(self.richMetadata_db)
143 def subtest_receptionOfSUBS(self):
145 Asking for the single available subtitle. The response should be
146 a valid SUBS message containing its contents
149 print >> sys.stderr, "test: test_subtitles_msgs_1_1 -----------------------"
150 ol_conn = OLConnection(self.my_keypair,'localhost',self.hisport)
152 bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(['nld'])
153 binmask = utilities.uintToBinaryString(bitmask, length=4)
155 request = GET_SUBS + \
162 subshandler = SubtitlesHandler()
163 subshandler.register(ol_conn, self.richMetadata_db, self.session)
165 ol_conn.send(request)
166 subs_data = ol_conn.recv()
167 print >> sys.stderr, "test: subtitles_messages : received SUBS response: len",len(subs_data)
168 self.assertEquals(SUBS, subs_data[0])
169 data = bdecode(subs_data[1:])
170 print >> sys.stderr, "test: subtitles_messages : received SUBS response: ", data
172 #check on the format of the response
173 self.assertTrue(isinstance(data,list))
174 self.assertEquals(4, len(data)) # for fields
175 self.assertEquals(self.mdto.channel,data[0])
176 self.assertEquals(self.mdto.infohash, data[1])
177 self.assertEquals(binmask, data[2])
178 self.assertTrue(isinstance(data[3],list))
179 self.assertEquals(1, len(data[3]))
180 with codecs.open(self.sub1, "rb", "utf-8") as sub:
181 expectedContents = sub.read()
182 self.assertEquals(expectedContents, data[3][0])
186 print >> sys.stderr, "test: subtitles_messages: received content is valid."
187 print >> sys.stderr, "End of test_subtitles_msgs_1_1 test --------------------"
190 def subtest_receptionOfSUBSTwoRequestsOneAvailable(self):
192 Asking for two subtitles while the recipent of the request has only one.
193 The response should contain only the one available subtitle content,
194 plus a bitmask that reflects the contents of the response.
197 print >> sys.stderr, "test: test_subtitles_msgs_2_1 -----------------------"
198 ol_conn = OLConnection(self.my_keypair,'localhost',self.hisport)
200 bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(['nld','eng'])
201 binmask = utilities.uintToBinaryString(bitmask, length=4)
203 request = GET_SUBS + \
210 subshandler = SubtitlesHandler()
211 subshandler.register(ol_conn, self.richMetadata_db, self.session)
213 ol_conn.send(request)
214 subs_data = ol_conn.recv()
215 self.assertEquals(SUBS, subs_data[0])
216 data = bdecode(subs_data[1:])
217 print >> sys.stderr, "test: subtitles_messages : received SUBS repsonse: ", data
219 #check on the format of the response
220 self.assertTrue(isinstance(data,list))
221 self.assertEquals(4, len(data)) # for fields
222 self.assertEquals(self.mdto.channel,data[0])
223 self.assertEquals(self.mdto.infohash, data[1])
225 #the receiver had only one of the two requested subtitles
226 # so I expect a different bitmask
227 bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(['nld'])
228 expectedBinarymask = utilities.uintToBinaryString(bitmask, length=4)
230 self.assertEquals(expectedBinarymask, data[2])
231 self.assertTrue(isinstance(data[3],list))
232 self.assertEquals(1, len(data[3]))
233 with codecs.open(self.sub1, "rb", "utf-8") as sub:
234 expectedContents = sub.read()
235 self.assertEquals(expectedContents, data[3][0])
238 print >> sys.stderr, "test: subtitles_messages: received content is valid."
239 print >> sys.stderr, "End of test_subtitles_msgs_2_1 test --------------------"
241 def subtest_invalidRequest1(self):
243 Trying to send an empty message.
244 The connection should be closed by the receiver
246 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_1 ------------------"
247 ol_conn = OLConnection(self.my_keypair,'localhost',self.hisport)
250 request = GET_SUBS + \
253 ol_conn.send(request)
254 self.assertEquals(0, len(ol_conn.recv()))
255 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_1: connection closed as expected"
258 print >> sys.stderr, "End of test_subtitles_msgs_invalid_request_1 ------------------"
260 def subtest_invalidRequest2(self):
262 Trying to send an invalid message (an integer instead of a 4 bytes binary string)
263 The connection should be closed by the receiver
265 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_2 ------------------"
266 ol_conn = OLConnection(self.my_keypair,'localhost',self.hisport)
269 request = GET_SUBS + \
276 ol_conn.send(request)
277 self.assertEquals(0, len(ol_conn.recv()))
278 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_2: connection closed as expected"
281 print >> sys.stderr, "End of test_subtitles_msgs_invalid_request_2 ------------------"
283 def subtest_invalidRequest3(self):
285 Trying to send an invalid message (valid for everythin except that there is one field more)
286 The connection should be closed by the receiver
288 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_3 ------------------"
289 ol_conn = OLConnection(self.my_keypair,'localhost',self.hisport)
291 bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(['nld','eng'])
292 binmask = utilities.uintToBinaryString(bitmask, length=4)
294 request = GET_SUBS + \
302 ol_conn.send(request)
303 self.assertEquals(0, len(ol_conn.recv()))
304 print >> sys.stderr, "test: test_subtitles_msgs_invalid_request_3: connection closed as expected"
307 print >> sys.stderr, "End of test_subtitles_msgs_invalid_request_3 ------------------"
309 def singtest_subs_messages(self):
312 self.subtest_receptionOfSUBS()
313 self.subtest_receptionOfSUBSTwoRequestsOneAvailable()
314 self.subtest_invalidRequest1()
315 self.subtest_invalidRequest2()
316 self.subtest_invalidRequest3()
318 #testMethods = [getattr(self, method) for method in dir(self) if method.startswith('subtest')]
320 #for m in testMethods:
325 suite = unittest.TestSuite()
326 # We should run the tests in a separate Python interpreter to prevent
327 # problems with our singleton classes, e.g. PeerDB, etc.
328 if len(sys.argv) != 2:
329 print "Usage: python test_channelcast_plus_subtitles.py <method name>"
331 suite.addTest(TestSubtitleMessages(sys.argv[1]))
336 unittest.main(defaultTest='test_suite',argv=[sys.argv[0]])
338 if __name__ == "__main__":