|
|
|
|
@ -13,6 +13,7 @@
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <numeric>
|
|
|
|
|
#include <vector>
|
|
|
|
|
@ -74,6 +75,41 @@ private:
|
|
|
|
|
std::string m_blob_path;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class TempArchivePath
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TempArchivePath()
|
|
|
|
|
{
|
|
|
|
|
const std::string base = Path::Combine(FileSystem::GetWorkingDirectory(), "duckstation_oa_path_test");
|
|
|
|
|
std::FILE* fp = FileSystem::OpenTemporaryCFile(base, &m_base_path);
|
|
|
|
|
if (fp)
|
|
|
|
|
{
|
|
|
|
|
std::fclose(fp);
|
|
|
|
|
FileSystem::DeleteFile(m_base_path.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~TempArchivePath()
|
|
|
|
|
{
|
|
|
|
|
if (!m_base_path.empty())
|
|
|
|
|
{
|
|
|
|
|
FileSystem::DeleteFile(fmt::format("{}.idx", m_base_path).c_str());
|
|
|
|
|
FileSystem::DeleteFile(fmt::format("{}.bin", m_base_path).c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsValid() const { return !m_base_path.empty(); }
|
|
|
|
|
const std::string& GetPath() const { return m_base_path; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::string m_base_path;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static ObjectArchive::KeySpan StringToCacheKey(std::string_view sv)
|
|
|
|
|
{
|
|
|
|
|
return ObjectArchive::KeySpan(reinterpret_cast<const u8*>(sv.data()), sv.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
static constexpr u32 TEST_VERSION = 1;
|
|
|
|
|
@ -95,6 +131,54 @@ TEST(ObjectArchive, CreateAndOpen)
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 0u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ObjectArchive, OpenPathInvalidationStatus)
|
|
|
|
|
{
|
|
|
|
|
TempArchivePath path;
|
|
|
|
|
ASSERT_TRUE(path.IsValid());
|
|
|
|
|
|
|
|
|
|
const u8 payload[] = {0xCA, 0xFE};
|
|
|
|
|
Error error;
|
|
|
|
|
bool was_invalidated = true;
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
ASSERT_TRUE(archive.OpenPath(path.GetPath(), TEST_VERSION, &error, &was_invalidated)) << error.GetDescription();
|
|
|
|
|
EXPECT_FALSE(was_invalidated);
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("persist"), payload, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
was_invalidated = true;
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
ASSERT_TRUE(archive.OpenPath(path.GetPath(), TEST_VERSION, &error, &was_invalidated)) << error.GetDescription();
|
|
|
|
|
EXPECT_FALSE(was_invalidated);
|
|
|
|
|
EXPECT_TRUE(archive.Contains(StringToCacheKey("persist")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
was_invalidated = false;
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
ASSERT_TRUE(archive.OpenPath(path.GetPath(), TEST_VERSION + 1, &error, &was_invalidated)) << error.GetDescription();
|
|
|
|
|
EXPECT_TRUE(was_invalidated);
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 0u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string index_path = fmt::format("{}.idx", path.GetPath());
|
|
|
|
|
FileSystem::ManagedCFilePtr index_file = FileSystem::OpenManagedCFile(index_path.c_str(), "r+b", &error);
|
|
|
|
|
ASSERT_TRUE(index_file) << error.GetDescription();
|
|
|
|
|
const u32 invalid_signature = 0;
|
|
|
|
|
ASSERT_EQ(std::fwrite(&invalid_signature, sizeof(invalid_signature), 1, index_file.get()), 1u);
|
|
|
|
|
index_file.reset();
|
|
|
|
|
|
|
|
|
|
was_invalidated = false;
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
ASSERT_TRUE(archive.OpenPath(path.GetPath(), TEST_VERSION + 1, &error, &was_invalidated)) << error.GetDescription();
|
|
|
|
|
EXPECT_TRUE(was_invalidated);
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 0u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ObjectArchive, InsertToClosedArchive)
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
@ -102,7 +186,7 @@ TEST(ObjectArchive, InsertToClosedArchive)
|
|
|
|
|
|
|
|
|
|
const u8 data[] = {1, 2, 3};
|
|
|
|
|
Error error;
|
|
|
|
|
EXPECT_FALSE(archive.Insert("key", data, sizeof(data), ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
EXPECT_FALSE(archive.Insert(StringToCacheKey("key"), data, ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ObjectArchive, EmptyKeyRejected)
|
|
|
|
|
@ -116,7 +200,7 @@ TEST(ObjectArchive, EmptyKeyRejected)
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
|
|
|
|
|
const u8 data[] = {0xAA};
|
|
|
|
|
EXPECT_FALSE(archive.Insert("", std::span<const u8>(data), ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
EXPECT_FALSE(archive.Insert({}, std::span<const u8>(data), ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
@ -134,15 +218,61 @@ TEST(ObjectArchive, InsertAndLookupRoundTrip)
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
|
|
|
|
|
const u8 payload[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("test_key", payload, sizeof(payload), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("test_key"), payload, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
|
|
|
|
|
auto result = archive.Lookup("test_key", &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey("test_key"), &error);
|
|
|
|
|
ASSERT_TRUE(result.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result->size(), sizeof(payload));
|
|
|
|
|
EXPECT_EQ(std::memcmp(result->data(), payload, sizeof(payload)), 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ObjectArchive, BinaryKeyRoundTrip)
|
|
|
|
|
{
|
|
|
|
|
TempArchiveFiles files;
|
|
|
|
|
ASSERT_TRUE(files.IsValid());
|
|
|
|
|
|
|
|
|
|
static constexpr std::array<u8, 6> key1 = {0x00, 0x61, 0x00, 0x62, 0x00, 0xFF};
|
|
|
|
|
static constexpr std::array<u8, 6> key2 = {0x00, 0x61, 0x00, 0x62, 0x01, 0xFF};
|
|
|
|
|
static constexpr std::array<u8, 3> payload1 = {0x12, 0x34, 0x56};
|
|
|
|
|
static constexpr std::array<u8, 2> payload2 = {0xAB, 0xCD};
|
|
|
|
|
const std::string_view key1_string(reinterpret_cast<const char*>(key1.data()), key1.size());
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
auto [idx, blob] = files.Release();
|
|
|
|
|
Error error;
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
ASSERT_TRUE(archive.Insert(key1, payload1, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
ASSERT_TRUE(archive.Insert(key2, payload2, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(archive.Contains(key1));
|
|
|
|
|
EXPECT_TRUE(archive.Contains(key2));
|
|
|
|
|
EXPECT_TRUE(archive.Contains(StringToCacheKey(key1_string)));
|
|
|
|
|
EXPECT_FALSE(archive.Contains(ObjectArchive::KeySpan(key1).first(key1.size() - 1)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(files.Reopen());
|
|
|
|
|
{
|
|
|
|
|
ObjectArchive archive;
|
|
|
|
|
auto [idx, blob] = files.Release();
|
|
|
|
|
Error error;
|
|
|
|
|
ASSERT_TRUE(archive.OpenFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
|
|
|
|
|
const std::optional<ObjectArchive::ObjectData> result1 = archive.Lookup(StringToCacheKey(key1_string), &error);
|
|
|
|
|
ASSERT_TRUE(result1.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result1->size(), payload1.size());
|
|
|
|
|
EXPECT_EQ(std::memcmp(result1->data(), payload1.data(), payload1.size()), 0);
|
|
|
|
|
|
|
|
|
|
const std::optional<ObjectArchive::ObjectData> result2 = archive.Lookup(ObjectArchive::KeySpan(key2), &error);
|
|
|
|
|
ASSERT_TRUE(result2.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result2->size(), payload2.size());
|
|
|
|
|
EXPECT_EQ(std::memcmp(result2->data(), payload2.data(), payload2.size()), 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Round-trip (compressed)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
@ -163,10 +293,10 @@ TEST(ObjectArchive, InsertAndLookupCompressed)
|
|
|
|
|
payload[i] = static_cast<u8>(i & 0xFF);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(
|
|
|
|
|
archive.Insert("compressed_key", std::span<const u8>(payload), ObjectArchive::CompressType::Zstandard, &error))
|
|
|
|
|
archive.Insert(StringToCacheKey("compressed_key"), payload, ObjectArchive::CompressType::Zstandard, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
|
|
|
|
|
auto result = archive.Lookup("compressed_key", &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey("compressed_key"), &error);
|
|
|
|
|
ASSERT_TRUE(result.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result->size(), payload.size());
|
|
|
|
|
EXPECT_EQ(std::memcmp(result->data(), payload.data(), payload.size()), 0);
|
|
|
|
|
@ -188,9 +318,9 @@ TEST(ObjectArchive, DuplicateKeyRejected)
|
|
|
|
|
|
|
|
|
|
const u8 data1[] = {1};
|
|
|
|
|
const u8 data2[] = {2};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("dup", std::span<const u8>(data1), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("dup"), data1, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
EXPECT_FALSE(archive.Insert("dup", std::span<const u8>(data2), ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
EXPECT_FALSE(archive.Insert(StringToCacheKey("dup"), data2, ObjectArchive::CompressType::Uncompressed, &error));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
@ -209,10 +339,10 @@ TEST(ObjectArchive, MissingKeyReturnsNullopt)
|
|
|
|
|
|
|
|
|
|
// Insert one key so the index is non-empty.
|
|
|
|
|
const u8 data[] = {0x42};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("exists", std::span<const u8>(data), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("exists"), data, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
|
|
|
|
|
auto result = archive.Lookup("does_not_exist", &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey("does_not_exist"), &error);
|
|
|
|
|
EXPECT_FALSE(result.has_value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -234,25 +364,25 @@ TEST(ObjectArchive, MultipleKeysCorrectIsolation)
|
|
|
|
|
const u8 m_data[] = {0xBB, 0xCC};
|
|
|
|
|
const u8 z_data[] = {0xDD, 0xEE, 0xFF};
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(archive.Insert("aaa", std::span<const u8>(a_data), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("aaa"), a_data, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
ASSERT_TRUE(archive.Insert("mmm", std::span<const u8>(m_data), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("mmm"), m_data, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
ASSERT_TRUE(archive.Insert("zzz", std::span<const u8>(z_data), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("zzz"), z_data, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
|
|
|
|
|
auto ra = archive.Lookup("aaa", &error);
|
|
|
|
|
auto ra = archive.Lookup(StringToCacheKey("aaa"), &error);
|
|
|
|
|
ASSERT_TRUE(ra.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(ra->size(), sizeof(a_data));
|
|
|
|
|
EXPECT_EQ((*ra)[0], 0xAA);
|
|
|
|
|
|
|
|
|
|
auto rm = archive.Lookup("mmm", &error);
|
|
|
|
|
auto rm = archive.Lookup(StringToCacheKey("mmm"), &error);
|
|
|
|
|
ASSERT_TRUE(rm.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(rm->size(), sizeof(m_data));
|
|
|
|
|
EXPECT_EQ((*rm)[0], 0xBB);
|
|
|
|
|
EXPECT_EQ((*rm)[1], 0xCC);
|
|
|
|
|
|
|
|
|
|
auto rz = archive.Lookup("zzz", &error);
|
|
|
|
|
auto rz = archive.Lookup(StringToCacheKey("zzz"), &error);
|
|
|
|
|
ASSERT_TRUE(rz.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(rz->size(), sizeof(z_data));
|
|
|
|
|
EXPECT_EQ((*rz)[0], 0xDD);
|
|
|
|
|
@ -273,7 +403,7 @@ TEST(ObjectArchive, ClearAndReinsert)
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
|
|
|
|
|
const u8 data1[] = {0x11, 0x22};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("key1", std::span<const u8>(data1), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("key1"), data1, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 1u);
|
|
|
|
|
|
|
|
|
|
@ -281,16 +411,16 @@ TEST(ObjectArchive, ClearAndReinsert)
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 0u);
|
|
|
|
|
|
|
|
|
|
// After clear, lookup should fail.
|
|
|
|
|
auto result = archive.Lookup("key1", &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey("key1"), &error);
|
|
|
|
|
EXPECT_FALSE(result.has_value());
|
|
|
|
|
|
|
|
|
|
// Re-insertion should succeed.
|
|
|
|
|
const u8 data2[] = {0x33, 0x44, 0x55};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("key2", std::span<const u8>(data2), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("key2"), data2, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 1u);
|
|
|
|
|
|
|
|
|
|
auto result2 = archive.Lookup("key2", &error);
|
|
|
|
|
auto result2 = archive.Lookup(StringToCacheKey("key2"), &error);
|
|
|
|
|
ASSERT_TRUE(result2.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result2->size(), sizeof(data2));
|
|
|
|
|
EXPECT_EQ(std::memcmp(result2->data(), data2, sizeof(data2)), 0);
|
|
|
|
|
@ -313,8 +443,7 @@ TEST(ObjectArchive, CloseAndReopenPersistence)
|
|
|
|
|
auto [idx, blob] = files.Release();
|
|
|
|
|
Error error;
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
ASSERT_TRUE(
|
|
|
|
|
archive.Insert("persist", std::span<const u8>(payload), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("persist"), payload, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
archive.Close();
|
|
|
|
|
}
|
|
|
|
|
@ -328,7 +457,7 @@ TEST(ObjectArchive, CloseAndReopenPersistence)
|
|
|
|
|
ASSERT_TRUE(archive.OpenFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
EXPECT_EQ(archive.GetSize(), 1u);
|
|
|
|
|
|
|
|
|
|
auto result = archive.Lookup("persist", &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey("persist"), &error);
|
|
|
|
|
ASSERT_TRUE(result.has_value()) << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result->size(), sizeof(payload));
|
|
|
|
|
EXPECT_EQ(std::memcmp(result->data(), payload, sizeof(payload)), 0);
|
|
|
|
|
@ -352,7 +481,7 @@ TEST(ObjectArchive, VersionMismatchCreatesEmpty)
|
|
|
|
|
ASSERT_TRUE(archive.CreateFile(idx, blob, TEST_VERSION, &error)) << error.GetDescription();
|
|
|
|
|
|
|
|
|
|
const u8 data[] = {0x01, 0x02};
|
|
|
|
|
ASSERT_TRUE(archive.Insert("v1_key", std::span<const u8>(data), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey("v1_key"), data, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< error.GetDescription();
|
|
|
|
|
archive.Close();
|
|
|
|
|
}
|
|
|
|
|
@ -415,7 +544,7 @@ TEST(ObjectArchive, LargeNumberOfObjectsUnsorted)
|
|
|
|
|
std::memset(payload, 0, sizeof(payload));
|
|
|
|
|
std::memcpy(payload, &i, sizeof(i));
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(archive.Insert(key, payload, sizeof(payload), ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
ASSERT_TRUE(archive.Insert(StringToCacheKey(key), payload, ObjectArchive::CompressType::Uncompressed, &error))
|
|
|
|
|
<< "Failed to insert key '" << key << "': " << error.GetDescription();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -433,7 +562,7 @@ TEST(ObjectArchive, LargeNumberOfObjectsUnsorted)
|
|
|
|
|
for (const size_t i : lookup_order)
|
|
|
|
|
{
|
|
|
|
|
const std::string key = fmt::format("object_{:04}", i);
|
|
|
|
|
auto result = archive.Lookup(key, &error);
|
|
|
|
|
auto result = archive.Lookup(StringToCacheKey(key), &error);
|
|
|
|
|
ASSERT_TRUE(result.has_value()) << "Lookup failed for key '" << key << "': " << error.GetDescription();
|
|
|
|
|
ASSERT_EQ(result->size(), 8u);
|
|
|
|
|
|
|
|
|
|
|