refactor: tr_block_info (#2908)

This commit is contained in:
Charles Kerr
2022-04-13 20:22:59 -05:00
committed by GitHub
parent 4a65956cc9
commit 9f9f60f1e3
13 changed files with 177 additions and 260 deletions

View File

@@ -3,45 +3,72 @@
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <event2/util.h>
#include "transmission.h"
#include "block-info.h"
#include "tr-assert.h"
void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in)
void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in) noexcept
{
total_size = total_size_in;
piece_size = piece_size_in;
TR_ASSERT(piece_size == 0 || piece_size >= BlockSize);
if (piece_size == 0)
TR_ASSERT(piece_size_in == 0 || piece_size_in >= BlockSize);
if (piece_size_in == 0)
{
*this = {};
return;
}
n_pieces = (total_size + piece_size - 1) / piece_size;
total_size_ = total_size_in;
piece_size_ = piece_size_in;
n_pieces_ = (total_size_ + piece_size_ - 1) / piece_size_;
n_blocks_ = (total_size_ + BlockSize - 1) / BlockSize;
auto remainder = total_size % piece_size;
final_piece_size = remainder != 0U ? remainder : piece_size;
auto remainder = total_size_ % piece_size_;
final_piece_size_ = remainder != 0U ? remainder : piece_size_;
remainder = total_size % BlockSize;
final_block_size = remainder != 0U ? remainder : BlockSize;
n_blocks = (total_size + BlockSize - 1) / BlockSize;
#ifdef TR_ENABLE_ASSERTS
uint64_t t = n_pieces - 1;
t *= piece_size;
t += final_piece_size;
TR_ASSERT(t == total_size);
t = n_blocks - 1;
t *= BlockSize;
t += final_block_size;
TR_ASSERT(t == total_size);
#endif
remainder = total_size_ % BlockSize;
final_block_size_ = remainder != 0U ? remainder : BlockSize;
}
tr_block_info::Location tr_block_info::byteLoc(uint64_t byte_idx) const noexcept
{
TR_ASSERT(byte_idx <= totalSize());
if (!isInitialized())
{
return {};
}
auto loc = Location{};
loc.byte = byte_idx;
if (byte_idx == totalSize()) // handle 0-byte files at the end of a torrent
{
loc.block = blockCount() - 1;
loc.piece = pieceCount() - 1;
}
else
{
loc.block = byte_idx / BlockSize;
loc.piece = byte_idx / pieceSize();
}
loc.block_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.block } * BlockSize));
loc.piece_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.piece } * pieceSize()));
return loc;
}
tr_block_info::Location tr_block_info::blockLoc(tr_block_index_t block) const noexcept
{
TR_ASSERT(block < blockCount());
return byteLoc(uint64_t{ block } * BlockSize);
}
tr_block_info::Location tr_block_info::pieceLoc(tr_piece_index_t piece, uint32_t offset, uint32_t length) const noexcept
{
TR_ASSERT(piece < pieceCount());
return byteLoc(uint64_t{ piece } * pieceSize() + offset + length);
}

View File

