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