test: add more cases for testSaveIntegrity
This commit is contained in:
1 parent
a7065034d1
commit
a7d9cecd35
1 file changed
+119
@@ -475,3 +475,122 @@ VF_TEST(repairDropsInsteadOfRebuildingWhenRegenerationIsTurnedOff) {
|
||||
CHECK_EQ(repaired.chunksDropped, static_cast<std::size_t>(1));
|
||||
}
|
||||
|
||||
VF_TEST(repairRemovesAnOrphanEntryAndKeepsTheRest) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
EntrySlot slot = slotOf(buffer, 1);
|
||||
saveWriteU32At(buffer.data(), buffer.size(), slot.entryAt + 16, 0u);
|
||||
refreshTableChecksum(buffer);
|
||||
|
||||
SaveScanner scanner;
|
||||
RepairResult repaired = scanner.scanAndRepair(buffer);
|
||||
CHECK(repaired.ok);
|
||||
CHECK_EQ(repaired.orphanEntriesRemoved, static_cast<std::size_t>(1));
|
||||
CHECK_EQ(repaired.chunksPreserved, static_cast<std::size_t>(2));
|
||||
|
||||
SaveContainer rebuilt;
|
||||
CHECK(readSaveContainer(repaired.output.data(), repaired.output.size(), rebuilt));
|
||||
CHECK_EQ(rebuilt.chunks.size(), static_cast<std::size_t>(2));
|
||||
CHECK(scanner.scan(repaired.output).clean());
|
||||
}
|
||||
|
||||
VF_TEST(repairIsRefusedWhenTheHeaderItselfIsFatal) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 2));
|
||||
saveWriteU32At(buffer.data(), buffer.size(), 0, 0u);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
RepairPlan plan = scanner.planRepair(buffer.data(), buffer.size(), report);
|
||||
CHECK(!plan.possible);
|
||||
CHECK(plan.actions.empty());
|
||||
CHECK(plan.refusal.find("backup") != std::string::npos);
|
||||
|
||||
RepairResult repaired = scanner.repair(buffer.data(), buffer.size(), plan);
|
||||
CHECK(!repaired.ok);
|
||||
CHECK(repaired.output.empty());
|
||||
CHECK_EQ(repaired.failure, plan.refusal);
|
||||
}
|
||||
|
||||
VF_TEST(repairPlanIsRefusedForABufferItWasNotBuiltFrom) {
|
||||
ByteBuffer first = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
ByteBuffer second = writeSaveContainer(buildContainer(SaveVersion::V4, 2));
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(first);
|
||||
RepairPlan plan = scanner.planRepair(second.data(), second.size(), report);
|
||||
CHECK(!plan.possible);
|
||||
CHECK(plan.refusal.find("different buffer") != std::string::npos);
|
||||
}
|
||||
|
||||
VF_TEST(regeneratedTerrainIsDeterministicAndFollowsTheSeed) {
|
||||
Chunk first = regenerateChunkFromSeed(99u, Vec3i{1, 2, 3});
|
||||
Chunk again = regenerateChunkFromSeed(99u, Vec3i{1, 2, 3});
|
||||
Chunk elsewhere = regenerateChunkFromSeed(99u, Vec3i{4, 2, 3});
|
||||
Chunk otherSeed = regenerateChunkFromSeed(100u, Vec3i{1, 2, 3});
|
||||
|
||||
CHECK(sameBlocks(first, again));
|
||||
CHECK(!sameBlocks(first, elsewhere));
|
||||
CHECK(!sameBlocks(first, otherSeed));
|
||||
|
||||
CHECK_EQ(regeneratedSurfaceHeight(99u, 0, 0), regeneratedSurfaceHeight(99u, 0, 0));
|
||||
CHECK(regeneratedSurfaceHeight(99u, 0, 0) >= 32);
|
||||
CHECK(regeneratedSurfaceHeight(99u, 0, 0) <= 64);
|
||||
CHECK(regeneratedSurfaceHeight(99u, 7, 9) >= 32);
|
||||
CHECK(regeneratedSurfaceHeight(99u, 7, 9) <= 64);
|
||||
}
|
||||
|
||||
VF_TEST(severityAndActionNamesStayReadable) {
|
||||
CHECK(std::string(issueSeverityName(IssueSeverity::Info)) == "info");
|
||||
CHECK(std::string(issueSeverityName(IssueSeverity::Warning)) == "warning");
|
||||
CHECK(std::string(issueSeverityName(IssueSeverity::Recoverable)) == "recoverable");
|
||||
CHECK(std::string(issueSeverityName(IssueSeverity::Fatal)) == "fatal");
|
||||
CHECK(IssueSeverity::Info < IssueSeverity::Warning);
|
||||
CHECK(IssueSeverity::Warning < IssueSeverity::Recoverable);
|
||||
CHECK(IssueSeverity::Recoverable < IssueSeverity::Fatal);
|
||||
|
||||
CHECK(std::string(integrityIssueName(IntegrityIssueKind::BadMagic)) == "badMagic");
|
||||
CHECK(std::string(integrityIssueName(IntegrityIssueKind::LightingInconsistent)) ==
|
||||
"lightingInconsistent");
|
||||
CHECK(std::string(repairActionName(RepairActionKind::RegenerateChunk)) == "regenerateChunk");
|
||||
CHECK(std::string(repairActionName(RepairActionKind::RemoveOrphanEntry)) ==
|
||||
"removeOrphanEntry");
|
||||
}
|
||||
|
||||
VF_TEST(aContainerDamagedInSeveralPlacesIsSalvagedInOnePass) {
|
||||
SaveContainer container = buildContainer(SaveVersion::V4, 5);
|
||||
ByteBuffer healthy = writeSaveContainer(container);
|
||||
ByteBuffer damaged = healthy;
|
||||
|
||||
EntrySlot broken = slotOf(damaged, 0);
|
||||
saveWriteU32At(damaged.data(), damaged.size(), broken.payloadAt + 8, 0u);
|
||||
|
||||
EntrySlot orphan = slotOf(damaged, 2);
|
||||
saveWriteU32At(damaged.data(), damaged.size(), orphan.entryAt + 16, 0u);
|
||||
|
||||
EntrySlot stale = slotOf(damaged, 3);
|
||||
std::size_t checksumAt = stale.payloadAt + stale.payloadBytes - 4;
|
||||
damaged[checksumAt] = static_cast<uint8_t>(damaged[checksumAt] ^ 0x0Fu);
|
||||
refreshTableChecksum(damaged);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(damaged);
|
||||
CHECK_EQ(report.countOf(IntegrityIssueKind::MalformedRecord), static_cast<std::size_t>(1));
|
||||
CHECK_EQ(report.countOf(IntegrityIssueKind::OrphanEntry), static_cast<std::size_t>(1));
|
||||
CHECK_EQ(report.countOf(IntegrityIssueKind::ChecksumMismatch), static_cast<std::size_t>(1));
|
||||
|
||||
RepairResult repaired = scanner.scanAndRepair(damaged);
|
||||
CHECK(repaired.ok);
|
||||
CHECK_EQ(repaired.chunksDropped, static_cast<std::size_t>(1));
|
||||
CHECK_EQ(repaired.orphanEntriesRemoved, static_cast<std::size_t>(1));
|
||||
CHECK_EQ(repaired.checksumsRewritten, static_cast<std::size_t>(1));
|
||||
CHECK_EQ(repaired.chunksPreserved, static_cast<std::size_t>(3));
|
||||
CHECK(scanner.scan(repaired.output).clean());
|
||||
|
||||
const Vec3i survivors[3] = {{1, 0, 2}, {3, 0, 6}, {4, 0, 8}};
|
||||
for (const Vec3i& coord : survivors) {
|
||||
ByteBuffer before;
|
||||
ByteBuffer after;
|
||||
CHECK(readChunkPayloadBytes(healthy.data(), healthy.size(), coord, before));
|
||||
CHECK(readChunkPayloadBytes(repaired.output.data(), repaired.output.size(), coord, after));
|
||||
CHECK(before == after);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user