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