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:
Charles Kerr 2021-11-25 14:30:13 -06:00 committed by GitHub
parent de169c7ec3
commit 3d2fa18c61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 8 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}