/* * This file Copyright (C) 2013-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * */ #include "transmission.h" #include "metainfo.h" #include "utils.h" #include "gtest/gtest.h" #include #include #include TEST(Metainfo, magnetLink) { // background info @ http://wiki.theory.org/BitTorrent_Magnet-URI_Webseeding char const constexpr* const MagnetLink = "magnet:?" "xt=urn:btih:14ffe5dd23188fd5cb53a1d47f1289db70abf31e" "&dn=ubuntu_12_04_1_desktop_32_bit" "&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce" "&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80" "&ws=http%3A%2F%2Ftransmissionbt.com"; auto* ctor = tr_ctorNew(nullptr); tr_ctorSetMetainfoFromMagnetLink(ctor, MagnetLink); auto inf = tr_info{}; auto const parse_result = tr_torrentParse(ctor, &inf); EXPECT_EQ(TR_PARSE_OK, parse_result); EXPECT_EQ(0, inf.fileCount); // because it's a magnet link EXPECT_EQ(2, inf.trackerCount); EXPECT_STREQ("http://tracker.publicbt.com/announce", inf.trackers[0].announce); EXPECT_STREQ("udp://tracker.publicbt.com:80", inf.trackers[1].announce); EXPECT_EQ(1, inf.webseedCount); EXPECT_STREQ("http://transmissionbt.com", inf.webseeds[0]); auto* const link = tr_torrentInfoGetMagnetLink(&inf); EXPECT_STREQ(MagnetLink, link); tr_free(link); /* cleanup */ tr_metainfoFree(&inf); tr_ctorFree(ctor); } #define BEFORE_PATH \ "d10:created by25:Transmission/2.82 (14160)13:creation datei1402280218e8:encoding5:UTF-84:infod5:filesld6:lengthi2e4:pathl" #define AFTER_PATH \ "eed6:lengthi2e4:pathl5:b.txteee4:name3:foo12:piece lengthi32768e6:pieces20:ÞÉ`âM‘‹Šs¡Å;˺¬.åÂà7:privatei0eee" // FIXME: split these into parameterized tests? TEST(Metainfo, bucket) { struct LocalTest { int expected_benc_err; int expected_parse_result; void const* benc; }; auto const tests = std::array{ LocalTest{ 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH }, /* allow empty components, but not =all= empty components, see bug #5517 */ { 0, TR_PARSE_OK, BEFORE_PATH "0:5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "0:0:" AFTER_PATH }, /* allow path separators in a filename (replaced with '_') */ { 0, TR_PARSE_OK, BEFORE_PATH "7:a/a.txt" AFTER_PATH }, /* allow "." components (skipped) */ { 0, TR_PARSE_OK, BEFORE_PATH "1:.5:a.txt" AFTER_PATH }, { 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt1:." AFTER_PATH }, /* allow ".." components (replaced with "__") */ { 0, TR_PARSE_OK, BEFORE_PATH "2:..5:a.txt" AFTER_PATH }, { 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt2:.." AFTER_PATH }, /* fail on empty string */ { EILSEQ, TR_PARSE_ERR, "" }, }; tr_logSetLevel(TR_LOG_SILENT); for (auto const& test : tests) { auto* ctor = tr_ctorNew(nullptr); int const err = tr_ctorSetMetainfo(ctor, test.benc, strlen(static_cast(test.benc))); EXPECT_EQ(test.expected_benc_err, err); if (err == 0) { tr_parse_result const parse_result = tr_torrentParse(ctor, nullptr); EXPECT_EQ(test.expected_parse_result, parse_result); } tr_ctorFree(ctor); } } TEST(Metainfo, sanitize) { struct LocalTest { char const* str; size_t len; char const* expected_result; bool expected_is_adjusted; }; auto const tests = std::array{ // skipped LocalTest{ "", 0, nullptr, false }, { ".", 1, nullptr, false }, { "..", 2, nullptr, true }, { ".....", 5, nullptr, false }, { " ", 2, nullptr, false }, { " . ", 3, nullptr, false }, { ". . .", 5, nullptr, false }, // replaced with '_' { "/", 1, "_", true }, { "////", 4, "____", true }, { "\\\\", 2, "__", true }, { "/../", 4, "_.._", true }, { "foo