Merge "Support base::logging on Windows."

This commit is contained in:
Dan Albert 2015-04-30 01:02:31 +00:00 committed by Gerrit Code Review
commit 9616e82988
4 changed files with 102 additions and 23 deletions

View file

@ -18,11 +18,13 @@ LOCAL_PATH := $(call my-dir)
libbase_src_files := \
file.cpp \
logging.cpp \
stringprintf.cpp \
strings.cpp \
libbase_test_src_files := \
file_test.cpp \
logging_test.cpp \
stringprintf_test.cpp \
strings_test.cpp \
test_main.cpp \
@ -38,7 +40,7 @@ libbase_cppflags := \
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_CLANG := true
LOCAL_SRC_FILES := $(libbase_src_files) logging.cpp
LOCAL_SRC_FILES := $(libbase_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@ -61,9 +63,6 @@ include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_SRC_FILES := $(libbase_src_files)
ifneq ($(HOST_OS),windows)
LOCAL_SRC_FILES += logging.cpp
endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@ -85,7 +84,7 @@ include $(BUILD_HOST_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_CLANG := true
LOCAL_SRC_FILES := $(libbase_test_src_files) logging_test.cpp
LOCAL_SRC_FILES := $(libbase_test_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase
@ -97,9 +96,6 @@ include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_SRC_FILES := $(libbase_test_src_files)
ifneq ($(HOST_OS),windows)
LOCAL_SRC_FILES += logging_test.cpp
endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase

View file

@ -27,12 +27,19 @@
#include <iostream>
#include <limits>
#include <mutex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#ifndef _WIN32
#include <mutex>
#else
#define NOGDI // Suppress the evil ERROR macro.
#include <windows.h>
#endif
#include "base/macros.h"
#include "base/strings.h"
#include "cutils/threads.h"
@ -45,10 +52,79 @@
#include <unistd.h>
#endif
namespace {
#ifndef _WIN32
using std::mutex;
using std::lock_guard;
#if defined(__GLIBC__)
const char* getprogname() {
return program_invocation_short_name;
}
#endif
#else
const char* getprogname() {
static bool first = true;
static char progname[MAX_PATH] = {};
if (first) {
// TODO(danalbert): This is a full path on Windows. Just get the basename.
DWORD nchars = GetModuleFileName(nullptr, progname, sizeof(progname));
DCHECK_GT(nchars, 0U);
first = false;
}
return progname;
}
class mutex {
public:
mutex() {
semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr);
CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
}
~mutex() {
CloseHandle(semaphore_);
}
void lock() {
DWORD result = WaitForSingleObject(semaphore_, INFINITE);
CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
}
void unlock() {
bool result = ReleaseSemaphore(semaphore_, 1, nullptr);
CHECK(result);
}
private:
HANDLE semaphore_;
};
template <typename LockT>
class lock_guard {
public:
explicit lock_guard(LockT& lock) : lock_(lock) {
lock_.lock();
}
~lock_guard() {
lock_.unlock();
}
private:
LockT& lock_;
DISALLOW_COPY_AND_ASSIGN(lock_guard);
};
#endif
} // namespace
namespace android {
namespace base {
static std::mutex logging_lock;
static mutex logging_lock;
#ifdef __ANDROID__
static LogFunction gLogger = LogdLogger();
@ -60,12 +136,6 @@ static bool gInitialized = false;
static LogSeverity gMinimumLogSeverity = INFO;
static std::unique_ptr<std::string> gProgramInvocationName;
#if defined(__GLIBC__)
static const char* getprogname() {
return program_invocation_short_name;
}
#endif
static const char* ProgramInvocationName() {
if (gProgramInvocationName == nullptr) {
gProgramInvocationName.reset(new std::string(getprogname()));
@ -182,7 +252,7 @@ void InitLogging(char* argv[]) {
}
void SetLogger(LogFunction&& logger) {
std::lock_guard<std::mutex> lock(logging_lock);
lock_guard<mutex> lock(logging_lock);
gLogger = std::move(logger);
}
@ -287,7 +357,7 @@ std::ostream& LogMessage::stream() {
void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
LogSeverity severity, const char* message) {
const char* tag = ProgramInvocationName();
std::lock_guard<std::mutex> lock(logging_lock);
lock_guard<mutex> lock(logging_lock);
gLogger(id, severity, tag, file, line, message);
}

View file

@ -85,6 +85,9 @@ std::string make_log_pattern(android::base::LogSeverity severity,
TEST(logging, LOG) {
ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
// We can't usefully check the output of any of these on Windows because we
// don't have std::regex, but we can at least make sure we printed at least as
// many characters are in the log message.
{
CapturedStderr cap;
LOG(WARNING) << "foobar";
@ -92,10 +95,13 @@ TEST(logging, LOG) {
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_GT(output.length(), strlen("foobar"));
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::WARNING, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
#endif
}
{
@ -105,10 +111,13 @@ TEST(logging, LOG) {
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_GT(output.length(), strlen("foobar"));
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::INFO, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
#endif
}
{
@ -129,10 +138,13 @@ TEST(logging, LOG) {
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_GT(output.length(), strlen("foobar"));
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::DEBUG, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
#endif
}
}
@ -145,10 +157,13 @@ TEST(logging, PLOG) {
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_GT(output.length(), strlen("foobar"));
#if !defined(_WIN32)
std::regex message_regex(make_log_pattern(
android::base::INFO, "foobar: No such file or directory"));
ASSERT_TRUE(std::regex_search(output, message_regex));
#endif
}
}
@ -161,11 +176,14 @@ TEST(logging, UNIMPLEMENTED) {
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_GT(output.length(), strlen("unimplemented"));
#if !defined(_WIN32)
std::string expected_message =
android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
std::regex message_regex(
make_log_pattern(android::base::ERROR, expected_message.c_str()));
ASSERT_TRUE(std::regex_search(output, message_regex));
#endif
}
}

View file

@ -20,11 +20,6 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
// No logging on Windows yet.
#if !defined(_WIN32)
android::base::InitLogging(argv, android::base::StderrLogger);
#endif
return RUN_ALL_TESTS();
}