summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes2018-05-23 11:16:46 -0500
committerElliott Hughes2018-05-23 12:06:20 -0500
commit1be0d1481b26281bf699238d5699b38a52b31382 (patch)
treeabe0ba22d28d621564481ef56040e27534605a11
parent9f6f8bf0dcb7f08c8c0afc1685f5d1a54b41b4cb (diff)
downloadplatform-system-core-1be0d1481b26281bf699238d5699b38a52b31382.tar.gz
platform-system-core-1be0d1481b26281bf699238d5699b38a52b31382.tar.xz
platform-system-core-1be0d1481b26281bf699238d5699b38a52b31382.zip
Add StdioLogger for command-line tools.
Bug: N/A Test: ran tests Change-Id: If366a4ea25aea1becdd3e443eba225e9bd52ebba
-rw-r--r--base/include/android-base/logging.h9
-rw-r--r--base/include/android-base/test_utils.h26
-rw-r--r--base/logging.cpp10
-rw-r--r--base/logging_test.cpp26
-rw-r--r--base/test_utils.cpp37
-rw-r--r--init/host_init_parser.cpp2
6 files changed, 84 insertions, 26 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*)>;
101using AbortFunction = std::function<void(const char*)>; 101using AbortFunction = std::function<void(const char*)>;
102 102
103// Loggers for use with InitLogging/SetLogger.
104
105// Log to the kernel log (dmesg).
103void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); 106void 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).
104void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*); 108void 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.
113void StdioLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
105 114
106void DefaultAborter(const char* abort_message); 115void 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
61class CapturedStderr { 61class 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
80class CapturedStderr : public CapturedStdFd {
81 public:
82 CapturedStderr() : CapturedStdFd(STDERR_FILENO) {}
83};
84
85class 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
215void 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
215void DefaultAborter(const char* abort_message) { 225void 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
209static void CheckMessage(const CapturedStderr& cap, android::base::LogSeverity severity, 209static 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
625TEST(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
37int mkstemp(char* template_name) { 39int 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
126CapturedStderr::CapturedStderr() : old_stderr_(-1) { 128CapturedStdFd::CapturedStdFd(int std_fd) : std_fd_(std_fd), old_fd_(-1) {
127 init(); 129 Init();
128} 130}
129 131
130CapturedStderr::~CapturedStderr() { 132CapturedStdFd::~CapturedStdFd() {
131 reset(); 133 Reset();
132} 134}
133 135
134int CapturedStderr::fd() const { 136int CapturedStdFd::fd() const {
135 return temp_file_.fd; 137 return temp_file_.fd;
136} 138}
137 139
138void CapturedStderr::init() { 140std::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
147void 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
149void CapturedStderr::reset() { 158void 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}
diff --git a/init/host_init_parser.cpp b/init/host_init_parser.cpp
index 5232b7e5e..df497eade 100644
--- a/init/host_init_parser.cpp
+++ b/init/host_init_parser.cpp
@@ -48,7 +48,7 @@ static Result<Success> do_stub(const BuiltinArguments& args) {
48#include "generated_stub_builtin_function_map.h" 48#include "generated_stub_builtin_function_map.h"
49 49
50int main(int argc, char** argv) { 50int main(int argc, char** argv) {
51 android::base::InitLogging(argv, &android::base::StderrLogger); 51 android::base::InitLogging(argv, &android::base::StdioLogger);
52 if (argc != 2) { 52 if (argc != 2) {
53 LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>"; 53 LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>";
54 return -1; 54 return -1;