mirror of
https://github.com/transmission/transmission.git
synced 2026-04-18 07:56:33 +01:00
* build: overhaul tr_add_external_auto_library * build: use package-provided CMake config file libevent * build: use package-provided CMake config file miniupnpc * build: update libutp find module * build: make LIBNAME an optional parameter * build: use package-provided CMake config file libdeflate * build: update libb64 find module * build: update libnatpmp find module * build: update libpsl find module * build: support system fast_float library * chore: reformat long brew commands * build: support system fmt library * build: support system rapidjson library * build: support system small library * build: support system library utf8cpp * build: support system library WideInteger * build: support system library gtest * fix: incorrectly labeled test suites * build: remove unused parameters from tr_add_external_auto_library * build: update crc32c cmake script * fix: dht system library * fix: add libutp interface target * code review: move TrGtest.cmake * code review: move tr_get_fmt_version into Findfmt.cmake * code review: use option() for gtest * code review: move find_package(PkgConfig) out of loop * build: delete FindCrc32c.cmake Impossible to parse package version from distributed source files. * code review: Finddht.cmake * build: delete FindFastFloat.cmake Impossible to parse package version from distributed source files. * code review: Findfmt.cmake * code review: Findlibb64.cmake * code review: Findlibdeflate.cmake * code review: Findlibevent.cmake * code review: Findlibnatpmp.cmake * code review: Findlibpsl.cmake * code review: Findlibutp.cmake * code review: Findlibminiupnpc.cmake * code review: FindRapidJSON.cmake * build: delete FindSmall.cmake Impossible to parse package version from distributed source files. * build: only accept cmake config package for utf8cpp Impossible to parse package version from distributed source files. * build: delete FindWideInteger.cmake Impossible to parse package version from distributed source files. * build: add `USE_SYSTEM_DEFAULT` * ci: drop Fedora 40 and adopt Fedora 43 * ci: try to silence system header warnings * ci: use `cmake --install` * Revert "build: only accept cmake config package for utf8cpp" This reverts commit2158d631fd. * build: harden utf8cpp find module * chore: bump wide-integer Pick upbf9398f9daandbcc726a30f* refactor: gtest should be included with angled brackets Now that gtest is built as a system library, it should be included with angled brackets instead of quotes. * code review: fixup libutp variables before `find_package_handle_standard_args` * code review: define `WIDE_INTEGER_HAS_LIMB_TYPE_UINT64` only for targets depending on WideInteger * chore: bump wide-integer Pickup4b2258acacso that wide-integer tests won't run in Transmission project.
187 lines
6.2 KiB
C++
187 lines
6.2 KiB
C++
// This file Copyright (C) 2022 Mnemosyne LLC.
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
// License text can be found in the licenses/ folder.
|
|
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstddef> // size_t
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <libtransmission/transmission.h>
|
|
|
|
#include <libtransmission/file.h>
|
|
#include <libtransmission/torrent-files.h>
|
|
#include "libtransmission/tr-macros.h"
|
|
#include <libtransmission/tr-strbuf.h>
|
|
|
|
#include "test-fixtures.h"
|
|
|
|
using namespace std::literals;
|
|
|
|
class TorrentFilesTest : public ::libtransmission::test::SandboxedTest
|
|
{
|
|
};
|
|
|
|
TEST_F(TorrentFilesTest, add)
|
|
{
|
|
auto constexpr Path = "/hello/world"sv;
|
|
auto constexpr Size = size_t{ 1024 };
|
|
|
|
auto files = tr_torrent_files{};
|
|
EXPECT_EQ(size_t{ 0U }, files.file_count());
|
|
EXPECT_TRUE(std::empty(files));
|
|
|
|
auto const file_index = files.add(Path, Size);
|
|
EXPECT_EQ(tr_file_index_t{ 0U }, file_index);
|
|
EXPECT_EQ(size_t{ 1U }, files.file_count());
|
|
EXPECT_EQ(Size, files.file_size(file_index));
|
|
EXPECT_EQ(Path, files.path(file_index));
|
|
EXPECT_FALSE(std::empty(files));
|
|
}
|
|
|
|
TEST_F(TorrentFilesTest, setPath)
|
|
{
|
|
auto constexpr Path1 = "/hello/world"sv;
|
|
auto constexpr Path2 = "/hello/there"sv;
|
|
auto constexpr Size = size_t{ 2048 };
|
|
|
|
auto files = tr_torrent_files{};
|
|
auto const file_index = files.add(Path1, Size);
|
|
EXPECT_EQ(Path1, files.path(file_index));
|
|
EXPECT_EQ(Size, files.file_size(file_index));
|
|
|
|
files.set_path(file_index, Path2);
|
|
EXPECT_EQ(Path2, files.path(file_index));
|
|
EXPECT_EQ(Size, files.file_size(file_index));
|
|
}
|
|
|
|
TEST_F(TorrentFilesTest, clear)
|
|
{
|
|
auto constexpr Path1 = "/hello/world"sv;
|
|
auto constexpr Path2 = "/hello/there"sv;
|
|
auto constexpr Size = size_t{ 2048 };
|
|
|
|
auto files = tr_torrent_files{};
|
|
files.add(Path1, Size);
|
|
EXPECT_EQ(size_t{ 1U }, files.file_count());
|
|
files.add(Path2, Size);
|
|
EXPECT_EQ(size_t{ 2U }, files.file_count());
|
|
|
|
files.clear();
|
|
EXPECT_TRUE(std::empty(files));
|
|
EXPECT_EQ(size_t{ 0U }, files.file_count());
|
|
}
|
|
|
|
TEST_F(TorrentFilesTest, find)
|
|
{
|
|
static auto constexpr Contents = "hello"sv;
|
|
auto const filename = tr_pathbuf{ sandboxDir(), "/first_dir/hello.txt"sv };
|
|
createFileWithContents(std::string{ filename }, std::data(Contents), std::size(Contents));
|
|
|
|
auto files = tr_torrent_files{};
|
|
auto const file_index = files.add("first_dir/hello.txt", 1024);
|
|
|
|
auto const search_path_1 = tr_pathbuf{ sandboxDir() };
|
|
auto const search_path_2 = tr_pathbuf{ "/tmp"sv };
|
|
|
|
auto search_path = std::vector<std::string_view>{ search_path_1.sv(), search_path_2.sv() };
|
|
auto found = files.find(file_index, std::data(search_path), std::size(search_path));
|
|
EXPECT_TRUE(found.has_value());
|
|
assert(found.has_value());
|
|
EXPECT_EQ(filename, found->filename());
|
|
|
|
// same search, but with the search paths reversed
|
|
search_path = std::vector<std::string_view>{ search_path_2.sv(), search_path_1.sv() };
|
|
found = files.find(file_index, std::data(search_path), std::size(search_path));
|
|
EXPECT_TRUE(found.has_value());
|
|
assert(found.has_value());
|
|
EXPECT_EQ(filename, found->filename());
|
|
|
|
// now make it an incomplete file
|
|
auto const partial_filename = tr_pathbuf{ filename, tr_torrent_files::PartialFileSuffix };
|
|
EXPECT_TRUE(tr_sys_path_rename(filename, partial_filename));
|
|
search_path = std::vector<std::string_view>{ search_path_1.sv(), search_path_2.sv() };
|
|
found = files.find(file_index, std::data(search_path), std::size(search_path));
|
|
EXPECT_TRUE(found.has_value());
|
|
assert(found.has_value());
|
|
EXPECT_EQ(partial_filename, found->filename());
|
|
|
|
// same search, but with the search paths reversed
|
|
search_path = std::vector<std::string_view>{ search_path_2.sv(), search_path_1.sv() };
|
|
found = files.find(file_index, std::data(search_path), std::size(search_path));
|
|
EXPECT_TRUE(found.has_value());
|
|
assert(found.has_value());
|
|
EXPECT_EQ(partial_filename, found->filename());
|
|
|
|
// what about if we look for a file that does not exist
|
|
EXPECT_TRUE(tr_sys_path_remove(partial_filename));
|
|
EXPECT_FALSE(files.find(file_index, std::data(search_path), std::size(search_path)));
|
|
}
|
|
|
|
TEST_F(TorrentFilesTest, hasAnyLocalData)
|
|
{
|
|
static auto constexpr Contents = "hello"sv;
|
|
auto const filename = tr_pathbuf{ sandboxDir(), "/first_dir/hello.txt"sv };
|
|
createFileWithContents(std::string{ filename }, std::data(Contents), std::size(Contents));
|
|
|
|
auto files = tr_torrent_files{};
|
|
files.add("first_dir/hello.txt", 1024);
|
|
|
|
auto const search_path_1 = tr_pathbuf{ sandboxDir() };
|
|
auto const search_path_2 = tr_pathbuf{ "/tmp"sv };
|
|
|
|
auto search_path = std::vector<std::string_view>{ search_path_1.sv(), search_path_2.sv() };
|
|
EXPECT_TRUE(files.has_any_local_data(std::data(search_path), 2U));
|
|
EXPECT_TRUE(files.has_any_local_data(std::data(search_path), 1U));
|
|
EXPECT_FALSE(files.has_any_local_data(std::data(search_path) + 1, 1U));
|
|
EXPECT_FALSE(files.has_any_local_data(std::data(search_path), 0U));
|
|
}
|
|
|
|
TEST_F(TorrentFilesTest, isSubpathPortable)
|
|
{
|
|
static auto constexpr NotWin32 = TR_IF_WIN32(false, true);
|
|
|
|
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 18>{ {
|
|
// never portable
|
|
{ ".", false },
|
|
{ "..", false },
|
|
|
|
// don't end with periods
|
|
{ "foo.", NotWin32 },
|
|
{ "foo..", NotWin32 },
|
|
|
|
// don't begin or end with whitespace
|
|
{ " foo ", NotWin32 },
|
|
{ " foo", NotWin32 },
|
|
{ "foo ", NotWin32 },
|
|
|
|
// reserved names
|
|
{ "COM1", NotWin32 },
|
|
{ "COM1.txt", NotWin32 },
|
|
{ "Com1", NotWin32 },
|
|
{ "com1", NotWin32 },
|
|
|
|
// reserved characters
|
|
{ "hell:o.txt", NotWin32 },
|
|
{ "hell\to.txt", NotWin32 },
|
|
|
|
// everything else
|
|
{ ".foo", true },
|
|
{ "com99.txt", true },
|
|
{ "foo", true },
|
|
{ "hello.txt", true },
|
|
{ "hello#.txt", true },
|
|
} };
|
|
|
|
for (auto const& [subpath, expected] : Tests)
|
|
{
|
|
EXPECT_EQ(expected, tr_torrent_files::is_subpath_sanitized(subpath)) << " subpath " << subpath;
|
|
}
|
|
}
|