test: cover testRegionCompact

This commit is contained in:
dualfroz committed 2026-09-12 19:50:59 +02:00
1 parent 3836db2624
commit 65523d4755
1 file changed
+161
+161
View File
@@ -154,3 +154,164 @@ VF_TEST(aChunkThatOutgrowsItsRunMovesToTheEndAndLeavesAHole) {
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{1, 0, 0}, busyChunk(3)), false)); CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{1, 0, 0}, busyChunk(3)), false));
CHECK(buffer.size() > sizeBefore); CHECK(buffer.size() > sizeBefore);
std::vector<ChunkFragment> after = compactor.survey(buffer);
CHECK_EQ(after.size(), static_cast<std::size_t>(3));
CHECK_EQ(after[1].sectorOffset, static_cast<uint32_t>(sizeBefore / saveSectorBytes));
CHECK(after[1].sectorCount > abandoned);
CHECK(compactor.fragmentationPercent(buffer) > 0);
SaveScanner scanner;
CHECK(scanner.scan(buffer).clean());
CHECK(!isCanonicalSaveLayout(buffer.data(), buffer.size()));
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK_EQ(stats.holeSectors, abandoned);
CHECK(stats.bytesReclaimed >= abandoned * saveSectorBytes);
CHECK_EQ(stats.fragmentationAfter, 0);
CHECK(isCanonicalSaveLayout(out.data(), out.size()));
}
VF_TEST(aChunkThatShrinksKeepsUnusedSectorsInsideItsOwnRun) {
SaveContainer container;
container.version = SaveVersion::V4;
container.chunks.push_back(buildRecord(Vec3i{0, 0, 0}, busyChunk(1)));
container.chunks.push_back(buildRecord(Vec3i{1, 0, 0}, uniformChunk(Block::Stone)));
ByteBuffer buffer = writeSaveContainer(container);
std::size_t sizeBefore = buffer.size();
RegionCompactor compactor;
uint32_t runBefore = compactor.survey(buffer)[0].sectorCount;
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{0, 0, 0}, uniformChunk(Block::Dirt)),
false));
CHECK_EQ(buffer.size(), sizeBefore);
std::vector<ChunkFragment> after = compactor.survey(buffer);
CHECK_EQ(after[0].sectorCount, runBefore);
CHECK(after[0].neededSectors < runBefore);
CHECK_EQ(after[0].excessSectors, runBefore - after[0].neededSectors);
CHECK(compactor.fragmentationPercent(buffer) > 0);
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK_EQ(stats.holeSectors, static_cast<uint32_t>(0));
CHECK_EQ(stats.excessSectors, runBefore - after[0].neededSectors);
CHECK(out.size() < buffer.size());
CHECK_EQ(stats.fragmentationAfter, 0);
}
VF_TEST(compactionRewritesEveryChunkByteIdentically) {
SaveContainer container;
container.version = SaveVersion::V4;
for (int i = 0; i < 5; ++i)
container.chunks.push_back(buildRecord(Vec3i{i, 1, i}, busyChunk(i * 17)));
ByteBuffer buffer = writeSaveContainer(container);
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{2, 1, 2}, uniformChunk(Block::Sand)),
false));
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{0, 1, 0}, busyChunk(5)), false));
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{4, 1, 4}, uniformChunk(Block::Gravel)),
false));
std::vector<Vec3i> coords = coordsOf(buffer);
CHECK_EQ(coords.size(), static_cast<std::size_t>(5));
std::vector<ByteBuffer> before;
for (const Vec3i& coord : coords) {
ByteBuffer payload;
CHECK(readChunkPayloadBytes(buffer.data(), buffer.size(), coord, payload));
before.push_back(payload);
}
RegionCompactor compactor;
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK(stats.ok);
CHECK_EQ(stats.chunksKept, static_cast<std::size_t>(5));
CHECK_EQ(stats.chunksDropped, static_cast<std::size_t>(0));
CHECK_EQ(stats.chunksRepacked, static_cast<std::size_t>(0));
for (std::size_t i = 0; i < coords.size(); ++i) {
ByteBuffer after;
CHECK(readChunkPayloadBytes(out.data(), out.size(), coords[i], after));
CHECK(after == before[i]);
}
CHECK(isCanonicalSaveLayout(out.data(), out.size()));
SaveScanner scanner;
CHECK(scanner.scan(out).clean());
}
VF_TEST(compactionReportsTheSectorsItGaveBack) {
ByteBuffer buffer = writeSaveContainer(uniformContainer(4));
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{1, 0, 0}, busyChunk(2)), false));
CHECK(updateChunkInPlace(buffer, buildRecord(Vec3i{3, 0, 0}, busyChunk(4)), false));
RegionCompactor compactor;
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK_EQ(stats.sectorBytes, saveSectorBytes);
CHECK_EQ(stats.bytesBefore, buffer.size());
CHECK_EQ(stats.bytesAfter, out.size());
CHECK_EQ(stats.bytesReclaimed, buffer.size() - out.size());
CHECK_EQ(stats.sectorsBefore, static_cast<uint32_t>(buffer.size() / saveSectorBytes));
CHECK_EQ(stats.sectorsAfter, static_cast<uint32_t>(out.size() / saveSectorBytes));
CHECK(stats.holeSectors > 0u);
CHECK(stats.chunksMoved > 0u);
CHECK_EQ(stats.operations, 4u + stats.chunksMoved + 1u);
CHECK(stats.fragmentationBefore > 0);
CHECK_EQ(stats.fragmentationAfter, 0);
}
VF_TEST(compactionDropsChunksThatHoldNothing) {
SaveContainer container;
container.version = SaveVersion::V4;
container.chunks.push_back(buildRecord(Vec3i{0, 0, 0}, uniformChunk(Block::Stone)));
container.chunks.push_back(buildRecord(Vec3i{1, 0, 0}, uniformChunk(Block::Air)));
container.chunks.push_back(buildRecord(Vec3i{2, 0, 0}, uniformChunk(Block::Dirt)));
ByteBuffer buffer = writeSaveContainer(container);
RegionCompactor compactor;
std::vector<ChunkFragment> fragments = compactor.survey(buffer);
CHECK(!fragments[0].empty);
CHECK(fragments[1].empty);
CHECK(!fragments[2].empty);
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK_EQ(stats.chunksDropped, static_cast<std::size_t>(1));
CHECK_EQ(stats.chunksKept, static_cast<std::size_t>(2));
CHECK_EQ(coordsOf(out).size(), static_cast<std::size_t>(2));
ByteBuffer gone;
CHECK(!readChunkPayloadBytes(out.data(), out.size(), Vec3i{1, 0, 0}, gone));
RegionCompactor keeper;
keeper.dropEmptyChunks = false;
ByteBuffer kept;
CompactionStats keptStats;
CHECK(keeper.compact(buffer, kept, keptStats));
CHECK_EQ(keptStats.chunksDropped, static_cast<std::size_t>(0));
CHECK_EQ(keptStats.chunksKept, static_cast<std::size_t>(3));
CHECK(kept == buffer);
}
VF_TEST(repackingWithCompressionShrinksTheFileAndStillReadsBack) {
SaveContainer container;
container.version = SaveVersion::V4;
container.chunks.push_back(buildRecord(Vec3i{0, 0, 0}, uniformChunk(Block::Stone)));
container.chunks.push_back(buildRecord(Vec3i{1, 0, 0}, uniformChunk(Block::Dirt)));
container.chunks.push_back(buildRecord(Vec3i{2, 0, 0}, busyChunk(9)));
ByteBuffer buffer = writeSaveContainer(container);
RegionCompactor compactor;
compactor.repackWithStrongerCompression = true;
ByteBuffer out;
CompactionStats stats;
CHECK(compactor.compact(buffer, out, stats));
CHECK(stats.chunksRepacked > 0u);
CHECK(out.size() < buffer.size());
CHECK(isCanonicalSaveLayout(out.data(), out.size()));