1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <lib/syslog/global.h>
6 #include <unittest/unittest.h>
7 
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <poll.h>
11 #include <unistd.h>
12 
13 extern void fx_log_reset_global(void);
14 
ends_with(const char * str,const char * suffix)15 bool ends_with(const char* str, const char* suffix) {
16   if (strlen(str) < strlen(suffix)) {
17     return false;
18   }
19   size_t l = strlen(suffix);
20   str += strlen(str) - l;
21   return strcmp(str, suffix) == 0;
22 }
23 
test_log_init(void)24 bool test_log_init(void) {
25   BEGIN_TEST;
26   fx_log_reset_global();
27   EXPECT_EQ(ZX_OK, fx_log_init(), "");
28   END_TEST;
29 }
30 
test_log_enabled_macro(void)31 bool test_log_enabled_macro(void) {
32   BEGIN_TEST;
33   fx_log_reset_global();
34   EXPECT_EQ(ZX_OK, fx_log_init(), "");
35   if (FX_VLOG_IS_ENABLED(1)) {
36     EXPECT_TRUE(false, "control should not reach this line");
37   }
38   if (!FX_LOG_IS_ENABLED(INFO)) {
39     EXPECT_TRUE(false, "control should not reach this line");
40   }
41   if (!FX_LOG_IS_ENABLED(ERROR)) {
42     EXPECT_TRUE(false, "control should not reach this line");
43   }
44   fx_log_reset_global();
45   END_TEST;
46 }
47 
init_helper(int fd,const char ** tags,int ntags)48 static inline zx_status_t init_helper(int fd, const char** tags, int ntags) {
49   fx_logger_config_t config = {.min_severity = FX_LOG_INFO,
50                                .console_fd = fd,
51                                .log_service_channel = ZX_HANDLE_INVALID,
52                                .tags = tags,
53                                .num_tags = ntags};
54 
55   return fx_log_init_with_config(&config);
56 }
57 
test_log_simple_write(void)58 bool test_log_simple_write(void) {
59   BEGIN_TEST;
60   fx_log_reset_global();
61   int pipefd[2];
62   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
63   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
64   FX_LOG(INFO, NULL, "test message");
65   char buf[256];
66   size_t n = read(pipefd[1], buf, sizeof(buf));
67   EXPECT_GT(n, 0u, "");
68   buf[n] = 0;
69   EXPECT_TRUE(ends_with(buf, "test message\n"), buf);
70   close(pipefd[1]);
71   fx_log_reset_global();
72   END_TEST;
73 }
74 
test_log_write(void)75 bool test_log_write(void) {
76   BEGIN_TEST;
77   fx_log_reset_global();
78   int pipefd[2];
79   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
80   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
81   FX_LOGF(INFO, NULL, "%d, %s", 10, "just some number");
82   char buf[256];
83   size_t n = read(pipefd[1], buf, sizeof(buf));
84   EXPECT_GT(n, 0u, "");
85   buf[n] = 0;
86   EXPECT_TRUE(ends_with(buf, "INFO: 10, just some number\n"), buf);
87   close(pipefd[1]);
88   fx_log_reset_global();
89   END_TEST;
90 }
91 
test_log_preprocessed_message(void)92 bool test_log_preprocessed_message(void) {
93   BEGIN_TEST;
94   fx_log_reset_global();
95   int pipefd[2];
96   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
97   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
98     FX_LOG(INFO, NULL, "%d, %s");
99   char buf[256];
100   size_t n = read(pipefd[1], buf, sizeof(buf));
101   EXPECT_GT(n, 0u, "");
102   buf[n] = 0;
103   EXPECT_TRUE(ends_with(buf, "INFO: %d, %s\n"), buf);
104   close(pipefd[1]);
105   fx_log_reset_global();
106   END_TEST;
107 }
108 
test_log_severity(void)109 bool test_log_severity(void) {
110   struct pollfd fd;
111   BEGIN_TEST;
112   fx_log_reset_global();
113   int pipefd[2];
114   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
115   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
116   FX_LOG_SET_SEVERITY(WARNING);
117   FX_LOGF(INFO, NULL, "%d, %s", 10, "just some number");
118   fd.fd = pipefd[1];
119   fd.events = POLLIN;
120   EXPECT_EQ(poll(&fd, 1, 1), 0, "");
121   close(pipefd[1]);
122   fx_log_reset_global();
123   END_TEST;
124 }
125 
test_log_write_with_tag(void)126 bool test_log_write_with_tag(void) {
127   BEGIN_TEST;
128   int pipefd[2];
129   fx_log_reset_global();
130   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
131   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
132   FX_LOGF(INFO, "tag", "%d, %s", 10, "just some string");
133   char buf[256];
134   size_t n = read(pipefd[1], buf, sizeof(buf));
135   EXPECT_GT(n, 0u, "");
136   buf[n] = 0;
137   EXPECT_TRUE(ends_with(buf, "[tag] INFO: 10, just some string\n"), buf);
138   close(pipefd[1]);
139   fx_log_reset_global();
140   END_TEST;
141 }
142 
test_log_write_with_global_tag(void)143 bool test_log_write_with_global_tag(void) {
144   BEGIN_TEST;
145   int pipefd[2];
146   fx_log_reset_global();
147   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
148   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], (const char* []){"gtag"}, 1), "");
149   FX_LOGF(INFO, "tag", "%d, %s", 10, "just some string");
150   char buf[256];
151   size_t n = read(pipefd[1], buf, sizeof(buf));
152   EXPECT_GT(n, 0u, "");
153   buf[n] = 0;
154   EXPECT_TRUE(ends_with(buf, "[gtag, tag] INFO: 10, just some string\n"), buf);
155   close(pipefd[1]);
156   fx_log_reset_global();
157   END_TEST;
158 }
159 
test_log_write_with_multi_global_tag(void)160 bool test_log_write_with_multi_global_tag(void) {
161   BEGIN_TEST;
162   int pipefd[2];
163   fx_log_reset_global();
164   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
165   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], (const char* []){"gtag", "gtag2"}, 2),
166             "");
167   FX_LOGF(INFO, "tag", "%d, %s", 10, "just some string");
168   char buf[256];
169   size_t n = read(pipefd[1], buf, sizeof(buf));
170   EXPECT_GT(n, 0u, "");
171   buf[n] = 0;
172   EXPECT_TRUE(ends_with(buf, "[gtag, gtag2, tag] INFO: 10, just some string\n"),
173               buf);
174   close(pipefd[1]);
175   fx_log_reset_global();
176   END_TEST;
177 }
178 
test_global_tag_limit(void)179 bool test_global_tag_limit(void) {
180   BEGIN_TEST;
181   fx_log_reset_global();
182   EXPECT_NE(ZX_OK, init_helper(-1, NULL, FX_LOG_MAX_TAGS + 1), "");
183   fx_log_reset_global();
184   END_TEST;
185 }
186 
test_msg_length_limit(void)187 bool test_msg_length_limit(void) {
188   BEGIN_TEST;
189   fx_log_reset_global();
190   int pipefd[2];
191   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
192   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
193   char msg[2048] = {0};
194   char buf[2048] = {0};
195   memset(msg, 'a', sizeof(msg) - 1);
196   FX_LOGF(INFO, NULL, "%s", msg);
197   size_t n = read(pipefd[1], buf, sizeof(buf));
198   EXPECT_GT(n, 0u, "");
199   msg[n] = 0;
200   EXPECT_TRUE(ends_with(buf, "a...\n"), buf);
201 
202   msg[0] = '%';
203   msg[1] = 's';
204   FX_LOG(INFO, NULL, msg);
205   n = read(pipefd[1], buf, sizeof(buf));
206   EXPECT_GT(n, 0u, "");
207   msg[n] = 0;
208   EXPECT_TRUE(ends_with(buf, "a...\n"), buf);
209   close(pipefd[1]);
210   fx_log_reset_global();
211   END_TEST;
212 }
213 
test_vlog_simple_write(void)214 bool test_vlog_simple_write(void) {
215   BEGIN_TEST;
216   fx_log_reset_global();
217   int pipefd[2];
218   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
219   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
220   FX_LOG_SET_VERBOSITY(1);
221   FX_VLOG(1, NULL, "test message");
222   char buf[256];
223   size_t n = read(pipefd[1], buf, sizeof(buf));
224   EXPECT_GT(n, 0u, "");
225   buf[n] = 0;
226   EXPECT_TRUE(ends_with(buf, "VLOG(1): test message\n"), buf);
227   close(pipefd[1]);
228   fx_log_reset_global();
229   END_TEST;
230 }
231 
test_vlog_write(void)232 bool test_vlog_write(void) {
233   BEGIN_TEST;
234   fx_log_reset_global();
235   int pipefd[2];
236   EXPECT_NE(pipe2(pipefd, O_NONBLOCK), -1, "");
237   EXPECT_EQ(ZX_OK, init_helper(pipefd[0], NULL, 0), "");
238   FX_LOG_SET_VERBOSITY(1);
239   FX_VLOGF(1, NULL, "%d, %s", 10, "just some number");
240   char buf[256];
241   size_t n = read(pipefd[1], buf, sizeof(buf));
242   EXPECT_GT(n, 0u, "");
243   buf[n] = 0;
244   EXPECT_TRUE(ends_with(buf, "VLOG(1): 10, just some number\n"), buf);
245   close(pipefd[1]);
246   fx_log_reset_global();
247   END_TEST;
248 }
249 
250 BEGIN_TEST_CASE(syslog_tests)
251 RUN_TEST(test_log_init)
252 RUN_TEST(test_log_simple_write)
253 RUN_TEST(test_log_write)
254 RUN_TEST(test_log_preprocessed_message)
255 RUN_TEST(test_log_severity)
256 RUN_TEST(test_log_write_with_tag)
257 RUN_TEST(test_log_write_with_global_tag)
258 RUN_TEST(test_log_write_with_multi_global_tag)
259 RUN_TEST(test_log_enabled_macro)
260 RUN_TEST(test_vlog_simple_write)
261 RUN_TEST(test_vlog_write)
262 END_TEST_CASE(syslog_tests)
263 
264 BEGIN_TEST_CASE(syslog_tests_edge_cases)
265 RUN_TEST(test_global_tag_limit)
266 RUN_TEST(test_msg_length_limit)
267 END_TEST_CASE(syslog_tests_edge_cases)
268