Attachment 'test_lightTracker.py'
Download 1 #!/usr/bin/env python
2
3 # Unit Test Suites for pyTracker Project
4 #
5 # Using standard unit test framework coming with Python
6 # To execute the test cases, type:
7 # >>python test_pyTracker.py
8 #
9 # Written by Alex Dong ( alex.dong at gmail.com)
10
11
12
13 import urllib2
14 import unittest
15 from bencode import bencode, bdecode
16 from urllib import quote
17 from models import peer_db
18 import web as db
19 from logger import logger
20 logger = logger('TEST_TRACKER')
21
22 '''
23 ===== Section: Test Code Structure ==========
24 1. There will be two annouce and scrape server pairs to be tested. One will
25 be public available track server and the other one will be the
26 local pyTracker.
27 2. Every test case will be executed twise. The first time executes against the
28 public track server to make sure the test case design and implementation
29 are correct. The second time against the local pyTracker server.
30 3. The test code has two layers:
31 1) meta-instruction layer: This layer contains all the low-level
32 instructions to deal with tracker server. For example,
33 announce('start'), _status_assertions, etc.
34 2) test case layer: This layer will be built on top of the
35 meta-instruction layer and it contains the main test case
36 scenarios and assertions.
37 '''
38 def requestURL(url):
39 fp = urllib2.urlopen(url)
40 r = bdecode(fp.read())
41 fp.close()
42 return r
43
44 # Global Constants. Used to build test cases.
45 public_tracker_url = 'http://tracker.torrentbox.com:2710/'
46 local_tracker_url = 'http://127.0.0.1:8080/tracker/'
47 target_tracker_url = local_tracker_url + "announce"
48 target_scraper_url = local_tracker_url + "scrape"
49
50 info_hash = '839be8624144b3f993118240d9332d673bff7523'
51 peer_id = 'M4-20-2-e918a1127f32'
52 port = 6881
53 size = 93989333
54 torrent_name = 'Madonna - Confessions on a dance floor'
55
56
57 class MetaInstruction(unittest.TestCase):
58 def __init__(self, url, info_hash, size, peer_id=peer_id, port=port):
59 self._url = url
60 self._info_hash = info_hash.decode('hex')
61 self._size = size
62 self._peer_id = peer_id
63 self._port = port
64
65 def status_assert(self, cur_status, expectation=None):
66 (cur_complete, cur_incomplete) = cur_status
67
68 if expectation:
69 if expectation['complete']=='down':
70 self.assert_(self._last_complete - 1 == cur_complete)
71 elif expectation['complete']=='up':
72 self.assert_(self._last_complete + 1 == cur_complete)
73 else:
74 self.assert_(self._last_complete == cur_complete)
75
76 if expectation['incomplete']=='down':
77 self.assert_(self._last_incomplete - 1 == cur_incomplete)
78 elif expectation['incomplete']=='up':
79 self.assert_(self._last_incomplete + 1 == cur_incomplete)
80 else:
81 self.assert_(self._last_incomplete == cur_incomplete)
82
83 (self._last_complete, self._last_incomplete) = cur_status
84
85 def scrape(self):
86 r = requestURL("%s?info_hash=%s" % (target_scraper_url, quote(self._info_hash)))
87 r = r['files'][self._info_hash]
88 return (r['complete'], r['incomplete'])
89
90 def announce(self, event, downloaded, uploaded, left):
91 # Make URL
92 url = "%s?info_hash=%s&peer_id=%s&compact=1&port=%s&event=%s&downloaded=%s&uploaded=%s&left=%s" % \
93 (self._url, quote(self._info_hash), quote(self._peer_id), str(self._port), event, downloaded, uploaded, left)
94 r = requestURL(url)
95 return (r['complete'], r['incomplete'])
96
97
98 class ExceptionalTestCases(unittest.TestCase):
99
100 def _has_failure(self, url):
101 r = requestURL(url)
102 self.assert_(r['failure reason:'] != None)
103
104 def testMissingInfoHash(self):
105 self._has_failure("%s?peer_id=%s" % (target_tracker_url, peer_id))
106
107 def testNonExistenceInfoHash(self):
108 self._has_failure("%s?info_hash=839be8624144b3f993118240d9332d673bf32322&peer_id=%s&port=%s" %
109 (target_tracker_url, peer_id, port))
110
111 def testInvalidPort(self):
112 self._has_failure("%s?info_hash=%s&peer_id=%s&port=68810976" %
113 (target_tracker_url, info_hash, peer_id))
114
115 def testInvalidEVent(self):
116 self._has_failure("%s?info_hash=%s&peer_id=%s&port=%s&event=Unknown" %
117 (target_tracker_url, info_hash, peer_id, port))
118
119 def testInvalidLeftAndEvent(self):
120 self._has_failure("%s?info_hash=%s&peer_id=%s&port=%s&event=Completed&left=25" %
121 (target_tracker_url, info_hash, peer_id, port))
122
123
124 class MultipleClientsDownloadMultipleTorrentsTestCases(unittest.TestCase):
125 def setUp(self):
126 self._ut_tor_1 = MetaInstruction(target_tracker_url, '101c9d63211c3c570ffbadd49c5649d3fb497273',93989333, "UT000000000000000001", 21056)
127 self._ut_tor_2 = MetaInstruction(target_tracker_url, '09bb5bb38283e111a5b830243525659e077d7f24',93989333, "UT000000000000000001", 21056)
128 self._ml_tor_1 = MetaInstruction(target_tracker_url, '101c9d63211c3c570ffbadd49c5649d3fb497273', 93989333, "Mainline000000000001", 61099)
129 self._ml_tor_2 = MetaInstruction(target_tracker_url, '09bb5bb38283e111a5b830243525659e077d7f24', 93989333, "Mainline000000000001", 61099)
130 peer_db.truncate()
131
132 def testOneClientMultipleTorrent(self):
133 pass
134
135 def testTwoClientsOneTorrent(self):
136 """'Mainline' seeding and 'UT' downloading"""
137 self._ml_tor_1.status_assert(self._ml_tor_1.announce('started', 93989333, 93989333, 0))
138 self._ml_tor_1.status_assert(self._ut_tor_1.announce('started', 93989333, 2342, 234231), {'complete':'equal', 'incomplete':'up'})
139 self._ml_tor_1.status_assert(self._ut_tor_1.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
140
141 def testTwoClientsReceiveCorrectLocationInfo(self):
142 pass
143
144 class OneClientDownloadsMultipleTorrentsTestCases(unittest.TestCase):
145 def setUp(self):
146 self._mi_1 = MetaInstruction(target_tracker_url, '101c9d63211c3c570ffbadd49c5649d3fb497273',93989333)
147 self._mi_2 = MetaInstruction(target_tracker_url, '09bb5bb38283e111a5b830243525659e077d7f24', 93989333)
148
149 def testTwoTorrentsAtSameOrder(self):
150 self._mi_1.status_assert(self._mi_1.announce('started', 93989333, 93989333, 0))
151 self._mi_2.status_assert(self._mi_2.announce('started', 93989333, 93989333, 0))
152 self._mi_2.status_assert(self._mi_2.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
153 self._mi_1.status_assert(self._mi_1.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
154
155 def testTwoTorrentsRequests(self):
156 self._mi_1.status_assert(self._mi_1.announce('started', 93989333, 93989333, 0))
157 self._mi_2.status_assert(self._mi_2.announce('started', 93989333, 93989333, 0))
158 self._mi_2.status_assert(self._mi_2.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
159 self._mi_1.status_assert(self._mi_1.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
160
161 def testTwoTorrentsRandomOrder(self):
162 self._mi_1.status_assert(self._mi_1.announce('started', 93989333, 93989333, 233345))
163 self._mi_1.status_assert(self._mi_1.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
164
165 self._mi_2.status_assert(self._mi_2.announce('started', 93989333, 93989333, 334234))
166 self._mi_2.status_assert(self._mi_2.announce('stopped', 93989333, 93989333, 0), {'complete':'equal', 'incomplete':'down'})
167 self._mi_2.status_assert(self._mi_2.announce('started', 93989333, 93989333, 234234), {'complete':'equal', 'incomplete':'up'})
168
169 self._mi_1.status_assert(self._mi_1.announce('completed', 93989333, 93989333, 0), {'complete':'equal', 'incomplete':'equal'})
170 self._mi_1.status_assert(self._mi_1.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
171
172 self._mi_2.status_assert(self._mi_2.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
173 self._mi_2.status_assert(self._mi_2.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
174
175 class SmokeTestCases(unittest.TestCase):
176 def setUp(self):
177 self._url = target_tracker_url
178 self._info_hash = info_hash
179 self._size = size
180 self._torrent_name = torrent_name
181 self._mi = MetaInstruction(self._url, self._info_hash, self._size)
182 peer_db.truncate()
183
184 def testInitialIncompleteStartup(self):
185 init = self._mi.scrape()
186 curr = self._mi.announce('started', 93989333, 93989333, 333)
187 self.assert_(init[0]==curr[0])
188 self.assert_(init[1]+1==curr[1])
189
190 def testInitialCompleteStartup(self):
191 init = self._mi.scrape()
192 curr = self._mi.announce('started', 93989333, 93989333, 0)
193 self.assert_(init[0]+1==curr[0]) # complete
194 self.assert_(init[1]==curr[1]) # incomplete
195
196 def testInitialSeeding(self):
197 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 0))
198 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
199
200 def testDownloaderRequests(self):
201 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 32424))
202 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 322), {'complete':'equal', 'incomplete':'equal'})
203
204 def testDuplicatedCompeteRequests(self):
205 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 32424))
206 self._mi.status_assert(self._mi.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
207 self._mi.status_assert(self._mi.announce('completed', 93989333, 93989333, 0), {'complete':'equal', 'incomplete':'equal'})
208 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
209
210 def testDuplicatedStartedRequests(self):
211 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 0))
212 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 0), {'complete':'equal', 'incomplete':'equal'})
213 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 0), {'complete':'equal', 'incomplete':'equal'})
214 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
215
216 def testDuplicatedStoppedRequests(self):
217 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 23420))
218 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 2342), {'complete':'equal', 'incomplete':'down'})
219 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 2342), {'complete':'equal', 'incomplete':'equal'})
220
221 def testResumeWorkflow(self):
222 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 234320))
223 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 234230), {'complete':'equal', 'incomplete':'down'})
224 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 234230), {'complete':'equal', 'incomplete':'up'})
225 self._mi.status_assert(self._mi.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
226 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
227
228 def testNormalWorkflow(self):
229 self._mi.status_assert(self._mi.announce('started', 93989333, 93989333, 234230))
230 self._mi.status_assert(self._mi.announce('completed', 93989333, 93989333, 0), {'complete':'up', 'incomplete':'down'})
231 self._mi.status_assert(self._mi.announce('stopped', 93989333, 93989333, 0), {'complete':'down', 'incomplete':'equal'})
232
233 if __name__ == '__main__':
234 db.db_parameters = dict(dbn='mysql', user='root', pw='root', db='bitspace')
235 db.load()
236 unittest.main()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.