Files
libtorrent/test/test_store_buffer.cpp

168 lines
3.6 KiB
C++

/*
Copyright (c) 2020-2021, Arvid Norberg
All rights reserved.
You may use, distribute and modify this code under the terms of the BSD license,
see LICENSE file.
*/
#include "test.hpp"
#include "libtorrent/aux_/store_buffer.hpp"
#include "libtorrent/io_context.hpp"
#include "libtorrent/disk_interface.hpp" // for default_block_size
using lt::aux::torrent_location;
using lt::aux::store_buffer;
namespace {
char buf1;
char buf2;
char buf3;
char buf4;
lt::storage_index_t const st0(0);
lt::storage_index_t const st1(1);
lt::piece_index_t const p0(0);
lt::piece_index_t const p1(1);
std::vector<torrent_location> build_locations()
{
std::vector<torrent_location> ret;
for (auto s : {st0, st1})
{
for (auto p : {p0, p1})
{
for (auto o : {0, lt::default_block_size})
{
ret.emplace_back(s, p, o);
}
}
}
return ret;
}
void check(store_buffer const& sb, torrent_location l, char const* expected)
{
bool called = false;
bool const ret = sb.get(l, [&](char const* buf) {
TEST_EQUAL(buf, expected);
called = true;
});
TEST_EQUAL(called, true);
TEST_EQUAL(ret, true);
}
void check_miss(store_buffer const& sb, torrent_location l)
{
int const ret = sb.get(l, [&](char const* b) {
TEST_ERROR(b);
return 1337;
});
TEST_EQUAL(ret, 0);
}
void check2(store_buffer const& sb, torrent_location l0, torrent_location l1
, char const* expected0, char const* expected1)
{
bool called = false;
int const ret = sb.get2(l0, l1, [&](char const* b0, char const* b1) {
TEST_EQUAL(b0, expected0);
TEST_EQUAL(b1, expected1);
called = true;
return 1337;
});
TEST_EQUAL(called, true);
TEST_EQUAL(ret, 1337);
}
void check2_miss(store_buffer const& sb, torrent_location l0, torrent_location l1)
{
int const ret = sb.get2(l0, l1, [&](char const* b0, char const* b1) {
TEST_ERROR(b0);
TEST_ERROR(b1);
return 1337;
});
TEST_EQUAL(ret, 0);
}
}
TORRENT_TEST(store_buffer_unique_keys)
{
auto const locations = build_locations();
lt::io_context ios;
store_buffer sb(ios);
// ensure all locations are independent
for (auto l1 : locations)
{
sb.insert(l1, &buf1);
for (auto l2 : locations)
{
if (l1 == l2)
check(sb, l1, &buf1);
else
check_miss(sb, l2);
}
sb.erase(l1);
}
}
TORRENT_TEST(store_buffer_get)
{
auto const loc = build_locations();
lt::io_context ios;
store_buffer sb(ios);
sb.insert(loc[0], &buf1);
sb.insert(loc[1], &buf2);
sb.insert(loc[2], &buf3);
sb.insert(loc[3], &buf4);
check(sb, loc[0], &buf1);
check(sb, loc[1], &buf2);
check(sb, loc[2], &buf3);
check(sb, loc[3], &buf4);
check_miss(sb, loc[4]);
check_miss(sb, loc[5]);
check_miss(sb, loc[6]);
check_miss(sb, loc[7]);
}
TORRENT_TEST(store_buffer_get2)
{
auto const loc = build_locations();
lt::io_context ios;
store_buffer sb(ios);
sb.insert(loc[0], &buf1);
sb.insert(loc[1], &buf2);
sb.insert(loc[2], &buf3);
sb.insert(loc[3], &buf4);
// left side
check2(sb, loc[0], loc[4], &buf1, nullptr);
check2(sb, loc[1], loc[5], &buf2, nullptr);
check2(sb, loc[2], loc[6], &buf3, nullptr);
check2(sb, loc[3], loc[7], &buf4, nullptr);
// right side
check2(sb, loc[4], loc[0], nullptr, &buf1);
check2(sb, loc[5], loc[1], nullptr, &buf2);
check2(sb, loc[6], loc[2], nullptr, &buf3);
check2(sb, loc[7], loc[3], nullptr, &buf4);
// both sides
check2(sb, loc[3], loc[0], &buf4, &buf1);
check2(sb, loc[2], loc[1], &buf3, &buf2);
check2(sb, loc[1], loc[2], &buf2, &buf3);
check2(sb, loc[0], loc[3], &buf1, &buf4);
// neither side
check2_miss(sb, loc[4], loc[7]);
check2_miss(sb, loc[5], loc[6]);
check2_miss(sb, loc[6], loc[5]);
check2_miss(sb, loc[7], loc[4]);
}