From 4d99c986d9310eb5fbc29618487577d645788eec Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 28 Feb 2017 12:59:01 -0800 Subject: [PATCH] liblog: add LOGGER_STDERR frontend Standalone, this logger provides no end-to-end capability. Only provides a writer, no reader transport. All output goes, logcat-like, into the stderr stream. Output can be adjusted with environment variables ANDROID_PRINTF_LOG and ANDROID_LOG_TAGS. liblog_*.__android_log_bswrite_and_print___max print fails if a string member is truncated with "Binary log entry conversion failed" and -1. We expose the truncated content in the tests and in LOGGER_STDERR. The purpose of this transport selection is for command-line tools, providing a means to shunt the logs to be mixed in with the tool's error stream. Test: gTest liblog-unit-tests Bug: 27405083 Change-Id: If344b6e3e67df2dc86ce317cfad8af8e857727b7 --- liblog/Android.bp | 1 + liblog/config_write.c | 23 +++ liblog/include/log/log_frontend.h | 11 +- liblog/logger_write.c | 6 +- liblog/stderr_write.c | 219 ++++++++++++++++++++++ liblog/tests/Android.mk | 2 + liblog/tests/liblog_test.cpp | 215 ++++++++++++++++----- liblog/tests/liblog_test_stderr.cpp | 5 + liblog/tests/liblog_test_stderr_local.cpp | 4 + 9 files changed, 428 insertions(+), 58 deletions(-) create mode 100644 liblog/stderr_write.c create mode 100644 liblog/tests/liblog_test_stderr.cpp create mode 100644 liblog/tests/liblog_test_stderr_local.cpp diff --git a/liblog/Android.bp b/liblog/Android.bp index 310dbf4c3..bb8c3af2b 100644 --- a/liblog/Android.bp +++ b/liblog/Android.bp @@ -26,6 +26,7 @@ liblog_sources = [ "logger_read.c", "logger_write.c", "logprint.c", + "stderr_write.c", ] liblog_host_sources = [ "fake_log_device.c", diff --git a/liblog/config_write.c b/liblog/config_write.c index 583dcff3a..6a6c2205d 100644 --- a/liblog/config_write.c +++ b/liblog/config_write.c @@ -78,6 +78,29 @@ LIBLOG_HIDDEN void __android_log_config_write() { &fakeLoggerWrite); #endif } + + if (__android_log_frontend & LOGGER_STDERR) { + extern struct android_log_transport_write stderrLoggerWrite; + + /* + * stderr logger should be primary if we can be the only one, or if + * already in the primary list. Otherwise land in the persist list. + * Remember we can be called here if we are already initialized. + */ + if (list_empty(&__android_log_transport_write)) { + __android_log_add_transport(&__android_log_transport_write, + &stderrLoggerWrite); + } else { + struct android_log_transport_write *transp; + write_transport_for_each(transp, &__android_log_transport_write) { + if (transp == &stderrLoggerWrite) { + return; + } + } + __android_log_add_transport(&__android_log_persist_write, + &stderrLoggerWrite); + } + } } LIBLOG_HIDDEN void __android_log_config_write_close() { diff --git a/liblog/include/log/log_frontend.h b/liblog/include/log/log_frontend.h index 952777971..5efa548af 100644 --- a/liblog/include/log/log_frontend.h +++ b/liblog/include/log/log_frontend.h @@ -17,11 +17,12 @@ extern "C" { /* * Logging frontends, bit mask to select features. Function returns selection. */ -#define LOGGER_DEFAULT 0x0 -#define LOGGER_LOGD 0x1 -#define LOGGER_KERNEL 0x2 /* Reserved/Deprecated */ -#define LOGGER_NULL 0x4 /* Does not release resources of other selections */ -#define LOGGER_LOCAL 0x8 /* logs sent to local memory */ +#define LOGGER_DEFAULT 0x00 +#define LOGGER_LOGD 0x01 +#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */ +#define LOGGER_NULL 0x04 /* Does not release resources of other selections */ +#define LOGGER_LOCAL 0x08 /* logs sent to local memory */ +#define LOGGER_STDERR 0x10 /* logs sent to stderr */ /* Both return the selected frontend flag mask, or negative errno */ int android_set_log_frontend(int frontend_flag); diff --git a/liblog/logger_write.c b/liblog/logger_write.c index e149e682f..2a9710164 100644 --- a/liblog/logger_write.c +++ b/liblog/logger_write.c @@ -664,9 +664,9 @@ LIBLOG_ABI_PUBLIC int android_set_log_frontend(int frontend_flag) return retval; } - __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD; + __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR; - frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD; + frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR; if (__android_log_frontend != frontend_flag) { __android_log_frontend = frontend_flag; @@ -695,7 +695,7 @@ LIBLOG_ABI_PUBLIC int android_get_log_frontend() if (write_to_log == __write_to_log_null) { ret = LOGGER_NULL; } else { - __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD; + __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR; ret = __android_log_frontend; if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) { diff --git a/liblog/stderr_write.c b/liblog/stderr_write.c new file mode 100644 index 000000000..b73929923 --- /dev/null +++ b/liblog/stderr_write.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * stderr write handler. Output is logcat-like, and responds to + * logcat's environment variables ANDROID_PRINTF_LOG and + * ANDROID_LOG_TAGS to filter output. + * + * This transport only provides a writer, that means that it does not + * provide an End-To-End capability as the logs are effectively _lost_ + * to the stderr file stream. The purpose of this transport is to + * supply a means for command line tools to report their logging + * to the stderr stream, in line with all other activities. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "log_portability.h" +#include "logger.h" + +static int stderrOpen(); +static void stderrClose(); +static int stderrAvailable(log_id_t logId); +static int stderrWrite(log_id_t logId, struct timespec* ts, + struct iovec* vec, size_t nr); + +struct stderrContext { + AndroidLogFormat* logformat; +#if defined(__ANDROID__) + EventTagMap* eventTagMap; +#endif +}; + +LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = { + .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node }, + .context.private = NULL, + .name = "stderr", + .available = stderrAvailable, + .open = stderrOpen, + .close = stderrClose, + .write = stderrWrite, +}; + +static int stderrOpen() +{ + struct stderrContext* ctx; + const char* envStr; + bool setFormat; + + if (!stderr || (fileno(stderr) < 0)) { + return -EBADF; + } + + if (stderrLoggerWrite.context.private) { + return fileno(stderr); + } + + ctx = calloc(1, sizeof(struct stderrContext)); + if (!ctx) { + return -ENOMEM; + } + + ctx->logformat = android_log_format_new(); + if (!ctx->logformat) { + free(ctx); + return -ENOMEM; + } + + envStr = getenv("ANDROID_PRINTF_LOG"); + setFormat = false; + + if (envStr) { + char* formats = strdup(envStr); + char* sv = NULL; + char* arg = formats; + while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) { + AndroidLogPrintFormat format = android_log_formatFromString(arg); + arg = NULL; + if (format == FORMAT_OFF) { + continue; + } + if (android_log_setPrintFormat(ctx->logformat, format) <= 0) { + continue; + } + setFormat = true; + } + free(formats); + } + if (!setFormat) { + AndroidLogPrintFormat format = android_log_formatFromString( + "threadtime"); + android_log_setPrintFormat(ctx->logformat, format); + } + envStr = getenv("ANDROID_LOG_TAGS"); + if (envStr) { + android_log_addFilterString(ctx->logformat, envStr); + } + stderrLoggerWrite.context.private = ctx; + + return fileno(stderr); +} + +static void stderrClose() +{ + struct stderrContext* ctx = stderrLoggerWrite.context.private; + + if (ctx) { + stderrLoggerWrite.context.private = NULL; + if (ctx->logformat) { + android_log_format_free(ctx->logformat); + ctx->logformat = NULL; + } +#if defined(__ANDROID__) + if (ctx->eventTagMap) { + android_closeEventTagMap(ctx->eventTagMap); + ctx->eventTagMap = NULL; + } +#endif + } +} + +static int stderrAvailable(log_id_t logId) +{ + if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) { + return -EINVAL; + } + return 1; +} + +static int stderrWrite(log_id_t logId, struct timespec* ts, + struct iovec* vec, size_t nr) +{ + struct log_msg log_msg; + AndroidLogEntry entry; + char binaryMsgBuf[1024]; + int err; + size_t i; + struct stderrContext* ctx = stderrLoggerWrite.context.private; + + if (!ctx) return -EBADF; + if (!vec || !nr) return -EINVAL; + + log_msg.entry.len = 0; + log_msg.entry.hdr_size = sizeof(log_msg.entry); + log_msg.entry.pid = getpid(); +#ifdef __BIONIC__ + log_msg.entry.tid = gettid(); +#else + log_msg.entry.tid = getpid(); +#endif + log_msg.entry.sec = ts->tv_sec; + log_msg.entry.nsec = ts->tv_nsec; + log_msg.entry.lid = logId; + log_msg.entry.uid = __android_log_uid(); + + for (i = 0; i < nr; ++i) { + size_t len = vec[i].iov_len; + if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) { + len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len; + } + if (!len) continue; + memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len); + log_msg.entry.len += len; + } + + if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) { +#if defined(__ANDROID__) + if (!ctx->eventTagMap) { + ctx->eventTagMap = android_openEventTagMap(NULL); + } +#endif + err = android_log_processBinaryLogBuffer(&log_msg.entry_v1, + &entry, +#if defined(__ANDROID__) + ctx->eventTagMap, +#else + NULL, +#endif + binaryMsgBuf, + sizeof(binaryMsgBuf)); + } else { + err = android_log_processLogBuffer(&log_msg.entry_v1, &entry); + } + + /* print known truncated data, in essence logcat --debug */ + if ((err < 0) && !entry.message) return -EINVAL; + + if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) { + return log_msg.entry.len; + } + + err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry); + if (err < 0) return errno ? -errno : -EINVAL; + return log_msg.entry.len; +} diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk index cfea45202..0e6432ced 100644 --- a/liblog/tests/Android.mk +++ b/liblog/tests/Android.mk @@ -57,6 +57,8 @@ test_c_flags := \ test_src_files := \ liblog_test_default.cpp \ liblog_test_local.cpp \ + liblog_test_stderr.cpp \ + liblog_test_stderr_local.cpp \ log_id_test.cpp \ log_radio_test.cpp \ log_read_test.cpp \ diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp index bc0ea4c25..2537fac23 100644 --- a/liblog/tests/liblog_test.cpp +++ b/liblog/tests/liblog_test.cpp @@ -47,7 +47,7 @@ #endif #endif -#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL)) +#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || !defined(USING_LOGGER_STDERR)) #ifdef liblog // a binary clue that we are overriding the test names // Does not support log reading blocking feature yet // Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD) @@ -62,6 +62,11 @@ #define USING_LOGGER_DEFAULT #endif #endif +#ifdef USING_LOGGER_STDERR +# define SUPPORTS_END_TO_END 0 +#else +# define SUPPORTS_END_TO_END 1 +#endif // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and // non-syscall libs. Since we are only using this in the emergency of @@ -98,7 +103,7 @@ TEST(liblog, __android_log_btwrite) { usleep(1000); } -#if (defined(__ANDROID__) && !defined(USING_LOGGER_LOCAL)) +#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT)) static std::string popenToString(std::string command) { std::string ret; @@ -176,8 +181,8 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); log_time ts(CLOCK_MONOTONIC); - ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); -#ifndef USING_LOGGER_LOCAL + EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); +#ifdef USING_LOGGER_DEFAULT // Check that we can close and reopen the logger bool pmsgActiveAfter__android_log_btwrite; bool logdwActiveAfter__android_log_btwrite; @@ -200,8 +205,8 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { #endif log_time ts1(CLOCK_MONOTONIC); - ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1))); -#ifndef USING_LOGGER_LOCAL + EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1))); +#ifdef USING_LOGGER_DEFAULT if (getuid() == AID_ROOT) { pmsgActiveAfter__android_log_btwrite = isPmsgActive(); logdwActiveAfter__android_log_btwrite = isLogdwActive(); @@ -220,7 +225,7 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { break; } - ASSERT_EQ(log_msg.entry.pid, pid); + EXPECT_EQ(log_msg.entry.pid, pid); if ((log_msg.entry.len != sizeof(android_log_event_long_t)) || (log_msg.id() != LOG_ID_EVENTS)) { @@ -242,8 +247,8 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { } } - EXPECT_EQ(1, count); - EXPECT_EQ(1, second_count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); + EXPECT_EQ(SUPPORTS_END_TO_END, second_count); android_logger_list_close(logger_list); #else @@ -251,6 +256,54 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { #endif } +#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL)) +static void print_frontend(const char* prefix, int logger) { + static const char orstr[] = " | "; + + if (!prefix) { + prefix = ""; + } + if (logger < 0) { + fprintf(stderr, "%s%s\n", prefix, strerror(-logger)); + return; + } + + if (logger == LOGGER_DEFAULT) { + fprintf(stderr, "%sLOGGER_DEFAULT", prefix); + prefix = orstr; + } + if (logger & LOGGER_LOGD) { + fprintf(stderr, "%sLOGGER_LOGD", prefix); + prefix = orstr; + } + if (logger & LOGGER_KERNEL) { + fprintf(stderr, "%sLOGGER_KERNEL", prefix); + prefix = orstr; + } + if (logger & LOGGER_NULL) { + fprintf(stderr, "%sLOGGER_NULL", prefix); + prefix = orstr; + } + if (logger & LOGGER_LOCAL) { + fprintf(stderr, "%sLOGGER_LOCAL", prefix); + prefix = orstr; + } + if (logger & LOGGER_STDERR) { + fprintf(stderr, "%sLOGGER_STDERR", prefix); + prefix = orstr; + } + logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL | + LOGGER_STDERR); + if (logger) { + fprintf(stderr, "%s0x%x", prefix, logger); + prefix = orstr; + } + if (prefix == orstr) { + fprintf(stderr, "\n"); + } +} +#endif + // This test makes little sense standalone, and requires the tests ahead // and behind us, to make us whole. We could incorporate a prefix and // suffix test to make this standalone, but opted to not complicate this. @@ -261,10 +314,14 @@ TEST(liblog, android_set_log_frontend) { #endif int logger = android_get_log_frontend(); + print_frontend("android_get_log_frontend = ", logger); EXPECT_NE(LOGGER_NULL, logger); - EXPECT_EQ(LOGGER_NULL, android_set_log_frontend(LOGGER_NULL)); - EXPECT_EQ(LOGGER_NULL, android_get_log_frontend()); + int ret; + EXPECT_EQ(LOGGER_NULL, ret = android_set_log_frontend(LOGGER_NULL)); + print_frontend("android_set_log_frontend = ", ret); + EXPECT_EQ(LOGGER_NULL, ret = android_get_log_frontend()); + print_frontend("android_get_log_frontend = ", ret); pid_t pid = getpid(); @@ -273,7 +330,7 @@ TEST(liblog, android_set_log_frontend) { LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); log_time ts(CLOCK_MONOTONIC); - ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); + EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); usleep(1000000); @@ -285,7 +342,7 @@ TEST(liblog, android_set_log_frontend) { break; } - ASSERT_EQ(log_msg.entry.pid, pid); + EXPECT_EQ(log_msg.entry.pid, pid); if ((log_msg.entry.len != sizeof(android_log_event_long_t)) || (log_msg.id() != LOG_ID_EVENTS)) { @@ -307,8 +364,10 @@ TEST(liblog, android_set_log_frontend) { android_logger_list_close(logger_list); - EXPECT_EQ(logger, android_set_log_frontend(logger)); - EXPECT_EQ(logger, android_get_log_frontend()); + EXPECT_EQ(logger, ret = android_set_log_frontend(logger)); + print_frontend("android_set_log_frontend = ", ret); + EXPECT_EQ(logger, ret = android_get_log_frontend()); + print_frontend("android_get_log_frontend = ", ret); // False negative if liblog.__android_log_btwrite__android_logger_list_read // fails above, so we will likely succeed. But we will have so many @@ -350,7 +409,7 @@ static void bswrite_test(const char *message) { log_time ts(CLOCK_REALTIME); #endif - ASSERT_LT(0, __android_log_bswrite(0, message)); + EXPECT_LT(0, __android_log_bswrite(0, message)); size_t num_lines = 1, size = 0, length = 0, total = 0; const char *cp = message; while (*cp) { @@ -382,7 +441,7 @@ static void bswrite_test(const char *message) { break; } - ASSERT_EQ(log_msg.entry.pid, pid); + EXPECT_EQ(log_msg.entry.pid, pid); if ((log_msg.entry.sec < (ts.tv_sec - 1)) || ((ts.tv_sec + 1) < log_msg.entry.sec) @@ -413,19 +472,26 @@ static void bswrite_test(const char *message) { int processBinaryLogBuffer = android_log_processBinaryLogBuffer( &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf)); EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer); - if (processBinaryLogBuffer == 0) { + if ((processBinaryLogBuffer == 0) || entry.message) { size_t line_overhead = 20; if (pid > 99999) ++line_overhead; if (pid > 999999) ++line_overhead; fflush(stderr); - EXPECT_EQ((int)((line_overhead * num_lines) + size), - android_log_printLogLine(logformat, fileno(stderr), &entry)); + if (processBinaryLogBuffer) { + EXPECT_GT((int)((line_overhead * num_lines) + size), + android_log_printLogLine(logformat, + fileno(stderr), &entry)); + } else { + EXPECT_EQ((int)((line_overhead * num_lines) + size), + android_log_printLogLine(logformat, + fileno(stderr), &entry)); + } } android_log_format_free(logformat); } } - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); android_logger_list_close(logger_list); #else @@ -527,7 +593,7 @@ static void buf_write_test(const char *message) { android_log_format_free(logformat); } - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); android_logger_list_close(logger_list); #else @@ -1058,9 +1124,13 @@ TEST(liblog, max_payload) { android_logger_list_close(logger_list); +#if SUPPORTS_END_TO_END EXPECT_EQ(true, matches); EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast(max_len)); +#else + EXPECT_EQ(false, matches); +#endif #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif @@ -1123,7 +1193,7 @@ TEST(liblog, __android_log_buf_print__maxtag) { android_log_format_free(logformat); } - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); android_logger_list_close(logger_list); #else @@ -1184,6 +1254,11 @@ TEST(liblog, too_big_payload) { android_logger_list_close(logger_list); +#if !SUPPORTS_END_TO_END + max_len = max_len ? + max_len : + LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag); +#endif EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag), static_cast(max_len)); @@ -1255,14 +1330,14 @@ TEST(liblog, dual_reader) { android_logger_list_close(logger_list1); android_logger_list_close(logger_list2); - EXPECT_EQ(num, count1); - EXPECT_EQ(num - 10, count2); + EXPECT_EQ(num * SUPPORTS_END_TO_END, count1); + EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#ifndef USING_LOGGER_LOCAL // Do not retest logprint +#ifdef USING_LOGGER_DEFAULT // Do not retest logprint static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) { return android_log_shouldPrintLine(p_format, tag, pri) && !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1)); @@ -1331,9 +1406,9 @@ TEST(liblog, filterRule) { android_log_format_free(p_format); } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT -#ifndef USING_LOGGER_LOCAL // Do not retest property handling +#ifdef USING_LOGGER_DEFAULT // Do not retest property handling TEST(liblog, is_loggable) { #ifdef __ANDROID__ static const char tag[] = "is_loggable"; @@ -1632,12 +1707,12 @@ TEST(liblog, is_loggable) { GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT // Following tests the specific issues surrounding error handling wrt logd. // Kills logd and toss all collected data, equivalent to logcat -b all -c, // except we also return errors to the logging callers. -#ifndef USING_LOGGER_LOCAL +#ifdef USING_LOGGER_DEFAULT #ifdef TEST_PREFIX // helper to liblog.enoent to count end-to-end matching logging messages. static int count_matching_ts(log_time ts) { @@ -1687,7 +1762,7 @@ TEST(liblog, enoent) { TEST_PREFIX log_time ts(CLOCK_MONOTONIC); EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); - EXPECT_EQ(1, count_matching_ts(ts)); + EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts)); // This call will fail if we are setuid(AID_SYSTEM), beware of any // test prior to this one playing with setuid and causing interference. @@ -1732,18 +1807,18 @@ TEST(liblog, enoent) { ts = log_time(CLOCK_MONOTONIC); EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); - EXPECT_EQ(1, count_matching_ts(ts)); + EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts)); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOCAL_LOGGER +#endif // USING_LOCAL_LOGD // Below this point we run risks of setuid(AID_SYSTEM) which may affect others. // Do not retest properties, and cannot log into LOG_ID_SECURITY -#ifndef USING_LOGGER_LOCAL +#ifdef USING_LOGGER_DEFAULT TEST(liblog, __security) { #ifdef __ANDROID__ static const char persist_key[] = "persist.logd.security"; @@ -1929,7 +2004,7 @@ TEST(liblog, __security_buffer) { GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT #ifdef TEST_PREFIX static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG, @@ -2047,7 +2122,7 @@ TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) { max_payload_buf, 200, count); - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif @@ -2063,7 +2138,7 @@ TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_l max_payload_buf, sizeof(max_payload_buf), count); - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif @@ -2095,7 +2170,7 @@ TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__subtag_too max_payload_buf, 200, count); - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif @@ -2118,6 +2193,46 @@ static void android_errorWriteLog_helper(int TAG, const char *SUBTAG, int& count count = 0; + // Do a Before and After on the count to measure the effect. Decrement + // what we find in Before to set the stage. + ASSERT_TRUE(NULL != (logger_list = android_logger_list_open( + LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); + + for (;;) { + log_msg log_msg; + if (android_logger_list_read(logger_list, &log_msg) <= 0) break; + + char *eventData = log_msg.msg(); + if (!eventData) continue; + + // Tag + int tag = get4LE(eventData); + eventData += 4; + + if (tag != TAG) continue; + + if (!SUBTAG) { + // This tag should not have been written because the data was null + --count; + break; + } + + // List type + eventData++; + // Number of elements in list + eventData++; + // Element #1: string type for subtag + eventData++; + + eventData +=4; + + if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue; + --count; + } + + android_logger_list_close(logger_list); + + // Do an After on the count to measure the effect. ASSERT_TRUE(NULL != (logger_list = android_logger_list_open( LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); @@ -2184,7 +2299,7 @@ TEST(liblog, android_errorWriteLog__android_logger_list_read__success) { #ifdef TEST_PREFIX int count; android_errorWriteLog_helper(123456785, "test-subtag", count); - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif @@ -2703,7 +2818,7 @@ static void create_android_logger(const char *(*fn)(uint32_t tag, size_t &expect EXPECT_EQ(0, strcmp(expected_string, msgBuf)); } - EXPECT_EQ(1, count); + EXPECT_EQ(SUPPORTS_END_TO_END, count); android_logger_list_close(logger_list); } @@ -2789,7 +2904,7 @@ TEST(liblog, create_android_logger_android_log_error_write_null) { #endif } -#ifndef USING_LOGGER_LOCAL // Do not retest logger list handling +#ifdef USING_LOGGER_DEFAULT // Do not retest logger list handling TEST(liblog, create_android_logger_overflow) { android_log_context ctx; @@ -2829,9 +2944,9 @@ TEST(liblog, android_log_write_list_buffer) { msgBuf, sizeof(msgBuf)), 0); EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]"); } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT -#ifndef USING_LOGGER_LOCAL // Do not retest pmsg functionality +#ifdef USING_LOGGER_DEFAULT // Do not retest pmsg functionality #ifdef __ANDROID__ static const char __pmsg_file[] = "/data/william-shakespeare/MuchAdoAboutNothing.txt"; @@ -2957,9 +3072,9 @@ TEST(liblog, __android_log_pmsg_file_read) { GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT -#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality +#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality #ifdef __ANDROID__ // must be: ' 0 kB' static bool isZero(const std::string &content, std::string::size_type pos, @@ -3063,9 +3178,9 @@ TEST(liblog, event_log_tags) { GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT -#ifndef USING_LOGGER_LOCAL // Do not retest ratelimit +#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit TEST(liblog, __android_log_ratelimit) { time_t state = 0; @@ -3097,9 +3212,9 @@ TEST(liblog, __android_log_ratelimit) { } // Do not test default seconds, to allow liblog to tune freely } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT -#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality +#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality TEST(liblog, android_lookupEventTagNum) { #ifdef __ANDROID__ EventTagMap* map = android_openEventTagMap(NULL); @@ -3115,4 +3230,4 @@ TEST(liblog, android_lookupEventTagNum) { GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } -#endif // !USING_LOGGER_LOCAL +#endif // USING_LOGGER_DEFAULT diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp new file mode 100644 index 000000000..f0cb192d7 --- /dev/null +++ b/liblog/tests/liblog_test_stderr.cpp @@ -0,0 +1,5 @@ +#include +#define liblog liblog_stderr +#define TEST_PREFIX android_set_log_frontend(LOGGER_STDERR); +#define USING_LOGGER_STDERR +#include "liblog_test.cpp" diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp new file mode 100644 index 000000000..1555b4e00 --- /dev/null +++ b/liblog/tests/liblog_test_stderr_local.cpp @@ -0,0 +1,4 @@ +#include +#define liblog liblog_stderr_local +#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL | LOGGER_STDERR); +#include "liblog_test.cpp"