2014-01-19 01:09:44 +00:00
|
|
|
|
/*
|
|
|
|
|
* This file Copyright (C) 2013-2014 Mnemosyne LLC
|
|
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2013-01-19 08:43:26 +00:00
|
|
|
|
#include <errno.h>
|
2013-02-04 21:45:20 +00:00
|
|
|
|
#include <stdio.h> /* fopen() */
|
2013-01-19 08:43:26 +00:00
|
|
|
|
#include <string.h> /* strcmp() */
|
|
|
|
|
|
|
|
|
|
#include "transmission.h"
|
2014-12-04 19:58:34 +00:00
|
|
|
|
#include "crypto-utils.h"
|
2014-07-08 00:08:43 +00:00
|
|
|
|
#include "file.h"
|
2013-01-19 08:43:26 +00:00
|
|
|
|
#include "resume.h"
|
|
|
|
|
#include "torrent.h" /* tr_isTorrent() */
|
2017-06-08 07:24:12 +00:00
|
|
|
|
#include "tr-assert.h"
|
2013-01-19 08:43:26 +00:00
|
|
|
|
#include "variant.h"
|
|
|
|
|
|
|
|
|
|
#include "libtransmission-test.h"
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
static tr_session* session = NULL;
|
2013-02-01 05:57:47 +00:00
|
|
|
|
|
2013-01-19 08:43:26 +00:00
|
|
|
|
#define check_have_none(tor, totalSize) \
|
2017-04-19 12:04:45 +00:00
|
|
|
|
do \
|
|
|
|
|
{ \
|
2017-04-20 16:02:19 +00:00
|
|
|
|
tr_stat const* tst = tr_torrentStat(tor); \
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(tst->activity, ==, TR_STATUS_STOPPED); \
|
|
|
|
|
check_int(tst->error, ==, TR_STAT_OK); \
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(tst->sizeWhenDone, ==, totalSize); \
|
|
|
|
|
check_uint(tst->leftUntilDone, ==, totalSize); \
|
|
|
|
|
check_uint(tor->info.totalSize, ==, totalSize); \
|
|
|
|
|
check_uint(tst->haveValid, ==, 0); \
|
2017-04-19 12:04:45 +00:00
|
|
|
|
} \
|
|
|
|
|
while (0)
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static bool testFileExistsAndConsistsOfThisString(tr_torrent const* tor, tr_file_index_t fileIndex, char const* str)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
char* path;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
size_t const str_len = strlen(str);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
bool success = false;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
path = tr_torrentFindFile(tor, fileIndex);
|
|
|
|
|
|
|
|
|
|
if (path != NULL)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-06-08 07:24:12 +00:00
|
|
|
|
TR_ASSERT(tr_sys_path_exists(path, NULL));
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-06-13 02:24:09 +00:00
|
|
|
|
size_t contents_len;
|
|
|
|
|
uint8_t* contents = tr_loadFile(path, &contents_len, NULL);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
success = contents != NULL && str_len == contents_len && memcmp(contents, str, contents_len) == 0;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_free(contents);
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
return success;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static void onRenameDone(tr_torrent* tor UNUSED, char const* oldpath UNUSED, char const* newname UNUSED, int error,
|
2017-04-19 12:04:45 +00:00
|
|
|
|
void* user_data)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
*(int*)user_data = error;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static int torrentRenameAndWait(tr_torrent* tor, char const* oldpath, char const* newname)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
int error = -1;
|
|
|
|
|
tr_torrentRenamePath(tor, oldpath, newname, onRenameDone, &error);
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
tr_wait_msec(10);
|
|
|
|
|
}
|
|
|
|
|
while (error == -1);
|
|
|
|
|
|
|
|
|
|
return error;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
static void torrentRemoveAndWait(tr_torrent* tor, int expected_torrent_count)
|
2016-12-25 16:44:38 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_torrentRemove(tor, false, NULL);
|
2016-12-25 16:44:38 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
while (tr_sessionCountTorrents(session) != expected_torrent_count)
|
|
|
|
|
{
|
|
|
|
|
tr_wait_msec(10);
|
|
|
|
|
}
|
2016-12-25 16:44:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 08:43:26 +00:00
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static void create_single_file_torrent_contents(char const* top)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
char* path = tr_buildPath(top, "hello-world.txt", NULL);
|
|
|
|
|
libtest_create_file_with_string_contents(path, "hello, world!\n");
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static tr_torrent* create_torrent_from_base64_metainfo(tr_ctor* ctor, char const* metainfo_base64)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
int err;
|
|
|
|
|
size_t metainfo_len;
|
|
|
|
|
char* metainfo;
|
|
|
|
|
tr_torrent* tor;
|
|
|
|
|
|
|
|
|
|
/* create the torrent ctor */
|
|
|
|
|
metainfo = tr_base64_decode_str(metainfo_base64, &metainfo_len);
|
2017-06-08 07:24:12 +00:00
|
|
|
|
TR_ASSERT(metainfo != NULL);
|
|
|
|
|
TR_ASSERT(metainfo_len > 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_ctorSetMetainfo(ctor, (uint8_t*)metainfo, metainfo_len);
|
|
|
|
|
tr_ctorSetPaused(ctor, TR_FORCE, true);
|
|
|
|
|
|
|
|
|
|
/* create the torrent */
|
|
|
|
|
err = 0;
|
|
|
|
|
tor = tr_torrentNew(ctor, &err, NULL);
|
2017-06-08 07:24:12 +00:00
|
|
|
|
TR_ASSERT(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
|
tr_free(metainfo);
|
|
|
|
|
return tor;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
static int test_single_filename_torrent(void)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
uint64_t loaded;
|
|
|
|
|
tr_torrent* tor;
|
|
|
|
|
char* tmpstr;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
size_t const totalSize = 14;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_ctor* ctor;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
tr_stat const* st;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* this is a single-file torrent whose file is hello-world.txt, holding the string "hello, world!" */
|
|
|
|
|
ctor = tr_ctorNew(session);
|
|
|
|
|
tor = create_torrent_from_base64_metainfo(ctor,
|
|
|
|
|
"ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0"
|
|
|
|
|
"ZWkxMzU4NTQ5MDk4ZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDY6bGVuZ3RoaTE0ZTQ6bmFtZTE1"
|
|
|
|
|
"OmhlbGxvLXdvcmxkLnR4dDEyOnBpZWNlIGxlbmd0aGkzMjc2OGU2OnBpZWNlczIwOukboJcrkFUY"
|
|
|
|
|
"f6LvqLXBVvSHqCk6Nzpwcml2YXRlaTBlZWU=");
|
|
|
|
|
check(tr_isTorrent(tor));
|
|
|
|
|
|
|
|
|
|
/* sanity check the info */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(tor->info.fileCount, ==, 1);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.files[0].name, ==, "hello-world.txt");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(!tor->info.files[0].is_renamed);
|
|
|
|
|
|
|
|
|
|
/* sanity check the (empty) stats */
|
|
|
|
|
libttest_blockingTorrentVerify(tor);
|
|
|
|
|
check_have_none(tor, totalSize);
|
|
|
|
|
|
|
|
|
|
create_single_file_torrent_contents(tor->currentDir);
|
|
|
|
|
|
|
|
|
|
/* sanity check the stats again, now that we've added the file */
|
|
|
|
|
libttest_blockingTorrentVerify(tor);
|
|
|
|
|
st = tr_torrentStat(tor);
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(st->activity, ==, TR_STATUS_STOPPED);
|
|
|
|
|
check_int(st->error, ==, TR_STAT_OK);
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(st->leftUntilDone, ==, 0);
|
|
|
|
|
check_uint(st->haveUnchecked, ==, 0);
|
|
|
|
|
check_uint(st->desiredAvailable, ==, 0);
|
|
|
|
|
check_uint(st->sizeWhenDone, ==, totalSize);
|
|
|
|
|
check_uint(st->haveValid, ==, totalSize);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*** okay! we've finally put together all the scaffolding to test
|
|
|
|
|
*** renaming a single-file torrent
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
/* confirm that bad inputs get caught */
|
|
|
|
|
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", NULL), ==, EINVAL);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", ""), ==, EINVAL);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", "."), ==, EINVAL);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", ".."), ==, EINVAL);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", "hello-world.txt"), ==, 0);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "hello-world.txt", "hello/world.txt"), ==, EINVAL);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
check(!tor->info.files[0].is_renamed);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.files[0].name, ==, "hello-world.txt");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
**** Now try a rename that should succeed
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
tmpstr = tr_buildPath(tor->currentDir, "hello-world.txt", NULL);
|
|
|
|
|
check(tr_sys_path_exists(tmpstr, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tr_torrentName(tor), ==, "hello-world.txt");
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, tor->info.name, "foobar"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(!tr_sys_path_exists(tmpstr, NULL)); /* confirm the old filename can't be found */
|
|
|
|
|
tr_free(tmpstr);
|
|
|
|
|
check(tor->info.files[0].is_renamed); /* confirm the file's 'renamed' flag is set */
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tr_torrentName(tor), ==, "foobar"); /* confirm the torrent's name is now 'foobar' */
|
|
|
|
|
check_str(tor->info.files[0].name, ==, "foobar"); /* confirm the file's name is now 'foobar' in our struct */
|
2017-05-30 17:56:12 +00:00
|
|
|
|
check_str(strstr(tor->info.torrent, "foobar"), ==, NULL); /* confirm the name in the .torrent file hasn't changed */
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tmpstr = tr_buildPath(tor->currentDir, "foobar", NULL);
|
|
|
|
|
check(tr_sys_path_exists(tmpstr, NULL)); /* confirm the file's name is now 'foobar' on the disk */
|
|
|
|
|
tr_free(tmpstr);
|
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n")); /* confirm the contents are right */
|
|
|
|
|
|
|
|
|
|
/* (while it's renamed: confirm that the .resume file remembers the changes) */
|
|
|
|
|
tr_torrentSaveResume(tor);
|
|
|
|
|
libttest_sync();
|
2017-07-26 18:20:30 +00:00
|
|
|
|
loaded = tr_torrentLoadResume(tor, ~0, ctor, NULL);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tr_torrentName(tor), ==, "foobar");
|
2017-05-30 17:56:12 +00:00
|
|
|
|
check_uint((loaded & TR_FR_NAME), !=, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
**** ...and rename it back again
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
tmpstr = tr_buildPath(tor->currentDir, "foobar", NULL);
|
|
|
|
|
check(tr_sys_path_exists(tmpstr, NULL));
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "foobar", "hello-world.txt"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(!tr_sys_path_exists(tmpstr, NULL));
|
|
|
|
|
check(tor->info.files[0].is_renamed);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.files[0].name, ==, "hello-world.txt");
|
|
|
|
|
check_str(tr_torrentName(tor), ==, "hello-world.txt");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_free(tmpstr);
|
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n"));
|
|
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
|
tr_ctorFree(ctor);
|
|
|
|
|
torrentRemoveAndWait(tor, 0);
|
|
|
|
|
return 0;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
****
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static void create_multifile_torrent_contents(char const* top)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
char* path;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
path = tr_buildPath(top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester", NULL);
|
|
|
|
|
libtest_create_file_with_string_contents(path, "It ain't easy bein' cheesy.\n");
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
path = tr_buildPath(top, "Felidae", "Pantherinae", "Panthera", "Tiger", "Tony", NULL);
|
|
|
|
|
libtest_create_file_with_string_contents(path, "They’re Grrrrreat!\n");
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
path = tr_buildPath(top, "Felidae", "Felinae", "Felis", "catus", "Kyphi", NULL);
|
|
|
|
|
libtest_create_file_with_string_contents(path, "Inquisitive\n");
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
path = tr_buildPath(top, "Felidae", "Felinae", "Felis", "catus", "Saffron", NULL);
|
|
|
|
|
libtest_create_file_with_string_contents(path, "Tough\n");
|
|
|
|
|
tr_free(path);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
libttest_sync();
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
static int test_multifile_torrent(void)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
uint64_t loaded;
|
|
|
|
|
tr_torrent* tor;
|
|
|
|
|
tr_ctor* ctor;
|
|
|
|
|
char* str;
|
|
|
|
|
char* tmp;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
static size_t const totalSize = 67;
|
|
|
|
|
tr_stat const* st;
|
|
|
|
|
tr_file const* files;
|
|
|
|
|
char const* strings[4];
|
|
|
|
|
char const* expected_files[4] =
|
2017-04-19 12:04:45 +00:00
|
|
|
|
{
|
|
|
|
|
"Felidae/Felinae/Acinonyx/Cheetah/Chester",
|
|
|
|
|
"Felidae/Felinae/Felis/catus/Kyphi",
|
|
|
|
|
"Felidae/Felinae/Felis/catus/Saffron",
|
|
|
|
|
"Felidae/Pantherinae/Panthera/Tiger/Tony"
|
|
|
|
|
};
|
2017-04-20 16:02:19 +00:00
|
|
|
|
char const* expected_contents[4] =
|
2017-04-19 12:04:45 +00:00
|
|
|
|
{
|
|
|
|
|
"It ain't easy bein' cheesy.\n",
|
|
|
|
|
"Inquisitive\n",
|
|
|
|
|
"Tough\n",
|
|
|
|
|
"They’re Grrrrreat!\n"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ctor = tr_ctorNew(session);
|
|
|
|
|
tor = create_torrent_from_base64_metainfo(ctor,
|
|
|
|
|
"ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0"
|
|
|
|
|
"ZWkxMzU4NTU1NDIwZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDU6ZmlsZXNsZDY6bGVuZ3RoaTI4"
|
|
|
|
|
"ZTQ6cGF0aGw3OkZlbGluYWU4OkFjaW5vbnl4NzpDaGVldGFoNzpDaGVzdGVyZWVkNjpsZW5ndGhp"
|
|
|
|
|
"MTJlNDpwYXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNTpLeXBoaWVlZDY6bGVuZ3RoaTZlNDpw"
|
|
|
|
|
"YXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNzpTYWZmcm9uZWVkNjpsZW5ndGhpMjFlNDpwYXRo"
|
|
|
|
|
"bDExOlBhbnRoZXJpbmFlODpQYW50aGVyYTU6VGlnZXI0OlRvbnllZWU0Om5hbWU3OkZlbGlkYWUx"
|
|
|
|
|
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
|
|
|
|
"dmF0ZWkwZWVl");
|
|
|
|
|
check(tr_isTorrent(tor));
|
|
|
|
|
files = tor->info.files;
|
|
|
|
|
|
|
|
|
|
/* sanity check the info */
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.name, ==, "Felidae");
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(tor->info.totalSize, ==, totalSize);
|
|
|
|
|
check_uint(tor->info.fileCount, ==, 4);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 4; ++i)
|
2017-04-19 12:04:45 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[i].name, ==, expected_files[i]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* sanity check the (empty) stats */
|
|
|
|
|
libttest_blockingTorrentVerify(tor);
|
|
|
|
|
check_have_none(tor, totalSize);
|
|
|
|
|
|
|
|
|
|
/* build the local data */
|
|
|
|
|
create_multifile_torrent_contents(tor->currentDir);
|
|
|
|
|
|
|
|
|
|
/* sanity check the (full) stats */
|
|
|
|
|
libttest_blockingTorrentVerify(tor);
|
|
|
|
|
st = tr_torrentStat(tor);
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(st->activity, ==, TR_STATUS_STOPPED);
|
|
|
|
|
check_int(st->error, ==, TR_STAT_OK);
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(st->leftUntilDone, ==, 0);
|
|
|
|
|
check_uint(st->haveUnchecked, ==, 0);
|
|
|
|
|
check_uint(st->desiredAvailable, ==, 0);
|
|
|
|
|
check_uint(st->sizeWhenDone, ==, totalSize);
|
|
|
|
|
check_uint(st->haveValid, ==, totalSize);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*** okay! let's test renaming.
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
/* rename a leaf... */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/catus/Kyphi", "placeholder"), ==, 0);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[1].name, ==, "Felidae/Felinae/Felis/catus/placeholder");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, 1, "Inquisitive\n"));
|
|
|
|
|
|
|
|
|
|
/* ...and back again */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/catus/placeholder", "Kyphi"), ==, 0);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[1].name, ==, "Felidae/Felinae/Felis/catus/Kyphi");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
testFileExistsAndConsistsOfThisString(tor, 1, "Inquisitive\n");
|
|
|
|
|
|
|
|
|
|
/* rename a branch... */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/catus", "placeholder"), ==, 0);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[0].name, ==, expected_files[0]);
|
|
|
|
|
check_str(files[1].name, ==, "Felidae/Felinae/Felis/placeholder/Kyphi");
|
|
|
|
|
check_str(files[2].name, ==, "Felidae/Felinae/Felis/placeholder/Saffron");
|
|
|
|
|
check_str(files[3].name, ==, expected_files[3]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, 1, expected_contents[1]));
|
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, 2, expected_contents[2]));
|
2017-04-30 16:25:26 +00:00
|
|
|
|
check(!files[0].is_renamed);
|
|
|
|
|
check(files[1].is_renamed);
|
|
|
|
|
check(files[2].is_renamed);
|
|
|
|
|
check(!files[3].is_renamed);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* (while the branch is renamed: confirm that the .resume file remembers the changes) */
|
|
|
|
|
tr_torrentSaveResume(tor);
|
|
|
|
|
/* this is a bit dodgy code-wise, but let's make sure the .resume file got the name */
|
|
|
|
|
tr_free(files[1].name);
|
|
|
|
|
tor->info.files[1].name = tr_strdup("gabba gabba hey");
|
2017-07-26 18:20:30 +00:00
|
|
|
|
loaded = tr_torrentLoadResume(tor, ~0, ctor, NULL);
|
2017-05-30 17:56:12 +00:00
|
|
|
|
check_uint((loaded & TR_FR_FILENAMES), !=, 0);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[0].name, ==, expected_files[0]);
|
|
|
|
|
check_str(files[1].name, ==, "Felidae/Felinae/Felis/placeholder/Kyphi");
|
|
|
|
|
check_str(files[2].name, ==, "Felidae/Felinae/Felis/placeholder/Saffron");
|
|
|
|
|
check_str(files[3].name, ==, expected_files[3]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* ...and back again */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/placeholder", "catus"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 4; ++i)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[i].name, ==, expected_files[i]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
check(testFileExistsAndConsistsOfThisString(tor, i, expected_contents[i]));
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
|
check(!files[0].is_renamed);
|
|
|
|
|
check(files[1].is_renamed);
|
|
|
|
|
check(files[2].is_renamed);
|
|
|
|
|
check(!files[3].is_renamed);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
**** Test it an incomplete torrent...
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
/* remove the directory Felidae/Felinae/Felis/catus */
|
|
|
|
|
str = tr_torrentFindFile(tor, 1);
|
2017-05-30 17:56:12 +00:00
|
|
|
|
check_str(str, !=, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_sys_path_remove(str, NULL);
|
|
|
|
|
tr_free(str);
|
|
|
|
|
str = tr_torrentFindFile(tor, 2);
|
2017-05-30 17:56:12 +00:00
|
|
|
|
check_str(str, !=, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_sys_path_remove(str, NULL);
|
|
|
|
|
tmp = tr_sys_path_dirname(str, NULL);
|
|
|
|
|
tr_sys_path_remove(tmp, NULL);
|
|
|
|
|
tr_free(tmp);
|
|
|
|
|
tr_free(str);
|
|
|
|
|
libttest_sync();
|
|
|
|
|
libttest_blockingTorrentVerify(tor);
|
|
|
|
|
testFileExistsAndConsistsOfThisString(tor, 0, expected_contents[0]);
|
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 1; i <= 2; ++i)
|
2017-04-19 12:04:45 +00:00
|
|
|
|
{
|
|
|
|
|
str = tr_torrentFindFile(tor, i);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(str, ==, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_free(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
testFileExistsAndConsistsOfThisString(tor, 3, expected_contents[3]);
|
|
|
|
|
|
|
|
|
|
/* rename a branch... */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/catus", "foo"), ==, 0);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[0].name, ==, expected_files[0]);
|
|
|
|
|
check_str(files[1].name, ==, "Felidae/Felinae/Felis/foo/Kyphi");
|
|
|
|
|
check_str(files[2].name, ==, "Felidae/Felinae/Felis/foo/Saffron");
|
|
|
|
|
check_str(files[3].name, ==, expected_files[3]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* ...and back again */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Felinae/Felis/foo", "catus"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 4; ++i)
|
2013-01-31 18:20:37 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[i].name, ==, expected_files[i]);
|
2013-01-31 18:20:37 +00:00
|
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae", "gabba"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
strings[0] = "gabba/Felinae/Acinonyx/Cheetah/Chester";
|
|
|
|
|
strings[1] = "gabba/Felinae/Felis/catus/Kyphi";
|
|
|
|
|
strings[2] = "gabba/Felinae/Felis/catus/Saffron";
|
|
|
|
|
strings[3] = "gabba/Pantherinae/Panthera/Tiger/Tony";
|
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 4; ++i)
|
2013-01-22 05:40:10 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[i].name, ==, strings[i]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
testFileExistsAndConsistsOfThisString(tor, i, expected_contents[i]);
|
2013-01-22 05:40:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
/* rename the root, then a branch, and then a leaf... */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "gabba", "Felidae"), ==, 0);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Pantherinae/Panthera/Tiger", "Snow Leopard"), ==, 0);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/Pantherinae/Panthera/Snow Leopard/Tony", "10.6"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
strings[0] = "Felidae/Felinae/Acinonyx/Cheetah/Chester";
|
|
|
|
|
strings[1] = "Felidae/Felinae/Felis/catus/Kyphi";
|
|
|
|
|
strings[2] = "Felidae/Felinae/Felis/catus/Saffron";
|
|
|
|
|
strings[3] = "Felidae/Pantherinae/Panthera/Snow Leopard/10.6";
|
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 4; ++i)
|
2013-01-22 05:40:10 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(files[i].name, ==, strings[i]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
testFileExistsAndConsistsOfThisString(tor, i, expected_contents[i]);
|
2013-01-22 05:40:10 +00:00
|
|
|
|
}
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_ctorFree(ctor);
|
|
|
|
|
torrentRemoveAndWait(tor, 0);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*** Test renaming prefixes (shouldn't work)
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
ctor = tr_ctorNew(session);
|
|
|
|
|
tor = create_torrent_from_base64_metainfo(ctor,
|
|
|
|
|
"ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0"
|
|
|
|
|
"ZWkxMzU4NTU1NDIwZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDU6ZmlsZXNsZDY6bGVuZ3RoaTI4"
|
|
|
|
|
"ZTQ6cGF0aGw3OkZlbGluYWU4OkFjaW5vbnl4NzpDaGVldGFoNzpDaGVzdGVyZWVkNjpsZW5ndGhp"
|
|
|
|
|
"MTJlNDpwYXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNTpLeXBoaWVlZDY6bGVuZ3RoaTZlNDpw"
|
|
|
|
|
"YXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNzpTYWZmcm9uZWVkNjpsZW5ndGhpMjFlNDpwYXRo"
|
|
|
|
|
"bDExOlBhbnRoZXJpbmFlODpQYW50aGVyYTU6VGlnZXI0OlRvbnllZWU0Om5hbWU3OkZlbGlkYWUx"
|
|
|
|
|
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
|
|
|
|
"dmF0ZWkwZWVl");
|
|
|
|
|
check(tr_isTorrent(tor));
|
|
|
|
|
files = tor->info.files;
|
|
|
|
|
|
|
|
|
|
/* rename prefix of top */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Feli", "FelidaeX"), ==, EINVAL);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.name, ==, "Felidae");
|
2017-04-30 16:25:26 +00:00
|
|
|
|
check(!files[0].is_renamed);
|
|
|
|
|
check(!files[1].is_renamed);
|
|
|
|
|
check(!files[2].is_renamed);
|
|
|
|
|
check(!files[3].is_renamed);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/* rename false path */
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "Felidae/FelinaeX", "Genus Felinae"), ==, EINVAL);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.name, ==, "Felidae");
|
2017-04-30 16:25:26 +00:00
|
|
|
|
check(!files[0].is_renamed);
|
|
|
|
|
check(!files[1].is_renamed);
|
|
|
|
|
check(!files[2].is_renamed);
|
|
|
|
|
check(!files[3].is_renamed);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
|
tr_ctorFree(ctor);
|
|
|
|
|
torrentRemoveAndWait(tor, 0);
|
|
|
|
|
return 0;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
static int test_partial_file(void)
|
2013-01-23 20:23:37 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_torrent* tor;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
tr_stat const* st;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_file_stat* fst;
|
2017-04-20 16:02:19 +00:00
|
|
|
|
uint32_t const pieceCount = 33;
|
|
|
|
|
uint32_t const pieceSize = 32768;
|
|
|
|
|
uint32_t const length[] = { 1048576, 4096, 512 };
|
|
|
|
|
uint64_t const totalSize = length[0] + length[1] + length[2];
|
|
|
|
|
char const* strings[3];
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
**** create our test torrent with an incomplete .part file
|
|
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
tor = libttest_zero_torrent_init(session);
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(tor->info.totalSize, ==, totalSize);
|
|
|
|
|
check_uint(tor->info.pieceSize, ==, pieceSize);
|
|
|
|
|
check_uint(tor->info.pieceCount, ==, pieceCount);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.files[0].name, ==, "files-filled-with-zeroes/1048576");
|
|
|
|
|
check_str(tor->info.files[1].name, ==, "files-filled-with-zeroes/4096");
|
|
|
|
|
check_str(tor->info.files[2].name, ==, "files-filled-with-zeroes/512");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
libttest_zero_torrent_populate(tor, false);
|
|
|
|
|
fst = tr_torrentFiles(tor, NULL);
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(fst[0].bytesCompleted, ==, length[0] - pieceSize);
|
|
|
|
|
check_uint(fst[1].bytesCompleted, ==, length[1]);
|
|
|
|
|
check_uint(fst[2].bytesCompleted, ==, length[2]);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_torrentFilesFree(fst, tor->info.fileCount);
|
|
|
|
|
st = tr_torrentStat(tor);
|
2017-05-29 20:39:51 +00:00
|
|
|
|
check_uint(st->sizeWhenDone, ==, totalSize);
|
|
|
|
|
check_uint(st->leftUntilDone, ==, pieceSize);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-05-29 20:22:36 +00:00
|
|
|
|
check_int(torrentRenameAndWait(tor, "files-filled-with-zeroes", "foo"), ==, 0);
|
|
|
|
|
check_int(torrentRenameAndWait(tor, "foo/1048576", "bar"), ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
strings[0] = "foo/bar";
|
|
|
|
|
strings[1] = "foo/4096";
|
|
|
|
|
strings[2] = "foo/512";
|
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 3; ++i)
|
2013-01-23 20:23:37 +00:00
|
|
|
|
{
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(tor->info.files[i].name, ==, strings[i]);
|
2013-01-23 20:23:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
strings[0] = "foo/bar.part";
|
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
|
for (tr_file_index_t i = 0; i < 3; ++i)
|
2013-01-23 20:23:37 +00:00
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
|
char* expected = tr_buildPath(tor->currentDir, strings[i], NULL);
|
|
|
|
|
char* path = tr_torrentFindFile(tor, i);
|
2017-05-29 19:48:02 +00:00
|
|
|
|
check_str(path, ==, expected);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
tr_free(path);
|
|
|
|
|
tr_free(expected);
|
2013-01-23 20:23:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
torrentRemoveAndWait(tor, 0);
|
|
|
|
|
return 0;
|
2013-01-23 20:23:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
****
|
|
|
|
|
***/
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
int main(void)
|
2013-01-19 08:43:26 +00:00
|
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
|
testFunc const tests[] =
|
2017-04-19 12:04:45 +00:00
|
|
|
|
{
|
|
|
|
|
test_single_filename_torrent,
|
|
|
|
|
test_multifile_torrent,
|
|
|
|
|
test_partial_file
|
|
|
|
|
};
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
session = libttest_session_init(NULL);
|
2017-05-29 17:05:24 +00:00
|
|
|
|
|
|
|
|
|
int ret = runTests(tests, NUM_TESTS(tests));
|
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
libttest_session_close(session);
|
2013-01-19 08:43:26 +00:00
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
|
return ret;
|
2013-01-19 08:43:26 +00:00
|
|
|
|
}
|