test: cover testSaveIntegrity
This commit is contained in:
1 parent
52643276c2
commit
6bcdf07562
1 file changed
+160
@@ -154,3 +154,163 @@ VF_TEST(aStaleRecordChecksumIsRecoverableAtTheEndOfTheRecord) {
|
||||
CHECK(report.repairable());
|
||||
}
|
||||
|
||||
VF_TEST(aTruncatedBufferIsRecoverableAtTheCutOffPayload) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
EntrySlot last = slotOf(buffer, 2);
|
||||
buffer.resize(buffer.size() - saveSectorBytes);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::TruncatedBuffer);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, last.payloadAt);
|
||||
CHECK_EQ(report.issues[0].entryIndex, 2);
|
||||
CHECK_EQ(report.readableChunks, static_cast<std::size_t>(2));
|
||||
}
|
||||
|
||||
VF_TEST(aHeaderPromisingMoreChunksThanFitIsRecoverable) {
|
||||
SaveContainer empty;
|
||||
empty.version = SaveVersion::V4;
|
||||
empty.sectorBytes = 64;
|
||||
ByteBuffer buffer = writeSaveContainer(empty);
|
||||
CHECK_EQ(buffer.size(), static_cast<std::size_t>(64));
|
||||
saveWriteU32At(buffer.data(), buffer.size(), 16, 3u);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.countOf(IntegrityIssueKind::ChunkCountOverrun), static_cast<std::size_t>(1));
|
||||
const IntegrityIssue* issue = report.firstOf(IntegrityIssueKind::ChunkCountOverrun);
|
||||
CHECK(issue != nullptr);
|
||||
if (issue == nullptr) return;
|
||||
CHECK(issue->severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(issue->byteOffset, static_cast<std::size_t>(16));
|
||||
CHECK_EQ(report.declaredChunks, static_cast<std::size_t>(3));
|
||||
CHECK_EQ(report.tableEntries, static_cast<std::size_t>(1));
|
||||
}
|
||||
|
||||
VF_TEST(aChunkFiledUnderTheWrongRegionIsRecoverable) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
EntrySlot slot = slotOf(buffer, 1);
|
||||
saveWriteU32At(buffer.data(), buffer.size(), slot.entryAt, static_cast<uint32_t>(100));
|
||||
refreshTableChecksum(buffer);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::ChunkOutsideRegion);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, slot.entryAt);
|
||||
CHECK_EQ(report.issues[0].entryIndex, 1);
|
||||
CHECK_EQ(report.issues[0].chunkCoord.x, 100);
|
||||
CHECK_EQ(report.readableChunks, static_cast<std::size_t>(2));
|
||||
}
|
||||
|
||||
VF_TEST(aChunkAboveTheWorldCeilingIsRecoverable) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
EntrySlot slot = slotOf(buffer, 0);
|
||||
saveWriteU32At(buffer.data(), buffer.size(), slot.entryAt + 4, static_cast<uint32_t>(40));
|
||||
refreshTableChecksum(buffer);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::ChunkHeightOutOfRange);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, slot.entryAt + 4);
|
||||
CHECK_EQ(report.issues[0].entryIndex, 0);
|
||||
CHECK(report.issues[0].detail.find("-4..19") != std::string::npos);
|
||||
}
|
||||
|
||||
VF_TEST(anEntryPointingAtNothingIsAnOrphan) {
|
||||
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;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::OrphanEntry);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, slot.entryAt + 12);
|
||||
CHECK_EQ(report.issues[0].entryIndex, 1);
|
||||
CHECK_EQ(report.readableChunks, static_cast<std::size_t>(2));
|
||||
}
|
||||
|
||||
VF_TEST(twoEntriesSharingSectorsAreReportedAsOverlapping) {
|
||||
ByteBuffer buffer = writeSaveContainer(buildContainer(SaveVersion::V4, 3));
|
||||
EntrySlot first = slotOf(buffer, 0);
|
||||
EntrySlot second = slotOf(buffer, 1);
|
||||
uint32_t offset = 0, count = 0, bytes = 0;
|
||||
CHECK(saveReadU32At(buffer.data(), buffer.size(), first.entryAt + 12, offset));
|
||||
CHECK(saveReadU32At(buffer.data(), buffer.size(), first.entryAt + 16, count));
|
||||
CHECK(saveReadU32At(buffer.data(), buffer.size(), first.entryAt + 20, bytes));
|
||||
saveWriteU32At(buffer.data(), buffer.size(), second.entryAt + 12, offset);
|
||||
saveWriteU32At(buffer.data(), buffer.size(), second.entryAt + 16, count);
|
||||
saveWriteU32At(buffer.data(), buffer.size(), second.entryAt + 20, bytes);
|
||||
refreshTableChecksum(buffer);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.countOf(IntegrityIssueKind::OverlappingEntries), static_cast<std::size_t>(1));
|
||||
const IntegrityIssue* issue = report.firstOf(IntegrityIssueKind::OverlappingEntries);
|
||||
CHECK(issue != nullptr);
|
||||
if (issue == nullptr) return;
|
||||
CHECK(issue->severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(issue->entryIndex, 1);
|
||||
CHECK_EQ(issue->byteOffset, second.entryAt + 12);
|
||||
}
|
||||
|
||||
VF_TEST(aBlockIndexOutsideThePaletteIsRecoverable) {
|
||||
SaveContainer container;
|
||||
container.version = SaveVersion::V2;
|
||||
Chunk blocks = uniformChunk(Block::Stone);
|
||||
blocks.set(1, 0, 0, Block::Grass);
|
||||
container.chunks.push_back(buildRecord(Vec3i{0, 0, 0}, blocks, SaveVersion::V2));
|
||||
container.chunks.push_back(
|
||||
buildRecord(Vec3i{1, 0, 0}, uniformChunk(Block::Dirt), SaveVersion::V2));
|
||||
ByteBuffer buffer = writeSaveContainer(container);
|
||||
|
||||
EntrySlot slot = slotOf(buffer, 0);
|
||||
std::size_t indicesAt = slot.payloadAt + 4 + 2 + 4;
|
||||
buffer[indicesAt + 5] = 200;
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::PaletteIndexOutOfRange);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, slot.payloadAt);
|
||||
CHECK_EQ(report.issues[0].entryIndex, 0);
|
||||
CHECK(report.issues[0].detail.find("200") != std::string::npos);
|
||||
}
|
||||
|
||||
VF_TEST(aLightPlaneOfTheWrongLengthIsRecoverable) {
|
||||
SaveContainer container;
|
||||
container.version = SaveVersion::V4;
|
||||
SaveChunkRecord record =
|
||||
buildRecord(Vec3i{0, 0, 0}, uniformChunk(Block::Stone), SaveVersion::V4);
|
||||
record.light.resize(100);
|
||||
container.chunks.push_back(std::move(record));
|
||||
ByteBuffer buffer = writeSaveContainer(container);
|
||||
|
||||
SaveScanner scanner;
|
||||
IntegrityReport report = scanner.scan(buffer);
|
||||
CHECK_EQ(report.issues.size(), static_cast<std::size_t>(1));
|
||||
CHECK(report.issues[0].kind == IntegrityIssueKind::LightingInconsistent);
|
||||
CHECK(report.issues[0].severity == IssueSeverity::Recoverable);
|
||||
CHECK_EQ(report.issues[0].byteOffset, slotOf(buffer, 0).payloadAt);
|
||||
CHECK(report.issues[0].detail.find("100") != std::string::npos);
|
||||
}
|
||||
|
||||
VF_TEST(lightThatDisagreesWithItsBlocksIsOnlyAWarning) {
|
||||
SaveContainer container;
|
||||
container.version = SaveVersion::V4;
|
||||
SaveChunkRecord record =
|
||||
buildRecord(Vec3i{0, 0, 0}, uniformChunk(Block::Stone), SaveVersion::V4);
|
||||
record.light[0] = 0xF0;
|
||||
record.light[1] = 0xF0;
|
||||
container.chunks.push_back(std::move(record));
|
||||
ByteBuffer buffer = writeSaveContainer(container);
|
||||
|
||||
Reference in new issue
Block a user