Test suite fixes for recent changes

This commit is contained in:
Jason Rhinelander 2021-06-16 18:58:31 -03:00
parent 3f1e69e79b
commit bcce006013
3 changed files with 244 additions and 157 deletions

View file

@ -7,55 +7,119 @@
#include <string>
using namespace oxen;
using oxen::storage::Item;
TEST_CASE("serialization - basic values", "[serialization]") {
TEST_CASE("v0 serialization - basic values", "[serialization]") {
const auto pub_key =
"054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e"s;
user_pubkey_t pub_key;
REQUIRE(pub_key.load("054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e"s));
const auto data = "data";
const auto hash = "hash";
const std::chrono::system_clock::time_point timestamp{12'345'678ms};
const auto ttl = 3456s;
message_t msg{pub_key, data, hash, timestamp, timestamp + ttl};
std::string msg_serialized;
serialize_message(msg_serialized, Item{msg});
const auto expected_serialized = oxenmq::to_hex(pub_key) +
std::vector<message_t> msgs;
msgs.emplace_back(pub_key, hash, timestamp, timestamp + ttl, data);
auto serialized = serialize_messages(msgs.begin(), msgs.end(), 0);
REQUIRE(serialized.size() == 1);
const auto expected_serialized = oxenmq::to_hex(pub_key.prefixed_hex()) +
"040000000000000068617368" // size+hash
"040000000000000064617461" // size+data
"08000000000000005a47463059513d3d" // size+data (ZGF0YQ== in b64)
"00bc340000000000" // ttl
"4e61bc0000000000" // timestamp
"0000000000000000"s; // nonce
CHECK(oxenmq::to_hex(msg_serialized) == expected_serialized);
const std::vector<Item> inputs{Item{msg}, Item{msg}};
const std::vector<std::string> batches = serialize_messages(inputs);
CHECK(oxenmq::to_hex(serialized.front()) == expected_serialized);
msgs.push_back(msgs.front());
const std::vector<std::string> batches = serialize_messages(msgs.begin(), msgs.end(), 0);
CHECK(batches.size() == 1);
CHECK(oxenmq::to_hex(batches[0]) == expected_serialized + expected_serialized);
const auto messages = deserialize_messages(batches[0]);
CHECK(messages.size() == 2);
for (int i = 0; i < messages.size(); ++i) {
CHECK(messages[i].pub_key == pub_key);
CHECK(messages[i].pubkey == pub_key);
CHECK(messages[i].data == data);
CHECK(messages[i].hash == hash);
CHECK(messages[i].timestamp == timestamp);
CHECK(messages[i].expiration == timestamp + ttl);
CHECK(messages[i].expiry == timestamp + ttl);
}
}
TEST_CASE("serialization - batch serialization", "[serialization]") {
const auto pub_key =
"054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e";
TEST_CASE("v0 serialization - batch serialization", "[serialization]") {
user_pubkey_t pub_key;
REQUIRE(pub_key.load("054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e"s));
std::string data(100000, 'x');
const auto hash = "hash";
const std::chrono::system_clock::time_point timestamp{1'622'576'077s};
const auto ttl = 24h;
message_t msg{pub_key, data, hash, timestamp, timestamp + ttl};
std::string buffer;
serialize_message(buffer, Item{msg});
const size_t num_messages = (SERIALIZATION_BATCH_SIZE / buffer.size()) + 1;
std::vector<Item> inputs(num_messages, Item{msg});
CHECK(serialize_messages(inputs).size() == 1);
inputs.push_back(Item{msg});
CHECK(serialize_messages(inputs).size() == 2);
std::vector<message_t> msgs;
msgs.emplace_back(pub_key, hash, timestamp, timestamp + ttl, data);
auto serialized = serialize_messages(msgs.begin(), msgs.end(), 0);
REQUIRE(serialized.size() == 1);
auto first = serialized.front();
const size_t num_messages = (SERIALIZATION_BATCH_SIZE / serialized.front().size()) + 1;
msgs = {num_messages, msgs.front()};
serialized = serialize_messages(msgs.begin(), msgs.end(), 0);
CHECK(serialized.size() == 1);
msgs.push_back(msgs.front());
serialized = serialize_messages(msgs.begin(), msgs.end(), 0);
CHECK(serialized.size() == 2);
}
TEST_CASE("v1 serialization - basic values", "[serialization]") {
user_pubkey_t pub_key;
REQUIRE(pub_key.load("054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e"s));
const auto data = "da\x00ta"s;
const auto hash = "hash\x00\x01\x02\x03"s;
const std::chrono::system_clock::time_point timestamp{12'345'678ms};
const auto expiry = timestamp + 3456s;
std::vector<message_t> msgs;
msgs.emplace_back(pub_key, hash, timestamp, expiry, data);
auto serialized = serialize_messages(msgs.begin(), msgs.end(), 1);
REQUIRE(serialized.size() == 1);
const auto expected_serialized =
"l"
"33:\x05\x43\x68\x52\x00\x05\x78\x6b\x24\x9b\xcd\x46\x1d\x28\xf7\x5e\x56" // pubkey
"\x0e\xa7\x94\x01\x4e\xeb\x17\xfc\xf6\x00\x3f\x37\xd8\x76\x78\x3e"
"8:hash\x00\x01\x02\x03" // hash
"i12345678e" // timestamp
"i15801678e" // expiry
"5:da\x00ta" // data
"e"s;
CHECK(serialized.front() == "\x01l"s + expected_serialized + "e");
msgs.push_back(msgs.front());
const std::vector<std::string> batches = serialize_messages(msgs.begin(), msgs.end(), 1);
CHECK(batches.size() == 1);
REQUIRE(batches[0] == "\x01l"s + expected_serialized + expected_serialized + "e");
const auto messages = deserialize_messages(batches[0]);
CHECK(messages.size() == 2);
for (int i = 0; i < messages.size(); ++i) {
CHECK(messages[i].pubkey == pub_key);
CHECK(messages[i].data == data);
CHECK(messages[i].hash == hash);
CHECK(messages[i].timestamp == timestamp);
CHECK(messages[i].expiry == expiry);
}
}
TEST_CASE("v1 serialization - batch serialization", "[serialization]") {
user_pubkey_t pub_key;
REQUIRE(pub_key.load("054368520005786b249bcd461d28f75e560ea794014eeb17fcf6003f37d876783e"s));
std::string data(100000, 'x');
const auto hash = "hash";
const std::chrono::system_clock::time_point timestamp{1'622'576'077s};
const auto ttl = 24h;
std::vector<message_t> msgs;
msgs.emplace_back(pub_key, hash, timestamp, timestamp + ttl, data);
auto serialized = serialize_messages(msgs.begin(), msgs.end(), 1);
REQUIRE(serialized.size() == 1);
auto first = serialized.front();
const size_t num_messages = (SERIALIZATION_BATCH_SIZE / (serialized.front().size() - 2));
msgs = {num_messages, msgs.front()};
serialized = serialize_messages(msgs.begin(), msgs.end(), 1);
CHECK(serialized.size() == 1);
msgs.push_back(msgs.front());
serialized = serialize_messages(msgs.begin(), msgs.end(), 1);
CHECK(serialized.size() == 2);
}

View file

@ -2,8 +2,9 @@
#include <iostream>
#include "oxend_key.h"
#include "swarm.h"
#include "request_handler.h"
#include "swarm.h"
#include "time.hpp"
#include <oxenmq/base64.h>
@ -70,18 +71,35 @@ TEST_CASE("service nodes - updates IP address", "[service-nodes][updates]") {
TEST_CASE("service nodes - message hashing", "[service-nodes][messages]") {
const auto timestamp = std::chrono::system_clock::time_point{1616650862026ms};
const auto ttl = 48h;
const auto pk = "05ffba630924aa1224bb930dde21c0d11bf004608f2812217f8ac812d6c7e3ad48";
const auto data = oxenmq::from_base64("CAES1gIKA1BVVBIPL2FwaS92MS9tZXNzYWdlGrsCCAYovfqZv4YvQq8CVwutUBbhRzZw80TvR6uTYMKg9DSagrtpeEpY31L7VxawfS8aSya0SiDa4J025SkjP13YX8g5pxgQ8Z6hgfNArMqr/tSijJ9miVKVDJ63YWE85O8kyWF8tdtZR5j0Vxb+JH5U8Rg1bp7ftKk3OSf7JJMcrUUrDnctQHe540zJ2OTDJ03DfubkX5NmKqEu5nhXGxeeDv3mTiL63fjtCvZYcikfjf6Nh1AX++HTgJ9SGoEIMastGUorFrmmXb2sbjHxNiJn0Radj/VzcA9VxYwBW5+AbGQ2d9+vvm7X+8vh+jIenJfjxf+8CWER+9adNfb4YUH07I+godNCV0O0J05gzqfKdT7J8MBZzFBtKrbk8oCagPpTsq/wZyYFKFKKD+q+zh704dYBILvs5yXUA96pIAA=");
const auto expiry = timestamp + 48h;
oxen::user_pubkey_t pk;
REQUIRE(pk.load("05ffba630924aa1224bb930dde21c0d11bf004608f2812217f8ac812d6c7e3ad48"));
const auto data = oxenmq::from_base64(
"CAES1gIKA1BVVBIPL2FwaS92MS9tZXNzYWdlGrsCCAYovfqZv4YvQq8CVwutUBbhRzZw80TvR6uTYMKg9DSag"
"rtpeEpY31L7VxawfS8aSya0SiDa4J025SkjP13YX8g5pxgQ8Z6hgfNArMqr/tSijJ9miVKVDJ63YWE85O8kyW"
"F8tdtZR5j0Vxb+JH5U8Rg1bp7ftKk3OSf7JJMcrUUrDnctQHe540zJ2OTDJ03DfubkX5NmKqEu5nhXGxeeDv3"
"mTiL63fjtCvZYcikfjf6Nh1AX++HTgJ9SGoEIMastGUorFrmmXb2sbjHxNiJn0Radj/VzcA9VxYwBW5+AbGQ2"
"d9+vvm7X+8vh+jIenJfjxf+8CWER+9adNfb4YUH07I+godNCV0O0J05gzqfKdT7J8MBZzFBtKrbk8oCagPpTs"
"q/wZyYFKFKKD+q+zh704dYBILvs5yXUA96pIAA=");
// The hash used here deliberately changed with the RPC overhaul as it now computes the hash
// from the expiry date (instead of TTL) and the binary data (instead of b64-encoded data).
const auto expected = "b44adb755e9bca15d2f22fb0775b75e48d1689c4e314cd38c73cc4f1b2a609d06ef3df928c5175ba1447ad168a126419674083f1d5537de8fc622c22632f3aa5";
auto expected_old =
"dd5f46395dbab44c9d96711a68cd70e326c4a39d6ccce7a319b0262c18699d20"
"44610196519ad7283e3defebcdf3bccd6499fce1254fdee661e68f0611dc3104";
CHECK(computeMessageHash(timestamp, expiry, pk, data, true /*old*/) == expected_old);
CHECK(oxen::compute_hash_sha512_hex({
std::to_string(oxen::to_epoch_ms(timestamp)) +
std::to_string(oxen::to_epoch_ms(expiry) - oxen::to_epoch_ms(timestamp)) +
pk.prefixed_hex() +
oxenmq::to_base64(data)})
== expected_old);
auto hash = oxen::computeMessageHash(timestamp, timestamp+ttl, pk, data);
CHECK(hash == expected);
hash = oxen::computeMessageHash("16166508620261616823662026"s + pk + data);
CHECK(hash == expected);
auto expected_new = "rY7K5YXNsg7d8LBP6R4OoOr6L7IMFxa3Tr8ca5v5nBI";
CHECK(computeMessageHash(timestamp, expiry, pk, data, false /*!old*/) == expected_new);
CHECK(oxen::compute_hash_blake2b_b64({
std::to_string(oxen::to_epoch_ms(timestamp)) +
std::to_string(oxen::to_epoch_ms(expiry)) +
pk.prefixed_raw() +
data})
== expected_new);
}

View file

@ -1,6 +1,8 @@
#include "Database.hpp"
#include "utils.hpp"
#include "oxen_logger.h"
#include <chrono>
#include <filesystem>
#include <iostream>
@ -9,183 +11,193 @@
#include <catch2/catch.hpp>
using oxen::storage::Item;
using namespace oxen;
using namespace std::literals;
struct StorageRAIIFixture {
StorageRAIIFixture() {
if (std::filesystem::remove("storage.db")) {
std::cout << "Pre-test db removal" << std::endl;
}
struct StorageDeleter {
StorageDeleter() {
std::filesystem::remove("storage.db");
}
~StorageRAIIFixture() {
if (std::filesystem::remove("storage.db")) {
std::cout << "Post-test db removal" << std::endl;
}
~StorageDeleter() {
std::filesystem::remove("storage.db");
}
};
TEST_CASE("storage - database file creation", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
Database storage{"."};
CHECK(std::filesystem::exists("storage.db"));
}
TEST_CASE("storage - data persistence", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
const auto hash = "myhash";
const auto pubkey = "mypubkey";
const auto bytes = "bytesasstring";
const auto ttl = 123456ms;
const auto now = std::chrono::system_clock::now();
{
Database storage{"."};
CHECK(storage.store(hash, pubkey, bytes, now, now + ttl));
CHECK(storage.store({pubkey, hash, now, now+ttl, bytes}));
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == 1);
// the database is closed when storage goes out of scope
}
{
// re-open the database
Database storage{"."};
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == 1);
CHECK(storage.retrieve(pubkey, items, lastHash));
auto items = storage.retrieve(pubkey, "");
REQUIRE(items.size() == 1);
CHECK(items[0].pub_key == pubkey);
CHECK_FALSE(items[0].pubkey); // pubkey is left unset when we retrieve for pubkey
CHECK(items[0].hash == hash);
CHECK(items[0].expiration - items[0].timestamp == ttl);
CHECK(items[0].expiry - items[0].timestamp == ttl);
CHECK(items[0].data == bytes);
}
}
TEST_CASE("storage - returns false when storing existing hash", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
const auto hash = "myhash";
const auto pubkey = "mypubkey";
const auto bytes = "bytesasstring";
const auto ttl = 123456ms;
const auto timestamp = std::chrono::system_clock::now();
Database storage{"."};
CHECK(storage.store(hash, pubkey, bytes, timestamp, timestamp + ttl));
// store using the same hash, FAIL is default behaviour
CHECK_FALSE(storage.store(hash, pubkey, bytes, timestamp, timestamp + ttl,
Database::DuplicateHandling::FAIL));
}
auto ins = storage.store({pubkey, hash, timestamp, timestamp + ttl, bytes});
REQUIRE(ins);
CHECK(*ins);
// store using the same hash, will fail
ins = storage.store({pubkey, hash, timestamp, timestamp + ttl, bytes});
REQUIRE(ins);
CHECK_FALSE(*ins);
TEST_CASE("storage - returns true when storing existing with ignore constraint", "[storage]") {
StorageRAIIFixture fixture;
const auto hash = "myhash";
const auto pubkey = "mypubkey";
const auto bytes = "bytesasstring";
const auto ttl = 123456ms;
const auto timestamp = std::chrono::system_clock::now();
Database storage{"."};
CHECK(storage.store(hash, pubkey, bytes, timestamp, timestamp + ttl));
// store using the same hash
CHECK(storage.store(hash, pubkey, bytes, timestamp, timestamp + ttl,
Database::DuplicateHandling::IGNORE));
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == 1);
}
TEST_CASE("storage - only return entries for specified pubkey", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
Database storage{"."};
auto now = std::chrono::system_clock::now();
CHECK(storage.store("hash0", "mypubkey", "bytesasstring0", now, now + 100s));
CHECK(storage.store("hash1", "otherpubkey", "bytesasstring1", now, now + 100s));
user_pubkey_t pubkey1, pubkey2;
REQUIRE(pubkey1.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
REQUIRE(pubkey2.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdee"));
auto now = std::chrono::system_clock::now();
CHECK(storage.store({pubkey1, "hash0", now, now + 100s, "bytesasstring0"}));
CHECK(storage.store({pubkey2, "hash1", now, now + 100s, "bytesasstring1"}));
CHECK(storage.get_owner_count() == 2);
CHECK(storage.get_message_count() == 2);
const auto lastHash = "";
{
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("mypubkey", items, lastHash));
auto items = storage.retrieve(pubkey1, lastHash);
REQUIRE(items.size() == 1);
CHECK(items[0].hash == "hash0");
}
{
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("otherpubkey", items, lastHash));
auto items = storage.retrieve(pubkey2, lastHash);
REQUIRE(items.size() == 1);
CHECK(items[0].hash == "hash1");
}
}
TEST_CASE("storage - return entries older than lasthash", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
Database storage{"."};
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
auto now = std::chrono::system_clock::now();
const size_t num_entries = 100;
for (size_t i = 0; i < num_entries; i++) {
const auto hash = std::string("hash") + std::to_string(i);
storage.store(hash, "mypubkey", "bytesasstring", now, now + 100s);
const auto hash = "hash" + std::to_string(i);
storage.store({pubkey, hash, now, now + 100s, "bytesasstring"});
}
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == 100);
{
std::vector<Item> items;
const auto lastHash = "hash0";
CHECK(storage.retrieve("mypubkey", items, lastHash));
auto items = storage.retrieve(pubkey, lastHash);
REQUIRE(items.size() == num_entries - 1);
CHECK(items[0].hash == "hash1");
}
{
std::vector<Item> items;
const auto lastHash =
std::string("hash") + std::to_string(num_entries / 2 - 1);
CHECK(storage.retrieve("mypubkey", items, lastHash));
auto items = storage.retrieve(pubkey, lastHash);
REQUIRE(items.size() == num_entries / 2);
CHECK(items[0].hash == "hash" + std::to_string(num_entries / 2));
}
}
TEST_CASE("storage - remove expired entries", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
const auto pubkey = "mypubkey";
user_pubkey_t pubkey1, pubkey2, pubkey3;
REQUIRE(pubkey1.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
REQUIRE(pubkey2.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdee"));
REQUIRE(pubkey3.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcded"));
Database storage{"."};
auto now = std::chrono::system_clock::now();
CHECK(storage.store("hash0", pubkey, "bytesasstring0", now, now + 1s));
CHECK(storage.store("hash1", pubkey, "bytesasstring0", now, now));
CHECK(storage.store({pubkey1, "hash0", now, now + 1s, "bytesasstring0"}));
CHECK(storage.store({pubkey1, "hash1", now, now, "bytesasstring0"}));
CHECK(storage.store({pubkey2, "hash2", now, now + 1s, "bytesasstring0"}));
CHECK(storage.store({pubkey3, "hash3", now, now, "bytesasstring0"}));
CHECK(storage.store({pubkey3, "hash4", now, now, "bytesasstring0"}));
CHECK(storage.store({pubkey3, "hash5", now, now, "bytesasstring0"}));
CHECK(storage.get_owner_count() == 3);
CHECK(storage.get_message_count() == 6);
{
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve(pubkey, items, lastHash));
auto items = storage.retrieve(pubkey1, lastHash);
REQUIRE(items.size() == 2);
}
std::this_thread::sleep_for(5ms);
storage.clean_expired();
{
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve(pubkey, items, lastHash));
auto items = storage.retrieve(pubkey1, lastHash);
REQUIRE(items.size() == 1);
CHECK(items[0].hash == "hash0");
}
CHECK(storage.get_owner_count() == 2);
CHECK(storage.get_message_count() == 2);
}
TEST_CASE("storage - bulk data storage", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
const auto pubkey = "mypubkey";
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
const auto bytes = "bytesasstring";
const auto ttl = 123456ms;
const auto timestamp = std::chrono::system_clock::now();
@ -196,28 +208,29 @@ TEST_CASE("storage - bulk data storage", "[storage]") {
// bulk store
{
std::vector<Item> items;
std::vector<message_t> items;
for (int i = 0; i < num_items; ++i) {
items.emplace_back(std::to_string(i), pubkey, timestamp,
timestamp + ttl, bytes);
items.emplace_back(pubkey, std::to_string(i), timestamp, timestamp + ttl, bytes);
}
CHECK(storage.bulk_store(items));
CHECK_NOTHROW(storage.bulk_store(items));
}
// retrieve
{
std::vector<Item> items;
CHECK(storage.retrieve(pubkey, items, ""));
auto items = storage.retrieve(pubkey, "");
CHECK(items.size() == num_items);
}
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == num_items);
}
TEST_CASE("storage - bulk storage with overlap", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
const auto pubkey = "mypubkey";
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
const auto bytes = "bytesasstring";
const auto ttl = 123456ms;
const auto timestamp = std::chrono::system_clock::now();
@ -226,72 +239,64 @@ TEST_CASE("storage - bulk storage with overlap", "[storage]") {
Database storage{"."};
// insert existing
CHECK(storage.store("0", pubkey, bytes, timestamp, timestamp + ttl));
// insert existing; the bulk store shouldn't fail when these conflicts already exist
CHECK(storage.store({pubkey, "0", timestamp, timestamp + ttl, bytes}));
CHECK(storage.store({pubkey, "5", timestamp, timestamp + ttl, bytes}));
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == 2);
// bulk store
{
std::vector<Item> items;
std::vector<message_t> items;
for (int i = 0; i < num_items; ++i) {
items.emplace_back(std::to_string(i), pubkey, timestamp, timestamp + ttl, bytes);
items.emplace_back(pubkey, std::to_string(i), timestamp, timestamp + ttl, bytes);
}
CHECK(storage.bulk_store(items));
CHECK_NOTHROW(storage.bulk_store(items));
}
CHECK(storage.get_owner_count() == 1);
CHECK(storage.get_message_count() == num_items);
// retrieve
{
std::vector<Item> items;
CHECK(storage.retrieve(pubkey, items, ""));
auto items = storage.retrieve(pubkey, "");
CHECK(items.size() == num_items);
}
}
TEST_CASE("storage - retrieve limit", "[storage]") {
StorageRAIIFixture fixture;
StorageDeleter fixture;
Database storage{"."};
user_pubkey_t pubkey;
REQUIRE(pubkey.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
auto now = std::chrono::system_clock::now();
const size_t num_entries = 100;
for (size_t i = 0; i < num_entries; i++) {
const auto hash = std::string("hash") + std::to_string(i);
storage.store(hash, "mypubkey", "bytesasstring", now, now + 100s);
const auto hash = "hash" + std::to_string(i);
storage.store({pubkey, hash, now, now + 100s, "bytesasstring"});
}
// should return all items
{
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("mypubkey", items, lastHash));
CHECK(items.size() == num_entries);
user_pubkey_t pubkey2;
REQUIRE(pubkey2.load("050123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdee"));
for (size_t i = 0; i < 5; i++) {
const auto hash = "anotherhash" + std::to_string(i);
storage.store({pubkey2, hash, now, now + 100s, "bytesasstring"});
}
// should return 10 items
{
const int num_results = 10;
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("mypubkey", items, lastHash, num_results));
CHECK(items.size() == num_results);
}
CHECK(storage.get_owner_count() == 2);
CHECK(storage.get_message_count() == num_entries + 5);
// should return 88 items
{
const int num_results = 88;
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("mypubkey", items, lastHash, num_results));
CHECK(items.size() == num_results);
}
// should return num_entries items
{
const int num_results = 2 * num_entries;
std::vector<Item> items;
const auto lastHash = "";
CHECK(storage.retrieve("mypubkey", items, lastHash, num_results));
CHECK(items.size() == num_entries);
}
CHECK(storage.retrieve(pubkey, "").size() == num_entries);
CHECK(storage.retrieve(pubkey, "", 10).size() == 10);
CHECK(storage.retrieve(pubkey, "", 88).size() == 88);
CHECK(storage.retrieve(pubkey, "", 99).size() == 99);
CHECK(storage.retrieve(pubkey, "", 100).size() == 100);
CHECK(storage.retrieve(pubkey, "", 101).size() == 100);
CHECK(storage.retrieve(pubkey2, "", 10).size() == 5);
}