test: cover testRegionCompact
This commit is contained in:
1 parent
3836db2624
commit
65523d4755
1 file changed
+161
@@ -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()));
|
||||||
|
|
||||||
Reference in new issue
Block a user