Merge pull request #641 from sergiud/nullptr

CHECK support for nullptr (fixes #341)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b2174e5..62ebbcc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,7 @@
 option (BUILD_SHARED_LIBS "Build shared libraries" ON)
 option (PRINT_UNSYMBOLIZED_STACK_TRACES
   "Print file offsets in traces instead of symbolizing" OFF)
+option (WITH_CUSTOM_PREFIX "Enable support for user-generated message prefixes" OFF)
 option (WITH_GFLAGS "Use gflags" ON)
 option (WITH_GTEST "Use googletest" ON)
 option (WITH_PKGCONFIG "Enable pkg-config support" ON)
@@ -594,10 +595,10 @@
 if (gflags_FOUND)
   target_link_libraries (glog PUBLIC gflags)
 
-  if (NOT BUILD_SHARED_LIBS)
-    # Don't use __declspec(dllexport|dllimport) if this is a static build
-    targeT_compile_definitions (glog PUBLIC GFLAGS_DLL_DECLARE_FLAG= GFLAGS_DLL_DEFINE_FLAG=)
-  endif (NOT BUILD_SHARED_LIBS)
+  target_compile_definitions (glog PRIVATE
+    GFLAGS_DLL_DECLARE_FLAG=GOOGLE_GLOG_DLL_DECL
+    GFLAGS_DLL_DEFINE_FLAG=GOOGLE_GLOG_DLL_DECL
+  )
 endif (gflags_FOUND)
 
 if (ANDROID)
@@ -611,6 +612,10 @@
   target_compile_definitions (glog PUBLIC GLOG_NO_ABBREVIATED_SEVERITIES)
 endif (WIN32)
 
+if (WITH_CUSTOM_PREFIX)
+  target_compile_definitions(glog PUBLIC GLOG_CUSTOM_PREFIX_SUPPORT)
+endif (WITH_CUSTOM_PREFIX)
+
 set_target_properties (glog PROPERTIES PUBLIC_HEADER "${GLOG_PUBLIC_H}")
 
 target_include_directories (glog BEFORE PUBLIC
@@ -647,6 +652,17 @@
 
   target_link_libraries (logging_unittest PRIVATE ${_GLOG_TEST_LIBS})
 
+  if (WITH_CUSTOM_PREFIX)
+    add_executable (logging_custom_prefix_unittest
+      src/logging_custom_prefix_unittest.cc
+    )
+
+    target_link_libraries (logging_custom_prefix_unittest PRIVATE ${_GLOG_TEST_LIBS})
+
+    add_test (NAME logging_custom_prefix
+              COMMAND logging_custom_prefix_unittest)
+  endif (WITH_CUSTOM_PREFIX)
+
   add_executable (stl_logging_unittest
     src/stl_logging_unittest.cc
   )
diff --git a/README.rst b/README.rst
index a983f21..93b2783 100644
--- a/README.rst
+++ b/README.rst
@@ -200,7 +200,7 @@
 You can log messages by severity level, control logging behavior from
 the command line, log based on conditionals, abort the program when
 expected conditions are not met, introduce your own verbose logging
-levels, and more.
+levels, customize the prefix attached to log messages, and more.
 
 Following sections describe the functionality supported by glog. Please note
 this description may not be complete but limited to the most useful ones. If you
@@ -516,6 +516,51 @@
          " than 1024, when you run the program with --v=1 or more. ";
          "Present occurence is " << google::COUNTER;
 
+
+Custom log prefix format
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+glog supports changing the format of the prefix attached to log messages by
+receiving a user-provided callback to be used to generate such strings.  That
+feature must be enabled at compile time by the ``WITH_CUSTOM_PREFIX`` flag.
+
+For each log entry, the callback will be invoked with a ``LogMessageInfo``
+struct containing the severity, filename, line number, thread ID, and time of
+the event. It will also be given a reference to the output stream, whose
+contents will be prepended to the actual message in the final log line.
+
+For example:
+
+   .. code:: cpp
+
+      /* This function writes a prefix that matches glog's default format.
+       * (The third parameter can be used to receive user-supplied data, and is
+       * NULL by default.)
+       */
+      void CustomPrefix(std::ostream &s, const LogMessageInfo &l, void*) {
+         s << l.severity[0]
+         << setw(4) << 1900 + l.time.year()
+         << setw(2) << 1 + l.time.month()
+         << setw(2) << l.time.day()
+         << ' '
+         << setw(2) << l.time.hour() << ':'
+         << setw(2) << l.time.min()  << ':'
+         << setw(2) << l.time.sec() << "."
+         << setw(6) << l.time.usec()
+         << ' '
+         << setfill(' ') << setw(5)
+         << l.thread_id << setfill('0')
+         << ' '
+         << l.filename << ':' << l.line_number << "]";
+      }
+
+
+To enable the use of ``CustomPrefix()``, simply give glog a pointer to it
+during initialization: ``InitGoogleLogging(argv[0], &CustomPrefix);``.
+
+Optionally, ``InitGoogleLogging()`` takes a third argument of type  ``void*``
+to pass on to the callback function.
+
 Failure Signal Handler
 ~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in
index a77e4d5..421f1e0 100644
--- a/src/glog/logging.h.in
+++ b/src/glog/logging.h.in
@@ -87,6 +87,14 @@
 #include <inttypes.h>           // a third place for uint16_t or u_int16_t
 #endif
 
+#ifdef GFLAGS_DLL_DECLARE_FLAG
+#define GLOG_GFLAGS_DLL_DECLARE_FLAG_WAS_DEFINED
+#pragma push_macro("GFLAGS_DLL_DECLARE_FLAG")
+#undef GFLAGS_DLL_DECLARE_FLAG
+#endif // defined(GFLAGS_DLL_DECLARE_FLAG)
+
+#define GFLAGS_DLL_DECLARE_FLAG GOOGLE_GLOG_DLL_DECL
+
 #if @ac_cv_have_libgflags@
 #include <gflags/gflags.h>
 #endif
@@ -120,6 +128,50 @@
 
 @ac_google_end_namespace@
 
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+struct LogMessageTime {
+  explicit LogMessageTime (const struct::tm& time_struct_,
+                           const time_t& timestamp_, const int32_t& usecs_):
+      time_struct(time_struct_), ts(timestamp_), usecs(usecs_) {}
+
+  const time_t& timestamp() const { return ts; }
+  const int& sec() const { return time_struct.tm_sec; }
+  const int32_t& usec() const { return usecs; }
+  const int& min() const { return time_struct.tm_min; }
+  const int& hour() const { return time_struct.tm_hour; }
+  const int& day() const { return time_struct.tm_mday; }
+  const int& month() const { return time_struct.tm_mon; }
+  const int& year() const { return time_struct.tm_year; }
+  const int& dayOfWeek() const { return time_struct.tm_wday; }
+  const int& dayInYear() const { return time_struct.tm_yday; }
+  const int& dst() const { return time_struct.tm_isdst; }
+
+  private:
+    const struct::tm& time_struct;
+    const time_t& ts;
+    const int32_t& usecs;
+};
+
+struct LogMessageInfo {
+  explicit LogMessageInfo(const char* const severity_,
+                          const char* const filename_,
+                          const int& line_number_,
+                          const int& thread_id_,
+                          const LogMessageTime& time_):
+      severity(severity_), filename(filename_), line_number(line_number_),
+      thread_id(thread_id_), time(time_)
+  {}
+
+  const char* const severity;
+  const char* const filename;
+  const int &line_number;
+  const int &thread_id;
+  const LogMessageTime& time;
+};
+
+typedef void(*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l, void* data);
+#endif
+
 // The global value of GOOGLE_STRIP_LOG. All the messages logged to
 // LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
 // If it can be determined at compile time that the message will not be
@@ -536,6 +588,12 @@
 // specified by argv0 in log outputs.
 GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
 
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0,
+                                            CustomPrefixCallback prefix_callback,
+                                            void* prefix_callback_data = NULL);
+#endif
+
 // Shutdown google's logging library.
 GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
 
@@ -1834,4 +1892,9 @@
 
 @ac_google_end_namespace@
 
+#ifdef GLOG_GFLAGS_DLL_DECLARE_FLAG_WAS_DEFINED
+#undef GLOG_GFLAGS_DLL_DECLARE_FLAG_WAS_DEFINED
+#pragma pop_macro("GFLAGS_DLL_DECLARE_FLAG")
+#endif // defined(GLOG_GFLAGS_DLL_DECLARE_FLAG_WAS_DEFINED)
+
 #endif // _LOGGING_H_
diff --git a/src/logging.cc b/src/logging.cc
index 4b9e180..71de91d 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -409,6 +409,15 @@
 base::Logger::~Logger() {
 }
 
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+namespace  {
+  // Optional user-configured callback to print custom prefixes.
+  CustomPrefixCallback custom_prefix_callback = NULL;
+  // User-provided data to pass to the callback:
+  void* custom_prefix_callback_data = NULL;
+}
+#endif
+
 namespace {
 
 // Encapsulates all file-system related state
@@ -1380,6 +1389,7 @@
   // after:  "/tmp/<base_filename>.<create_time>.<pid>"
   string cleaned_base_filename;
 
+  size_t real_filepath_size = filepath.size();
   for (size_t i = 0; i < base_filename.size(); ++i) {
     const char& c = base_filename[i];
 
@@ -1400,15 +1410,29 @@
   // `cleaned_base_filename` in `filepath` if the user
   // has set a custom filename extension.
   if (!filename_extension.empty()) {
-    if (filepath.find(filename_extension) != cleaned_base_filename.size()) {
+    if (cleaned_base_filename.size() >= real_filepath_size) {
       return false;
     }
-    cleaned_base_filename += filename_extension;
+    // for origin version, `filename_extension` is middle of the `filepath`.
+    string ext = filepath.substr(cleaned_base_filename.size(), filename_extension.size());
+    if (ext == filename_extension) {
+      cleaned_base_filename += filename_extension;
+    }
+    else {
+      // for new version, `filename_extension` is right of the `filepath`.
+      if (filename_extension.size() >= real_filepath_size) {
+        return false;
+      }
+      real_filepath_size = filepath.size() - filename_extension.size();
+      if (filepath.substr(real_filepath_size) != filename_extension) {
+        return false;
+      }
+    }
   }
 
   // The characters after `cleaned_base_filename` should match the format:
   // YYYYMMDD-HHMMSS.pid
-  for (size_t i = cleaned_base_filename.size(); i < filepath.size(); i++) {
+  for (size_t i = cleaned_base_filename.size(); i < real_filepath_size; i++) {
     const char& c = filepath[i];
 
     if (i <= cleaned_base_filename.size() + 7) { // 0 ~ 7 : YYYYMMDD
@@ -1593,20 +1617,37 @@
   //    (log level, GMT year, month, date, time, thread_id, file basename, line)
   // We exclude the thread_id for the default thread.
   if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
-    stream() << LogSeverityNames[severity][0]
-             << setw(4) << 1900+data_->tm_time_.tm_year
-             << setw(2) << 1+data_->tm_time_.tm_mon
-             << setw(2) << data_->tm_time_.tm_mday
-             << ' '
-             << setw(2) << data_->tm_time_.tm_hour  << ':'
-             << setw(2) << data_->tm_time_.tm_min   << ':'
-             << setw(2) << data_->tm_time_.tm_sec   << "."
-             << setw(6) << data_->usecs_
-             << ' '
-             << setfill(' ') << setw(5)
-             << static_cast<unsigned int>(GetTID()) << setfill('0')
-             << ' '
-             << data_->basename_ << ':' << data_->line_ << "] ";
+    #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+      if (custom_prefix_callback == NULL) {
+    #endif
+          stream() << LogSeverityNames[severity][0]
+                   << setw(4) << 1900+data_->tm_time_.tm_year
+                   << setw(2) << 1+data_->tm_time_.tm_mon
+                   << setw(2) << data_->tm_time_.tm_mday
+                   << ' '
+                   << setw(2) << data_->tm_time_.tm_hour  << ':'
+                   << setw(2) << data_->tm_time_.tm_min   << ':'
+                   << setw(2) << data_->tm_time_.tm_sec   << "."
+                   << setw(6) << data_->usecs_
+                   << ' '
+                   << setfill(' ') << setw(5)
+                   << static_cast<unsigned int>(GetTID()) << setfill('0')
+                   << ' '
+                   << data_->basename_ << ':' << data_->line_ << "] ";
+    #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+      } else {
+        custom_prefix_callback(
+                stream(),
+                LogMessageInfo(LogSeverityNames[severity],
+                               data_->basename_, data_->line_, GetTID(),
+                               LogMessageTime(data_->tm_time_,
+                                              data_->timestamp_,
+                                              data_->usecs_)),
+                custom_prefix_callback_data
+                );
+        stream() << " ";
+      }
+    #endif
   }
   data_->num_prefix_chars_ = data_->stream_.pcount();
 
@@ -2517,6 +2558,16 @@
   glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
 }
 
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+void InitGoogleLogging(const char* argv0,
+                       CustomPrefixCallback prefix_callback,
+                       void* prefix_callback_data) {
+  custom_prefix_callback = prefix_callback;
+  custom_prefix_callback_data = prefix_callback_data;
+  InitGoogleLogging(argv0);
+}
+#endif
+
 void ShutdownGoogleLogging() {
   glog_internal_namespace_::ShutdownGoogleLoggingUtilities();
   LogDestination::DeleteLogDestinations();
diff --git a/src/logging_custom_prefix_unittest.cc b/src/logging_custom_prefix_unittest.cc
new file mode 100644
index 0000000..c9fb5b8
--- /dev/null
+++ b/src/logging_custom_prefix_unittest.cc
@@ -0,0 +1,1374 @@
+// Copyright (c) 2002, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney
+
+#include "utilities.h"
+
+#include <fcntl.h>
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "base/commandlineflags.h"
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
+#include "googletest.h"
+
+DECLARE_string(log_backtrace_at);  // logging.cc
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using testing::_;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::AllOf;
+using testing::StrNe;
+using testing::StrictMock;
+using testing::InitGoogleMock;
+using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
+#endif
+
+using namespace std;
+using namespace GOOGLE_NAMESPACE;
+
+// Some non-advertised functions that we want to test or use.
+_START_GOOGLE_NAMESPACE_
+namespace base {
+namespace internal {
+bool GetExitOnDFatal();
+void SetExitOnDFatal(bool value);
+}  // namespace internal
+}  // namespace base
+_END_GOOGLE_NAMESPACE_
+
+static void TestLogging(bool check_counts);
+static void TestRawLogging();
+static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
+static void TestLoggingLevels();
+static void TestLogString();
+static void TestLogSink();
+static void TestLogToString();
+static void TestLogSinkWaitTillSent();
+static void TestCHECK();
+static void TestDCHECK();
+static void TestSTREQ();
+static void TestBasename();
+static void TestBasenameAppendWhenNoTimestamp();
+static void TestTwoProcessesWrite();
+static void TestSymlink();
+static void TestExtension();
+static void TestWrapper();
+static void TestErrno();
+static void TestTruncate();
+static void TestCustomLoggerDeletionOnShutdown();
+
+static int x = -1;
+static void BM_Check1(int n) {
+  while (n-- > 0) {
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+  }
+}
+BENCHMARK(BM_Check1);
+
+static void CheckFailure(int a, int b, const char* file, int line, const char* msg);
+static void BM_Check3(int n) {
+  while (n-- > 0) {
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+  }
+}
+BENCHMARK(BM_Check3);
+
+static void BM_Check2(int n) {
+  if (n == 17) {
+    x = 5;
+  }
+  while (n-- > 0) {
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+  }
+}
+BENCHMARK(BM_Check2);
+
+static void CheckFailure(int, int, const char* /* file */, int /* line */,
+                         const char* /* msg */) {
+}
+
+static void BM_logspeed(int n) {
+  while (n-- > 0) {
+    LOG(INFO) << "test message";
+  }
+}
+BENCHMARK(BM_logspeed);
+
+static void BM_vlog(int n) {
+  while (n-- > 0) {
+    VLOG(1) << "test message";
+  }
+}
+BENCHMARK(BM_vlog);
+
+// Dynamically generate a prefix using the default format and write it to the stream.
+void PrefixAttacher(std::ostream &s, const LogMessageInfo &l, void* data) {
+  // Assert that `data` contains the expected contents before producing the
+  // prefix (otherwise causing the tests to fail):
+  if (data == NULL || *static_cast<string*>(data) != "good data") {
+    return;
+  }
+
+  s << l.severity[0]
+    << setw(4) << 1900 + l.time.year()
+    << setw(2) << 1 + l.time.month()
+    << setw(2) << l.time.day()
+    << ' '
+    << setw(2) << l.time.hour() << ':'
+    << setw(2) << l.time.min()  << ':'
+    << setw(2) << l.time.sec() << "."
+    << setw(6) << l.time.usec()
+    << ' '
+    << setfill(' ') << setw(5)
+    << l.thread_id << setfill('0')
+    << ' '
+    << l.filename << ':' << l.line_number << "]";
+}
+
+int main(int argc, char **argv) {
+  FLAGS_colorlogtostderr = false;
+  FLAGS_timestamp_in_logfile_name = true;
+#ifdef HAVE_LIB_GFLAGS
+  ParseCommandLineFlags(&argc, &argv, true);
+#endif
+  // Make sure stderr is not buffered as stderr seems to be buffered
+  // on recent windows.
+  setbuf(stderr, NULL);
+
+  // Test some basics before InitGoogleLogging:
+  CaptureTestStderr();
+  LogWithLevels(FLAGS_v, FLAGS_stderrthreshold,
+                FLAGS_logtostderr, FLAGS_alsologtostderr);
+  LogWithLevels(0, 0, 0, 0);  // simulate "before global c-tors"
+  const string early_stderr = GetCapturedTestStderr();
+
+  // Setting a custom prefix generator (it will use the default format so that
+  // the golden outputs can be reused):
+  string prefix_attacher_data = "good data";
+  InitGoogleLogging(argv[0], &PrefixAttacher, static_cast<void*>(&prefix_attacher_data));
+
+  RunSpecifiedBenchmarks();
+
+  FLAGS_logtostderr = true;
+
+  InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+  InitGoogleMock(&argc, argv);
+#endif
+
+  // so that death tests run before we use threads
+  CHECK_EQ(RUN_ALL_TESTS(), 0);
+
+  CaptureTestStderr();
+
+  // re-emit early_stderr
+  LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr;
+
+  TestLogging(true);
+  TestRawLogging();
+  TestLoggingLevels();
+  TestLogString();
+  TestLogSink();
+  TestLogToString();
+  TestLogSinkWaitTillSent();
+  TestCHECK();
+  TestDCHECK();
+  TestSTREQ();
+
+  // TODO: The golden test portion of this test is very flakey.
+  EXPECT_TRUE(
+      MungeAndDiffTestStderr(FLAGS_test_srcdir + "/src/logging_custom_prefix_unittest.err"));
+
+  FLAGS_logtostderr = false;
+
+  TestBasename();
+  TestBasenameAppendWhenNoTimestamp();
+  TestTwoProcessesWrite();
+  TestSymlink();
+  TestExtension();
+  TestWrapper();
+  TestErrno();
+  TestTruncate();
+  TestCustomLoggerDeletionOnShutdown();
+
+  fprintf(stdout, "PASS\n");
+  return 0;
+}
+
+void TestLogging(bool check_counts) {
+  int64 base_num_infos   = LogMessage::num_messages(GLOG_INFO);
+  int64 base_num_warning = LogMessage::num_messages(GLOG_WARNING);
+  int64 base_num_errors  = LogMessage::num_messages(GLOG_ERROR);
+
+  LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4;
+  for ( int i = 0; i < 10; ++i ) {
+    int old_errno = errno;
+    errno = i;
+    PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER;
+    errno = old_errno;
+
+    LOG_EVERY_N(ERROR, 3) << "Log every 3, iteration " << COUNTER << endl;
+    LOG_EVERY_N(ERROR, 4) << "Log every 4, iteration " << COUNTER << endl;
+
+    LOG_IF_EVERY_N(WARNING, true, 5) << "Log if every 5, iteration " << COUNTER;
+    LOG_IF_EVERY_N(WARNING, false, 3)
+        << "Log if every 3, iteration " << COUNTER;
+    LOG_IF_EVERY_N(INFO, true, 1) << "Log if every 1, iteration " << COUNTER;
+    LOG_IF_EVERY_N(ERROR, (i < 3), 2)
+        << "Log if less than 3 every 2, iteration " << COUNTER;
+  }
+  LOG_IF(WARNING, true) << "log_if this";
+  LOG_IF(WARNING, false) << "don't log_if this";
+
+  char s[] = "array";
+  LOG(INFO) << s;
+  const char const_s[] = "const array";
+  LOG(INFO) << const_s;
+  int j = 1000;
+  LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
+             << setw(1) << hex << j;
+
+  {
+    google::LogMessage outer(__FILE__, __LINE__, GLOG_ERROR);
+    outer.stream() << "outer";
+
+    LOG(ERROR) << "inner";
+  }
+
+  LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
+
+  if (check_counts) {
+    CHECK_EQ(base_num_infos   + 14, LogMessage::num_messages(GLOG_INFO));
+    CHECK_EQ(base_num_warning + 3,  LogMessage::num_messages(GLOG_WARNING));
+    CHECK_EQ(base_num_errors  + 17, LogMessage::num_messages(GLOG_ERROR));
+  }
+}
+
+static void NoAllocNewHook() {
+  LOG(FATAL) << "unexpected new";
+}
+
+struct NewHook {
+  NewHook() {
+    g_new_hook = &NoAllocNewHook;
+  }
+  ~NewHook() {
+    g_new_hook = NULL;
+  }
+};
+
+TEST(DeathNoAllocNewHook, logging) {
+ // tests that NewHook used below works
+ NewHook new_hook;
+ ASSERT_DEATH({
+   new int;
+ }, "unexpected new");
+}
+
+void TestRawLogging() {
+  string* foo = new string("foo ");
+  string huge_str(50000, 'a');
+
+  FlagSaver saver;
+
+  // Check that RAW loggging does not use mallocs.
+  NewHook new_hook;
+
+  RAW_LOG(INFO, "%s%s%d%c%f", foo->c_str(), "bar ", 10, ' ', 3.4);
+  char s[] = "array";
+  RAW_LOG(WARNING, "%s", s);
+  const char const_s[] = "const array";
+  RAW_LOG(INFO, "%s", const_s);
+  void* p = reinterpret_cast<void*>(PTR_TEST_VALUE);
+  RAW_LOG(INFO, "ptr %p", p);
+  p = NULL;
+  RAW_LOG(INFO, "ptr %p", p);
+  int j = 1000;
+  RAW_LOG(ERROR, "%s%d%c%010d%s%1x", foo->c_str(), j, ' ', j, " ", j);
+  RAW_VLOG(0, "foo %d", j);
+
+#ifdef NDEBUG
+  RAW_LOG(INFO, "foo %d", j);  // so that have same stderr to compare
+#else
+  RAW_DLOG(INFO, "foo %d", j);  // test RAW_DLOG in debug mode
+#endif
+
+  // test how long messages are chopped:
+  RAW_LOG(WARNING, "Huge string: %s", huge_str.c_str());
+  RAW_VLOG(0, "Huge string: %s", huge_str.c_str());
+
+  FLAGS_v = 0;
+  RAW_LOG(INFO, "log");
+  RAW_VLOG(0, "vlog 0 on");
+  RAW_VLOG(1, "vlog 1 off");
+  RAW_VLOG(2, "vlog 2 off");
+  RAW_VLOG(3, "vlog 3 off");
+  FLAGS_v = 2;
+  RAW_LOG(INFO, "log");
+  RAW_VLOG(1, "vlog 1 on");
+  RAW_VLOG(2, "vlog 2 on");
+  RAW_VLOG(3, "vlog 3 off");
+
+#ifdef NDEBUG
+  RAW_DCHECK(1 == 2, " RAW_DCHECK's shouldn't be compiled in normal mode");
+#endif
+
+  RAW_CHECK(1 == 1, "should be ok");
+  RAW_DCHECK(true, "should be ok");
+
+  delete foo;
+}
+
+void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
+  RAW_LOG(INFO,
+          "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d",
+          v, severity, err, alsoerr);
+
+  FlagSaver saver;
+
+  FLAGS_v = v;
+  FLAGS_stderrthreshold = severity;
+  FLAGS_logtostderr = err;
+  FLAGS_alsologtostderr = alsoerr;
+
+  RAW_VLOG(-1, "vlog -1");
+  RAW_VLOG(0, "vlog 0");
+  RAW_VLOG(1, "vlog 1");
+  RAW_LOG(INFO, "log info");
+  RAW_LOG(WARNING, "log warning");
+  RAW_LOG(ERROR, "log error");
+
+  VLOG(-1) << "vlog -1";
+  VLOG(0) << "vlog 0";
+  VLOG(1) << "vlog 1";
+  LOG(INFO) << "log info";
+  LOG(WARNING) << "log warning";
+  LOG(ERROR) << "log error";
+
+  VLOG_IF(-1, true) << "vlog_if -1";
+  VLOG_IF(-1, false) << "don't vlog_if -1";
+  VLOG_IF(0, true) << "vlog_if 0";
+  VLOG_IF(0, false) << "don't vlog_if 0";
+  VLOG_IF(1, true) << "vlog_if 1";
+  VLOG_IF(1, false) << "don't vlog_if 1";
+  LOG_IF(INFO, true) << "log_if info";
+  LOG_IF(INFO, false) << "don't log_if info";
+  LOG_IF(WARNING, true) << "log_if warning";
+  LOG_IF(WARNING, false) << "don't log_if warning";
+  LOG_IF(ERROR, true) << "log_if error";
+  LOG_IF(ERROR, false) << "don't log_if error";
+
+  int c;
+  c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1);
+  c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1);
+  c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1);
+  c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1);
+  c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0);
+  c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0);
+
+  c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
+  EXPECT_EQ(c, -1);
+  c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
+  EXPECT_EQ(c, -1);
+  c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
+  EXPECT_EQ(c, 0);
+  c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
+  EXPECT_EQ(c, 0);
+  c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
+  EXPECT_EQ(c, 1);
+  c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
+  EXPECT_EQ(c, 1);
+  c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
+  EXPECT_EQ(c, 0);
+  c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
+  EXPECT_EQ(c, 0);
+}
+
+void TestLoggingLevels() {
+  LogWithLevels(0, GLOG_INFO, false, false);
+  LogWithLevels(1, GLOG_INFO, false, false);
+  LogWithLevels(-1, GLOG_INFO, false, false);
+  LogWithLevels(0, GLOG_WARNING, false, false);
+  LogWithLevels(0, GLOG_ERROR, false, false);
+  LogWithLevels(0, GLOG_FATAL, false, false);
+  LogWithLevels(0, GLOG_FATAL, true, false);
+  LogWithLevels(0, GLOG_FATAL, false, true);
+  LogWithLevels(1, GLOG_WARNING, false, false);
+  LogWithLevels(1, GLOG_FATAL, false, true);
+}
+
+TEST(DeathRawCHECK, logging) {
+  ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
+               "RAW: Check false failed: failure 1");
+  ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"),
+               "RAW: Check 1 == 2 failed: failure 2");
+}
+
+void TestLogString() {
+  vector<string> errors;
+  vector<string> *no_errors = NULL;
+
+  LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info";
+  LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning";
+  LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error";
+
+  LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info";
+  LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning";
+  LOG_STRING(ERROR, NULL) << "LOG_STRING: " << "reported error";
+
+  for (size_t i = 0; i < errors.size(); ++i) {
+    LOG(INFO) << "Captured by LOG_STRING:  " << errors[i];
+  }
+}
+
+void TestLogToString() {
+  string error;
+  string* no_error = NULL;
+
+  LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info";
+  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
+  LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning";
+  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
+  LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error";
+  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
+
+  LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info";
+  LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning";
+  LOG_TO_STRING(ERROR, NULL) << "LOG_TO_STRING: " << "reported error";
+}
+
+class TestLogSinkImpl : public LogSink {
+ public:
+  vector<string> errors;
+  virtual void send(LogSeverity severity, const char* /* full_filename */,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len, int usecs) {
+    errors.push_back(
+      ToString(severity, base_filename, line, tm_time, message, message_len, usecs));
+  }
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) {
+    send(severity, full_filename, base_filename, line,
+         tm_time, message, message_len, 0);
+  }
+};
+
+void TestLogSink() {
+  TestLogSinkImpl sink;
+  LogSink *no_sink = NULL;
+
+  LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info";
+  LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning";
+  LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error";
+
+  LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info";
+  LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning";
+  LOG_TO_SINK(NULL, ERROR) << "LOG_TO_SINK: " << "reported error";
+
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info";
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning";
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error";
+
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info";
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning";
+  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(NULL, ERROR)
+      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed error";
+
+  LOG(INFO) << "Captured by LOG_TO_SINK:";
+  for (size_t i = 0; i < sink.errors.size(); ++i) {
+    LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
+      << sink.errors[i];
+  }
+}
+
+// For testing using CHECK*() on anonymous enums.
+enum {
+  CASE_A,
+  CASE_B
+};
+
+void TestCHECK() {
+  // Tests using CHECK*() on int values.
+  CHECK(1 == 1);
+  CHECK_EQ(1, 1);
+  CHECK_NE(1, 2);
+  CHECK_GE(1, 1);
+  CHECK_GE(2, 1);
+  CHECK_LE(1, 1);
+  CHECK_LE(1, 2);
+  CHECK_GT(2, 1);
+  CHECK_LT(1, 2);
+
+  // Tests using CHECK*() on anonymous enums.
+  // Apple's GCC doesn't like this.
+#if !defined(OS_MACOSX)
+  CHECK_EQ(CASE_A, CASE_A);
+  CHECK_NE(CASE_A, CASE_B);
+  CHECK_GE(CASE_A, CASE_A);
+  CHECK_GE(CASE_B, CASE_A);
+  CHECK_LE(CASE_A, CASE_A);
+  CHECK_LE(CASE_A, CASE_B);
+  CHECK_GT(CASE_B, CASE_A);
+  CHECK_LT(CASE_A, CASE_B);
+#endif
+}
+
+void TestDCHECK() {
+#ifdef NDEBUG
+  DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode";
+#endif
+  DCHECK( 1 == 1 );
+  DCHECK_EQ(1, 1);
+  DCHECK_NE(1, 2);
+  DCHECK_GE(1, 1);
+  DCHECK_GE(2, 1);
+  DCHECK_LE(1, 1);
+  DCHECK_LE(1, 2);
+  DCHECK_GT(2, 1);
+  DCHECK_LT(1, 2);
+
+  int64* orig_ptr = new int64;
+  int64* ptr = DCHECK_NOTNULL(orig_ptr);
+  CHECK_EQ(ptr, orig_ptr);
+  delete orig_ptr;
+}
+
+void TestSTREQ() {
+  CHECK_STREQ("this", "this");
+  CHECK_STREQ(NULL, NULL);
+  CHECK_STRCASEEQ("this", "tHiS");
+  CHECK_STRCASEEQ(NULL, NULL);
+  CHECK_STRNE("this", "tHiS");
+  CHECK_STRNE("this", NULL);
+  CHECK_STRCASENE("this", "that");
+  CHECK_STRCASENE(NULL, "that");
+  CHECK_STREQ((string("a")+"b").c_str(), "ab");
+  CHECK_STREQ(string("test").c_str(),
+              (string("te") + string("st")).c_str());
+}
+
+TEST(DeathSTREQ, logging) {
+  ASSERT_DEATH(CHECK_STREQ(NULL, "this"), "");
+  ASSERT_DEATH(CHECK_STREQ("this", "siht"), "");
+  ASSERT_DEATH(CHECK_STRCASEEQ(NULL, "siht"), "");
+  ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), "");
+  ASSERT_DEATH(CHECK_STRNE(NULL, NULL), "");
+  ASSERT_DEATH(CHECK_STRNE("this", "this"), "");
+  ASSERT_DEATH(CHECK_STREQ((string("a")+"b").c_str(), "abc"), "");
+}
+
+TEST(CheckNOTNULL, Simple) {
+  int64 t;
+  void *ptr = static_cast<void *>(&t);
+  void *ref = CHECK_NOTNULL(ptr);
+  EXPECT_EQ(ptr, ref);
+  CHECK_NOTNULL(reinterpret_cast<char *>(ptr));
+  CHECK_NOTNULL(reinterpret_cast<unsigned char *>(ptr));
+  CHECK_NOTNULL(reinterpret_cast<int *>(ptr));
+  CHECK_NOTNULL(reinterpret_cast<int64 *>(ptr));
+}
+
+TEST(DeathCheckNN, Simple) {
+  ASSERT_DEATH(CHECK_NOTNULL(static_cast<void *>(NULL)), "");
+}
+
+// Get list of file names that match pattern
+static void GetFiles(const string& pattern, vector<string>* files) {
+  files->clear();
+#if defined(HAVE_GLOB_H)
+  glob_t g;
+  const int r = glob(pattern.c_str(), 0, NULL, &g);
+  CHECK((r == 0) || (r == GLOB_NOMATCH)) << ": error matching " << pattern;
+  for (size_t i = 0; i < g.gl_pathc; i++) {
+    files->push_back(string(g.gl_pathv[i]));
+  }
+  globfree(&g);
+#elif defined(OS_WINDOWS)
+  WIN32_FIND_DATAA data;
+  HANDLE handle = FindFirstFileA(pattern.c_str(), &data);
+  size_t index = pattern.rfind('\\');
+  if (index == string::npos) {
+    LOG(FATAL) << "No directory separator.";
+  }
+  const string dirname = pattern.substr(0, index + 1);
+  if (handle == INVALID_HANDLE_VALUE) {
+    // Finding no files is OK.
+    return;
+  }
+  do {
+    files->push_back(dirname + data.cFileName);
+  } while (FindNextFileA(handle, &data));
+  BOOL result = FindClose(handle);
+  LOG_SYSRESULT(result);
+#else
+# error There is no way to do glob.
+#endif
+}
+
+// Delete files patching pattern
+static void DeleteFiles(const string& pattern) {
+  vector<string> files;
+  GetFiles(pattern, &files);
+  for (size_t i = 0; i < files.size(); i++) {
+    CHECK(unlink(files[i].c_str()) == 0) << ": " << strerror(errno);
+  }
+}
+
+//check string is in file (or is *NOT*, depending on optional checkInFileOrNot)
+static void CheckFile(const string& name, const string& expected_string, const bool checkInFileOrNot = true) {
+  vector<string> files;
+  GetFiles(name + "*", &files);
+  CHECK_EQ(files.size(), 1UL);
+
+  FILE* file = fopen(files[0].c_str(), "r");
+  CHECK(file != NULL) << ": could not open " << files[0];
+  char buf[1000];
+  while (fgets(buf, sizeof(buf), file) != NULL) {
+    char* first = strstr(buf, expected_string.c_str());
+    //if first == NULL, not found.
+    //Terser than if (checkInFileOrNot && first != NULL || !check...
+    if (checkInFileOrNot != (first == NULL)) {
+      fclose(file);
+      return;
+    }
+  }
+  fclose(file);
+  LOG(FATAL) << "Did " << (checkInFileOrNot? "not " : "") << "find " << expected_string << " in " << files[0];
+}
+
+static void TestBasename() {
+  fprintf(stderr, "==== Test setting log file basename\n");
+  const string dest = FLAGS_test_tmpdir + "/logging_test_basename";
+  DeleteFiles(dest + "*");
+
+  SetLogDestination(GLOG_INFO, dest.c_str());
+  LOG(INFO) << "message to new base";
+  FlushLogFiles(GLOG_INFO);
+
+  CheckFile(dest, "message to new base");
+
+  // Release file handle for the destination file to unlock the file in Windows.
+  LogToStderr();
+  DeleteFiles(dest + "*");
+}
+
+static void TestBasenameAppendWhenNoTimestamp() {
+  fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n");
+  const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
+  DeleteFiles(dest + "*");
+
+  ofstream out(dest.c_str());
+  out << "test preexisting content" << endl;
+  out.close();
+
+  CheckFile(dest, "test preexisting content");
+
+  FLAGS_timestamp_in_logfile_name=false;
+  SetLogDestination(GLOG_INFO, dest.c_str());
+  LOG(INFO) << "message to new base, appending to preexisting file";
+  FlushLogFiles(GLOG_INFO);
+  FLAGS_timestamp_in_logfile_name=true;
+
+  //if the logging overwrites the file instead of appending it will fail.
+  CheckFile(dest, "test preexisting content");
+  CheckFile(dest, "message to new base, appending to preexisting file");
+
+  // Release file handle for the destination file to unlock the file in Windows.
+  LogToStderr();
+  DeleteFiles(dest + "*");
+}
+
+static void TestTwoProcessesWrite() {
+// test only implemented for platforms with fork & wait; the actual implementation relies on flock
+#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL)
+  fprintf(stderr, "==== Test setting log file basename and two processes writing - second should fail\n");
+  const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
+  DeleteFiles(dest + "*");
+
+  //make both processes write into the same file (easier test)
+  FLAGS_timestamp_in_logfile_name=false;
+  SetLogDestination(GLOG_INFO, dest.c_str());
+  LOG(INFO) << "message to new base, parent";
+  FlushLogFiles(GLOG_INFO);
+
+  pid_t pid = fork();
+  CHECK_ERR(pid);
+  if (pid == 0) {
+    LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file";
+    ShutdownGoogleLogging(); //for children proc
+    exit(0);
+  } else if (pid > 0) {
+    wait(NULL);
+  }
+  FLAGS_timestamp_in_logfile_name=true;
+
+  CheckFile(dest, "message to new base, parent");
+  CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false);
+
+  // Release
+  LogToStderr();
+  DeleteFiles(dest + "*");
+#endif
+}
+
+static void TestSymlink() {
+#ifndef OS_WINDOWS
+  fprintf(stderr, "==== Test setting log file symlink\n");
+  string dest = FLAGS_test_tmpdir + "/logging_test_symlink";
+  string sym = FLAGS_test_tmpdir + "/symlinkbase";
+  DeleteFiles(dest + "*");
+  DeleteFiles(sym + "*");
+
+  SetLogSymlink(GLOG_INFO, "symlinkbase");
+  SetLogDestination(GLOG_INFO, dest.c_str());
+  LOG(INFO) << "message to new symlink";
+  FlushLogFiles(GLOG_INFO);
+  CheckFile(sym, "message to new symlink");
+
+  DeleteFiles(dest + "*");
+  DeleteFiles(sym + "*");
+#endif
+}
+
+static void TestExtension() {
+  fprintf(stderr, "==== Test setting log file extension\n");
+  string dest = FLAGS_test_tmpdir + "/logging_test_extension";
+  DeleteFiles(dest + "*");
+
+  SetLogDestination(GLOG_INFO, dest.c_str());
+  SetLogFilenameExtension("specialextension");
+  LOG(INFO) << "message to new extension";
+  FlushLogFiles(GLOG_INFO);
+  CheckFile(dest, "message to new extension");
+
+  // Check that file name ends with extension
+  vector<string> filenames;
+  GetFiles(dest + "*", &filenames);
+  CHECK_EQ(filenames.size(), 1UL);
+  CHECK(strstr(filenames[0].c_str(), "specialextension") != NULL);
+
+  // Release file handle for the destination file to unlock the file in Windows.
+  LogToStderr();
+  DeleteFiles(dest + "*");
+}
+
+struct MyLogger : public base::Logger {
+  string data;
+
+  virtual void Write(bool /* should_flush */,
+                     time_t /* timestamp */,
+                     const char* message,
+                     int length) {
+    data.append(message, length);
+  }
+
+  virtual void Flush() { }
+
+  virtual uint32 LogSize() { return data.length(); }
+};
+
+static void TestWrapper() {
+  fprintf(stderr, "==== Test log wrapper\n");
+
+  MyLogger my_logger;
+  base::Logger* old_logger = base::GetLogger(GLOG_INFO);
+  base::SetLogger(GLOG_INFO, &my_logger);
+  LOG(INFO) << "Send to wrapped logger";
+  FlushLogFiles(GLOG_INFO);
+  base::SetLogger(GLOG_INFO, old_logger);
+
+  CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL);
+}
+
+static void TestErrno() {
+  fprintf(stderr, "==== Test errno preservation\n");
+
+  errno = ENOENT;
+  TestLogging(false);
+  CHECK_EQ(errno, ENOENT);
+}
+
+static void TestOneTruncate(const char *path, int64 limit, int64 keep,
+                            int64 dsize, int64 ksize, int64 expect) {
+  int fd;
+  CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
+
+  const char *discardstr = "DISCARDME!", *keepstr = "KEEPME!";
+  const size_t discard_size = strlen(discardstr), keep_size = strlen(keepstr);
+
+  // Fill the file with the requested data; first discard data, then kept data
+  int64 written = 0;
+  while (written < dsize) {
+    int bytes = min<int64>(dsize - written, discard_size);
+    CHECK_ERR(write(fd, discardstr, bytes));
+    written += bytes;
+  }
+  written = 0;
+  while (written < ksize) {
+    int bytes = min<int64>(ksize - written, keep_size);
+    CHECK_ERR(write(fd, keepstr, bytes));
+    written += bytes;
+  }
+
+  TruncateLogFile(path, limit, keep);
+
+  // File should now be shorter
+  struct stat statbuf;
+  CHECK_ERR(fstat(fd, &statbuf));
+  CHECK_EQ(statbuf.st_size, expect);
+  CHECK_ERR(lseek(fd, 0, SEEK_SET));
+
+  // File should contain the suffix of the original file
+  const size_t buf_size = statbuf.st_size + 1;
+  char* buf = new char[buf_size];
+  memset(buf, 0, buf_size);
+  CHECK_ERR(read(fd, buf, buf_size));
+
+  const char *p = buf;
+  int64 checked = 0;
+  while (checked < expect) {
+    int bytes = min<int64>(expect - checked, keep_size);
+    CHECK(!memcmp(p, keepstr, bytes));
+    checked += bytes;
+  }
+  close(fd);
+  delete[] buf;
+}
+
+static void TestTruncate() {
+#ifdef HAVE_UNISTD_H
+  fprintf(stderr, "==== Test log truncation\n");
+  string path = FLAGS_test_tmpdir + "/truncatefile";
+
+  // Test on a small file
+  TestOneTruncate(path.c_str(), 10, 10, 10, 10, 10);
+
+  // And a big file (multiple blocks to copy)
+  TestOneTruncate(path.c_str(), 2<<20, 4<<10, 3<<20, 4<<10, 4<<10);
+
+  // Check edge-case limits
+  TestOneTruncate(path.c_str(), 10, 20, 0, 20, 20);
+  TestOneTruncate(path.c_str(), 10, 0, 0, 0, 0);
+  TestOneTruncate(path.c_str(), 10, 50, 0, 10, 10);
+  TestOneTruncate(path.c_str(), 50, 100, 0, 30, 30);
+
+  // MacOSX 10.4 doesn't fail in this case.
+  // Windows doesn't have symlink.
+  // Let's just ignore this test for these cases.
+#if !defined(OS_MACOSX) && !defined(OS_WINDOWS)
+  // Through a symlink should fail to truncate
+  string linkname = path + ".link";
+  unlink(linkname.c_str());
+  CHECK_ERR(symlink(path.c_str(), linkname.c_str()));
+  TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30);
+#endif
+
+  // The /proc/self path makes sense only for linux.
+#if defined(OS_LINUX)
+  // Through an open fd symlink should work
+  int fd;
+  CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
+  char fdpath[64];
+  snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
+  TestOneTruncate(fdpath, 10, 10, 10, 10, 10);
+#endif
+
+#endif
+}
+
+struct RecordDeletionLogger : public base::Logger {
+  RecordDeletionLogger(bool* set_on_destruction,
+                       base::Logger* wrapped_logger) :
+      set_on_destruction_(set_on_destruction),
+      wrapped_logger_(wrapped_logger)
+  {
+    *set_on_destruction_ = false;
+  }
+  virtual ~RecordDeletionLogger() {
+    *set_on_destruction_ = true;
+  }
+  virtual void Write(bool force_flush,
+                     time_t timestamp,
+                     const char* message,
+                     int length) {
+    wrapped_logger_->Write(force_flush, timestamp, message, length);
+  }
+  virtual void Flush() { wrapped_logger_->Flush(); }
+  virtual uint32 LogSize() { return wrapped_logger_->LogSize(); }
+ private:
+  bool* set_on_destruction_;
+  base::Logger* wrapped_logger_;
+};
+
+static void TestCustomLoggerDeletionOnShutdown() {
+  bool custom_logger_deleted = false;
+  base::SetLogger(GLOG_INFO,
+                  new RecordDeletionLogger(&custom_logger_deleted,
+                                           base::GetLogger(GLOG_INFO)));
+  ShutdownGoogleLogging();
+  EXPECT_TRUE(custom_logger_deleted);
+}
+
+_START_GOOGLE_NAMESPACE_
+namespace glog_internal_namespace_ {
+extern  // in logging.cc
+bool SafeFNMatch_(const char* pattern, size_t patt_len,
+                  const char* str, size_t str_len);
+} // namespace glog_internal_namespace_
+using glog_internal_namespace_::SafeFNMatch_;
+_END_GOOGLE_NAMESPACE_
+
+static bool WrapSafeFNMatch(string pattern, string str) {
+  pattern += "abc";
+  str += "defgh";
+  return SafeFNMatch_(pattern.data(), pattern.size() - 3,
+                      str.data(), str.size() - 5);
+}
+
+TEST(SafeFNMatch, logging) {
+  CHECK(WrapSafeFNMatch("foo", "foo"));
+  CHECK(!WrapSafeFNMatch("foo", "bar"));
+  CHECK(!WrapSafeFNMatch("foo", "fo"));
+  CHECK(!WrapSafeFNMatch("foo", "foo2"));
+  CHECK(WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext"));
+  CHECK(WrapSafeFNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"));
+  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/baz.ext"));
+  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo"));
+  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext.zip"));
+  CHECK(WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext"));
+  CHECK(WrapSafeFNMatch("ba?/*.ext", "baZ/FOO.ext"));
+  CHECK(!WrapSafeFNMatch("ba?/*.ext", "barr/foo.ext"));
+  CHECK(!WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext2"));
+  CHECK(WrapSafeFNMatch("ba?/*", "bar/foo.ext2"));
+  CHECK(WrapSafeFNMatch("ba?/*", "bar/"));
+  CHECK(!WrapSafeFNMatch("ba?/?", "bar/"));
+  CHECK(!WrapSafeFNMatch("ba?/*", "bar"));
+}
+
+// TestWaitingLogSink will save messages here
+// No lock: Accessed only by TestLogSinkWriter thread
+// and after its demise by its creator.
+static vector<string> global_messages;
+
+// helper for TestWaitingLogSink below.
+// Thread that does the logic of TestWaitingLogSink
+// It's free to use LOG() itself.
+class TestLogSinkWriter : public Thread {
+ public:
+
+  TestLogSinkWriter() : should_exit_(false) {
+    SetJoinable(true);
+    Start();
+  }
+
+  // Just buffer it (can't use LOG() here).
+  void Buffer(const string& message) {
+    mutex_.Lock();
+    RAW_LOG(INFO, "Buffering");
+    messages_.push(message);
+    mutex_.Unlock();
+    RAW_LOG(INFO, "Buffered");
+  }
+
+  // Wait for the buffer to clear (can't use LOG() here).
+  void Wait() {
+    RAW_LOG(INFO, "Waiting");
+    mutex_.Lock();
+    while (!NoWork()) {
+      mutex_.Unlock();
+      SleepForMilliseconds(1);
+      mutex_.Lock();
+    }
+    RAW_LOG(INFO, "Waited");
+    mutex_.Unlock();
+  }
+
+  // Trigger thread exit.
+  void Stop() {
+    MutexLock l(&mutex_);
+    should_exit_ = true;
+  }
+
+ private:
+
+  // helpers ---------------
+
+  // For creating a "Condition".
+  bool NoWork() { return messages_.empty(); }
+  bool HaveWork() { return !messages_.empty() || should_exit_; }
+
+  // Thread body; CAN use LOG() here!
+  virtual void Run() {
+    while (1) {
+      mutex_.Lock();
+      while (!HaveWork()) {
+        mutex_.Unlock();
+        SleepForMilliseconds(1);
+        mutex_.Lock();
+      }
+      if (should_exit_ && messages_.empty()) {
+        mutex_.Unlock();
+        break;
+      }
+      // Give the main thread time to log its message,
+      // so that we get a reliable log capture to compare to golden file.
+      // Same for the other sleep below.
+      SleepForMilliseconds(20);
+      RAW_LOG(INFO, "Sink got a messages");  // only RAW_LOG under mutex_ here
+      string message = messages_.front();
+      messages_.pop();
+      // Normally this would be some more real/involved logging logic
+      // where LOG() usage can't be eliminated,
+      // e.g. pushing the message over with an RPC:
+      int messages_left = messages_.size();
+      mutex_.Unlock();
+      SleepForMilliseconds(20);
+      // May not use LOG while holding mutex_, because Buffer()
+      // acquires mutex_, and Buffer is called from LOG(),
+      // which has its own internal mutex:
+      // LOG()->LogToSinks()->TestWaitingLogSink::send()->Buffer()
+      LOG(INFO) << "Sink is sending out a message: " << message;
+      LOG(INFO) << "Have " << messages_left << " left";
+      global_messages.push_back(message);
+    }
+  }
+
+  // data ---------------
+
+  Mutex mutex_;
+  bool should_exit_;
+  queue<string> messages_;  // messages to be logged
+};
+
+// A log sink that exercises WaitTillSent:
+// it pushes data to a buffer and wakes up another thread to do the logging
+// (that other thread can than use LOG() itself),
+class TestWaitingLogSink : public LogSink {
+ public:
+
+  TestWaitingLogSink() {
+    tid_ = pthread_self();  // for thread-specific behavior
+    AddLogSink(this);
+  }
+  ~TestWaitingLogSink() {
+    RemoveLogSink(this);
+    writer_.Stop();
+    writer_.Join();
+  }
+
+  // (re)define LogSink interface
+
+  virtual void send(LogSeverity severity, const char* /* full_filename */,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len, int usecs) {
+    // Push it to Writer thread if we are the original logging thread.
+    // Note: Something like ThreadLocalLogSink is a better choice
+    //       to do thread-specific LogSink logic for real.
+    if (pthread_equal(tid_, pthread_self())) {
+      writer_.Buffer(ToString(severity, base_filename, line,
+                              tm_time, message, message_len, usecs));
+    }
+  }
+
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) {
+    send(severity, full_filename, base_filename, line, tm_time, message, message_len);
+  }
+
+  virtual void WaitTillSent() {
+    // Wait for Writer thread if we are the original logging thread.
+    if (pthread_equal(tid_, pthread_self()))  writer_.Wait();
+  }
+
+ private:
+
+  pthread_t tid_;
+  TestLogSinkWriter writer_;
+};
+
+// Check that LogSink::WaitTillSent can be used in the advertised way.
+// We also do golden-stderr comparison.
+static void TestLogSinkWaitTillSent() {
+  { TestWaitingLogSink sink;
+    // Sleeps give the sink threads time to do all their work,
+    // so that we get a reliable log capture to compare to the golden file.
+    LOG(INFO) << "Message 1";
+    SleepForMilliseconds(60);
+    LOG(ERROR) << "Message 2";
+    SleepForMilliseconds(60);
+    LOG(WARNING) << "Message 3";
+    SleepForMilliseconds(60);
+  }
+  for (size_t i = 0; i < global_messages.size(); ++i) {
+    LOG(INFO) << "Sink capture: " << global_messages[i];
+  }
+  CHECK_EQ(global_messages.size(), 3UL);
+}
+
+TEST(Strerror, logging) {
+  int errcode = EINTR;
+  char *msg = strdup(strerror(errcode));
+  const size_t buf_size = strlen(msg) + 1;
+  char *buf = new char[buf_size];
+  CHECK_EQ(posix_strerror_r(errcode, NULL, 0), -1);
+  buf[0] = 'A';
+  CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
+  CHECK_EQ(buf[0], 'A');
+  CHECK_EQ(posix_strerror_r(errcode, NULL, buf_size), -1);
+#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+  // MacOSX or FreeBSD considers this case is an error since there is
+  // no enough space.
+  CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
+#else
+  CHECK_EQ(posix_strerror_r(errcode, buf, 1), 0);
+#endif
+  CHECK_STREQ(buf, "");
+  CHECK_EQ(posix_strerror_r(errcode, buf, buf_size), 0);
+  CHECK_STREQ(buf, msg);
+  delete[] buf;
+  CHECK_EQ(msg, StrError(errcode));
+  free(msg);
+}
+
+// Simple routines to look at the sizes of generated code for LOG(FATAL) and
+// CHECK(..) via objdump
+/*
+static void MyFatal() {
+  LOG(FATAL) << "Failed";
+}
+static void MyCheck(bool a, bool b) {
+  CHECK_EQ(a, b);
+}
+*/
+#ifdef HAVE_LIB_GMOCK
+
+TEST(DVLog, Basic) {
+  ScopedMockLog log;
+
+#if NDEBUG
+  // We are expecting that nothing is logged.
+  EXPECT_CALL(log, Log(_, _, _)).Times(0);
+#else
+  EXPECT_CALL(log, Log(INFO, __FILE__, "debug log"));
+#endif
+
+  FLAGS_v = 1;
+  DVLOG(1) << "debug log";
+}
+
+TEST(DVLog, V0) {
+  ScopedMockLog log;
+
+  // We are expecting that nothing is logged.
+  EXPECT_CALL(log, Log(_, _, _)).Times(0);
+
+  FLAGS_v = 0;
+  DVLOG(1) << "debug log";
+}
+
+TEST(LogAtLevel, Basic) {
+  ScopedMockLog log;
+
+  // The function version outputs "logging.h" as a file name.
+  EXPECT_CALL(log, Log(WARNING, StrNe(__FILE__), "function version"));
+  EXPECT_CALL(log, Log(INFO, __FILE__, "macro version"));
+
+  int severity = WARNING;
+  LogAtLevel(severity, "function version");
+
+  severity = INFO;
+  // We can use the macro version as a C++ stream.
+  LOG_AT_LEVEL(severity) << "macro" << ' ' << "version";
+}
+
+TEST(TestExitOnDFatal, ToBeOrNotToBe) {
+  // Check the default setting...
+  EXPECT_TRUE(base::internal::GetExitOnDFatal());
+
+  // Turn off...
+  base::internal::SetExitOnDFatal(false);
+  EXPECT_FALSE(base::internal::GetExitOnDFatal());
+
+  // We don't die.
+  {
+    ScopedMockLog log;
+    //EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
+    // LOG(DFATAL) has severity FATAL if debugging, but is
+    // downgraded to ERROR if not debugging.
+    const LogSeverity severity =
+#ifdef NDEBUG
+        ERROR;
+#else
+        FATAL;
+#endif
+    EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
+    LOG(DFATAL) << "This should not be fatal";
+  }
+
+  // Turn back on...
+  base::internal::SetExitOnDFatal(true);
+  EXPECT_TRUE(base::internal::GetExitOnDFatal());
+
+#ifdef GTEST_HAS_DEATH_TEST
+  // Death comes on little cats' feet.
+  EXPECT_DEBUG_DEATH({
+      LOG(DFATAL) << "This should be fatal in debug mode";
+    }, "This should be fatal in debug mode");
+#endif
+}
+
+#ifdef HAVE_STACKTRACE
+
+static void BacktraceAtHelper() {
+  LOG(INFO) << "Not me";
+
+// The vertical spacing of the next 3 lines is significant.
+  LOG(INFO) << "Backtrace me";
+}
+static int kBacktraceAtLine = __LINE__ - 2;  // The line of the LOG(INFO) above
+
+TEST(LogBacktraceAt, DoesNotBacktraceWhenDisabled) {
+  StrictMock<ScopedMockLog> log;
+
+  FLAGS_log_backtrace_at = "";
+
+  EXPECT_CALL(log, Log(_, _, "Backtrace me"));
+  EXPECT_CALL(log, Log(_, _, "Not me"));
+
+  BacktraceAtHelper();
+}
+
+TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
+  StrictMock<ScopedMockLog> log;
+
+  char where[100];
+  snprintf(where, 100, "%s:%d", const_basename(__FILE__), kBacktraceAtLine);
+  FLAGS_log_backtrace_at = where;
+
+  // The LOG at the specified line should include a stacktrace which includes
+  // the name of the containing function, followed by the log message.
+  // We use HasSubstr()s instead of ContainsRegex() for environments
+  // which don't have regexp.
+  EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"),
+                                   HasSubstr("BacktraceAtHelper"),
+                                   HasSubstr("main"),
+                                   HasSubstr("Backtrace me"))));
+  // Other LOGs should not include a backtrace.
+  EXPECT_CALL(log, Log(_, _, "Not me"));
+
+  BacktraceAtHelper();
+}
+
+#endif // HAVE_STACKTRACE
+
+#endif // HAVE_LIB_GMOCK
+
+struct UserDefinedClass {
+  bool operator==(const UserDefinedClass&) const { return true; }
+};
+
+inline ostream& operator<<(ostream& out, const UserDefinedClass&) {
+  out << "OK";
+  return out;
+}
+
+TEST(UserDefinedClass, logging) {
+  UserDefinedClass u;
+  vector<string> buf;
+  LOG_STRING(INFO, &buf) << u;
+  CHECK_EQ(1UL, buf.size());
+  CHECK(buf[0].find("OK") != string::npos);
+
+  // We must be able to compile this.
+  CHECK_EQ(u, u);
+}
diff --git a/src/logging_custom_prefix_unittest.err b/src/logging_custom_prefix_unittest.err
new file mode 100644
index 0000000..3e7f5d4
--- /dev/null
+++ b/src/logging_custom_prefix_unittest.err
@@ -0,0 +1,307 @@
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WARNING: Logging before InitGoogleLogging() is written to STDERR
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] foo bar 10 3.4
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 1
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 1
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 5, iteration 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 1
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 2
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 3
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 4
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 4
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 5
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 5
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 5, iteration 6
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 6
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 7
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 7
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 8
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 9
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 9
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 10
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 10
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if this
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] const array
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] foo 1000 0000001000 3e8
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] inner
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] outer
+no prefix
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo bar 10 3.400000
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: const array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: ptr __PTRTEST__
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: ptr __NULLP__
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 2 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING:  LOG_STRING: collected info
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING:  LOG_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING:  LOG_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_SINK:
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected info
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING:  LOG_TO_STRING: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING:  LOG_TO_STRING: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING:  LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3