Skip to content

Commit 9c9b01b

Browse files
Test stream handlers and Stream::is_readable()
1 parent b18a6e8 commit 9c9b01b

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

test/test.cc

+111
Original file line numberDiff line numberDiff line change
@@ -8434,3 +8434,114 @@ TEST(ClientInThreadTest, Issue2068) {
84348434
t.join();
84358435
}
84368436
}
8437+
8438+
template <typename S, typename C>
8439+
static void stream_handler_test(S &svr, C &cli) {
8440+
const auto delay = std::chrono::milliseconds{200};
8441+
const auto timeout_us =
8442+
std::chrono::duration_cast<std::chrono::microseconds>(delay).count() / 2;
8443+
8444+
svr.Get("/", [delay](const Request &req, Response &res) {
8445+
// Request should contain limited default headers
8446+
EXPECT_EQ(req.has_header("Host"), true);
8447+
EXPECT_EQ(req.has_header("User-Agent"), true);
8448+
EXPECT_EQ(req.has_header("Connection"), true);
8449+
// Need connection to close at the end for test to succeed
8450+
EXPECT_EQ(req.get_header_value("Connection"), "close");
8451+
// REMOTE_ADDR, REMOTE_PORT, LOCAL_ADDR, LOCAL_PORT = 4
8452+
EXPECT_EQ(req.headers.size(), (4 + 3));
8453+
8454+
res.set_stream_handler([&](Stream &strm) -> bool {
8455+
char buf[16]{};
8456+
// Client shpuld time out first
8457+
std::this_thread::sleep_for(delay);
8458+
strm.write(buf, sizeof(buf));
8459+
8460+
// Synchronize with client and close connection
8461+
EXPECT_TRUE(strm.wait_readable());
8462+
8463+
// Read to avoid RST on Windows
8464+
strm.read(buf, sizeof(buf));
8465+
8466+
return true;
8467+
});
8468+
});
8469+
auto thread = std::thread([&]() { svr.listen(HOST, PORT); });
8470+
8471+
auto se = detail::scope_exit([&] {
8472+
svr.stop();
8473+
thread.join();
8474+
ASSERT_FALSE(svr.is_running());
8475+
});
8476+
8477+
svr.wait_until_ready();
8478+
8479+
Request req;
8480+
req.method = "GET";
8481+
req.path = "/";
8482+
req.response_handler = [](const Response &res) -> bool {
8483+
EXPECT_EQ(res.get_header_value("Connection"), "close");
8484+
EXPECT_EQ(res.headers.size(), 1);
8485+
return true;
8486+
};
8487+
req.stream_handler = [delay](Stream &strm) -> bool {
8488+
char buf[16]{};
8489+
ssize_t n = 0;
8490+
// Buffer should be empty and first read should time out
8491+
EXPECT_FALSE(strm.is_readable());
8492+
EXPECT_FALSE(strm.wait_readable());
8493+
8494+
// Sever will send data soon
8495+
std::this_thread::sleep_for(delay);
8496+
EXPECT_TRUE(strm.wait_readable());
8497+
8498+
n = strm.read(buf, sizeof(buf) / 2);
8499+
EXPECT_EQ(sizeof(buf) / 2, n);
8500+
8501+
// Server sent 16 bytes, we read 8; remainder should be buffered
8502+
EXPECT_TRUE(strm.is_readable());
8503+
8504+
// Read remaining bytes from buffer
8505+
n = strm.read(buf, sizeof(buf) / 2);
8506+
EXPECT_EQ(sizeof(buf) / 2, n);
8507+
8508+
// Buffer should be empty
8509+
EXPECT_FALSE(strm.is_readable());
8510+
8511+
// Signal server to close connection
8512+
strm.write(buf, sizeof(buf));
8513+
std::this_thread::sleep_for(delay);
8514+
8515+
// Server should have closed connection
8516+
n = strm.read(buf, sizeof(buf));
8517+
EXPECT_EQ(0, n);
8518+
8519+
return true;
8520+
};
8521+
8522+
cli.set_read_timeout(0, timeout_us);
8523+
8524+
Response res;
8525+
Error error;
8526+
ASSERT_TRUE(cli.send(req, res, error));
8527+
EXPECT_EQ(StatusCode::OK_200, res.status);
8528+
EXPECT_EQ(res.headers.size(), 1);
8529+
EXPECT_TRUE(res.body.empty());
8530+
}
8531+
8532+
TEST(StreamHandlerTest, Basic) {
8533+
Server svr;
8534+
Client cli(HOST, PORT);
8535+
8536+
stream_handler_test(svr, cli);
8537+
}
8538+
8539+
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
8540+
TEST(StreamHandlerTest, BasicSSL) {
8541+
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
8542+
SSLClient cli(HOST, PORT);
8543+
cli.enable_server_certificate_verification(false);
8544+
8545+
stream_handler_test(svr, cli);
8546+
}
8547+
#endif

0 commit comments

Comments
 (0)