test: extend coverage of testWorldBackup
This commit is contained in:
1 parent
8fab041683
commit
1fca2b5564
1 file changed
+136
@@ -314,3 +314,139 @@ VF_TEST(captureMigratedLiftsAnOldSaveBeforeStoringIt) {
|
|||||||
legacy.chunks.push_back(buildRecord({1, 0, 0}, texturedChunk(2), SaveVersion::V1));
|
legacy.chunks.push_back(buildRecord({1, 0, 0}, texturedChunk(2), SaveVersion::V1));
|
||||||
ByteBuffer ancient = writeSaveContainer(legacy);
|
ByteBuffer ancient = writeSaveContainer(legacy);
|
||||||
|
|
||||||
|
BackupStore store;
|
||||||
|
uint32_t id = store.captureMigrated(BackupKind::Full, ancient, 0);
|
||||||
|
CHECK(id != 0u);
|
||||||
|
const BackupEntry* entry = store.index().find(id);
|
||||||
|
CHECK(entry != nullptr);
|
||||||
|
if (entry == nullptr) return;
|
||||||
|
CHECK(entry->version == currentSaveVersion);
|
||||||
|
|
||||||
|
RestoreResult restored = store.restore(id);
|
||||||
|
CHECK(restored.ok);
|
||||||
|
SaveContainer reloaded;
|
||||||
|
CHECK(readSaveContainer(restored.save.data(), restored.save.size(), reloaded));
|
||||||
|
CHECK(reloaded.version == SaveVersion::V4);
|
||||||
|
for (const SaveChunkRecord& before : legacy.chunks) {
|
||||||
|
const SaveChunkRecord* after = reloaded.find(before.coord);
|
||||||
|
CHECK(after != nullptr);
|
||||||
|
if (after == nullptr) continue;
|
||||||
|
for (std::size_t i = 0; i < before.blocks.raw().size(); ++i)
|
||||||
|
CHECK(before.blocks.raw()[i] == after->blocks.raw()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer modern = writeSaveContainer(baseContainer());
|
||||||
|
saveWriteU32At(modern.data(), modern.size(), 4, 9u);
|
||||||
|
CHECK_EQ(store.captureMigrated(BackupKind::Full, modern, 10), static_cast<uint32_t>(0));
|
||||||
|
CHECK(store.lastFailure().find("migration") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(retentionKeepsTheLatestAndPrunesTheChainsNobodyNeeds) {
|
||||||
|
SaveContainer container = baseContainer();
|
||||||
|
BackupStore store;
|
||||||
|
store.retention.keepLatest = 2;
|
||||||
|
store.retention.dailyBuckets = 1;
|
||||||
|
store.retention.weeklyBuckets = 1;
|
||||||
|
|
||||||
|
std::vector<uint32_t> ids;
|
||||||
|
std::vector<ByteBuffer> saves;
|
||||||
|
const uint64_t ticks[6] = {0, 1000, 24000, 25000, 48000, 49000};
|
||||||
|
const BackupKind kinds[6] = {BackupKind::Full, BackupKind::Incremental,
|
||||||
|
BackupKind::Full, BackupKind::Incremental,
|
||||||
|
BackupKind::Full, BackupKind::Incremental};
|
||||||
|
for (int step = 0; step < 6; ++step) {
|
||||||
|
replaceChunk(container, {1, 0, 0}, texturedChunk(step));
|
||||||
|
ByteBuffer save = writeSaveContainer(container);
|
||||||
|
uint32_t id = store.capture(kinds[step], save, ticks[step]);
|
||||||
|
CHECK(id != 0u);
|
||||||
|
ids.push_back(id);
|
||||||
|
saves.push_back(save);
|
||||||
|
}
|
||||||
|
CHECK_EQ(store.index().count(), static_cast<std::size_t>(6));
|
||||||
|
|
||||||
|
std::vector<uint32_t> removed = store.prune(49000);
|
||||||
|
CHECK_EQ(removed.size(), static_cast<std::size_t>(4));
|
||||||
|
if (removed.size() == 4) {
|
||||||
|
CHECK_EQ(removed[0], ids[0]);
|
||||||
|
CHECK_EQ(removed[1], ids[1]);
|
||||||
|
CHECK_EQ(removed[2], ids[2]);
|
||||||
|
CHECK_EQ(removed[3], ids[3]);
|
||||||
|
}
|
||||||
|
CHECK_EQ(store.index().count(), static_cast<std::size_t>(2));
|
||||||
|
CHECK(store.index().find(ids[4]) != nullptr);
|
||||||
|
CHECK(store.index().find(ids[5]) != nullptr);
|
||||||
|
|
||||||
|
RestoreResult survivor = store.restore(ids[5]);
|
||||||
|
CHECK(survivor.ok);
|
||||||
|
CHECK(survivor.save == saves[5]);
|
||||||
|
CHECK(!store.restore(ids[1]).ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(retentionAlsoKeepsOneBackupPerRecentDay) {
|
||||||
|
ByteBuffer save = writeSaveContainer(baseContainer());
|
||||||
|
BackupStore store;
|
||||||
|
store.retention.keepLatest = 1;
|
||||||
|
store.retention.dailyBuckets = 2;
|
||||||
|
store.retention.weeklyBuckets = 0;
|
||||||
|
|
||||||
|
uint32_t oldest = store.capture(BackupKind::Full, save, 0);
|
||||||
|
uint32_t sameDay = store.capture(BackupKind::Full, save, 100);
|
||||||
|
uint32_t nextDay = store.capture(BackupKind::Full, save, 30000);
|
||||||
|
CHECK(oldest != 0u);
|
||||||
|
CHECK(sameDay != 0u);
|
||||||
|
CHECK(nextDay != 0u);
|
||||||
|
|
||||||
|
std::vector<uint32_t> removed = store.prune(30000);
|
||||||
|
CHECK_EQ(removed.size(), static_cast<std::size_t>(1));
|
||||||
|
if (!removed.empty()) CHECK_EQ(removed[0], oldest);
|
||||||
|
CHECK(store.index().find(sameDay) != nullptr);
|
||||||
|
CHECK(store.index().find(nextDay) != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(retentionNeverPrunesAnAncestorAKeptBackupStillNeeds) {
|
||||||
|
SaveContainer container = baseContainer();
|
||||||
|
ByteBuffer save0 = writeSaveContainer(container);
|
||||||
|
replaceChunk(container, {1, 0, 0}, texturedChunk(3));
|
||||||
|
ByteBuffer save1 = writeSaveContainer(container);
|
||||||
|
replaceChunk(container, {2, 0, 0}, texturedChunk(4));
|
||||||
|
ByteBuffer save2 = writeSaveContainer(container);
|
||||||
|
|
||||||
|
BackupStore store;
|
||||||
|
store.retention.keepLatest = 1;
|
||||||
|
store.retention.dailyBuckets = 0;
|
||||||
|
store.retention.weeklyBuckets = 0;
|
||||||
|
|
||||||
|
uint32_t id0 = store.capture(BackupKind::Full, save0, 0);
|
||||||
|
uint32_t id1 = store.capture(BackupKind::Incremental, save1, 1000);
|
||||||
|
uint32_t id2 = store.capture(BackupKind::Incremental, save2, 2000);
|
||||||
|
|
||||||
|
std::vector<uint32_t> removed = store.prune(2000);
|
||||||
|
CHECK(removed.empty());
|
||||||
|
CHECK_EQ(store.index().count(), static_cast<std::size_t>(3));
|
||||||
|
CHECK(store.index().find(id0) != nullptr);
|
||||||
|
CHECK(store.index().find(id1) != nullptr);
|
||||||
|
CHECK(store.restore(id2).save == save2);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(aBrokenChainCannotBeExtendedWithANewIncremental) {
|
||||||
|
SaveContainer container = baseContainer();
|
||||||
|
ByteBuffer save0 = writeSaveContainer(container);
|
||||||
|
replaceChunk(container, {1, 0, 0}, texturedChunk(3));
|
||||||
|
ByteBuffer save1 = writeSaveContainer(container);
|
||||||
|
|
||||||
|
BackupStore store;
|
||||||
|
uint32_t id0 = store.capture(BackupKind::Full, save0, 0);
|
||||||
|
uint32_t id1 = store.capture(BackupKind::Incremental, save1, 1000);
|
||||||
|
CHECK(id1 != 0u);
|
||||||
|
CHECK(store.drop(id0));
|
||||||
|
|
||||||
|
replaceChunk(container, {2, 0, 0}, texturedChunk(5));
|
||||||
|
ByteBuffer save2 = writeSaveContainer(container);
|
||||||
|
CHECK_EQ(store.capture(BackupKind::Incremental, save2, 2000), static_cast<uint32_t>(0));
|
||||||
|
CHECK(store.lastFailure().find("broken chain") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(backupKindNamesStayReadable) {
|
||||||
|
CHECK(std::string(backupKindName(BackupKind::Full)) == "full");
|
||||||
|
CHECK(std::string(backupKindName(BackupKind::Incremental)) == "incremental");
|
||||||
|
}
|
||||||
Reference in new issue
Block a user