test: cover testNetServer
This commit is contained in:
1 parent
5c104046b4
commit
b77f92afb0
1 file changed
+162
@@ -158,3 +158,165 @@ VF_TEST(aBlockChangeInsideBothViewsReachesEachClientExactlyOnce) {
|
||||
CHECK(server.sessionFor(slotLeft)->view().hasChunk(Vec3i{1, 0, 0}));
|
||||
CHECK(server.sessionFor(slotRight)->view().hasChunk(Vec3i{1, 0, 0}));
|
||||
|
||||
server.setBlock(20, 3, 5, Block::Glowstone);
|
||||
for (uint64_t tick = 80; tick < 120; ++tick) {
|
||||
server.update(tick);
|
||||
left.step(tick);
|
||||
right.step(tick);
|
||||
}
|
||||
|
||||
CHECK(left.world.blockAt(20, 3, 5) == Block::Glowstone);
|
||||
CHECK(right.world.blockAt(20, 3, 5) == Block::Glowstone);
|
||||
CHECK_EQ(left.session->stats().blockChangesApplied, static_cast<uint64_t>(1));
|
||||
CHECK_EQ(right.session->stats().blockChangesApplied, static_cast<uint64_t>(1));
|
||||
CHECK_EQ(server.stats().blockUpdatesSent, static_cast<uint64_t>(2));
|
||||
CHECK_EQ(server.stats().editsApplied, static_cast<uint64_t>(1));
|
||||
}
|
||||
|
||||
VF_TEST(aBlockChangeIsNeverSentToAClientThatDoesNotHoldThatChunk) {
|
||||
ServerConfig config = quietServerConfig();
|
||||
World world;
|
||||
NetServer server(world, config);
|
||||
buildTerrain(world, -6, 6);
|
||||
|
||||
int slotNear = server.acceptClient();
|
||||
int slotFar = server.acceptClient();
|
||||
placeAt(server, slotNear, 8.0f, 8.0f, 8.0f);
|
||||
placeAt(server, slotFar, 72.0f, 8.0f, 72.0f);
|
||||
|
||||
TransportConfig transportConfig = config.transport;
|
||||
SessionConfig sessionConfig = clientConfigFor(config);
|
||||
RemoteClient near(server, slotNear, transportConfig, sessionConfig, "near");
|
||||
RemoteClient far(server, slotFar, transportConfig, sessionConfig, "far");
|
||||
for (uint64_t tick = 0; tick < 60; ++tick) {
|
||||
server.update(tick);
|
||||
near.step(tick);
|
||||
far.step(tick);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) server.setBlock(i, 3, 0, Block::Obsidian);
|
||||
for (uint64_t tick = 60; tick < 100; ++tick) {
|
||||
server.update(tick);
|
||||
near.step(tick);
|
||||
far.step(tick);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) CHECK(near.world.blockAt(i, 3, 0) == Block::Obsidian);
|
||||
CHECK_EQ(near.session->stats().blockChangesApplied, static_cast<uint64_t>(3));
|
||||
CHECK_EQ(far.session->stats().blockChangesApplied, static_cast<uint64_t>(0));
|
||||
CHECK_EQ(far.session->stats().multiBlockChangesApplied, static_cast<uint64_t>(0));
|
||||
CHECK_EQ(far.world.chunkAt(Vec3i{0, 0, 0}), nullptr);
|
||||
CHECK_EQ(server.stats().blockUpdatesSent, static_cast<uint64_t>(3));
|
||||
}
|
||||
|
||||
VF_TEST(anEditFromOneClientIsBroadcastToTheOtherThroughTheAuthoritativeWorld) {
|
||||
ServerConfig config = quietServerConfig();
|
||||
World world;
|
||||
NetServer server(world, config);
|
||||
buildTerrain(world, -2, 2);
|
||||
|
||||
int slotA = server.acceptClient();
|
||||
int slotB = server.acceptClient();
|
||||
placeAt(server, slotA, 8.0f, 8.0f, 8.0f);
|
||||
placeAt(server, slotB, 8.0f, 8.0f, 8.0f);
|
||||
|
||||
TransportConfig transportConfig = config.transport;
|
||||
SessionConfig sessionConfig = clientConfigFor(config);
|
||||
RemoteClient builder(server, slotA, transportConfig, sessionConfig, "builder");
|
||||
RemoteClient watcher(server, slotB, transportConfig, sessionConfig, "watcher");
|
||||
for (uint64_t tick = 0; tick < 40; ++tick) {
|
||||
server.update(tick);
|
||||
builder.step(tick);
|
||||
watcher.step(tick);
|
||||
}
|
||||
|
||||
builder.session->requestBlockEdit(4, 9, 4, Block::Glowstone);
|
||||
for (uint64_t tick = 40; tick < 80; ++tick) {
|
||||
server.update(tick);
|
||||
builder.step(tick);
|
||||
watcher.step(tick);
|
||||
}
|
||||
|
||||
CHECK(world.blockAt(4, 9, 4) == Block::Glowstone);
|
||||
CHECK(builder.world.blockAt(4, 9, 4) == Block::Glowstone);
|
||||
CHECK(watcher.world.blockAt(4, 9, 4) == Block::Glowstone);
|
||||
CHECK_EQ(server.stats().editsApplied, static_cast<uint64_t>(1));
|
||||
CHECK_EQ(watcher.session->stats().blockChangesApplied, static_cast<uint64_t>(1));
|
||||
}
|
||||
|
||||
VF_TEST(theBandwidthBudgetDelaysPacketsAcrossTicksWithoutLosingAnyOfThem) {
|
||||
ServerConfig config = quietServerConfig();
|
||||
config.viewRadius = 1;
|
||||
config.chunksPerClientPerTick = 4;
|
||||
config.bytesPerClientPerTick = 220;
|
||||
World world;
|
||||
NetServer server(world, config);
|
||||
buildTerrain(world, -3, 3);
|
||||
|
||||
int slot = server.acceptClient();
|
||||
placeAt(server, slot, 8.0f, 8.0f, 8.0f);
|
||||
TransportConfig transportConfig = config.transport;
|
||||
RemoteClient only(server, slot, transportConfig, clientConfigFor(config), "budgeted");
|
||||
|
||||
bool everQueued = false;
|
||||
uint64_t peakQueuedBytes = 0;
|
||||
for (uint64_t tick = 0; tick < 40; ++tick) {
|
||||
server.update(tick);
|
||||
only.step(tick);
|
||||
if (server.stats().queuedPackets > 0) everQueued = true;
|
||||
if (server.stats().queuedBytes > peakQueuedBytes)
|
||||
peakQueuedBytes = server.stats().queuedBytes;
|
||||
// A single oversized packet is allowed through on its own, but the
|
||||
// budget must never be exceeded by a whole extra packet.
|
||||
CHECK(server.stats().bytesSentThisTick <= 220u + 4096u);
|
||||
}
|
||||
CHECK(everQueued);
|
||||
CHECK(peakQueuedBytes > 220u);
|
||||
|
||||
for (uint64_t tick = 40; tick < 400; ++tick) {
|
||||
server.update(tick);
|
||||
only.step(tick);
|
||||
}
|
||||
CHECK_EQ(server.stats().queuedPackets, static_cast<uint64_t>(0));
|
||||
CHECK_EQ(only.world.chunkCount(), static_cast<std::size_t>(5));
|
||||
CHECK_EQ(only.session->stats().chunksApplied, static_cast<uint64_t>(5));
|
||||
|
||||
// Nothing was dropped on the way: the client sees the same blocks.
|
||||
for (int x = 0; x < chunkSize; ++x)
|
||||
for (int z = 0; z < chunkSize; ++z)
|
||||
CHECK(only.world.blockAt(x, 3, z) == world.blockAt(x, 3, z));
|
||||
}
|
||||
|
||||
VF_TEST(anUnbudgetedServerSendsTheSameChunksInFarFewerTicks) {
|
||||
ServerConfig budgeted = quietServerConfig();
|
||||
budgeted.viewRadius = 1;
|
||||
budgeted.chunksPerClientPerTick = 4;
|
||||
budgeted.bytesPerClientPerTick = 220;
|
||||
|
||||
ServerConfig open = budgeted;
|
||||
open.bytesPerClientPerTick = 0;
|
||||
|
||||
uint64_t ticksNeeded[2] = {0, 0};
|
||||
for (int variant = 0; variant < 2; ++variant) {
|
||||
const ServerConfig& config = variant == 0 ? budgeted : open;
|
||||
World world;
|
||||
NetServer server(world, config);
|
||||
buildTerrain(world, -3, 3);
|
||||
int slot = server.acceptClient();
|
||||
placeAt(server, slot, 8.0f, 8.0f, 8.0f);
|
||||
TransportConfig transportConfig = config.transport;
|
||||
RemoteClient only(server, slot, transportConfig, clientConfigFor(config), "probe");
|
||||
|
||||
uint64_t tick = 0;
|
||||
for (; tick < 500; ++tick) {
|
||||
server.update(tick);
|
||||
only.step(tick);
|
||||
if (only.world.chunkCount() == 5) break;
|
||||
}
|
||||
ticksNeeded[variant] = tick;
|
||||
CHECK_EQ(only.world.chunkCount(), static_cast<std::size_t>(5));
|
||||
}
|
||||
CHECK(ticksNeeded[0] > ticksNeeded[1]);
|
||||
CHECK(ticksNeeded[1] < 20u);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user