@@ -9,56 +9,60 @@
#include "transmission.h"
#include "tr-assert.h"
struct tr_block_info
{
private:
uint64_t total_size_ = 0;
uint64_t piece_size_ = 0;
uint64_t n_pieces_ = 0;
tr_block_index_t n_blocks_ = 0;
uint32_t final_block_size_ = 0;
uint32_t final_piece_size_ = 0;
public:
static auto constexpr BlockSize = uint32_t{ 1024 * 16 };
uint64_t total_size = 0;
uint64_t piece_size = 0;
uint64_t n_pieces = 0;
tr_block_info() noexcept = default;
tr_block_index_t n_blocks = 0;
uint32_t final_block_size = 0;
uint32_t final_piece_size = 0;
tr_block_info() = default;
tr_block_info(uint64_t total_size_in, uint64_t piece_size_in)
tr_block_info(uint64_t total_size_in, uint64_t piece_size_in) noexcept
{
initSizes(total_size_in, piece_size_in);
}
void initSizes(uint64_t total_size_in, uint64_t piece_size_in);
void initSizes(uint64_t total_size_in, uint64_t piece_size_in) noexcept;
[[nodiscard]] constexpr auto blockCount() const noexcept
{
return n_blocks;
return n_blocks_;
}
// return the number of bytes in `block`
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const noexcept
{
return block + 1 == n_blocks ? final_block_size : BlockSize;
return block + 1 == n_blocks_ ? final_block_size_ : BlockSize;
}
[[nodiscard]] constexpr auto pieceCount() const noexcept
{
return n_pieces;
return n_pieces_;
}
[[nodiscard]] constexpr auto pieceSize() const noexcept
{
return piece_size;
return piece_size_;
}
// return the number of bytes in `piece`
[[nodiscard]] constexpr auto pieceSize(tr_piece_index_t piece) const noexcept
{
return piece + 1 == n_pieces ? final_piece_size : pieceSize();
return piece + 1 == n_pieces_ ? final_piece_size_ : pieceSize();
}
[[nodiscard]] constexpr tr_block_span_t blockSpanForPiece(tr_piece_index_t piece) const
[[nodiscard]] constexpr auto totalSize() const noexcept
{
return total_size_;
}
[[nodiscard]] tr_block_span_t blockSpanForPiece(tr_piece_index_t piece) const noexcept
{
if (!isInitialized())
{
@@ -68,11 +72,6 @@ struct tr_block_info
return { pieceLoc(piece).block, pieceLastLoc(piece).block + 1 };
}
[[nodiscard]] constexpr auto totalSize() const noexcept
{
return total_size;
}
struct Location
{
uint64_t byte = 0;
@@ -95,79 +94,23 @@ struct tr_block_info
};
// Location of the first byte in `block`.
[[nodiscard]] Location constexpr blockLoc(tr_block_index_t block) const
{
TR_ASSERT(block < n_blocks);
return byteLoc(uint64_t{ block } * BlockSize);
}
// Location of the last byte in `block`.
[[nodiscard]] Location constexpr blockLastLoc(tr_block_index_t block) const
{
if (!isInitialized())
{
return {};
}
return byteLoc(uint64_t{ block } * BlockSize + blockSize(block) - 1);
}
[[nodiscard]] Location blockLoc(tr_block_index_t block) const noexcept;
// Location of the first byte (+ optional offset and length) in `piece`
[[nodiscard]] Location constexpr pieceLoc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const
{
TR_ASSERT(piece < n_pieces);
return byteLoc(uint64_t{ piece } * pieceSize() + offset + length);
}
// Location of the last byte in `piece`.
[[nodiscard]] Location constexpr pieceLastLoc(tr_piece_index_t piece) const
{
if (!isInitialized())
{
return {};
}
return byteLoc(uint64_t{ piece } * pieceSize() + pieceSize(piece) - 1);
}
[[nodiscard]] Location pieceLoc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const noexcept;
// Location of the torrent's nth byte
[[nodiscard]] Location constexpr byteLoc(uint64_t byte_idx) const
{
TR_ASSERT(byte_idx <= total_size);
if (!isInitialized())
{
return {};
}
auto loc = Location{};
loc.byte = byte_idx;
if (byte_idx == totalSize()) // handle 0-byte files at the end of a torrent
{
loc.block = blockCount() - 1;
loc.piece = pieceCount() - 1;
}
else
{
loc.block = byte_idx / BlockSize;
loc.piece = byte_idx / pieceSize();
}
loc.block_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.block } * BlockSize));
loc.piece_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.piece } * pieceSize()));
return loc;
}
[[nodiscard]] static uint32_t bestBlockSize(uint64_t piece_size);
[[nodiscard]] Location byteLoc(uint64_t byte_idx) const noexcept;
private:
// Location of the last byte in `piece`.
[[nodiscard]] Location pieceLastLoc(tr_piece_index_t piece) const
{
return byteLoc(static_cast<uint64_t>(piece) * pieceSize() + pieceSize(piece) - 1);
}
[[nodiscard]] bool constexpr isInitialized() const noexcept
{
return piece_size != 0;
return piece_size_ != 0;
}
};

View File

