PageRenderTime 107ms CodeModel.GetById 20ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 1ms

/thirdparty/breakpad/third_party/glog/src/logging_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 1210 lines | 911 code | 180 blank | 119 comment | 58 complexity | a40288f6bebb3a090f7bcfa29a527585 MD5 | raw file
   1// Copyright (c) 2002, Google Inc.
   2// All rights reserved.
   3//
   4// Redistribution and use in source and binary forms, with or without
   5// modification, are permitted provided that the following conditions are
   6// met:
   7//
   8//     * Redistributions of source code must retain the above copyright
   9// notice, this list of conditions and the following disclaimer.
  10//     * Redistributions in binary form must reproduce the above
  11// copyright notice, this list of conditions and the following disclaimer
  12// in the documentation and/or other materials provided with the
  13// distribution.
  14//     * Neither the name of Google Inc. nor the names of its
  15// contributors may be used to endorse or promote products derived from
  16// this software without specific prior written permission.
  17//
  18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29//
  30// Author: Ray Sidney
  31
  32#include "config_for_unittests.h"
  33#include "utilities.h"
  34
  35#include <fcntl.h>
  36#ifdef HAVE_GLOB_H
  37# include <glob.h>
  38#endif
  39#include <sys/stat.h>
  40#ifdef HAVE_UNISTD_H
  41# include <unistd.h>
  42#endif
  43
  44#include <iomanip>
  45#include <iostream>
  46#include <memory>
  47#include <queue>
  48#include <sstream>
  49#include <string>
  50#include <vector>
  51
  52#include <stdio.h>
  53#include <stdlib.h>
  54
  55#include "base/commandlineflags.h"
  56#include "glog/logging.h"
  57#include "glog/raw_logging.h"
  58#include "googletest.h"
  59
  60DECLARE_string(log_backtrace_at);  // logging.cc
  61
  62#ifdef HAVE_LIB_GFLAGS
  63#include <gflags/gflags.h>
  64#endif
  65
  66#ifdef HAVE_LIB_GMOCK
  67#include <gmock/gmock.h>
  68#include "mock-log.h"
  69// Introduce several symbols from gmock.
  70using testing::_;
  71using testing::AnyNumber;
  72using testing::HasSubstr;
  73using testing::AllOf;
  74using testing::StrNe;
  75using testing::StrictMock;
  76using testing::InitGoogleMock;
  77using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
  78#endif
  79
  80using namespace std;
  81using namespace GOOGLE_NAMESPACE;
  82
  83// Some non-advertised functions that we want to test or use.
  84_START_GOOGLE_NAMESPACE_
  85namespace base {
  86namespace internal {
  87bool GetExitOnDFatal();
  88void SetExitOnDFatal(bool value);
  89}  // namespace internal
  90}  // namespace base
  91_END_GOOGLE_NAMESPACE_
  92
  93static void TestLogging(bool check_counts);
  94static void TestRawLogging();
  95static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
  96static void TestLoggingLevels();
  97static void TestLogString();
  98static void TestLogSink();
  99static void TestLogToString();
 100static void TestLogSinkWaitTillSent();
 101static void TestCHECK();
 102static void TestDCHECK();
 103static void TestSTREQ();
 104static void TestBasename();
 105static void TestSymlink();
 106static void TestExtension();
 107static void TestWrapper();
 108static void TestErrno();
 109static void TestTruncate();
 110
 111static int x = -1;
 112static void BM_Check1(int n) {
 113  while (n-- > 0) {
 114    CHECK_GE(n, x);
 115    CHECK_GE(n, x);
 116    CHECK_GE(n, x);
 117    CHECK_GE(n, x);
 118    CHECK_GE(n, x);
 119    CHECK_GE(n, x);
 120    CHECK_GE(n, x);
 121    CHECK_GE(n, x);
 122  }
 123}
 124BENCHMARK(BM_Check1);
 125
 126static void CheckFailure(int a, int b, const char* file, int line, const char* msg);
 127static void BM_Check3(int n) {
 128  while (n-- > 0) {
 129    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 130    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 131    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 132    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 133    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 134    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 135    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 136    if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
 137  }
 138}
 139BENCHMARK(BM_Check3);
 140
 141static void BM_Check2(int n) {
 142  if (n == 17) {
 143    x = 5;
 144  }
 145  while (n-- > 0) {
 146    CHECK(n >= x);
 147    CHECK(n >= x);
 148    CHECK(n >= x);
 149    CHECK(n >= x);
 150    CHECK(n >= x);
 151    CHECK(n >= x);
 152    CHECK(n >= x);
 153    CHECK(n >= x);
 154  }
 155}
 156BENCHMARK(BM_Check2);
 157
 158static void CheckFailure(int a, int b, const char* file, int line, const char* msg) {
 159}
 160
 161static void BM_logspeed(int n) {
 162  while (n-- > 0) {
 163    LOG(INFO) << "test message";
 164  }
 165}
 166BENCHMARK(BM_logspeed);
 167
 168static void BM_vlog(int n) {
 169  while (n-- > 0) {
 170    VLOG(1) << "test message";
 171  }
 172}
 173BENCHMARK(BM_vlog);
 174
 175int main(int argc, char **argv) {
 176#ifdef HAVE_LIB_GFLAGS
 177  ParseCommandLineFlags(&argc, &argv, true);
 178#endif
 179
 180  // Test some basics before InitGoogleLogging:
 181  CaptureTestStderr();
 182  LogWithLevels(FLAGS_v, FLAGS_stderrthreshold,
 183                FLAGS_logtostderr, FLAGS_alsologtostderr);
 184  LogWithLevels(0, 0, 0, 0);  // simulate "before global c-tors"
 185  const string early_stderr = GetCapturedTestStderr();
 186
 187  InitGoogleLogging(argv[0]);
 188
 189  RunSpecifiedBenchmarks();
 190
 191  FLAGS_logtostderr = true;
 192
 193  InitGoogleTest(&argc, argv);
 194#ifdef HAVE_LIB_GMOCK
 195  InitGoogleMock(&argc, argv);
 196#endif
 197
 198  // so that death tests run before we use threads
 199  CHECK_EQ(RUN_ALL_TESTS(), 0);
 200
 201  CaptureTestStderr();
 202
 203  // re-emit early_stderr
 204  LogMessage("dummy", LogMessage::kNoLogPrefix, INFO).stream() << early_stderr;
 205
 206  TestLogging(true);
 207  TestRawLogging();
 208  TestLoggingLevels();
 209  TestLogString();
 210  TestLogSink();
 211  TestLogToString();
 212  TestLogSinkWaitTillSent();
 213  TestCHECK();
 214  TestDCHECK();
 215  TestSTREQ();
 216
 217  // TODO: The golden test portion of this test is very flakey.
 218  EXPECT_TRUE(
 219      MungeAndDiffTestStderr(FLAGS_test_srcdir + "/src/logging_unittest.err"));
 220
 221  FLAGS_logtostderr = false;
 222
 223  TestBasename();
 224  TestSymlink();
 225  TestExtension();
 226  TestWrapper();
 227  TestErrno();
 228  TestTruncate();
 229
 230  ShutdownGoogleLogging();
 231
 232  fprintf(stdout, "PASS\n");
 233  return 0;
 234}
 235
 236void TestLogging(bool check_counts) {
 237  int64 base_num_infos   = LogMessage::num_messages(INFO);
 238  int64 base_num_warning = LogMessage::num_messages(WARNING);
 239  int64 base_num_errors  = LogMessage::num_messages(ERROR);
 240
 241  LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4;
 242  for ( int i = 0; i < 10; ++i ) {
 243    int old_errno = errno;
 244    errno = i;
 245    PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER;
 246    errno = old_errno;
 247
 248    LOG_EVERY_N(ERROR, 3) << "Log every 3, iteration " << COUNTER << endl;
 249    LOG_EVERY_N(ERROR, 4) << "Log every 4, iteration " << COUNTER << endl;
 250
 251    LOG_IF_EVERY_N(WARNING, true, 5) << "Log if every 5, iteration " << COUNTER;
 252    LOG_IF_EVERY_N(WARNING, false, 3)
 253        << "Log if every 3, iteration " << COUNTER;
 254    LOG_IF_EVERY_N(INFO, true, 1) << "Log if every 1, iteration " << COUNTER;
 255    LOG_IF_EVERY_N(ERROR, (i < 3), 2)
 256        << "Log if less than 3 every 2, iteration " << COUNTER;
 257  }
 258  LOG_IF(WARNING, true) << "log_if this";
 259  LOG_IF(WARNING, false) << "don't log_if this";
 260
 261  char s[] = "array";
 262  LOG(INFO) << s;
 263  const char const_s[] = "const array";
 264  LOG(INFO) << const_s;
 265  int j = 1000;
 266  LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
 267             << setw(1) << hex << j;
 268
 269  LogMessage("foo", LogMessage::kNoLogPrefix, INFO).stream() << "no prefix";
 270
 271  if (check_counts) {
 272    CHECK_EQ(base_num_infos   + 14, LogMessage::num_messages(INFO));
 273    CHECK_EQ(base_num_warning + 3,  LogMessage::num_messages(WARNING));
 274    CHECK_EQ(base_num_errors  + 15, LogMessage::num_messages(ERROR));
 275  }
 276}
 277
 278static void NoAllocNewHook() {
 279  CHECK(false) << "unexpected new";
 280}
 281
 282struct NewHook {
 283  NewHook() {
 284    g_new_hook = &NoAllocNewHook;
 285  }
 286  ~NewHook() {
 287    g_new_hook = NULL;
 288  }
 289};
 290
 291TEST(DeathNoAllocNewHook, logging) {
 292  // tests that NewHook used below works
 293  NewHook new_hook;
 294  ASSERT_DEATH({
 295    new int;
 296  }, "unexpected new");
 297}
 298
 299void TestRawLogging() {
 300  string* foo = new string("foo ");
 301  string huge_str(50000, 'a');
 302
 303  FlagSaver saver;
 304
 305  // Check that RAW loggging does not use mallocs.
 306  NewHook new_hook;
 307
 308  RAW_LOG(INFO, "%s%s%d%c%f", foo->c_str(), "bar ", 10, ' ', 3.4);
 309  char s[] = "array";
 310  RAW_LOG(WARNING, "%s", s);
 311  const char const_s[] = "const array";
 312  RAW_LOG(INFO, "%s", const_s);
 313  void* p = reinterpret_cast<void*>(0x12345678);
 314  RAW_LOG(INFO, "ptr %p", p);
 315  p = NULL;
 316  RAW_LOG(INFO, "ptr %p", p);
 317  int j = 1000;
 318  RAW_LOG(ERROR, "%s%d%c%010d%s%1x", foo->c_str(), j, ' ', j, " ", j);
 319  RAW_VLOG(0, "foo %d", j);
 320
 321#ifdef NDEBUG
 322  RAW_LOG(INFO, "foo %d", j);  // so that have same stderr to compare
 323#else
 324  RAW_DLOG(INFO, "foo %d", j);  // test RAW_DLOG in debug mode
 325#endif
 326
 327  // test how long messages are chopped:
 328  RAW_LOG(WARNING, "Huge string: %s", huge_str.c_str());
 329  RAW_VLOG(0, "Huge string: %s", huge_str.c_str());
 330
 331  FLAGS_v = 0;
 332  RAW_LOG(INFO, "log");
 333  RAW_VLOG(0, "vlog 0 on");
 334  RAW_VLOG(1, "vlog 1 off");
 335  RAW_VLOG(2, "vlog 2 off");
 336  RAW_VLOG(3, "vlog 3 off");
 337  FLAGS_v = 2;
 338  RAW_LOG(INFO, "log");
 339  RAW_VLOG(1, "vlog 1 on");
 340  RAW_VLOG(2, "vlog 2 on");
 341  RAW_VLOG(3, "vlog 3 off");
 342
 343#ifdef NDEBUG
 344  RAW_DCHECK(1 == 2, " RAW_DCHECK's shouldn't be compiled in normal mode");
 345#endif
 346
 347  RAW_CHECK(1 == 1, "should be ok");
 348  RAW_DCHECK(true, "should be ok");
 349
 350  delete foo;
 351}
 352
 353void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
 354  RAW_LOG(INFO,
 355          "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d",
 356          v, severity, err, alsoerr);
 357
 358  FlagSaver saver;
 359
 360  FLAGS_v = v;
 361  FLAGS_stderrthreshold = severity;
 362  FLAGS_logtostderr = err;
 363  FLAGS_alsologtostderr = alsoerr;
 364
 365  RAW_VLOG(-1, "vlog -1");
 366  RAW_VLOG(0, "vlog 0");
 367  RAW_VLOG(1, "vlog 1");
 368  RAW_LOG(INFO, "log info");
 369  RAW_LOG(WARNING, "log warning");
 370  RAW_LOG(ERROR, "log error");
 371
 372  VLOG(-1) << "vlog -1";
 373  VLOG(0) << "vlog 0";
 374  VLOG(1) << "vlog 1";
 375  LOG(INFO) << "log info";
 376  LOG(WARNING) << "log warning";
 377  LOG(ERROR) << "log error";
 378
 379  VLOG_IF(-1, true) << "vlog_if -1";
 380  VLOG_IF(-1, false) << "don't vlog_if -1";
 381  VLOG_IF(0, true) << "vlog_if 0";
 382  VLOG_IF(0, false) << "don't vlog_if 0";
 383  VLOG_IF(1, true) << "vlog_if 1";
 384  VLOG_IF(1, false) << "don't vlog_if 1";
 385  LOG_IF(INFO, true) << "log_if info";
 386  LOG_IF(INFO, false) << "don't log_if info";
 387  LOG_IF(WARNING, true) << "log_if warning";
 388  LOG_IF(WARNING, false) << "don't log_if warning";
 389  LOG_IF(ERROR, true) << "log_if error";
 390  LOG_IF(ERROR, false) << "don't log_if error";
 391
 392  int c;
 393  c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1);
 394  c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1);
 395  c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1);
 396  c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1);
 397  c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0);
 398  c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0);
 399
 400  c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
 401  EXPECT_EQ(c, -1);
 402  c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
 403  EXPECT_EQ(c, -1);
 404  c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
 405  EXPECT_EQ(c, 0);
 406  c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
 407  EXPECT_EQ(c, 0);
 408  c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
 409  EXPECT_EQ(c, 1);
 410  c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
 411  EXPECT_EQ(c, 1);
 412  c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
 413  EXPECT_EQ(c, 0);
 414  c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
 415  EXPECT_EQ(c, 0);
 416}
 417
 418void TestLoggingLevels() {
 419  LogWithLevels(0, INFO, false, false);
 420  LogWithLevels(1, INFO, false, false);
 421  LogWithLevels(-1, INFO, false, false);
 422  LogWithLevels(0, WARNING, false, false);
 423  LogWithLevels(0, ERROR, false, false);
 424  LogWithLevels(0, FATAL, false, false);
 425  LogWithLevels(0, FATAL, true, false);
 426  LogWithLevels(0, FATAL, false, true);
 427  LogWithLevels(1, WARNING, false, false);
 428  LogWithLevels(1, FATAL, false, true);
 429}
 430
 431TEST(DeathRawCHECK, logging) {
 432  ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
 433               "RAW: Check false failed: failure 1");
 434  ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"),
 435               "RAW: Check 1 == 2 failed: failure 2");
 436}
 437
 438void TestLogString() {
 439  vector<string> errors;
 440  vector<string> *no_errors = NULL;
 441
 442  LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info";
 443  LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning";
 444  LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error";
 445
 446  LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info";
 447  LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning";
 448  LOG_STRING(ERROR, NULL) << "LOG_STRING: " << "reported error";
 449
 450  for (size_t i = 0; i < errors.size(); ++i) {
 451    LOG(INFO) << "Captured by LOG_STRING:  " << errors[i];
 452  }
 453}
 454
 455void TestLogToString() {
 456  string error;
 457  string* no_error = NULL;
 458
 459  LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info";
 460  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
 461  LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning";
 462  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
 463  LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error";
 464  LOG(INFO) << "Captured by LOG_TO_STRING:  " << error;
 465
 466  LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info";
 467  LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning";
 468  LOG_TO_STRING(ERROR, NULL) << "LOG_TO_STRING: " << "reported error";
 469}
 470
 471class TestLogSinkImpl : public LogSink {
 472 public:
 473  vector<string> errors;
 474  virtual void send(LogSeverity severity, const char* full_filename,
 475                    const char* base_filename, int line,
 476                    const struct tm* tm_time,
 477                    const char* message, size_t message_len) {
 478    errors.push_back(
 479      ToString(severity, base_filename, line, tm_time, message, message_len));
 480  }
 481};
 482
 483void TestLogSink() {
 484  TestLogSinkImpl sink;
 485  LogSink *no_sink = NULL;
 486
 487  LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info";
 488  LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning";
 489  LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error";
 490
 491  LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info";
 492  LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning";
 493  LOG_TO_SINK(NULL, ERROR) << "LOG_TO_SINK: " << "reported error";
 494
 495  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
 496      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info";
 497  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
 498      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning";
 499  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
 500      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error";
 501
 502  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
 503      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info";
 504  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
 505      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning";
 506  LOG_TO_SINK_BUT_NOT_TO_LOGFILE(NULL, ERROR)
 507      << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed error";
 508
 509  LOG(INFO) << "Captured by LOG_TO_SINK:";
 510  for (size_t i = 0; i < sink.errors.size(); ++i) {
 511    LogMessage("foo", LogMessage::kNoLogPrefix, INFO).stream()
 512      << sink.errors[i];
 513  }
 514}
 515
 516// For testing using CHECK*() on anonymous enums.
 517enum {
 518  CASE_A,
 519  CASE_B
 520};
 521
 522void TestCHECK() {
 523  // Tests using CHECK*() on int values.
 524  CHECK(1 == 1);
 525  CHECK_EQ(1, 1);
 526  CHECK_NE(1, 2);
 527  CHECK_GE(1, 1);
 528  CHECK_GE(2, 1);
 529  CHECK_LE(1, 1);
 530  CHECK_LE(1, 2);
 531  CHECK_GT(2, 1);
 532  CHECK_LT(1, 2);
 533
 534  // Tests using CHECK*() on anonymous enums.
 535  // Apple's GCC doesn't like this.
 536#if !defined(OS_MACOSX)
 537  CHECK_EQ(CASE_A, CASE_A);
 538  CHECK_NE(CASE_A, CASE_B);
 539  CHECK_GE(CASE_A, CASE_A);
 540  CHECK_GE(CASE_B, CASE_A);
 541  CHECK_LE(CASE_A, CASE_A);
 542  CHECK_LE(CASE_A, CASE_B);
 543  CHECK_GT(CASE_B, CASE_A);
 544  CHECK_LT(CASE_A, CASE_B);
 545#endif
 546}
 547
 548void TestDCHECK() {
 549#ifdef NDEBUG
 550  DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode";
 551#endif
 552  DCHECK( 1 == 1 );
 553  DCHECK_EQ(1, 1);
 554  DCHECK_NE(1, 2);
 555  DCHECK_GE(1, 1);
 556  DCHECK_GE(2, 1);
 557  DCHECK_LE(1, 1);
 558  DCHECK_LE(1, 2);
 559  DCHECK_GT(2, 1);
 560  DCHECK_LT(1, 2);
 561
 562  auto_ptr<int64> sptr(new int64);
 563  int64* ptr = DCHECK_NOTNULL(sptr.get());
 564  CHECK_EQ(ptr, sptr.get());
 565}
 566
 567void TestSTREQ() {
 568  CHECK_STREQ("this", "this");
 569  CHECK_STREQ(NULL, NULL);
 570  CHECK_STRCASEEQ("this", "tHiS");
 571  CHECK_STRCASEEQ(NULL, NULL);
 572  CHECK_STRNE("this", "tHiS");
 573  CHECK_STRNE("this", NULL);
 574  CHECK_STRCASENE("this", "that");
 575  CHECK_STRCASENE(NULL, "that");
 576  CHECK_STREQ((string("a")+"b").c_str(), "ab");
 577  CHECK_STREQ(string("test").c_str(),
 578              (string("te") + string("st")).c_str());
 579}
 580
 581TEST(DeathSTREQ, logging) {
 582  ASSERT_DEATH(CHECK_STREQ(NULL, "this"), "");
 583  ASSERT_DEATH(CHECK_STREQ("this", "siht"), "");
 584  ASSERT_DEATH(CHECK_STRCASEEQ(NULL, "siht"), "");
 585  ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), "");
 586  ASSERT_DEATH(CHECK_STRNE(NULL, NULL), "");
 587  ASSERT_DEATH(CHECK_STRNE("this", "this"), "");
 588  ASSERT_DEATH(CHECK_STREQ((string("a")+"b").c_str(), "abc"), "");
 589}
 590
 591TEST(CheckNOTNULL, Simple) {
 592  int64 t;
 593  void *ptr = static_cast<void *>(&t);
 594  void *ref = CHECK_NOTNULL(ptr);
 595  EXPECT_EQ(ptr, ref);
 596  CHECK_NOTNULL(reinterpret_cast<char *>(ptr));
 597  CHECK_NOTNULL(reinterpret_cast<unsigned char *>(ptr));
 598  CHECK_NOTNULL(reinterpret_cast<int *>(ptr));
 599  CHECK_NOTNULL(reinterpret_cast<int64 *>(ptr));
 600}
 601
 602TEST(DeathCheckNN, Simple) {
 603  ASSERT_DEATH(CHECK_NOTNULL(static_cast<void *>(NULL)), "");
 604}
 605
 606// Get list of file names that match pattern
 607static void GetFiles(const string& pattern, vector<string>* files) {
 608  files->clear();
 609#if defined(HAVE_GLOB_H)
 610  glob_t g;
 611  const int r = glob(pattern.c_str(), 0, NULL, &g);
 612  CHECK((r == 0) || (r == GLOB_NOMATCH)) << ": error matching " << pattern;
 613  for (int i = 0; i < g.gl_pathc; i++) {
 614    files->push_back(string(g.gl_pathv[i]));
 615  }
 616  globfree(&g);
 617#elif defined(OS_WINDOWS)
 618  WIN32_FIND_DATAA data;
 619  HANDLE handle = FindFirstFileA(pattern.c_str(), &data);
 620  size_t index = pattern.rfind('\\');
 621  if (index == string::npos) {
 622    LOG(FATAL) << "No directory separator.";
 623  }
 624  const string dirname = pattern.substr(0, index + 1);
 625  if (FAILED(handle)) {
 626    // Finding no files is OK.
 627    return;
 628  }
 629  do {
 630    files->push_back(dirname + data.cFileName);
 631  } while (FindNextFileA(handle, &data));
 632  LOG_SYSRESULT(FindClose(handle));
 633#else
 634# error There is no way to do glob.
 635#endif
 636}
 637
 638// Delete files patching pattern
 639static void DeleteFiles(const string& pattern) {
 640  vector<string> files;
 641  GetFiles(pattern, &files);
 642  for (size_t i = 0; i < files.size(); i++) {
 643    CHECK(unlink(files[i].c_str()) == 0) << ": " << strerror(errno);
 644  }
 645}
 646
 647static void CheckFile(const string& name, const string& expected_string) {
 648  vector<string> files;
 649  GetFiles(name + "*", &files);
 650  CHECK_EQ(files.size(), 1);
 651
 652  FILE* file = fopen(files[0].c_str(), "r");
 653  CHECK(file != NULL) << ": could not open " << files[0];
 654  char buf[1000];
 655  while (fgets(buf, sizeof(buf), file) != NULL) {
 656    if (strstr(buf, expected_string.c_str()) != NULL) {
 657      fclose(file);
 658      return;
 659    }
 660  }
 661  fclose(file);
 662  LOG(FATAL) << "Did not find " << expected_string << " in " << files[0];
 663}
 664
 665static void TestBasename() {
 666  fprintf(stderr, "==== Test setting log file basename\n");
 667  const string dest = FLAGS_test_tmpdir + "/logging_test_basename";
 668  DeleteFiles(dest + "*");
 669
 670  SetLogDestination(INFO, dest.c_str());
 671  LOG(INFO) << "message to new base";
 672  FlushLogFiles(INFO);
 673
 674  CheckFile(dest, "message to new base");
 675
 676  // Release file handle for the destination file to unlock the file in Windows.
 677  LogToStderr();
 678  DeleteFiles(dest + "*");
 679}
 680
 681static void TestSymlink() {
 682#ifndef OS_WINDOWS
 683  fprintf(stderr, "==== Test setting log file symlink\n");
 684  string dest = FLAGS_test_tmpdir + "/logging_test_symlink";
 685  string sym = FLAGS_test_tmpdir + "/symlinkbase";
 686  DeleteFiles(dest + "*");
 687  DeleteFiles(sym + "*");
 688
 689  SetLogSymlink(INFO, "symlinkbase");
 690  SetLogDestination(INFO, dest.c_str());
 691  LOG(INFO) << "message to new symlink";
 692  FlushLogFiles(INFO);
 693  CheckFile(sym, "message to new symlink");
 694
 695  DeleteFiles(dest + "*");
 696  DeleteFiles(sym + "*");
 697#endif
 698}
 699
 700static void TestExtension() {
 701  fprintf(stderr, "==== Test setting log file extension\n");
 702  string dest = FLAGS_test_tmpdir + "/logging_test_extension";
 703  DeleteFiles(dest + "*");
 704
 705  SetLogDestination(INFO, dest.c_str());
 706  SetLogFilenameExtension("specialextension");
 707  LOG(INFO) << "message to new extension";
 708  FlushLogFiles(INFO);
 709  CheckFile(dest, "message to new extension");
 710
 711  // Check that file name ends with extension
 712  vector<string> filenames;
 713  GetFiles(dest + "*", &filenames);
 714  CHECK_EQ(filenames.size(), 1);
 715  CHECK(strstr(filenames[0].c_str(), "specialextension") != NULL);
 716
 717  // Release file handle for the destination file to unlock the file in Windows.
 718  LogToStderr();
 719  DeleteFiles(dest + "*");
 720}
 721
 722struct MyLogger : public base::Logger {
 723  string data;
 724
 725  virtual void Write(bool should_flush,
 726                     time_t timestamp,
 727                     const char* message,
 728                     int length) {
 729    data.append(message, length);
 730  }
 731
 732  virtual void Flush() { }
 733
 734  virtual uint32 LogSize() { return data.length(); }
 735};
 736
 737static void TestWrapper() {
 738  fprintf(stderr, "==== Test log wrapper\n");
 739
 740  MyLogger my_logger;
 741  base::Logger* old_logger = base::GetLogger(INFO);
 742  base::SetLogger(INFO, &my_logger);
 743  LOG(INFO) << "Send to wrapped logger";
 744  FlushLogFiles(INFO);
 745  base::SetLogger(INFO, old_logger);
 746
 747  CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL);
 748}
 749
 750static void TestErrno() {
 751  fprintf(stderr, "==== Test errno preservation\n");
 752
 753  errno = ENOENT;
 754  TestLogging(false);
 755  CHECK_EQ(errno, ENOENT);
 756}
 757
 758static void TestOneTruncate(const char *path, int64 limit, int64 keep,
 759                            int64 dsize, int64 ksize, int64 expect) {
 760  int fd;
 761  CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
 762
 763  const char *discardstr = "DISCARDME!", *keepstr = "KEEPME!";
 764
 765  // Fill the file with the requested data; first discard data, then kept data
 766  int64 written = 0;
 767  while (written < dsize) {
 768    int bytes = min<int64>(dsize - written, strlen(discardstr));
 769    CHECK_ERR(write(fd, discardstr, bytes));
 770    written += bytes;
 771  }
 772  written = 0;
 773  while (written < ksize) {
 774    int bytes = min<int64>(ksize - written, strlen(keepstr));
 775    CHECK_ERR(write(fd, keepstr, bytes));
 776    written += bytes;
 777  }
 778
 779  TruncateLogFile(path, limit, keep);
 780
 781  // File should now be shorter
 782  struct stat statbuf;
 783  CHECK_ERR(fstat(fd, &statbuf));
 784  CHECK_EQ(statbuf.st_size, expect);
 785  CHECK_ERR(lseek(fd, 0, SEEK_SET));
 786
 787  // File should contain the suffix of the original file
 788  int buf_size = statbuf.st_size + 1;
 789  char* buf = new char[buf_size];
 790  memset(buf, 0, sizeof(buf));
 791  CHECK_ERR(read(fd, buf, buf_size));
 792
 793  const char *p = buf;
 794  int64 checked = 0;
 795  while (checked < expect) {
 796    int bytes = min<int64>(expect - checked, strlen(keepstr));
 797    CHECK(!memcmp(p, keepstr, bytes));
 798    checked += bytes;
 799  }
 800  close(fd);
 801  delete[] buf;
 802}
 803
 804static void TestTruncate() {
 805#ifdef HAVE_UNISTD_H
 806  fprintf(stderr, "==== Test log truncation\n");
 807  string path = FLAGS_test_tmpdir + "/truncatefile";
 808
 809  // Test on a small file
 810  TestOneTruncate(path.c_str(), 10, 10, 10, 10, 10);
 811
 812  // And a big file (multiple blocks to copy)
 813  TestOneTruncate(path.c_str(), 2<<20, 4<<10, 3<<20, 4<<10, 4<<10);
 814
 815  // Check edge-case limits
 816  TestOneTruncate(path.c_str(), 10, 20, 0, 20, 20);
 817  TestOneTruncate(path.c_str(), 10, 0, 0, 0, 0);
 818  TestOneTruncate(path.c_str(), 10, 50, 0, 10, 10);
 819  TestOneTruncate(path.c_str(), 50, 100, 0, 30, 30);
 820
 821  // MacOSX 10.4 doesn't fail in this case.
 822  // Windows doesn't have symlink.
 823  // Let's just ignore this test for these cases.
 824#if !defined(OS_MACOSX) && !defined(OS_WINDOWS)
 825  // Through a symlink should fail to truncate
 826  string linkname = path + ".link";
 827  unlink(linkname.c_str());
 828  CHECK_ERR(symlink(path.c_str(), linkname.c_str()));
 829  TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30);
 830#endif
 831
 832  // The /proc/self path makes sense only for linux.
 833#if defined(OS_LINUX)
 834  // Through an open fd symlink should work
 835  int fd;
 836  CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
 837  char fdpath[64];
 838  snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
 839  TestOneTruncate(fdpath, 10, 10, 10, 10, 10);
 840#endif
 841
 842#endif
 843}
 844
 845_START_GOOGLE_NAMESPACE_
 846namespace glog_internal_namespace_ {
 847extern  // in logging.cc
 848bool SafeFNMatch_(const char* pattern, size_t patt_len,
 849                  const char* str, size_t str_len);
 850} // namespace glog_internal_namespace_
 851using glog_internal_namespace_::SafeFNMatch_;
 852_END_GOOGLE_NAMESPACE_
 853
 854static bool WrapSafeFNMatch(string pattern, string str) {
 855  pattern += "abc";
 856  str += "defgh";
 857  return SafeFNMatch_(pattern.data(), pattern.size() - 3,
 858                      str.data(), str.size() - 5);
 859}
 860
 861TEST(SafeFNMatch, logging) {
 862  CHECK(WrapSafeFNMatch("foo", "foo"));
 863  CHECK(!WrapSafeFNMatch("foo", "bar"));
 864  CHECK(!WrapSafeFNMatch("foo", "fo"));
 865  CHECK(!WrapSafeFNMatch("foo", "foo2"));
 866  CHECK(WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext"));
 867  CHECK(WrapSafeFNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"));
 868  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/baz.ext"));
 869  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo"));
 870  CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext.zip"));
 871  CHECK(WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext"));
 872  CHECK(WrapSafeFNMatch("ba?/*.ext", "baZ/FOO.ext"));
 873  CHECK(!WrapSafeFNMatch("ba?/*.ext", "barr/foo.ext"));
 874  CHECK(!WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext2"));
 875  CHECK(WrapSafeFNMatch("ba?/*", "bar/foo.ext2"));
 876  CHECK(WrapSafeFNMatch("ba?/*", "bar/"));
 877  CHECK(!WrapSafeFNMatch("ba?/?", "bar/"));
 878  CHECK(!WrapSafeFNMatch("ba?/*", "bar"));
 879}
 880
 881// TestWaitingLogSink will save messages here
 882// No lock: Accessed only by TestLogSinkWriter thread
 883// and after its demise by its creator.
 884static vector<string> global_messages;
 885
 886// helper for TestWaitingLogSink below.
 887// Thread that does the logic of TestWaitingLogSink
 888// It's free to use LOG() itself.
 889class TestLogSinkWriter : public Thread {
 890 public:
 891
 892  TestLogSinkWriter() : should_exit_(false) {
 893    SetJoinable(true);
 894    Start();
 895  }
 896
 897  // Just buffer it (can't use LOG() here).
 898  void Buffer(const string& message) {
 899    mutex_.Lock();
 900    RAW_LOG(INFO, "Buffering");
 901    messages_.push(message);
 902    mutex_.Unlock();
 903    RAW_LOG(INFO, "Buffered");
 904  }
 905
 906  // Wait for the buffer to clear (can't use LOG() here).
 907  void Wait() {
 908    RAW_LOG(INFO, "Waiting");
 909    mutex_.Lock();
 910    while (!NoWork()) {
 911      mutex_.Unlock();
 912      SleepForMilliseconds(1);
 913      mutex_.Lock();
 914    }
 915    RAW_LOG(INFO, "Waited");
 916    mutex_.Unlock();
 917  }
 918
 919  // Trigger thread exit.
 920  void Stop() {
 921    MutexLock l(&mutex_);
 922    should_exit_ = true;
 923  }
 924
 925 private:
 926
 927  // helpers ---------------
 928
 929  // For creating a "Condition".
 930  bool NoWork() { return messages_.empty(); }
 931  bool HaveWork() { return !messages_.empty() || should_exit_; }
 932
 933  // Thread body; CAN use LOG() here!
 934  virtual void Run() {
 935    while (1) {
 936      mutex_.Lock();
 937      while (!HaveWork()) {
 938        mutex_.Unlock();
 939        SleepForMilliseconds(1);
 940        mutex_.Lock();
 941      }
 942      if (should_exit_ && messages_.empty()) {
 943        mutex_.Unlock();
 944        break;
 945      }
 946      // Give the main thread time to log its message,
 947      // so that we get a reliable log capture to compare to golden file.
 948      // Same for the other sleep below.
 949      SleepForMilliseconds(20);
 950      RAW_LOG(INFO, "Sink got a messages");  // only RAW_LOG under mutex_ here
 951      string message = messages_.front();
 952      messages_.pop();
 953      // Normally this would be some more real/involved logging logic
 954      // where LOG() usage can't be eliminated,
 955      // e.g. pushing the message over with an RPC:
 956      int messages_left = messages_.size();
 957      mutex_.Unlock();
 958      SleepForMilliseconds(20);
 959      // May not use LOG while holding mutex_, because Buffer()
 960      // acquires mutex_, and Buffer is called from LOG(),
 961      // which has its own internal mutex:
 962      // LOG()->LogToSinks()->TestWaitingLogSink::send()->Buffer()
 963      LOG(INFO) << "Sink is sending out a message: " << message;
 964      LOG(INFO) << "Have " << messages_left << " left";
 965      global_messages.push_back(message);
 966    }
 967  }
 968
 969  // data ---------------
 970
 971  Mutex mutex_;
 972  bool should_exit_;
 973  queue<string> messages_;  // messages to be logged
 974};
 975
 976// A log sink that exercises WaitTillSent:
 977// it pushes data to a buffer and wakes up another thread to do the logging
 978// (that other thread can than use LOG() itself),
 979class TestWaitingLogSink : public LogSink {
 980 public:
 981
 982  TestWaitingLogSink() {
 983    tid_ = pthread_self();  // for thread-specific behavior
 984    AddLogSink(this);
 985  }
 986  ~TestWaitingLogSink() {
 987    RemoveLogSink(this);
 988    writer_.Stop();
 989    writer_.Join();
 990  }
 991
 992  // (re)define LogSink interface
 993
 994  virtual void send(LogSeverity severity, const char* full_filename,
 995                    const char* base_filename, int line,
 996                    const struct tm* tm_time,
 997                    const char* message, size_t message_len) {
 998    // Push it to Writer thread if we are the original logging thread.
 999    // Note: Something like ThreadLocalLogSink is a better choice
1000    //       to do thread-specific LogSink logic for real.
1001    if (pthread_equal(tid_, pthread_self())) {
1002      writer_.Buffer(ToString(severity, base_filename, line,
1003                              tm_time, message, message_len));
1004    }
1005  }
1006  virtual void WaitTillSent() {
1007    // Wait for Writer thread if we are the original logging thread.
1008    if (pthread_equal(tid_, pthread_self()))  writer_.Wait();
1009  }
1010
1011 private:
1012
1013  pthread_t tid_;
1014  TestLogSinkWriter writer_;
1015};
1016
1017// Check that LogSink::WaitTillSent can be used in the advertised way.
1018// We also do golden-stderr comparison.
1019static void TestLogSinkWaitTillSent() {
1020  { TestWaitingLogSink sink;
1021    // Sleeps give the sink threads time to do all their work,
1022    // so that we get a reliable log capture to compare to the golden file.
1023    LOG(INFO) << "Message 1";
1024    SleepForMilliseconds(60);
1025    LOG(ERROR) << "Message 2";
1026    SleepForMilliseconds(60);
1027    LOG(WARNING) << "Message 3";
1028    SleepForMilliseconds(60);
1029  }
1030  for (size_t i = 0; i < global_messages.size(); ++i) {
1031    LOG(INFO) << "Sink capture: " << global_messages[i];
1032  }
1033  CHECK_EQ(global_messages.size(), 3);
1034}
1035
1036TEST(Strerror, logging) {
1037  int errcode = EINTR;
1038  char *msg = strdup(strerror(errcode));
1039  int buf_size = strlen(msg) + 1;
1040  char *buf = new char[buf_size];
1041  CHECK_EQ(posix_strerror_r(errcode, NULL, 0), -1);
1042  buf[0] = 'A';
1043  CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
1044  CHECK_EQ(buf[0], 'A');
1045  CHECK_EQ(posix_strerror_r(errcode, NULL, buf_size), -1);
1046#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
1047  // MacOSX or FreeBSD considers this case is an error since there is
1048  // no enough space.
1049  CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
1050#else
1051  CHECK_EQ(posix_strerror_r(errcode, buf, 1), 0);
1052#endif
1053  CHECK_STREQ(buf, "");
1054  CHECK_EQ(posix_strerror_r(errcode, buf, buf_size), 0);
1055  CHECK_STREQ(buf, msg);
1056  free(msg);
1057  delete[] buf;
1058}
1059
1060// Simple routines to look at the sizes of generated code for LOG(FATAL) and
1061// CHECK(..) via objdump
1062void MyFatal() {
1063  LOG(FATAL) << "Failed";
1064}
1065void MyCheck(bool a, bool b) {
1066  CHECK_EQ(a, b);
1067}
1068
1069#ifdef HAVE_LIB_GMOCK
1070
1071TEST(DVLog, Basic) {
1072  ScopedMockLog log;
1073
1074#if NDEBUG
1075  // We are expecting that nothing is logged.
1076  EXPECT_CALL(log, Log(_, _, _)).Times(0);
1077#else
1078  EXPECT_CALL(log, Log(INFO, __FILE__, "debug log"));
1079#endif
1080
1081  FLAGS_v = 1;
1082  DVLOG(1) << "debug log";
1083}
1084
1085TEST(DVLog, V0) {
1086  ScopedMockLog log;
1087
1088  // We are expecting that nothing is logged.
1089  EXPECT_CALL(log, Log(_, _, _)).Times(0);
1090
1091  FLAGS_v = 0;
1092  DVLOG(1) << "debug log";
1093}
1094
1095TEST(LogAtLevel, Basic) {
1096  ScopedMockLog log;
1097
1098  // The function version outputs "logging.h" as a file name.
1099  EXPECT_CALL(log, Log(WARNING, StrNe(__FILE__), "function version"));
1100  EXPECT_CALL(log, Log(INFO, __FILE__, "macro version"));
1101
1102  int severity = WARNING;
1103  LogAtLevel(severity, "function version");
1104
1105  severity = INFO;
1106  // We can use the macro version as a C++ stream.
1107  LOG_AT_LEVEL(severity) << "macro" << ' ' << "version";
1108}
1109
1110TEST(TestExitOnDFatal, ToBeOrNotToBe) {
1111  // Check the default setting...
1112  EXPECT_TRUE(base::internal::GetExitOnDFatal());
1113
1114  // Turn off...
1115  base::internal::SetExitOnDFatal(false);
1116  EXPECT_FALSE(base::internal::GetExitOnDFatal());
1117
1118  // We don't die.
1119  {
1120    ScopedMockLog log;
1121    //EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
1122    // LOG(DFATAL) has severity FATAL if debugging, but is
1123    // downgraded to ERROR if not debugging.
1124    const LogSeverity severity =
1125#ifdef NDEBUG
1126        ERROR;
1127#else
1128        FATAL;
1129#endif
1130    EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
1131    LOG(DFATAL) << "This should not be fatal";
1132  }
1133
1134  // Turn back on...
1135  base::internal::SetExitOnDFatal(true);
1136  EXPECT_TRUE(base::internal::GetExitOnDFatal());
1137
1138#ifdef GTEST_HAS_DEATH_TEST
1139  // Death comes on little cats' feet.
1140  EXPECT_DEBUG_DEATH({
1141      LOG(DFATAL) << "This should be fatal in debug mode";
1142    }, "This should be fatal in debug mode");
1143#endif
1144}
1145
1146#ifdef HAVE_STACKTRACE
1147
1148static void BacktraceAtHelper() {
1149  LOG(INFO) << "Not me";
1150
1151// The vertical spacing of the next 3 lines is significant.
1152  LOG(INFO) << "Backtrace me";
1153}
1154static int kBacktraceAtLine = __LINE__ - 2;  // The line of the LOG(INFO) above
1155
1156TEST(LogBacktraceAt, DoesNotBacktraceWhenDisabled) {
1157  StrictMock<ScopedMockLog> log;
1158
1159  FLAGS_log_backtrace_at = "";
1160
1161  EXPECT_CALL(log, Log(_, _, "Backtrace me"));
1162  EXPECT_CALL(log, Log(_, _, "Not me"));
1163
1164  BacktraceAtHelper();
1165}
1166
1167TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
1168  StrictMock<ScopedMockLog> log;
1169
1170  char where[100];
1171  snprintf(where, 100, "%s:%d", const_basename(__FILE__), kBacktraceAtLine);
1172  FLAGS_log_backtrace_at = where;
1173
1174  // The LOG at the specified line should include a stacktrace which includes
1175  // the name of the containing function, followed by the log message.
1176  // We use HasSubstr()s instead of ContainsRegex() for environments
1177  // which don't have regexp.
1178  EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"),
1179                                   HasSubstr("BacktraceAtHelper"),
1180                                   HasSubstr("main"),
1181                                   HasSubstr("Backtrace me"))));
1182  // Other LOGs should not include a backtrace.
1183  EXPECT_CALL(log, Log(_, _, "Not me"));
1184
1185  BacktraceAtHelper();
1186}
1187
1188#endif // HAVE_STACKTRACE
1189
1190#endif // HAVE_LIB_GMOCK
1191
1192struct UserDefinedClass {
1193  bool operator==(const UserDefinedClass& rhs) const { return true; }
1194};
1195
1196inline ostream& operator<<(ostream& out, const UserDefinedClass& u) {
1197  out << "OK";
1198  return out;
1199}
1200
1201TEST(UserDefinedClass, logging) {
1202  UserDefinedClass u;
1203  vector<string> buf;
1204  LOG_STRING(INFO, &buf) << u;
1205  CHECK_EQ(1, buf.size());
1206  CHECK(buf[0].find("OK") != string::npos);
1207
1208  // We must be able to compile this.
1209  CHECK_EQ(u, u);
1210}