Add libjingle-style stream-style logging.

Add a highly stripped-down version of libjingle's base/logging.h. It is
a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
semantics to ease a transition to that format.

Also add some helper macros for easy API and function failure logging.

Review URL: https://webrtc-codereview.appspot.com/931010

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3099 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/system_wrappers/source/logging_unittest.cc b/webrtc/system_wrappers/source/logging_unittest.cc
new file mode 100644
index 0000000..45acbfd
--- /dev/null
+++ b/webrtc/system_wrappers/source/logging_unittest.cc
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/system_wrappers/interface/logging.h"
+
+#include "gtest/gtest.h"
+#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+namespace {
+
+const size_t kBoilerplateLength = 71;
+
+class LoggingTest : public ::testing::Test, public TraceCallback {
+ public:
+  virtual void Print(const TraceLevel level,
+                     const char* msg,
+                     const int length) {
+    CriticalSectionScoped cs(crit_.get());
+    // We test the length here to ensure (with high likelihood) that only our
+    // traces will be tested.
+    if (level_ != kTraceNone &&
+        expected_log_.str().size() == length - kBoilerplateLength - 1) {
+      EXPECT_EQ(level_, level);
+      EXPECT_EQ(expected_log_.str(), &msg[kBoilerplateLength]);
+      level_ = kTraceNone;
+      cv_->Wake();
+    }
+  }
+
+ protected:
+  LoggingTest()
+    : crit_(CriticalSectionWrapper::CreateCriticalSection()),
+      cv_(ConditionVariableWrapper::CreateConditionVariable()),
+      level_(kTraceNone),
+      expected_log_() {
+  }
+
+  void SetUp() {
+    Trace::CreateTrace();
+    Trace::SetTraceCallback(this);
+    // Reduce the chance that spurious traces will ruin the test.
+    Trace::SetLevelFilter(kTraceWarning | kTraceError);
+  }
+
+  void TearDown() {
+    CriticalSectionScoped cs(crit_.get());
+    Trace::SetTraceCallback(NULL);
+    Trace::ReturnTrace();
+    ASSERT_EQ(kTraceNone, level_) << "Print() was not called";
+  }
+
+  scoped_ptr<CriticalSectionWrapper> crit_;
+  scoped_ptr<ConditionVariableWrapper> cv_;
+  TraceLevel level_;
+  int length_;
+  std::ostringstream expected_log_;
+};
+
+TEST_F(LoggingTest, LogStream) {
+  {
+    CriticalSectionScoped cs(crit_.get());
+    level_ = kTraceWarning;
+    std::string msg = "Important message";
+    expected_log_ << "(logging_unittest.cc:" << __LINE__ + 1 << "): " << msg;
+    LOG(WARNING) << msg;
+    cv_->SleepCS(*crit_.get());
+  }
+}
+
+TEST_F(LoggingTest, LogFunctionError) {
+  {
+    CriticalSectionScoped cs(crit_.get());
+    int bar = 42;
+    int baz = 99;
+    level_ = kTraceError;
+    expected_log_ << "(logging_unittest.cc:" << __LINE__ + 2
+                  << "): Foo failed: bar=" << bar << ", baz=" << baz;
+    LOG_FERR2(LS_ERROR, Foo, bar, baz);
+    cv_->SleepCS(*crit_.get());
+  }
+}
+
+}  // namespace
+}  // namespace webrtc