1 | #include <assert.h> |
---|
2 | #include <errno.h> |
---|
3 | #include <stdio.h> /* remove() */ |
---|
4 | #include <string.h> /* strcmp() */ |
---|
5 | #include <stdio.h> |
---|
6 | |
---|
7 | #include <sys/types.h> /* stat() */ |
---|
8 | #include <sys/stat.h> /* stat() */ |
---|
9 | #include <unistd.h> /* stat(), sync() */ |
---|
10 | |
---|
11 | #include "transmission.h" |
---|
12 | #include "resume.h" |
---|
13 | #include "torrent.h" /* tr_isTorrent() */ |
---|
14 | #include "utils.h" /* tr_mkdirp() */ |
---|
15 | #include "variant.h" |
---|
16 | |
---|
17 | #include "libtransmission-test.h" |
---|
18 | |
---|
19 | /*** |
---|
20 | **** |
---|
21 | ***/ |
---|
22 | |
---|
23 | #define check_have_none(tor, totalSize) \ |
---|
24 | do { \ |
---|
25 | const tr_stat * st = tr_torrentStat(tor); \ |
---|
26 | check_int_eq (TR_STATUS_STOPPED, st->activity); \ |
---|
27 | check_int_eq (TR_STAT_OK, st->error); \ |
---|
28 | check_int_eq (totalSize, st->sizeWhenDone); \ |
---|
29 | check_int_eq (totalSize, st->leftUntilDone); \ |
---|
30 | check_int_eq (totalSize, tor->info.totalSize); \ |
---|
31 | check_int_eq (0, st->haveValid); \ |
---|
32 | } while (0) |
---|
33 | |
---|
34 | static bool |
---|
35 | testFileExistsAndConsistsOfThisString (const tr_torrent * tor, tr_file_index_t fileIndex, const char * str) |
---|
36 | { |
---|
37 | char * path; |
---|
38 | const size_t str_len = strlen (str); |
---|
39 | bool success = false; |
---|
40 | |
---|
41 | path = tr_torrentFindFile (tor, fileIndex); |
---|
42 | if (path != NULL) |
---|
43 | { |
---|
44 | uint8_t * contents; |
---|
45 | size_t contents_len; |
---|
46 | |
---|
47 | assert (tr_fileExists (path, NULL)); |
---|
48 | |
---|
49 | contents = tr_loadFile (path, &contents_len); |
---|
50 | |
---|
51 | success = (str_len == contents_len) |
---|
52 | && (!memcmp (contents, str, contents_len)); |
---|
53 | |
---|
54 | tr_free (contents); |
---|
55 | tr_free (path); |
---|
56 | } |
---|
57 | |
---|
58 | return success; |
---|
59 | } |
---|
60 | |
---|
61 | static void |
---|
62 | onRenameDone (tr_torrent * tor UNUSED, const char * oldpath UNUSED, const char * newname UNUSED, int error, void * user_data) |
---|
63 | { |
---|
64 | *(int*)user_data = error; |
---|
65 | } |
---|
66 | |
---|
67 | static int |
---|
68 | torrentRenameAndWait (tr_torrent * tor, |
---|
69 | const char * oldpath, |
---|
70 | const char * newname) |
---|
71 | { |
---|
72 | int error = -1; |
---|
73 | tr_torrentRenamePath (tor, oldpath, newname, onRenameDone, &error); |
---|
74 | do { |
---|
75 | tr_wait_msec (10); |
---|
76 | } while (error == -1); |
---|
77 | return error; |
---|
78 | } |
---|
79 | |
---|
80 | /*** |
---|
81 | **** |
---|
82 | ***/ |
---|
83 | |
---|
84 | static void |
---|
85 | create_file_with_contents (const char * path, const char * str) |
---|
86 | { |
---|
87 | int rv; |
---|
88 | FILE * fp; |
---|
89 | char * dir; |
---|
90 | const int tmperr = errno; |
---|
91 | |
---|
92 | dir = tr_dirname (path); |
---|
93 | errno = 0; |
---|
94 | rv = tr_mkdirp (dir, 0700); |
---|
95 | assert (errno == 0); |
---|
96 | assert (rv == 0); |
---|
97 | tr_free (dir); |
---|
98 | |
---|
99 | remove (path); |
---|
100 | fp = fopen (path, "wb"); |
---|
101 | fprintf (fp, "%s", str); |
---|
102 | fclose (fp); |
---|
103 | |
---|
104 | sync (); |
---|
105 | |
---|
106 | errno = tmperr; |
---|
107 | } |
---|
108 | |
---|
109 | static void |
---|
110 | create_single_file_torrent_contents (const char * top) |
---|
111 | { |
---|
112 | char * path = tr_buildPath (top, "hello-world.txt", NULL); |
---|
113 | create_file_with_contents (path, "hello, world!\n"); |
---|
114 | tr_free (path); |
---|
115 | } |
---|
116 | |
---|
117 | static tr_torrent * |
---|
118 | create_torrent_from_base64_metainfo (tr_ctor * ctor, const char * metainfo_base64) |
---|
119 | { |
---|
120 | int err; |
---|
121 | int metainfo_len; |
---|
122 | char * metainfo; |
---|
123 | tr_torrent * tor; |
---|
124 | |
---|
125 | /* create the torrent ctor */ |
---|
126 | metainfo = tr_base64_decode (metainfo_base64, -1, &metainfo_len); |
---|
127 | assert (metainfo != NULL); |
---|
128 | assert (metainfo_len > 0); |
---|
129 | assert (session != NULL); |
---|
130 | tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, metainfo_len); |
---|
131 | tr_ctorSetPaused (ctor, TR_FORCE, true); |
---|
132 | |
---|
133 | /* create the torrent */ |
---|
134 | err = 0; |
---|
135 | tor = tr_torrentNew (ctor, &err); |
---|
136 | assert (!err); |
---|
137 | |
---|
138 | /* cleanup */ |
---|
139 | tr_free (metainfo); |
---|
140 | return tor; |
---|
141 | } |
---|
142 | |
---|
143 | static int |
---|
144 | test_single_filename_torrent (void) |
---|
145 | { |
---|
146 | uint64_t loaded; |
---|
147 | tr_torrent * tor; |
---|
148 | char * tmpstr; |
---|
149 | const size_t totalSize = 14; |
---|
150 | tr_ctor * ctor; |
---|
151 | const tr_stat * st; |
---|
152 | |
---|
153 | /* this is a single-file torrent whose file is hello-world.txt, holding the string "hello, world!" */ |
---|
154 | ctor = tr_ctorNew (session); |
---|
155 | tor = create_torrent_from_base64_metainfo (ctor, |
---|
156 | "ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0" |
---|
157 | "ZWkxMzU4NTQ5MDk4ZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDY6bGVuZ3RoaTE0ZTQ6bmFtZTE1" |
---|
158 | "OmhlbGxvLXdvcmxkLnR4dDEyOnBpZWNlIGxlbmd0aGkzMjc2OGU2OnBpZWNlczIwOukboJcrkFUY" |
---|
159 | "f6LvqLXBVvSHqCk6Nzpwcml2YXRlaTBlZWU="); |
---|
160 | check (tr_isTorrent (tor)); |
---|
161 | |
---|
162 | /* sanity check the info */ |
---|
163 | check_int_eq (1, tor->info.fileCount); |
---|
164 | check_streq ("hello-world.txt", tor->info.files[0].name); |
---|
165 | check (!tor->info.files[0].is_renamed); |
---|
166 | |
---|
167 | /* sanity check the (empty) stats */ |
---|
168 | libttest_blockingTorrentVerify (tor); |
---|
169 | check_have_none (tor, totalSize); |
---|
170 | |
---|
171 | create_single_file_torrent_contents (tor->currentDir); |
---|
172 | |
---|
173 | /* sanity check the stats again, now that we've added the file */ |
---|
174 | libttest_blockingTorrentVerify (tor); |
---|
175 | st = tr_torrentStat (tor); |
---|
176 | check_int_eq (TR_STATUS_STOPPED, st->activity); |
---|
177 | check_int_eq (TR_STAT_OK, st->error); |
---|
178 | check_int_eq (0, st->leftUntilDone); |
---|
179 | check_int_eq (0, st->haveUnchecked); |
---|
180 | check_int_eq (0, st->desiredAvailable); |
---|
181 | check_int_eq (totalSize, st->sizeWhenDone); |
---|
182 | check_int_eq (totalSize, st->haveValid); |
---|
183 | |
---|
184 | /** |
---|
185 | *** okay! we've finally put together all the scaffolding to test |
---|
186 | *** renaming a single-file torrent |
---|
187 | **/ |
---|
188 | |
---|
189 | /* confirm that bad inputs get caught */ |
---|
190 | |
---|
191 | check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", NULL)); |
---|
192 | check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", "")); |
---|
193 | check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", ".")); |
---|
194 | check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", "..")); |
---|
195 | check_int_eq (0, torrentRenameAndWait (tor, "hello-world.txt", "hello-world.txt")); |
---|
196 | check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", "hello/world.txt")); |
---|
197 | |
---|
198 | check (!tor->info.files[0].is_renamed); |
---|
199 | check_streq ("hello-world.txt", tor->info.files[0].name); |
---|
200 | |
---|
201 | /*** |
---|
202 | **** Now try a rename that should succeed |
---|
203 | ***/ |
---|
204 | |
---|
205 | tmpstr = tr_buildPath (tor->currentDir, "hello-world.txt", NULL); |
---|
206 | check (tr_fileExists (tmpstr, NULL)); |
---|
207 | check_streq ("hello-world.txt", tr_torrentName(tor)); |
---|
208 | check_int_eq (0, torrentRenameAndWait (tor, tor->info.name, "foobar")); |
---|
209 | check (!tr_fileExists (tmpstr, NULL)); /* confirm the old filename can't be found */ |
---|
210 | tr_free (tmpstr); |
---|
211 | check (tor->info.files[0].is_renamed); /* confirm the file's 'renamed' flag is set */ |
---|
212 | check_streq ("foobar", tr_torrentName(tor)); /* confirm the torrent's name is now 'foobar' */ |
---|
213 | check_streq ("foobar", tor->info.files[0].name); /* confirm the file's name is now 'foobar' in our struct */ |
---|
214 | check (strstr (tor->info.torrent, "foobar") == NULL); /* confirm the name in the .torrent file hasn't changed */ |
---|
215 | tmpstr = tr_buildPath (tor->currentDir, "foobar", NULL); |
---|
216 | check (tr_fileExists (tmpstr, NULL)); /* confirm the file's name is now 'foobar' on the disk */ |
---|
217 | tr_free (tmpstr); |
---|
218 | check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n")); /* confirm the contents are right */ |
---|
219 | |
---|
220 | /* (while it's renamed: confirm that the .resume file remembers the changes) */ |
---|
221 | tr_torrentSaveResume (tor); |
---|
222 | sync (); |
---|
223 | loaded = tr_torrentLoadResume (tor, ~0, ctor); |
---|
224 | check_streq ("foobar", tr_torrentName(tor)); |
---|
225 | check ((loaded & TR_FR_NAME) != 0); |
---|
226 | |
---|
227 | /*** |
---|
228 | **** ...and rename it back again |
---|
229 | ***/ |
---|
230 | |
---|
231 | tmpstr = tr_buildPath (tor->currentDir, "foobar", NULL); |
---|
232 | check (tr_fileExists (tmpstr, NULL)); |
---|
233 | check_int_eq (0, torrentRenameAndWait (tor, "foobar", "hello-world.txt")); |
---|
234 | check (!tr_fileExists (tmpstr, NULL)); |
---|
235 | check (tor->info.files[0].is_renamed); |
---|
236 | check_streq ("hello-world.txt", tor->info.files[0].name); |
---|
237 | check_streq ("hello-world.txt", tr_torrentName(tor)); |
---|
238 | tr_free (tmpstr); |
---|
239 | check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n")); |
---|
240 | |
---|
241 | /* cleanup */ |
---|
242 | tr_ctorFree (ctor); |
---|
243 | tr_torrentRemove (tor, false, NULL); |
---|
244 | return 0; |
---|
245 | } |
---|
246 | |
---|
247 | /*** |
---|
248 | **** |
---|
249 | **** |
---|
250 | **** |
---|
251 | ***/ |
---|
252 | |
---|
253 | static void |
---|
254 | create_multifile_torrent_contents (const char * top) |
---|
255 | { |
---|
256 | char * path; |
---|
257 | |
---|
258 | path = tr_buildPath (top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester", NULL); |
---|
259 | create_file_with_contents (path, "It ain't easy bein' cheesy.\n"); |
---|
260 | tr_free (path); |
---|
261 | |
---|
262 | path = tr_buildPath (top, "Felidae", "Pantherinae", "Panthera", "Tiger", "Tony", NULL); |
---|
263 | create_file_with_contents (path, "Theyâre Grrrrreat!\n"); |
---|
264 | tr_free (path); |
---|
265 | |
---|
266 | path = tr_buildPath (top, "Felidae", "Felinae", "Felis", "catus", "Kyphi", NULL); |
---|
267 | create_file_with_contents (path, "Inquisitive\n"); |
---|
268 | tr_free (path); |
---|
269 | |
---|
270 | path = tr_buildPath (top, "Felidae", "Felinae", "Felis", "catus", "Saffron", NULL); |
---|
271 | create_file_with_contents (path, "Tough\n"); |
---|
272 | tr_free (path); |
---|
273 | |
---|
274 | sync (); |
---|
275 | } |
---|
276 | |
---|
277 | static int |
---|
278 | test_multifile_torrent (void) |
---|
279 | { |
---|
280 | tr_file_index_t i; |
---|
281 | uint64_t loaded; |
---|
282 | tr_torrent * tor; |
---|
283 | tr_ctor * ctor; |
---|
284 | char * str; |
---|
285 | char * tmp; |
---|
286 | static const size_t totalSize = 67; |
---|
287 | const tr_stat * st; |
---|
288 | const tr_file * files; |
---|
289 | const char * strings[4]; |
---|
290 | const char * expected_files[4] = { |
---|
291 | "Felidae/Felinae/Acinonyx/Cheetah/Chester", |
---|
292 | "Felidae/Felinae/Felis/catus/Kyphi", |
---|
293 | "Felidae/Felinae/Felis/catus/Saffron", |
---|
294 | "Felidae/Pantherinae/Panthera/Tiger/Tony" |
---|
295 | }; |
---|
296 | const char * expected_contents[4] = { |
---|
297 | "It ain't easy bein' cheesy.\n", |
---|
298 | "Inquisitive\n", |
---|
299 | "Tough\n", |
---|
300 | "Theyâre Grrrrreat!\n" |
---|
301 | }; |
---|
302 | |
---|
303 | ctor = tr_ctorNew (session); |
---|
304 | tor = create_torrent_from_base64_metainfo (ctor, |
---|
305 | "ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0" |
---|
306 | "ZWkxMzU4NTU1NDIwZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDU6ZmlsZXNsZDY6bGVuZ3RoaTI4" |
---|
307 | "ZTQ6cGF0aGw3OkZlbGluYWU4OkFjaW5vbnl4NzpDaGVldGFoNzpDaGVzdGVyZWVkNjpsZW5ndGhp" |
---|
308 | "MTJlNDpwYXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNTpLeXBoaWVlZDY6bGVuZ3RoaTZlNDpw" |
---|
309 | "YXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNzpTYWZmcm9uZWVkNjpsZW5ndGhpMjFlNDpwYXRo" |
---|
310 | "bDExOlBhbnRoZXJpbmFlODpQYW50aGVyYTU6VGlnZXI0OlRvbnllZWU0Om5hbWU3OkZlbGlkYWUx" |
---|
311 | "MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp" |
---|
312 | "dmF0ZWkwZWVl"); |
---|
313 | check (tr_isTorrent (tor)); |
---|
314 | files = tor->info.files; |
---|
315 | |
---|
316 | /* sanity check the info */ |
---|
317 | check_streq (tor->info.name, "Felidae"); |
---|
318 | check_int_eq (totalSize, tor->info.totalSize); |
---|
319 | check_int_eq (4, tor->info.fileCount); |
---|
320 | for (i=0; i<4; ++i) |
---|
321 | check_streq (expected_files[i], files[i].name); |
---|
322 | |
---|
323 | /* sanity check the (empty) stats */ |
---|
324 | libttest_blockingTorrentVerify (tor); |
---|
325 | check_have_none (tor, totalSize); |
---|
326 | |
---|
327 | /* build the local data */ |
---|
328 | create_multifile_torrent_contents (tor->currentDir); |
---|
329 | |
---|
330 | /* sanity check the (full) stats */ |
---|
331 | libttest_blockingTorrentVerify (tor); |
---|
332 | st = tr_torrentStat (tor); |
---|
333 | check_int_eq (TR_STATUS_STOPPED, st->activity); |
---|
334 | check_int_eq (TR_STAT_OK, st->error); |
---|
335 | check_int_eq (0, st->leftUntilDone); |
---|
336 | check_int_eq (0, st->haveUnchecked); |
---|
337 | check_int_eq (0, st->desiredAvailable); |
---|
338 | check_int_eq (totalSize, st->sizeWhenDone); |
---|
339 | check_int_eq (totalSize, st->haveValid); |
---|
340 | |
---|
341 | |
---|
342 | /** |
---|
343 | *** okay! let's test renaming. |
---|
344 | **/ |
---|
345 | |
---|
346 | /* rename a leaf... */ |
---|
347 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus/Kyphi", "placeholder")); |
---|
348 | check_streq (files[1].name, "Felidae/Felinae/Felis/catus/placeholder"); |
---|
349 | check (testFileExistsAndConsistsOfThisString (tor, 1, "Inquisitive\n")); |
---|
350 | |
---|
351 | /* ...and back again */ |
---|
352 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus/placeholder", "Kyphi")); |
---|
353 | check_streq (files[1].name, "Felidae/Felinae/Felis/catus/Kyphi"); |
---|
354 | testFileExistsAndConsistsOfThisString (tor, 1, "Inquisitive\n"); |
---|
355 | |
---|
356 | /* rename a branch... */ |
---|
357 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus", "placeholder")); |
---|
358 | check_streq (expected_files[0], files[0].name); |
---|
359 | check_streq ("Felidae/Felinae/Felis/placeholder/Kyphi", files[1].name); |
---|
360 | check_streq ("Felidae/Felinae/Felis/placeholder/Saffron", files[2].name); |
---|
361 | check_streq (expected_files[3], files[3].name); |
---|
362 | check (testFileExistsAndConsistsOfThisString (tor, 1, expected_contents[1])); |
---|
363 | check (testFileExistsAndConsistsOfThisString (tor, 2, expected_contents[2])); |
---|
364 | check (files[0].is_renamed == false); |
---|
365 | check (files[1].is_renamed == true); |
---|
366 | check (files[2].is_renamed == true); |
---|
367 | check (files[3].is_renamed == false); |
---|
368 | |
---|
369 | /* (while the branch is renamed: confirm that the .resume file remembers the changes) */ |
---|
370 | tr_torrentSaveResume (tor); |
---|
371 | /* this is a bit dodgy code-wise, but let's make sure the .resume file got the name */ |
---|
372 | tr_free (files[1].name); |
---|
373 | tor->info.files[1].name = tr_strdup ("gabba gabba hey"); |
---|
374 | loaded = tr_torrentLoadResume (tor, ~0, ctor); |
---|
375 | check ((loaded & TR_FR_FILENAMES) != 0); |
---|
376 | check_streq (expected_files[0], files[0].name); |
---|
377 | check_streq ("Felidae/Felinae/Felis/placeholder/Kyphi", files[1].name); |
---|
378 | check_streq ("Felidae/Felinae/Felis/placeholder/Saffron", files[2].name); |
---|
379 | check_streq (expected_files[3], files[3].name); |
---|
380 | |
---|
381 | /* ...and back again */ |
---|
382 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/placeholder", "catus")); |
---|
383 | for (i=0; i<4; ++i) |
---|
384 | { |
---|
385 | check_streq (expected_files[i], files[i].name); |
---|
386 | check (testFileExistsAndConsistsOfThisString (tor, 1, expected_contents[1])); |
---|
387 | } |
---|
388 | check (files[0].is_renamed == false); |
---|
389 | check (files[1].is_renamed == true); |
---|
390 | check (files[2].is_renamed == true); |
---|
391 | check (files[3].is_renamed == false); |
---|
392 | |
---|
393 | /*** |
---|
394 | **** Test it an incomplete torrent... |
---|
395 | ***/ |
---|
396 | |
---|
397 | /* remove the directory Felidae/Felinae/Felis/catus */ |
---|
398 | str = tr_torrentFindFile (tor, 1); |
---|
399 | check (str != NULL); |
---|
400 | remove (str); |
---|
401 | tr_free (str); |
---|
402 | str = tr_torrentFindFile (tor, 2); |
---|
403 | check (str != NULL); |
---|
404 | remove (str); |
---|
405 | tmp = tr_dirname (str); |
---|
406 | remove (tmp); |
---|
407 | tr_free (tmp); |
---|
408 | tr_free (str); |
---|
409 | sync (); |
---|
410 | libttest_blockingTorrentVerify (tor); |
---|
411 | testFileExistsAndConsistsOfThisString (tor, 0, expected_contents[0]); |
---|
412 | for (i=1; i<=2; ++i) |
---|
413 | { |
---|
414 | str = tr_torrentFindFile (tor, i); |
---|
415 | check_streq (NULL, str); |
---|
416 | tr_free (str); |
---|
417 | } |
---|
418 | testFileExistsAndConsistsOfThisString (tor, 3, expected_contents[3]); |
---|
419 | |
---|
420 | /* rename a branch... */ |
---|
421 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus", "foo")); |
---|
422 | check_streq (expected_files[0], files[0].name); |
---|
423 | check_streq ("Felidae/Felinae/Felis/foo/Kyphi", files[1].name); |
---|
424 | check_streq ("Felidae/Felinae/Felis/foo/Saffron", files[2].name); |
---|
425 | check_streq (expected_files[3], files[3].name); |
---|
426 | |
---|
427 | /* ...and back again */ |
---|
428 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/foo", "catus")); |
---|
429 | for (i=0; i<4; ++i) |
---|
430 | check_streq (expected_files[i], files[i].name); |
---|
431 | |
---|
432 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae", "gabba")); |
---|
433 | strings[0] = "gabba/Felinae/Acinonyx/Cheetah/Chester"; |
---|
434 | strings[1] = "gabba/Felinae/Felis/catus/Kyphi"; |
---|
435 | strings[2] = "gabba/Felinae/Felis/catus/Saffron"; |
---|
436 | strings[3] = "gabba/Pantherinae/Panthera/Tiger/Tony"; |
---|
437 | for (i=0; i<4; ++i) |
---|
438 | { |
---|
439 | check_streq (strings[i], files[i].name); |
---|
440 | testFileExistsAndConsistsOfThisString (tor, i, expected_contents[i]); |
---|
441 | } |
---|
442 | |
---|
443 | /* rename the root, then a branch, and then a leaf... */ |
---|
444 | check_int_eq (0, torrentRenameAndWait (tor, "gabba", "Felidae")); |
---|
445 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Pantherinae/Panthera/Tiger", "Snow Leopard")); |
---|
446 | check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Pantherinae/Panthera/Snow Leopard/Tony", "10.6")); |
---|
447 | strings[0] = "Felidae/Felinae/Acinonyx/Cheetah/Chester"; |
---|
448 | strings[1] = "Felidae/Felinae/Felis/catus/Kyphi"; |
---|
449 | strings[2] = "Felidae/Felinae/Felis/catus/Saffron"; |
---|
450 | strings[3] = "Felidae/Pantherinae/Panthera/Snow Leopard/10.6"; |
---|
451 | for (i=0; i<4; ++i) |
---|
452 | { |
---|
453 | check_streq (strings[i], files[i].name); |
---|
454 | testFileExistsAndConsistsOfThisString (tor, i, expected_contents[i]); |
---|
455 | } |
---|
456 | |
---|
457 | /*** |
---|
458 | **** |
---|
459 | ***/ |
---|
460 | |
---|
461 | /* cleanup */ |
---|
462 | tr_ctorFree (ctor); |
---|
463 | tr_torrentRemove (tor, false, NULL); |
---|
464 | return 0; |
---|
465 | } |
---|
466 | |
---|
467 | /*** |
---|
468 | **** |
---|
469 | ***/ |
---|
470 | |
---|
471 | static int |
---|
472 | test_partial_file (void) |
---|
473 | { |
---|
474 | tr_file_index_t i; |
---|
475 | tr_torrent * tor; |
---|
476 | const tr_stat * st; |
---|
477 | tr_file_stat * fst; |
---|
478 | const uint32_t pieceCount = 33; |
---|
479 | const uint32_t pieceSize = 32768; |
---|
480 | const uint32_t length[] = { 1048576, 4096, 512 }; |
---|
481 | const uint64_t totalSize = length[0] + length[1] + length[2]; |
---|
482 | const char * strings[3]; |
---|
483 | |
---|
484 | /*** |
---|
485 | **** create our test torrent with an incomplete .part file |
---|
486 | ***/ |
---|
487 | |
---|
488 | tor = libtransmission_test_zero_torrent_init (); |
---|
489 | check_int_eq (totalSize, tor->info.totalSize); |
---|
490 | check_int_eq (pieceSize, tor->info.pieceSize); |
---|
491 | check_int_eq (pieceCount, tor->info.pieceCount); |
---|
492 | check_streq ("files-filled-with-zeroes/1048576", tor->info.files[0].name); |
---|
493 | check_streq ("files-filled-with-zeroes/4096", tor->info.files[1].name); |
---|
494 | check_streq ("files-filled-with-zeroes/512", tor->info.files[2].name); |
---|
495 | |
---|
496 | libtransmission_test_zero_torrent_populate (tor, false); |
---|
497 | fst = tr_torrentFiles (tor, NULL); |
---|
498 | check_int_eq (length[0] - pieceSize, fst[0].bytesCompleted); |
---|
499 | check_int_eq (length[1], fst[1].bytesCompleted); |
---|
500 | check_int_eq (length[2], fst[2].bytesCompleted); |
---|
501 | tr_torrentFilesFree (fst, tor->info.fileCount); |
---|
502 | st = tr_torrentStat (tor); |
---|
503 | check_int_eq (totalSize, st->sizeWhenDone); |
---|
504 | check_int_eq (pieceSize, st->leftUntilDone); |
---|
505 | |
---|
506 | /*** |
---|
507 | **** |
---|
508 | ***/ |
---|
509 | |
---|
510 | check_int_eq (0, torrentRenameAndWait (tor, "files-filled-with-zeroes", "foo")); |
---|
511 | check_int_eq (0, torrentRenameAndWait (tor, "foo/1048576", "bar")); |
---|
512 | strings[0] = "foo/bar"; |
---|
513 | strings[1] = "foo/4096"; |
---|
514 | strings[2] = "foo/512"; |
---|
515 | for (i=0; i<3; ++i) |
---|
516 | { |
---|
517 | check_streq (strings[i], tor->info.files[i].name); |
---|
518 | } |
---|
519 | |
---|
520 | strings[0] = "foo/bar.part"; |
---|
521 | for (i=0; i<3; ++i) |
---|
522 | { |
---|
523 | char * expected = tr_buildPath (tor->currentDir, strings[i], NULL); |
---|
524 | char * path = tr_torrentFindFile (tor, i); |
---|
525 | check_streq (expected, path); |
---|
526 | tr_free (path); |
---|
527 | tr_free (expected); |
---|
528 | } |
---|
529 | |
---|
530 | tr_torrentRemove (tor, false, NULL); |
---|
531 | return 0; |
---|
532 | } |
---|
533 | |
---|
534 | /*** |
---|
535 | **** |
---|
536 | ***/ |
---|
537 | |
---|
538 | int |
---|
539 | main (void) |
---|
540 | { |
---|
541 | int ret; |
---|
542 | const testFunc tests[] = { test_single_filename_torrent, |
---|
543 | test_multifile_torrent, |
---|
544 | test_partial_file }; |
---|
545 | |
---|
546 | libtransmission_test_session_init (); |
---|
547 | ret = runTests (tests, NUM_TESTS (tests)); |
---|
548 | libtransmission_test_session_close (); |
---|
549 | |
---|
550 | return ret; |
---|
551 | } |
---|