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