Skip to content

Commit 109f6f1

Browse files
committed
Fixed some bugs in the socket appender (TCP) test code.
1 parent 5433025 commit 109f6f1

File tree

1 file changed

+91
-64
lines changed

1 file changed

+91
-64
lines changed

test/app/socket_appender_test.cpp

Lines changed: 91 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class socket_init {
4242
};
4343
#endif
4444

45+
enum class log_server_status { LOG_SERVER_AWAITING_STARTUP, LOG_SERVER_RUNNING, LOG_SERVER_FINISHED };
46+
4547
int main(int argc, char **argv) {
4648
#ifdef _WIN32
4749
socket_init ws_init{};
@@ -96,10 +98,8 @@ void set_socket_recv_timeout(log4cpp::common::socket_fd sockfd) {
9698
#endif
9799
}
98100

99-
void tcp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer_stack prefer, unsigned short port,
100-
unsigned int expected_log_count) {
101-
std::string prefer_str;
102-
log4cpp::common::to_string(prefer, prefer_str);
101+
void tcp_log_server_loop(std::atomic<log_server_status> &status, log4cpp::common::prefer_stack prefer,
102+
unsigned short port, unsigned int expected_log_count) {
103103
log4cpp::common::socket_fd server_fd =
104104
socket(prefer == log4cpp::common::prefer_stack::IPv6 ? AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
105105
if (log4cpp::common::INVALID_FD == server_fd) {
@@ -108,25 +108,40 @@ void tcp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer
108108
}
109109

110110
sockaddr_storage local_addr{};
111+
socklen_t addr_len = 0;
112+
#ifdef _DEBUG
113+
char addr_str[INET6_ADDRSTRLEN];
114+
#endif
111115
if (prefer == log4cpp::common::prefer_stack::IPv6) {
112116
// NOLINTNEXTLINE
113117
sockaddr_in6 &local_addr6 = reinterpret_cast<sockaddr_in6 &>(local_addr);
114118
local_addr6.sin6_family = AF_INET6;
115119
local_addr6.sin6_addr = in6addr_any;
116120
local_addr6.sin6_port = htons(port);
121+
addr_len = sizeof(sockaddr_in6);
122+
#ifdef _DEBUG
123+
inet_ntop(AF_INET6, &local_addr6.sin6_addr, addr_str, sizeof(addr_str));
124+
#endif
117125
}
118126
else {
119127
// NOLINTNEXTLINE
120128
sockaddr_in &local_addr4 = reinterpret_cast<sockaddr_in &>(local_addr);
121129
local_addr4.sin_family = AF_INET;
122130
local_addr4.sin_addr.s_addr = INADDR_ANY;
123131
local_addr4.sin_port = htons(port);
132+
addr_len = sizeof(sockaddr_in);
133+
#ifdef _DEBUG
134+
inet_ntop(AF_INET, &local_addr4.sin_addr, addr_str, sizeof(addr_str));
135+
#endif
124136
}
125137

138+
#ifdef _DEBUG
139+
log4cpp::common::log4c_debug(stdout, "[tcp_socket_appender_test] bind %s@%u\n", addr_str, port);
140+
#endif
141+
126142
set_reuse_addr_port(server_fd);
127143

128-
int val = bind(server_fd, reinterpret_cast<sockaddr *>(&local_addr),
129-
prefer == log4cpp::common::prefer_stack::IPv6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));
144+
int val = bind(server_fd, reinterpret_cast<sockaddr *>(&local_addr), addr_len);
130145
if (-1 == val) {
131146
#ifdef _WIN32
132147
int wsa_error = WSAGetLastError();
@@ -154,13 +169,6 @@ void tcp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer
154169
}
155170

156171
sockaddr_storage remote_addr{};
157-
socklen_t addr_len = 0;
158-
if (prefer == log4cpp::common::prefer_stack::IPv6) {
159-
addr_len = sizeof(sockaddr_in6);
160-
}
161-
else {
162-
addr_len = sizeof(sockaddr_in);
163-
}
164172
log4cpp::common::socket_fd client_fd = accept(server_fd, reinterpret_cast<sockaddr *>(&remote_addr), &addr_len);
165173
if (log4cpp::common::INVALID_FD == client_fd) {
166174
#ifdef _WIN32
@@ -175,36 +183,90 @@ void tcp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer
175183
return;
176184
}
177185
char buffer[1024];
186+
std::string pending;
178187
unsigned int actual_log_count = 0;
179188
set_socket_recv_timeout(client_fd);
180-
srv_running.store(true);
181-
while (srv_running.load()) {
189+
status.store(log_server_status::LOG_SERVER_RUNNING);
190+
for (actual_log_count = 0; actual_log_count < expected_log_count;) {
182191
ssize_t len = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
183192
if (len > 0) {
184193
buffer[len] = 0;
185-
++actual_log_count;
186-
printf("[tcp_socket_appender_test] [%u]: %s", actual_log_count, buffer);
194+
pending.append(buffer, static_cast<size_t>(len));
195+
196+
size_t pos = 0;
197+
while (true) {
198+
size_t nl = pending.find('\n', pos);
199+
if (nl == std::string::npos) break;
200+
201+
std::string line = pending.substr(pos, nl - pos);
202+
if (!line.empty() && line.back() == '\r') line.pop_back();
203+
204+
++actual_log_count;
205+
printf("[tcp_socket_appender_test] [%u]: %s\n", actual_log_count, line.c_str());
206+
207+
pos = nl + 1;
208+
}
209+
pending.erase(0, pos);
187210
}
188211
else if (len == -1) {
189212
if (errno != EINTR) {
213+
#ifdef _DEBUG
214+
log4cpp::common::log4c_debug(stderr, "[tcp_socket_appender_test] interrupted");
215+
#endif
190216
break;
191217
}
192218
}
193219
else {
194220
// Connection closed by peer
221+
#ifdef _DEBUG
222+
log4cpp::common::log4c_debug(stderr, "[tcp_socket_appender_test] recv failed! errno:%d,%s\n", errno,
223+
strerror(errno));
224+
#endif
195225
break;
196226
}
197227
}
228+
status.store(log_server_status::LOG_SERVER_FINISHED);
198229
log4cpp::common::shutdown_socket(client_fd);
199230
log4cpp::common::close_socket(client_fd);
200231
log4cpp::common::close_socket(server_fd);
201-
ASSERT_GE(expected_log_count, actual_log_count);
202-
ASSERT_GT(actual_log_count, 0U);
232+
ASSERT_EQ(expected_log_count, actual_log_count);
203233
fflush(stdout);
204234
}
205235

206-
void udp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer_stack prefer, unsigned short port,
207-
unsigned int expected_log_count) {
236+
TEST(socket_appender_test, tcp_socket_appender_test) {
237+
const std::string config_file = "tcp_socket_appender_test.json";
238+
auto &log_mgr = log4cpp::supervisor::get_logger_manager();
239+
ASSERT_NO_THROW(log_mgr.load_config(config_file));
240+
const log4cpp::config::log4cpp *config = log_mgr.get_config();
241+
const log4cpp::config::socket_appender &socker_appender_cfg = config->appenders.socket.value();
242+
unsigned short port = socker_appender_cfg.port;
243+
log4cpp::common::prefer_stack prefer = socker_appender_cfg.prefer;
244+
245+
std::atomic status(log_server_status::LOG_SERVER_AWAITING_STARTUP);
246+
247+
const std::shared_ptr<log4cpp::log::logger> log = log4cpp::logger_manager::get_logger();
248+
log4cpp::log_level max_level = log->get_level();
249+
unsigned int expected_log_count = static_cast<int>(max_level) + 1; // enum is zero-indexed
250+
251+
std::thread log_server_thread =
252+
std::thread(&tcp_log_server_loop, std::ref(status), prefer, port, expected_log_count);
253+
254+
while (log_server_status::LOG_SERVER_RUNNING != status.load()) {
255+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
256+
}
257+
258+
log->trace("this is a trace");
259+
log->debug("this is a debug");
260+
log->info("this is a info");
261+
log->warn("this is an warning");
262+
log->error("this is an error");
263+
log->fatal("this is a fatal");
264+
265+
log_server_thread.join();
266+
}
267+
268+
void udp_log_server_loop(std::atomic<log_server_status> &status, log4cpp::common::prefer_stack prefer,
269+
unsigned short port, unsigned int expected_log_count) {
208270
log4cpp::common::socket_fd server_fd =
209271
socket(prefer == log4cpp::common::prefer_stack::IPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
210272
if (log4cpp::common::INVALID_FD == server_fd) {
@@ -266,8 +328,8 @@ void udp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer
266328
unsigned int actual_log_count = 0;
267329
sockaddr_storage remote_addr{};
268330
socklen_t remote_addr_len = sizeof(remote_addr);
269-
srv_running.store(true);
270-
while (srv_running.load()) {
331+
status.store(log_server_status::LOG_SERVER_RUNNING);
332+
for (actual_log_count = 0; actual_log_count < expected_log_count;) {
271333
ssize_t len = recvfrom(server_fd, buffer, sizeof(buffer) - 1, 0,
272334
reinterpret_cast<struct sockaddr *>(&remote_addr), &remote_addr_len);
273335
if (len > 0) {
@@ -283,48 +345,13 @@ void udp_log_server_loop(std::atomic<bool> &srv_running, log4cpp::common::prefer
283345
// Since UDP is connectionless, a recvfrom return value of 0 signifies the successful receipt of a zero-length
284346
// datagram, and the program should continue its loop
285347
}
348+
status.store(log_server_status::LOG_SERVER_FINISHED);
286349
log4cpp::common::shutdown_socket(server_fd);
287350
log4cpp::common::close_socket(server_fd);
288-
ASSERT_GE(expected_log_count, actual_log_count);
289-
ASSERT_GT(actual_log_count, 0U);
351+
ASSERT_EQ(expected_log_count, actual_log_count);
290352
fflush(stdout);
291353
}
292354

293-
TEST(socket_appender_test, tcp_socket_appender_test) {
294-
const std::string config_file = "tcp_socket_appender_test.json";
295-
auto &log_mgr = log4cpp::supervisor::get_logger_manager();
296-
ASSERT_NO_THROW(log_mgr.load_config(config_file));
297-
const log4cpp::config::log4cpp *config = log_mgr.get_config();
298-
const log4cpp::config::socket_appender &socker_appender_cfg = config->appenders.socket.value();
299-
unsigned short port = socker_appender_cfg.port;
300-
log4cpp::common::prefer_stack prefer = socker_appender_cfg.prefer;
301-
302-
std::atomic<bool> running(false);
303-
304-
const std::shared_ptr<log4cpp::log::logger> log = log4cpp::logger_manager::get_logger();
305-
log4cpp::log_level max_level = log->get_level();
306-
unsigned int expected_log_count = static_cast<int>(max_level) + 1; // enum is zero-indexed
307-
308-
std::thread log_server_thread =
309-
std::thread(&tcp_log_server_loop, std::ref(running), prefer, port, expected_log_count);
310-
311-
while (!running.load()) {
312-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
313-
}
314-
315-
log->trace("this is a trace");
316-
log->debug("this is a debug");
317-
log->info("this is a info");
318-
log->warn("this is an warning");
319-
log->error("this is an error");
320-
log->fatal("this is a fatal");
321-
322-
std::this_thread::sleep_for(std::chrono::seconds(1));
323-
324-
running.store(false);
325-
log_server_thread.join();
326-
}
327-
328355
TEST(socket_appender_test, udp_socket_appender_test) {
329356
const std::string config_file = "udp_socket_appender_test.json";
330357
auto &log_mgr = log4cpp::supervisor::get_logger_manager();
@@ -334,14 +361,14 @@ TEST(socket_appender_test, udp_socket_appender_test) {
334361
unsigned short port = socker_appender_cfg.port;
335362
log4cpp::common::prefer_stack prefer = socker_appender_cfg.prefer;
336363

337-
std::atomic<bool> running(false);
364+
std::atomic status(log_server_status::LOG_SERVER_AWAITING_STARTUP);
338365
const std::shared_ptr<log4cpp::log::logger> log = log4cpp::logger_manager::get_logger();
339366
log4cpp::log_level max_level = log->get_level();
340367
unsigned int expected_log_count = static_cast<int>(max_level) + 1; // enum is zero-indexed
341368

342369
std::thread log_server_thread =
343-
std::thread(&udp_log_server_loop, std::ref(running), prefer, port, expected_log_count);
344-
while (!running.load()) {
370+
std::thread(&udp_log_server_loop, std::ref(status), prefer, port, expected_log_count);
371+
while (log_server_status::LOG_SERVER_RUNNING != status.load()) {
345372
std::this_thread::sleep_for(std::chrono::milliseconds(100));
346373
}
347374
log->trace("this is a trace");
@@ -350,6 +377,6 @@ TEST(socket_appender_test, udp_socket_appender_test) {
350377
log->warn("this is an warning");
351378
log->error("this is an error");
352379
log->fatal("this is a fatal");
353-
running.store(false);
380+
354381
log_server_thread.join();
355382
}

0 commit comments

Comments
 (0)