test: improve tr_bitfield and tr_block_info coverage (#2226)
* test: improve coverage in tr_bitfield::raw() * test: improve coverage in tr_bitfield::count() * test: improve coverage for edge cases in tr_bitfield::setSpan() * test: confirm that excess bits in setRaw() are set to zero * fix: edge case of tr_block_info::initBlocks() where piece_size is 0 this should not happen in production, but cover it anyway
This commit is contained in:
parent
de169c7ec3
commit
3d2fa18c61
|
@ -359,6 +359,13 @@ void tr_bitfield::set(size_t nth, bool value)
|
|||
/* Sets bit range [begin, end) to 1 */
|
||||
void tr_bitfield::setSpan(size_t begin, size_t end, bool value)
|
||||
{
|
||||
// bounds check
|
||||
end = std::min(end, bit_count_);
|
||||
if (end == 0 || begin >= end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// did anything change?
|
||||
size_t const old_count = count(begin, end);
|
||||
size_t const new_count = value ? (end - begin) : 0;
|
||||
|
@ -367,13 +374,7 @@ void tr_bitfield::setSpan(size_t begin, size_t end, bool value)
|
|||
return;
|
||||
}
|
||||
|
||||
// bounds check
|
||||
--end;
|
||||
if (end >= bit_count_ || begin > end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ensureNthBitAlloced(end))
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -44,6 +44,7 @@ void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in)
|
|||
|
||||
if (piece_size == 0 || block_size == 0)
|
||||
{
|
||||
*this = {};
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "transmission.h"
|
||||
#include "crypto-utils.h"
|
||||
|
@ -15,7 +18,7 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(Bitfield, countRange)
|
||||
TEST(Bitfield, count)
|
||||
{
|
||||
auto constexpr IterCount = int{ 10000 };
|
||||
|
||||
|
@ -59,6 +62,18 @@ TEST(Bitfield, countRange)
|
|||
auto const count2 = bf.count(begin, end);
|
||||
EXPECT_EQ(count1, count2);
|
||||
}
|
||||
|
||||
auto bf = tr_bitfield{ 0 };
|
||||
EXPECT_EQ(0, bf.count(0, 0));
|
||||
EXPECT_EQ(0, bf.count(0, 1));
|
||||
|
||||
bf = tr_bitfield{ 100 };
|
||||
EXPECT_EQ(0, bf.count(0, 0));
|
||||
EXPECT_EQ(0, bf.count(0, 100));
|
||||
bf.setHasAll();
|
||||
EXPECT_EQ(0, bf.count(0, 0));
|
||||
EXPECT_EQ(1, bf.count(0, 1));
|
||||
EXPECT_EQ(100, bf.count(0, 100));
|
||||
}
|
||||
|
||||
TEST(Bitfield, ctorFromFlagArray)
|
||||
|
@ -96,7 +111,7 @@ TEST(Bitfield, setRaw)
|
|||
auto constexpr TestByte = uint8_t{ 10 };
|
||||
auto constexpr TestByteTrueBits = 2;
|
||||
|
||||
auto const raw = std::vector<uint8_t>(100, TestByte);
|
||||
auto raw = std::vector<uint8_t>(100, TestByte);
|
||||
|
||||
auto bf = tr_bitfield(std::size(raw) * 8);
|
||||
bf.setRaw(std::data(raw), std::size(raw));
|
||||
|
@ -115,6 +130,24 @@ TEST(Bitfield, setRaw)
|
|||
}
|
||||
EXPECT_EQ(TestByte, test);
|
||||
EXPECT_EQ(raw, bf.raw());
|
||||
|
||||
// check that has-all bitfield gets all-true
|
||||
bf = tr_bitfield(std::size(raw) * 8);
|
||||
bf.setHasAll();
|
||||
raw = bf.raw();
|
||||
EXPECT_EQ(std::size(bf) / 8, std::size(raw));
|
||||
EXPECT_EQ(std::numeric_limits<unsigned char>::max(), raw[0]);
|
||||
|
||||
// check that the spare bits t the end are zero
|
||||
bf = tr_bitfield{ 1 };
|
||||
uint8_t by = ~uint8_t{};
|
||||
bf.setRaw(&by, 1);
|
||||
EXPECT_TRUE(bf.hasAll());
|
||||
EXPECT_FALSE(bf.hasNone());
|
||||
EXPECT_EQ(1, bf.count());
|
||||
raw = bf.raw();
|
||||
EXPECT_EQ(1, std::size(raw));
|
||||
EXPECT_EQ(1 << 7, raw[0]);
|
||||
}
|
||||
|
||||
TEST(Bitfield, bitfields)
|
||||
|
@ -211,6 +244,32 @@ TEST(Bitfield, bitfields)
|
|||
{
|
||||
EXPECT_EQ(field.test(i), (4 <= i && i < 5));
|
||||
}
|
||||
|
||||
/* test tr_bitfield::setSpan when end runs beyond the end of the bitfield */
|
||||
field.setHasNone();
|
||||
field.setSpan(100, 1000);
|
||||
EXPECT_FALSE(field.hasNone());
|
||||
EXPECT_FALSE(field.hasAll());
|
||||
EXPECT_EQ(std::size(field) - 100, field.count());
|
||||
|
||||
/* test tr_bitfield::unsetSpan when it changes nothing */
|
||||
field.setHasNone();
|
||||
field.unsetSpan(0, 100);
|
||||
EXPECT_TRUE(field.hasNone());
|
||||
EXPECT_FALSE(field.hasAll());
|
||||
EXPECT_EQ(0, field.count());
|
||||
|
||||
/* test tr_bitfield::setSpan when it changes nothing */
|
||||
field.setHasAll();
|
||||
field.setSpan(0, 100);
|
||||
EXPECT_FALSE(field.hasNone());
|
||||
EXPECT_TRUE(field.hasAll());
|
||||
EXPECT_EQ(std::size(field), field.count());
|
||||
|
||||
/* test tr_bitfield::setSpan with an invalid span doesn't crash */
|
||||
field.setHasAll();
|
||||
field.setSpan(0, 0);
|
||||
EXPECT_TRUE(field.hasAll());
|
||||
}
|
||||
|
||||
TEST(Bitfield, hasAllNone)
|
||||
|
|
|
@ -35,6 +35,16 @@ TEST_F(BlockInfoTest, fieldsAreSet)
|
|||
EXPECT_EQ(PieceSize, info.final_piece_size);
|
||||
EXPECT_EQ(PieceSize, info.piece_size);
|
||||
EXPECT_EQ(TotalSize, info.total_size);
|
||||
|
||||
info.initSizes(0, 0);
|
||||
EXPECT_EQ(0, info.block_size);
|
||||
EXPECT_EQ(0, info.final_block_size);
|
||||
EXPECT_EQ(0, info.n_blocks_in_final_piece);
|
||||
EXPECT_EQ(0, info.n_blocks_in_piece);
|
||||
EXPECT_EQ(0, info.n_pieces);
|
||||
EXPECT_EQ(0, info.final_piece_size);
|
||||
EXPECT_EQ(0, info.piece_size);
|
||||
EXPECT_EQ(0, info.total_size);
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, handlesOddSize)
|
||||
|
@ -147,4 +157,9 @@ TEST_F(BlockInfoTest, blockSpanForPiece)
|
|||
EXPECT_EQ(16, info.blockSpanForPiece(3).end);
|
||||
EXPECT_EQ(16, info.blockSpanForPiece(4).begin);
|
||||
EXPECT_EQ(17, info.blockSpanForPiece(4).end);
|
||||
|
||||
// test that uninitialized block_info returns an invalid span
|
||||
info = tr_block_info{};
|
||||
EXPECT_EQ(0, info.blockSpanForPiece(0).begin);
|
||||
EXPECT_EQ(0, info.blockSpanForPiece(0).end);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue