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 <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 13extern void fx_log_reset_global(void); 14 15bool 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 24bool 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 31bool 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 48static 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 58bool 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 75bool 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 92bool 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 109bool 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 126bool 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 143bool 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 160bool 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 179bool 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 187bool 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 214bool 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 232bool 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 250BEGIN_TEST_CASE(syslog_tests) 251RUN_TEST(test_log_init) 252RUN_TEST(test_log_simple_write) 253RUN_TEST(test_log_write) 254RUN_TEST(test_log_preprocessed_message) 255RUN_TEST(test_log_severity) 256RUN_TEST(test_log_write_with_tag) 257RUN_TEST(test_log_write_with_global_tag) 258RUN_TEST(test_log_write_with_multi_global_tag) 259RUN_TEST(test_log_enabled_macro) 260RUN_TEST(test_vlog_simple_write) 261RUN_TEST(test_vlog_write) 262END_TEST_CASE(syslog_tests) 263 264BEGIN_TEST_CASE(syslog_tests_edge_cases) 265RUN_TEST(test_global_tag_limit) 266RUN_TEST(test_msg_length_limit) 267END_TEST_CASE(syslog_tests_edge_cases) 268