@@ -17,7 +17,7 @@ uint64_t tr_completion::computeHasValid() const
{
uint64_t size = 0;
for (tr_piece_index_t piece = 0, n = block_info_->n_pieces; piece < n; ++piece)
for (tr_piece_index_t piece = 0, n_pieces = block_info_->pieceCount(); piece < n_pieces; ++piece)
{
if (hasPiece(piece))
{
@@ -42,12 +42,12 @@ uint64_t tr_completion::computeSizeWhenDone() const
{
if (hasAll())
{
return block_info_->total_size;
return block_info_->totalSize();
}
// count bytes that we want or that we already have
auto size = uint64_t{ 0 };
for (tr_piece_index_t piece = 0; piece < block_info_->n_pieces; ++piece)
for (tr_piece_index_t piece = 0, n_pieces = block_info_->pieceCount(); piece < n_pieces; ++piece)
{
if (tor_->pieceIsWanted(piece))
{
@@ -122,7 +122,7 @@ tr_completeness tr_completion::status() const
std::vector<uint8_t> tr_completion::createPieceBitfield() const
{
size_t const n = block_info_->n_pieces;
size_t const n = block_info_->pieceCount();
auto pieces = tr_bitfield{ n };
auto flags = std::make_unique<bool[]>(n);
@@ -199,9 +199,9 @@ uint64_t tr_completion::countHasBytesInBlocks(tr_block_span_t span) const
uint64_t n = blocks_.count(begin, end);
n *= tr_block_info::BlockSize;
if (end == block_info_->n_blocks && blocks_.test(end - 1))
if (end == block_info_->blockCount() && blocks_.test(end - 1))
{
n -= tr_block_info::BlockSize - block_info_->final_block_size;
n -= tr_block_info::BlockSize - block_info_->blockSize(end - 1);
}
return n;
@@ -210,8 +210,8 @@ uint64_t tr_completion::countHasBytesInBlocks(tr_block_span_t span) const
uint64_t tr_completion::countHasBytesInSpan(tr_byte_span_t span) const
{
// confirm the span is valid
span.begin = std::clamp(span.begin, uint64_t{ 0 }, block_info_->total_size);
span.end = std::clamp(span.end, uint64_t{ 0 }, block_info_->total_size);
span.begin = std::clamp(span.begin, uint64_t{ 0 }, block_info_->totalSize());
span.end = std::clamp(span.end, uint64_t{ 0 }, block_info_->totalSize());
auto const [begin_byte, end_byte] = span;
if (begin_byte >= end_byte)
{

View File

@@ -35,7 +35,7 @@ struct tr_completion
explicit tr_completion(torrent_view const* tor, tr_block_info const* block_info)
: tor_{ tor }
, block_info_{ block_info }
, blocks_{ block_info_->n_blocks }
, blocks_{ block_info_->blockCount() }
{
blocks_.setHasNone();
}
@@ -67,7 +67,7 @@ struct tr_completion
[[nodiscard]] bool hasPiece(tr_piece_index_t piece) const
{
return block_info_->piece_size != 0 && countMissingBlocksInPiece(piece) == 0;
return block_info_->pieceSize() != 0 && countMissingBlocksInPiece(piece) == 0;
}
[[nodiscard]] constexpr uint64_t hasTotal() const noexcept
@@ -84,7 +84,7 @@ struct tr_completion
[[nodiscard]] constexpr double percentComplete() const
{
auto const denom = block_info_->total_size;
auto const denom = block_info_->totalSize();
return denom ? std::clamp(double(size_now_) / denom, 0.0, 1.0) : 0.0;
}

View File

@@ -30,9 +30,9 @@ public:
void setPath(tr_file_index_t, std::string_view path);
void reserve(size_t);
tr_file_index_t add(std::string_view path, uint64_t size);
void shrinkToFit();
void clear() noexcept;
tr_file_index_t add(std::string_view path, uint64_t size);
struct FoundFile : public tr_sys_path_info
{

View File

@@ -116,7 +116,7 @@ int readOrWriteBytes(
// We didn't find the file that we want to write to.
// Let's figure out where it goes so that we can create it.
auto const base = tor->currentDir();
auto const suffix = tor->session->isIncompleteFileNamingEnabled ? tr_torrent::PartialFileSuffix : ""sv;
auto const suffix = tor->session->isIncompleteFileNamingEnabled ? tr_files::PartialFileSuffix : ""sv;
found = { {}, tr_pathbuf{ base, "/"sv, tor->fileSubpath(file_index), suffix }, std::size(base) };
}

View File

@@ -454,7 +454,7 @@ std::string_view tr_torrent_metainfo::parseImpl(tr_torrent_metainfo& setme, tr_v
// do the size and piece size match up?
setme.block_info_.initSizes(total_size, piece_size);
if (setme.block_info_.n_pieces != std::size(setme.pieces_))
if (setme.block_info_.pieceCount() != std::size(setme.pieces_))
{
return "piece count and file sizes do not match";
}

View File

@@ -86,7 +86,7 @@ public:
{
return blockInfo().blockSize(block);
}
[[nodiscard]] constexpr auto blockSpanForPiece(tr_piece_index_t piece) const
[[nodiscard]] auto blockSpanForPiece(tr_piece_index_t piece) const
{
return blockInfo().blockSpanForPiece(piece);
}

View File

@@ -645,7 +645,7 @@ static bool isNewTorrentASeed(tr_torrent* tor)
}
// it's not a new seed if a file is partial
if (tr_strvEndsWith(found->filename(), tr_torrent::PartialFileSuffix))
if (tr_strvEndsWith(found->filename(), tr_files::PartialFileSuffix))
{
return false;
}
@@ -2253,7 +2253,7 @@ static void deleteLocalData(tr_torrent const* tor, tr_fileFunc func)
if (!tr_sys_path_exists(filename.c_str()))
{
filename += tr_torrent::PartialFileSuffix;
filename += tr_files::PartialFileSuffix;
if (!tr_sys_path_exists(filename.c_str()))
{
@@ -2863,14 +2863,14 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname)
if (!tr_sys_path_exists(src.c_str())) /* check for it as a partial */
{
src += tr_torrent::PartialFileSuffix;
src += tr_files::PartialFileSuffix;
}
if (tr_sys_path_exists(src.c_str()))
{
auto const parent = tr_sys_path_dirname(src);
auto const tgt = tr_strvEndsWith(src, tr_torrent::PartialFileSuffix) ?
tr_pathbuf{ parent, '/', newname, tr_torrent::PartialFileSuffix } :
auto const tgt = tr_strvEndsWith(src, tr_files::PartialFileSuffix) ?
tr_pathbuf{ parent, '/', newname, tr_files::PartialFileSuffix } :
tr_pathbuf{ parent, '/', newname };
auto tmp = errno;

View File

@@ -165,7 +165,7 @@ public:
{
return metainfo_.blockSize(block);
}
[[nodiscard]] constexpr auto blockSpanForPiece(tr_piece_index_t piece) const
[[nodiscard]] auto blockSpanForPiece(tr_piece_index_t piece) const
{
return metainfo_.blockSpanForPiece(piece);
}
@@ -582,8 +582,6 @@ public:
torrent's content than any other mime-type. */
[[nodiscard]] std::string_view primaryMimeType() const;
static constexpr std::string_view PartialFileSuffix = std::string_view{ ".part" };
tr_torrent_metainfo metainfo_;
// TODO(ckerr): make private once some of torrent.cc's `tr_torrentFoo()` methods are member functions

View File

@@ -24,18 +24,18 @@ TEST_F(BlockInfoTest, fieldsAreSet)
uint64_t constexpr TotalSize = PieceSize * PieceCount;
info.initSizes(TotalSize, PieceSize);
EXPECT_EQ(ExpectedBlockSize, info.final_block_size);
EXPECT_EQ(PieceCount, info.n_pieces);
EXPECT_EQ(PieceSize, info.final_piece_size);
EXPECT_EQ(PieceSize, info.piece_size);
EXPECT_EQ(TotalSize, info.total_size);
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.blockCount() - 1));
EXPECT_EQ(PieceCount, info.pieceCount());
EXPECT_EQ(PieceSize, info.pieceSize(info.pieceCount() - 1));
EXPECT_EQ(PieceSize, info.pieceSize());
EXPECT_EQ(TotalSize, info.totalSize());
info.initSizes(0, 0);
EXPECT_EQ(0U, info.final_block_size);
EXPECT_EQ(0U, info.n_pieces);
EXPECT_EQ(0U, info.final_piece_size);
EXPECT_EQ(0U, info.piece_size);
EXPECT_EQ(0U, info.total_size);
EXPECT_EQ(0U, info.blockSize(info.blockCount() - 1));
EXPECT_EQ(0U, info.pieceCount());
EXPECT_EQ(0U, info.pieceSize(info.pieceCount() - 1));
EXPECT_EQ(0U, info.pieceSize());
EXPECT_EQ(0U, info.totalSize());
}
TEST_F(BlockInfoTest, handlesOddSize)
@@ -49,11 +49,11 @@ TEST_F(BlockInfoTest, handlesOddSize)
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
info.initSizes(TotalSize, PieceSize);
EXPECT_EQ(1U, info.final_block_size);
EXPECT_EQ(1U, info.final_piece_size);
EXPECT_EQ(PieceCount, info.n_pieces);
EXPECT_EQ(PieceSize, info.piece_size);
EXPECT_EQ(TotalSize, info.total_size);
EXPECT_EQ(1U, info.blockSize(info.blockCount() - 1));
EXPECT_EQ(1U, info.pieceSize(info.pieceCount() - 1));
EXPECT_EQ(PieceCount, info.pieceCount());
EXPECT_EQ(PieceSize, info.pieceSize());
EXPECT_EQ(TotalSize, info.totalSize());
}
TEST_F(BlockInfoTest, pieceSize)
@@ -67,8 +67,8 @@ TEST_F(BlockInfoTest, pieceSize)
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
info.initSizes(TotalSize, PieceSize);
EXPECT_EQ(PieceSize, info.pieceSize(info.n_pieces - 2));
EXPECT_EQ(1U, info.pieceSize(info.n_pieces - 1));
EXPECT_EQ(PieceSize, info.pieceSize(info.pieceCount() - 2));
EXPECT_EQ(1U, info.pieceSize(info.pieceCount() - 1));
}
TEST_F(BlockInfoTest, blockSize)
@@ -82,8 +82,8 @@ TEST_F(BlockInfoTest, blockSize)
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
info.initSizes(TotalSize, PieceSize);
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.n_blocks - 2));
EXPECT_EQ(1U, info.blockSize(info.n_blocks - 1));
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.blockCount() - 2));
EXPECT_EQ(1U, info.blockSize(info.blockCount() - 1));
}
TEST_F(BlockInfoTest, blockSpanForPiece)
@@ -142,32 +142,6 @@ TEST_F(BlockInfoTest, blockLoc)
EXPECT_EQ(0U, loc.piece_offset);
}
TEST_F(BlockInfoTest, blockLastLoc)
{
auto info = tr_block_info{};
uint64_t constexpr ExpectedBlockSize = 1024 * 16;
uint64_t constexpr ExpectedBlocksPerPiece = 4;
uint64_t constexpr PieceSize = ExpectedBlockSize * ExpectedBlocksPerPiece;
uint64_t constexpr PieceCount = 5;
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
info.initSizes(TotalSize, PieceSize);
auto loc = info.blockLastLoc(0);
EXPECT_EQ(ExpectedBlockSize - 1, loc.byte);
EXPECT_EQ(0U, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
EXPECT_EQ(0U, loc.piece);
EXPECT_EQ(ExpectedBlockSize - 1, loc.piece_offset);
loc = info.blockLastLoc(info.blockCount() - 1);
EXPECT_EQ(info.totalSize() - 1, loc.byte);
EXPECT_EQ(info.blockCount() - 1, loc.block);
EXPECT_EQ(info.totalSize() - 1 - (ExpectedBlockSize * (info.blockCount() - 1)), loc.block_offset);
EXPECT_EQ(info.pieceCount() - 1, loc.piece);
EXPECT_EQ(info.totalSize() - 1 - PieceSize * (PieceCount - 1), loc.piece_offset);
}
TEST_F(BlockInfoTest, pieceLoc)
{
auto info = tr_block_info{};
@@ -216,32 +190,6 @@ TEST_F(BlockInfoTest, pieceLoc)
EXPECT_EQ(1U, loc.piece_offset);
}
TEST_F(BlockInfoTest, pieceLastLoc)
{
auto info = tr_block_info{};
uint64_t constexpr ExpectedBlockSize = 1024 * 16;
uint64_t constexpr ExpectedBlocksPerPiece = 4;
uint64_t constexpr PieceSize = ExpectedBlockSize * ExpectedBlocksPerPiece;
uint64_t constexpr PieceCount = 5;
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
info.initSizes(TotalSize, PieceSize);
auto loc = info.pieceLastLoc(0);
EXPECT_EQ(PieceSize - 1, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece - 1, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
EXPECT_EQ(0U, loc.piece);
EXPECT_EQ(PieceSize - 1, loc.piece_offset);
loc = info.pieceLastLoc(info.pieceCount() - 1);
EXPECT_EQ(info.totalSize() - 1, loc.byte);
EXPECT_EQ(info.blockCount() - 1, loc.block);
EXPECT_EQ(info.totalSize() - 1 - (ExpectedBlockSize * (info.blockCount() - 1)), loc.block_offset);
EXPECT_EQ(info.pieceCount() - 1, loc.piece);
EXPECT_EQ(info.totalSize() - 1 - PieceSize * (PieceCount - 1), loc.piece_offset);
}
TEST_F(BlockInfoTest, byteLoc)
{
auto info = tr_block_info{};

View File

@@ -66,14 +66,14 @@ TEST_F(CompletionTest, setBlocks)
EXPECT_FALSE(completion.hasAll());
EXPECT_EQ(0, completion.hasTotal());
auto bitfield = tr_bitfield{ block_info.n_blocks };
auto bitfield = tr_bitfield{ block_info.blockCount() };
bitfield.setHasAll();
// test that the bitfield did get replaced
completion.setBlocks(bitfield);
EXPECT_TRUE(completion.blocks().hasAll());
EXPECT_TRUE(completion.hasAll());
EXPECT_EQ(block_info.total_size, completion.hasTotal());
EXPECT_EQ(block_info.totalSize(), completion.hasTotal());
}
TEST_F(CompletionTest, hasBlock)
@@ -217,21 +217,21 @@ TEST_F(CompletionTest, hasTotalAndValid)
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
// check that adding the final piece adjusts by block_info.final_piece_size
completion.setHasPiece(block_info.n_pieces - 1, true);
EXPECT_EQ(block_info.final_piece_size, completion.hasTotal());
completion.setHasPiece(block_info.pieceCount() - 1, true);
EXPECT_EQ(block_info.pieceSize(block_info.pieceCount() - 1), completion.hasTotal());
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
// check that adding a non-final piece adjusts by block_info.piece_size
// check that adding a non-final piece adjusts by block_info.pieceSize()
completion.setHasPiece(0, true);
EXPECT_EQ(block_info.final_piece_size + block_info.piece_size, completion.hasTotal());
EXPECT_EQ(block_info.pieceSize(block_info.pieceCount() - 1) + block_info.pieceSize(), completion.hasTotal());
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
// check that removing the final piece adjusts by block_info.final_piece_size
completion.setHasPiece(block_info.n_pieces - 1, false);
EXPECT_EQ(block_info.piece_size, completion.hasValid());
completion.setHasPiece(block_info.pieceCount() - 1, false);
EXPECT_EQ(block_info.pieceSize(), completion.hasValid());
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
// check that removing a non-final piece adjusts by block_info.piece_size
// check that removing a non-final piece adjusts by block_info.pieceSize()
completion.setHasPiece(0, false);
EXPECT_EQ(0, completion.hasValid());
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
@@ -251,41 +251,43 @@ TEST_F(CompletionTest, leftUntilDone)
// check that the initial blank-slate state has nothing
auto completion = tr_completion(&torrent, &block_info);
EXPECT_EQ(block_info.total_size, completion.leftUntilDone());
EXPECT_EQ(block_info.totalSize(), completion.leftUntilDone());
// check that adding the final piece adjusts by block_info.final_piece_size
completion.addPiece(block_info.n_pieces - 1);
EXPECT_EQ(block_info.total_size - block_info.final_piece_size, completion.leftUntilDone());
completion.addPiece(block_info.pieceCount() - 1);
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(block_info.pieceCount() - 1), completion.leftUntilDone());
// check that adding a non-final piece adjusts by block_info.piece_size
// check that adding a non-final piece adjusts by block_info.pieceSize()
completion.addPiece(0);
EXPECT_EQ(block_info.total_size - block_info.final_piece_size - block_info.piece_size, completion.leftUntilDone());
EXPECT_EQ(
block_info.totalSize() - block_info.pieceSize(block_info.pieceCount() - 1) - block_info.pieceSize(),
completion.leftUntilDone());
// check that removing the final piece adjusts by block_info.final_piece_size
completion.removePiece(block_info.n_pieces - 1);
EXPECT_EQ(block_info.total_size - block_info.piece_size, completion.leftUntilDone());
completion.removePiece(block_info.pieceCount() - 1);
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(), completion.leftUntilDone());
// check that dnd-flagging a piece we already have affects nothing
torrent.dnd_pieces.insert(0);
completion.invalidateSizeWhenDone();
EXPECT_EQ(block_info.total_size - block_info.piece_size, completion.leftUntilDone());
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(), completion.leftUntilDone());
torrent.dnd_pieces.clear();
completion.invalidateSizeWhenDone();
// check that dnd-flagging a piece we DON'T already have adjusts by block_info.piece_size
// check that dnd-flagging a piece we DON'T already have adjusts by block_info.pieceSize()
torrent.dnd_pieces.insert(1);
completion.invalidateSizeWhenDone();
EXPECT_EQ(block_info.total_size - block_info.piece_size * 2, completion.leftUntilDone());
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize() * 2, completion.leftUntilDone());
torrent.dnd_pieces.clear();
completion.invalidateSizeWhenDone();
// check that removing a non-final piece adjusts by block_info.piece_size
// check that removing a non-final piece adjusts by block_info.pieceSize()
completion.removePiece(0);
EXPECT_EQ(block_info.total_size, completion.leftUntilDone());
EXPECT_EQ(block_info.totalSize(), completion.leftUntilDone());
// check that adding a block adjusts by block_info.block_size
completion.addBlock(0);
EXPECT_EQ(block_info.total_size - tr_block_info::BlockSize, completion.leftUntilDone());
EXPECT_EQ(block_info.totalSize() - tr_block_info::BlockSize, completion.leftUntilDone());
}
TEST_F(CompletionTest, sizeWhenDone)
@@ -297,13 +299,13 @@ TEST_F(CompletionTest, sizeWhenDone)
// check that adding or removing blocks or pieces does not affect sizeWhenDone
auto completion = tr_completion(&torrent, &block_info);
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
completion.addBlock(0);
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
completion.addPiece(0);
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
completion.removePiece(0);
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
// check that flagging complete pieces as dnd does not affect sizeWhenDone
for (size_t i = 0; i < 32; ++i)
@@ -312,7 +314,7 @@ TEST_F(CompletionTest, sizeWhenDone)
torrent.dnd_pieces.insert(i);
}
completion.invalidateSizeWhenDone();
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
// check that flagging missing pieces as dnd does not affect sizeWhenDone
for (size_t i = 32; i < 48; ++i)
@@ -320,7 +322,7 @@ TEST_F(CompletionTest, sizeWhenDone)
torrent.dnd_pieces.insert(i);
}
completion.invalidateSizeWhenDone();
EXPECT_EQ(block_info.total_size - 16 * block_info.piece_size, completion.sizeWhenDone());
EXPECT_EQ(block_info.totalSize() - 16 * block_info.pieceSize(), completion.sizeWhenDone());
}
TEST_F(CompletionTest, createPieceBitfield)
@@ -335,7 +337,7 @@ TEST_F(CompletionTest, createPieceBitfield)
auto buf = std::array<char, 65>{};
ASSERT_EQ(std::size(buf), block_info.pieceCount());
EXPECT_TRUE(tr_rand_buffer(std::data(buf), std::size(buf)));
for (uint64_t i = 0; i < block_info.n_pieces; ++i)
for (uint64_t i = 0; i < block_info.pieceCount(); ++i)
{
if ((buf[i] % 2) != 0)
{
@@ -346,9 +348,9 @@ TEST_F(CompletionTest, createPieceBitfield)
// serialize it to a raw bitfield, read it back into a bitfield,
// and test that the new bitfield matches
auto const pieces_raw_bitfield = completion.createPieceBitfield();
tr_bitfield pieces{ size_t(block_info.n_pieces) };
tr_bitfield pieces{ size_t(block_info.pieceCount()) };
pieces.setRaw(std::data(pieces_raw_bitfield), std::size(pieces_raw_bitfield));
for (uint64_t i = 0; i < block_info.n_pieces; ++i)
for (uint64_t i = 0; i < block_info.pieceCount(); ++i)
{
EXPECT_EQ(completion.hasPiece(i), pieces.test(i));
}
@@ -372,12 +374,11 @@ TEST_F(CompletionTest, countMissingBytesInPiece)
completion.addPiece(0);
EXPECT_EQ(0U, completion.countMissingBytesInPiece(0));
auto const final_piece = block_info.n_pieces - 1;
auto const final_block = block_info.n_blocks - 1;
auto const final_piece = block_info.pieceCount() - 1;
auto const final_block = block_info.blockCount() - 1;
EXPECT_EQ(block_info.pieceSize(final_piece), completion.countMissingBytesInPiece(final_piece));
completion.addBlock(final_block);
EXPECT_EQ(1U, block_info.final_piece_size);
EXPECT_EQ(1U, block_info.final_block_size);
EXPECT_EQ(1U, block_info.pieceSize(block_info.pieceCount() - 1));
EXPECT_TRUE(completion.hasPiece(final_piece));
EXPECT_EQ(0U, completion.countMissingBytesInPiece(final_piece));
}
@@ -393,7 +394,7 @@ TEST_F(CompletionTest, amountDone)
// make bins s.t. each bin is a single piece
auto bins = std::array<float, TotalSize / PieceSize>{};
for (tr_piece_index_t piece = 0; piece < block_info.n_pieces; ++piece)
for (tr_piece_index_t piece = 0; piece < block_info.pieceCount(); ++piece)
{
completion.removePiece(piece);
}
@@ -412,7 +413,7 @@ TEST_F(CompletionTest, amountDone)
EXPECT_DOUBLE_EQ(0.0, bins[1]);
// all pieces
for (tr_piece_index_t piece = 0; piece < block_info.n_pieces; ++piece)
for (tr_piece_index_t piece = 0; piece < block_info.pieceCount(); ++piece)
{
completion.addPiece(piece);
}
@@ -435,7 +436,7 @@ TEST_F(CompletionTest, countHasBytesInSpan)
auto completion = tr_completion(&torrent, &block_info);
// torrent is complete
auto blocks = tr_bitfield{ block_info.n_blocks };
auto blocks = tr_bitfield{ block_info.blockCount() };
blocks.setHasAll();
completion.setBlocks(blocks);

View File

@@ -50,9 +50,9 @@ protected:
FileSizes[14] + FileSizes[15] + FileSizes[16] ==
TotalSize);
EXPECT_EQ(11, block_info_.n_pieces);
EXPECT_EQ(PieceSize, block_info_.piece_size);
EXPECT_EQ(TotalSize, block_info_.total_size);
EXPECT_EQ(11, block_info_.pieceCount());
EXPECT_EQ(PieceSize, block_info_.pieceSize());
EXPECT_EQ(TotalSize, block_info_.totalSize());
EXPECT_EQ(TotalSize, std::accumulate(std::begin(FileSizes), std::end(FileSizes), uint64_t{ 0 }));
}
};
@@ -123,7 +123,7 @@ TEST_F(FilePieceMapTest, pieceSpan)
offset += FileSizes[file];
}
EXPECT_EQ(TotalSize, offset);
EXPECT_EQ(block_info_.n_pieces, fpm.pieceSpan(std::size(FileSizes) - 1).end);
EXPECT_EQ(block_info_.pieceCount(), fpm.pieceSpan(std::size(FileSizes) - 1).end);
}
TEST_F(FilePieceMapTest, priorities)
@@ -134,14 +134,14 @@ TEST_F(FilePieceMapTest, priorities)
// make a helper to compare file & piece priorities
auto expected_file_priorities = std::vector<tr_priority_t>(n_files, TR_PRI_NORMAL);
auto expected_piece_priorities = std::vector<tr_priority_t>(block_info_.n_pieces, TR_PRI_NORMAL);
auto expected_piece_priorities = std::vector<tr_priority_t>(block_info_.pieceCount(), TR_PRI_NORMAL);
auto const compare_to_expected = [&, this]()
{
for (tr_file_index_t i = 0; i < n_files; ++i)
{
EXPECT_EQ(int(expected_file_priorities[i]), int(file_priorities.filePriority(i)));
}
for (tr_piece_index_t i = 0; i < block_info_.n_pieces; ++i)
for (tr_piece_index_t i = 0; i < block_info_.pieceCount(); ++i)
{
EXPECT_EQ(int(expected_piece_priorities[i]), int(file_priorities.piecePriority(i)));
}
@@ -265,14 +265,14 @@ TEST_F(FilePieceMapTest, wanted)
// make a helper to compare file & piece priorities
auto expected_files_wanted = tr_bitfield(n_files);
auto expected_pieces_wanted = tr_bitfield(block_info_.n_pieces);
auto expected_pieces_wanted = tr_bitfield(block_info_.pieceCount());
auto const compare_to_expected = [&, this]()
{
for (tr_file_index_t i = 0; i < n_files; ++i)
{
EXPECT_EQ(int(expected_files_wanted.test(i)), int(files_wanted.fileWanted(i)));
}
for (tr_piece_index_t i = 0; i < block_info_.n_pieces; ++i)
for (tr_piece_index_t i = 0; i < block_info_.pieceCount(); ++i)
{
EXPECT_EQ(int(expected_pieces_wanted.test(i)), int(files_wanted.pieceWanted(i)));
}