diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/include/android-base/logging.h | 9 | ||||
-rw-r--r-- | base/include/android-base/test_utils.h | 26 | ||||
-rw-r--r-- | base/logging.cpp | 10 | ||||
-rw-r--r-- | base/logging_test.cpp | 26 | ||||
-rw-r--r-- | base/test_utils.cpp | 37 |
5 files changed, 83 insertions, 25 deletions
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h index cc7aaf68c..05a12e71a 100644 --- a/base/include/android-base/logging.h +++ b/base/include/android-base/logging.h | |||
@@ -100,8 +100,17 @@ using LogFunction = std::function<void(LogId, LogSeverity, const char*, const ch | |||
100 | unsigned int, const char*)>; | 100 | unsigned int, const char*)>; |
101 | using AbortFunction = std::function<void(const char*)>; | 101 | using AbortFunction = std::function<void(const char*)>; |
102 | 102 | ||
103 | // Loggers for use with InitLogging/SetLogger. | ||
104 | |||
105 | // Log to the kernel log (dmesg). | ||
103 | void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); | 106 | void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); |
107 | // Log to stderr in the full logcat format (with pid/tid/time/tag details). | ||
104 | void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); | 108 | void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); |
109 | // Log just the message to stdout/stderr (without pid/tid/time/tag details). | ||
110 | // The choice of stdout versus stderr is based on the severity. | ||
111 | // Errors are also prefixed by the program name (as with err(3)/error(3)). | ||
112 | // Useful for replacing printf(3)/perror(3)/err(3)/error(3) in command-line tools. | ||
113 | void StdioLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); | ||
105 | 114 | ||
106 | void DefaultAborter(const char* abort_message); | 115 | void DefaultAborter(const char* abort_message); |
107 | 116 | ||
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h index b95fa07ce..b29676f7c 100644 --- a/base/include/android-base/test_utils.h +++ b/base/include/android-base/test_utils.h | |||
@@ -58,21 +58,33 @@ class TemporaryDir { | |||
58 | DISALLOW_COPY_AND_ASSIGN(TemporaryDir); | 58 | DISALLOW_COPY_AND_ASSIGN(TemporaryDir); |
59 | }; | 59 | }; |
60 | 60 | ||
61 | class CapturedStderr { | 61 | class CapturedStdFd { |
62 | public: | 62 | public: |
63 | CapturedStderr(); | 63 | CapturedStdFd(int std_fd); |
64 | ~CapturedStderr(); | 64 | ~CapturedStdFd(); |
65 | 65 | ||
66 | int fd() const; | 66 | int fd() const; |
67 | std::string str(); | ||
67 | 68 | ||
68 | private: | 69 | private: |
69 | void init(); | 70 | void Init(); |
70 | void reset(); | 71 | void Reset(); |
71 | 72 | ||
72 | TemporaryFile temp_file_; | 73 | TemporaryFile temp_file_; |
73 | int old_stderr_; | 74 | int std_fd_; |
75 | int old_fd_; | ||
74 | 76 | ||
75 | DISALLOW_COPY_AND_ASSIGN(CapturedStderr); | 77 | DISALLOW_COPY_AND_ASSIGN(CapturedStdFd); |
78 | }; | ||
79 | |||
80 | class CapturedStderr : public CapturedStdFd { | ||
81 | public: | ||
82 | CapturedStderr() : CapturedStdFd(STDERR_FILENO) {} | ||
83 | }; | ||
84 | |||
85 | class CapturedStdout : public CapturedStdFd { | ||
86 | public: | ||
87 | CapturedStdout() : CapturedStdFd(STDOUT_FILENO) {} | ||
76 | }; | 88 | }; |
77 | 89 | ||
78 | #define ASSERT_MATCH(str, pattern) \ | 90 | #define ASSERT_MATCH(str, pattern) \ |
diff --git a/base/logging.cpp b/base/logging.cpp index a33da2211..978d56d07 100644 --- a/base/logging.cpp +++ b/base/logging.cpp | |||
@@ -212,6 +212,16 @@ void StderrLogger(LogId, LogSeverity severity, const char* tag, const char* file | |||
212 | timestamp, getpid(), GetThreadId(), file, line, message); | 212 | timestamp, getpid(), GetThreadId(), file, line, message); |
213 | } | 213 | } |
214 | 214 | ||
215 | void StdioLogger(LogId, LogSeverity severity, const char* /*tag*/, const char* /*file*/, | ||
216 | unsigned int /*line*/, const char* message) { | ||
217 | if (severity >= WARNING) { | ||
218 | fflush(stdout); | ||
219 | fprintf(stderr, "%s: %s\n", getprogname(), message); | ||
220 | } else { | ||
221 | fprintf(stdout, "%s\n", message); | ||
222 | } | ||
223 | } | ||
224 | |||
215 | void DefaultAborter(const char* abort_message) { | 225 | void DefaultAborter(const char* abort_message) { |
216 | #ifdef __ANDROID__ | 226 | #ifdef __ANDROID__ |
217 | android_set_abort_message(abort_message); | 227 | android_set_abort_message(abort_message); |
diff --git a/base/logging_test.cpp b/base/logging_test.cpp index 5f689faf3..75b4ea045 100644 --- a/base/logging_test.cpp +++ b/base/logging_test.cpp | |||
@@ -206,11 +206,9 @@ static std::string make_log_pattern(android::base::LogSeverity severity, | |||
206 | } | 206 | } |
207 | #endif | 207 | #endif |
208 | 208 | ||
209 | static void CheckMessage(const CapturedStderr& cap, android::base::LogSeverity severity, | 209 | static void CheckMessage(CapturedStderr& cap, android::base::LogSeverity severity, |
210 | const char* expected, const char* expected_tag = nullptr) { | 210 | const char* expected, const char* expected_tag = nullptr) { |
211 | std::string output; | 211 | std::string output = cap.str(); |
212 | ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); | ||
213 | android::base::ReadFdToString(cap.fd(), &output); | ||
214 | 212 | ||
215 | // We can't usefully check the output of any of these on Windows because we | 213 | // We can't usefully check the output of any of these on Windows because we |
216 | // don't have std::regex, but we can at least make sure we printed at least as | 214 | // don't have std::regex, but we can at least make sure we printed at least as |
@@ -623,3 +621,23 @@ TEST(logging, SetDefaultTag) { | |||
623 | } | 621 | } |
624 | CheckMessage(cap, android::base::LogSeverity::INFO, expected_msg, expected_tag); | 622 | CheckMessage(cap, android::base::LogSeverity::INFO, expected_msg, expected_tag); |
625 | } | 623 | } |
624 | |||
625 | TEST(logging, StdioLogger) { | ||
626 | std::string err_str; | ||
627 | std::string out_str; | ||
628 | { | ||
629 | CapturedStderr cap_err; | ||
630 | CapturedStdout cap_out; | ||
631 | android::base::SetLogger(android::base::StdioLogger); | ||
632 | LOG(INFO) << "out"; | ||
633 | LOG(ERROR) << "err"; | ||
634 | err_str = cap_err.str(); | ||
635 | out_str = cap_out.str(); | ||
636 | } | ||
637 | |||
638 | // For INFO we expect just the literal "out\n". | ||
639 | ASSERT_EQ("out\n", out_str) << out_str; | ||
640 | // Whereas ERROR logging includes the program name. | ||
641 | ASSERT_EQ(android::base::Basename(android::base::GetExecutablePath()) + ": err\n", err_str) | ||
642 | << err_str; | ||
643 | } | ||
diff --git a/base/test_utils.cpp b/base/test_utils.cpp index 1619c2134..5096369e7 100644 --- a/base/test_utils.cpp +++ b/base/test_utils.cpp | |||
@@ -14,7 +14,6 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "android-base/logging.h" | ||
18 | #include "android-base/test_utils.h" | 17 | #include "android-base/test_utils.h" |
19 | 18 | ||
20 | #include <fcntl.h> | 19 | #include <fcntl.h> |
@@ -33,6 +32,9 @@ | |||
33 | 32 | ||
34 | #include <string> | 33 | #include <string> |
35 | 34 | ||
35 | #include <android-base/file.h> | ||
36 | #include <android-base/logging.h> | ||
37 | |||
36 | #ifdef _WIN32 | 38 | #ifdef _WIN32 |
37 | int mkstemp(char* template_name) { | 39 | int mkstemp(char* template_name) { |
38 | if (_mktemp(template_name) == nullptr) { | 40 | if (_mktemp(template_name) == nullptr) { |
@@ -123,31 +125,38 @@ bool TemporaryDir::init(const std::string& tmp_dir) { | |||
123 | return (mkdtemp(path) != nullptr); | 125 | return (mkdtemp(path) != nullptr); |
124 | } | 126 | } |
125 | 127 | ||
126 | CapturedStderr::CapturedStderr() : old_stderr_(-1) { | 128 | CapturedStdFd::CapturedStdFd(int std_fd) : std_fd_(std_fd), old_fd_(-1) { |
127 | init(); | 129 | Init(); |
128 | } | 130 | } |
129 | 131 | ||
130 | CapturedStderr::~CapturedStderr() { | 132 | CapturedStdFd::~CapturedStdFd() { |
131 | reset(); | 133 | Reset(); |
132 | } | 134 | } |
133 | 135 | ||
134 | int CapturedStderr::fd() const { | 136 | int CapturedStdFd::fd() const { |
135 | return temp_file_.fd; | 137 | return temp_file_.fd; |
136 | } | 138 | } |
137 | 139 | ||
138 | void CapturedStderr::init() { | 140 | std::string CapturedStdFd::str() { |
141 | std::string result; | ||
142 | CHECK_EQ(0, TEMP_FAILURE_RETRY(lseek(fd(), 0, SEEK_SET))); | ||
143 | android::base::ReadFdToString(fd(), &result); | ||
144 | return result; | ||
145 | } | ||
146 | |||
147 | void CapturedStdFd::Init() { | ||
139 | #if defined(_WIN32) | 148 | #if defined(_WIN32) |
140 | // On Windows, stderr is often buffered, so make sure it is unbuffered so | 149 | // On Windows, stderr is often buffered, so make sure it is unbuffered so |
141 | // that we can immediately read back what was written to stderr. | 150 | // that we can immediately read back what was written to stderr. |
142 | CHECK_EQ(0, setvbuf(stderr, NULL, _IONBF, 0)); | 151 | if (std_fd_ == STDERR_FILENO) CHECK_EQ(0, setvbuf(stderr, NULL, _IONBF, 0)); |
143 | #endif | 152 | #endif |
144 | old_stderr_ = dup(STDERR_FILENO); | 153 | old_fd_ = dup(std_fd_); |
145 | CHECK_NE(-1, old_stderr_); | 154 | CHECK_NE(-1, old_fd_); |
146 | CHECK_NE(-1, dup2(fd(), STDERR_FILENO)); | 155 | CHECK_NE(-1, dup2(fd(), std_fd_)); |
147 | } | 156 | } |
148 | 157 | ||
149 | void CapturedStderr::reset() { | 158 | void CapturedStdFd::Reset() { |
150 | CHECK_NE(-1, dup2(old_stderr_, STDERR_FILENO)); | 159 | CHECK_NE(-1, dup2(old_fd_, std_fd_)); |
151 | CHECK_EQ(0, close(old_stderr_)); | 160 | CHECK_EQ(0, close(old_fd_)); |
152 | // Note: cannot restore prior setvbuf() setting. | 161 | // Note: cannot restore prior setvbuf() setting. |
153 | } | 162 | } |