6 #include <sys/socket.h>
10 #include <logcommon.h>
11 #include <logconfig.h>
13 int (*write_to_log)(log_id_t, log_priority, const char *tag, const char *msg) = NULL;
14 void (*destroy_backend)() = NULL;
16 extern void __dlog_init_pipe(const struct log_config *conf);
20 static bool critical_failure_detected = false;
21 void __wrap_syslog_critical_failure(const char *message, ...)
23 critical_failure_detected = true;
26 int __wrap_dup2(int oldfd, int newfd)
28 assert(oldfd == 1337);
29 assert(newfd == 1337);
33 static int fail_write;
34 static size_t called_write;
35 ssize_t __wrap_write(int fd, const void *buf, size_t count)
39 const ssize_t retval = (fail_write & 1) ? -1 : (300 + called_write);
44 static int fail_connect;
45 static size_t called_connect;
46 int __wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
50 const int retval = (fail_connect & 1) ? -1 : (100 + called_connect);
55 static int fail_recv_pipe;
56 static size_t called_recv_pipe;
57 static int expected_timeout = DEFAULT_WAIT_PIPE_MS;
58 int __wrap_recv_pipe(int sockfd, int timeout_ms)
60 assert(timeout_ms == expected_timeout);
61 expected_timeout /= 2;
62 if (expected_timeout < MIN_WAIT_PIPE_MS)
63 expected_timeout = MIN_WAIT_PIPE_MS;
67 const int retval = (fail_recv_pipe & 1) ? -1 : 1337;
72 static bool fail_socket;
73 int __wrap_socket(int domain, int type, int protocol)
84 int __wrap_close(int fd)
86 assert(fd == 1337 || fd == 17);
93 struct log_config conf = {NULL, NULL};
95 __dlog_init_pipe(&conf);
96 assert(critical_failure_detected);
97 assert(!write_to_log);
98 critical_failure_detected = false;
100 assert(LOG_ID_MAIN == 0);
101 for (int i = 1; i < LOG_ID_MAX; ++i) {
102 char key[MAX_CONF_KEY_LEN];
103 assert(snprintf(key, sizeof key, "%s_write_sock", log_name_by_id((log_id_t)i)) > 0);
104 log_config_set(&conf, key, "/foo");
107 #define MAXLEN (sizeof((struct sockaddr_un *)NULL)->sun_path) // static const size_t was not enough and there is no constexpr in C
108 char pipe_path[MAXLEN + 2] = { 'x', 'f', 'o', 'o', '\0',
109 [5 ... MAXLEN] = 'x' };
112 log_config_set(&conf, "main_write_sock", pipe_path); // "xfoo"
113 __dlog_init_pipe(&conf);
114 assert(critical_failure_detected);
115 assert(!write_to_log);
116 assert(!destroy_backend);
117 critical_failure_detected = false;
121 log_config_set(&conf, "main_write_sock", pipe_path); // "/fooxxxxxx..."
122 __dlog_init_pipe(&conf);
123 assert(critical_failure_detected);
124 assert(!write_to_log);
125 assert(!destroy_backend);
126 critical_failure_detected = false;
129 log_config_set(&conf, "main_write_sock", pipe_path); // "/foo"
130 __dlog_init_pipe(&conf);
131 assert(!critical_failure_detected);
132 assert(write_to_log);
133 assert(destroy_backend);
135 #define ACTUAL_PAYLOAD_SIZE (LOG_MAX_PAYLOAD_SIZE - 5) // 1 priority, 3 tag "xx\0", 1 null terminator
136 char payload[ACTUAL_PAYLOAD_SIZE + 1] = { [0 ... ACTUAL_PAYLOAD_SIZE] = 'x' };
138 #define F(B, P, L) assert(write_to_log(B, P, "xx", L) == DLOG_ERROR_INVALID_PARAMETER)
139 F(LOG_ID_MAIN , DLOG_ERROR , payload);
140 payload[ACTUAL_PAYLOAD_SIZE] = '\0';
142 F(LOG_ID_INVALID, DLOG_ERROR , payload);
143 F(LOG_ID_MAX , DLOG_ERROR , payload);
144 F(LOG_ID_MAIN , DLOG_UNKNOWN , payload);
145 F(LOG_ID_MAIN , (log_priority) -7, payload);
146 F(LOG_ID_MAIN , (log_priority) 23, payload);
147 F(LOG_ID_MAIN , DLOG_ERROR , NULL);
150 #define TC(FC, FW, FR, ERR, RES, TAG, CC, CW, CR) do { \
153 fail_recv_pipe = FR; \
154 errno_to_set = ERR; \
155 assert(write_to_log(LOG_ID_MAIN, DLOG_ERROR, TAG, payload) == RES); \
156 assert(CC == called_connect); \
157 assert(CW == called_write); \
158 assert(CR == called_recv_pipe); \
159 called_connect = 0; \
161 called_recv_pipe = 0; \
164 const size_t ITERATIONS_TO_REACH_MIN_TIMEOUT = 2 + (int) log2((float) DEFAULT_WAIT_PIPE_MS / MIN_WAIT_PIPE_MS);
165 for (size_t i = 0; i < ITERATIONS_TO_REACH_MIN_TIMEOUT; ++i)
166 TC(0, 0, 1, 13, -1, "xx", 1, 1, 1);
167 assert(expected_timeout == MIN_WAIT_PIPE_MS);
170 TC(0, 0, 0, 56, -1, "xx", 0, 0, 0);
173 TC(1, 0, 0, 27, -1, "xx", 1, 0, 0);
175 #define WTC(FW, ERR, RES, CC, CW, CR) TC(0, FW, 0, ERR, RES, "xx", CC, CW, CR)
176 WTC(1 , EIO, -1, 1, 1, 0);
177 WTC(0 , EIO, 302, 1, 2, 1);
178 // at this point the first connection succeeded
179 WTC(3 , EBADF, -1, 1, 2, 0);
180 WTC(3 , EPIPE, -1, 1, 2, 0);
181 WTC(1 , EIO, -1, 0, 1, 0);
182 WTC(13, EBADF, -1, 1, 4, 1);
183 WTC(5 , EPIPE, -1, 1, 3, 1);
184 WTC(5 , EBADF, 304, 1, 4, 1);
185 WTC(1 , EBADF, 304, 1, 4, 1);
186 WTC(1 , EPIPE, 303, 1, 3, 1);
189 // NULL tag is fine, apparently.
190 TC(0, 0, 0, 45, 301, NULL, 0, 1, 0);
195 assert(closed == 1); // just MAIN, we'd never used the others