Add tests for shutdown vs close
This commit is contained in:
@@ -55,3 +55,115 @@ TEST_CASE("Echo test") {
|
|||||||
server->shutdown();
|
server->shutdown();
|
||||||
runThread.join();
|
runThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ShutdownTestHandler : ConnectionHandler {
|
||||||
|
Arena arena;
|
||||||
|
std::span<std::string_view> reply;
|
||||||
|
WeakRef<MessageSender> wconn;
|
||||||
|
std::latch received_data{1};
|
||||||
|
ConnectionShutdown shutdown_mode = ConnectionShutdown::None;
|
||||||
|
std::atomic<bool> connection_closed{false};
|
||||||
|
|
||||||
|
void on_data_arrived(std::string_view data, Connection &conn) override {
|
||||||
|
reply = arena.allocate_span<std::string_view>(1);
|
||||||
|
reply[0] = arena.copy_string(data);
|
||||||
|
wconn = conn.get_weak_ref();
|
||||||
|
received_data.count_down();
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_connection_closed(Connection &) override { connection_closed = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Connection shutdown write-only mode") {
|
||||||
|
ShutdownTestHandler handler;
|
||||||
|
handler.shutdown_mode = ConnectionShutdown::WriteOnly;
|
||||||
|
weaseldb::Config config;
|
||||||
|
auto server = Server::create(config, handler, {});
|
||||||
|
int fd = server->create_local_connection();
|
||||||
|
|
||||||
|
auto runThread = std::thread{[&]() { server->run(); }};
|
||||||
|
|
||||||
|
// Send data to trigger handler
|
||||||
|
int w = write(fd, "test", 4);
|
||||||
|
REQUIRE(w == 4);
|
||||||
|
|
||||||
|
handler.received_data.wait();
|
||||||
|
|
||||||
|
// Send response with write shutdown
|
||||||
|
if (auto conn = handler.wconn.lock()) {
|
||||||
|
auto *conn_ptr = static_cast<Connection *>(conn.get());
|
||||||
|
conn_ptr->append_bytes(std::exchange(handler.reply, {}),
|
||||||
|
std::move(handler.arena),
|
||||||
|
ConnectionShutdown::WriteOnly);
|
||||||
|
} else {
|
||||||
|
REQUIRE(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the response
|
||||||
|
char buf[5];
|
||||||
|
buf[4] = 0;
|
||||||
|
int r = read(fd, buf, 4);
|
||||||
|
REQUIRE(r == 4);
|
||||||
|
CHECK(std::string(buf) == "test");
|
||||||
|
|
||||||
|
// After write shutdown, we should get EOF when trying to read more
|
||||||
|
char extra_buf[1];
|
||||||
|
int eof_result = read(fd, extra_buf, 1);
|
||||||
|
CHECK(eof_result == 0); // EOF indicates successful write shutdown
|
||||||
|
|
||||||
|
// Connection should still be alive (not closed) after write shutdown
|
||||||
|
// We can verify this by checking that we can still write to the socket
|
||||||
|
int write_result = write(fd, "x", 1);
|
||||||
|
CHECK(write_result == 1); // Should succeed - connection still alive
|
||||||
|
CHECK(handler.connection_closed.load() ==
|
||||||
|
false); // Connection should still be alive
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
server->shutdown();
|
||||||
|
runThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Connection shutdown full mode") {
|
||||||
|
ShutdownTestHandler handler;
|
||||||
|
handler.shutdown_mode = ConnectionShutdown::Full;
|
||||||
|
weaseldb::Config config;
|
||||||
|
auto server = Server::create(config, handler, {});
|
||||||
|
int fd = server->create_local_connection();
|
||||||
|
|
||||||
|
auto runThread = std::thread{[&]() { server->run(); }};
|
||||||
|
|
||||||
|
// Send data to trigger handler
|
||||||
|
int w = write(fd, "test", 4);
|
||||||
|
REQUIRE(w == 4);
|
||||||
|
|
||||||
|
handler.received_data.wait();
|
||||||
|
|
||||||
|
// Send response with full shutdown
|
||||||
|
if (auto conn = handler.wconn.lock()) {
|
||||||
|
auto *conn_ptr = static_cast<Connection *>(conn.get());
|
||||||
|
conn_ptr->append_bytes(std::exchange(handler.reply, {}),
|
||||||
|
std::move(handler.arena), ConnectionShutdown::Full);
|
||||||
|
} else {
|
||||||
|
REQUIRE(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the response - connection should close after this
|
||||||
|
char buf[5];
|
||||||
|
buf[4] = 0;
|
||||||
|
int r = read(fd, buf, 4);
|
||||||
|
REQUIRE(r == 4);
|
||||||
|
CHECK(std::string(buf) == "test");
|
||||||
|
|
||||||
|
// Connection should be closed by server (full shutdown)
|
||||||
|
char extra_buf[1];
|
||||||
|
int close_result = read(fd, extra_buf, 1);
|
||||||
|
CHECK(close_result == 0); // EOF indicates connection was closed
|
||||||
|
|
||||||
|
// The blocking read already synchronized - connection is definitely closed
|
||||||
|
CHECK(handler.connection_closed.load() ==
|
||||||
|
true); // Connection should be closed
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
server->shutdown();
|
||||||
|
runThread.join();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user