c1df14e593980c5a573b098b66653dab74dc0f38
[platform/upstream/glog.git] / src / googletest.h
1 // Copyright (c) 2009, 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: Shinichiro Hamaji
31 //   (based on googletest: http://code.google.com/p/googletest/)
32
33 #ifdef GOOGLETEST_H__
34 #error You must not include this file twice.
35 #endif
36 #define GOOGLETEST_H__
37
38 #include "utilities.h"
39
40 #include <ctype.h>
41 #include <setjmp.h>
42 #include <time.h>
43
44 #include <map>
45 #include <sstream>
46 #include <string>
47 #include <vector>
48
49 #include <stdio.h>
50 #include <stdlib.h>
51
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55 #ifdef HAVE_UNISTD_H
56 # include <unistd.h>
57 #endif
58
59 #include "base/commandlineflags.h"
60
61 using std::map;
62 using std::string;
63 using std::vector;
64
65 _START_GOOGLE_NAMESPACE_
66
67 extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
68
69 _END_GOOGLE_NAMESPACE_
70
71 #undef GOOGLE_GLOG_DLL_DECL
72 #define GOOGLE_GLOG_DLL_DECL
73
74 static inline string GetTempDir() {
75 #ifndef OS_WINDOWS
76   return "/tmp";
77 #else
78   char tmp[MAX_PATH];
79   GetTempPathA(MAX_PATH, tmp);
80   return tmp;
81 #endif
82 }
83
84 #ifdef OS_WINDOWS
85 // The test will run in glog/vsproject/<project name>
86 // (e.g., glog/vsproject/logging_unittest).
87 static const char TEST_SRC_DIR[] = "../..";
88 #else
89 static const char TEST_SRC_DIR[] = ".";
90 #endif
91
92 DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
93 DEFINE_string(test_srcdir, TEST_SRC_DIR,
94               "Source-dir root, needed to find glog_unittest_flagfile");
95 DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
96 #ifdef NDEBUG
97 DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
98 #else
99 DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
100 #endif
101
102 #ifdef HAVE_LIB_GTEST
103 # include <gtest/gtest.h>
104 // Use our ASSERT_DEATH implementation.
105 # undef ASSERT_DEATH
106 # undef ASSERT_DEBUG_DEATH
107 using testing::InitGoogleTest;
108 #else
109
110 _START_GOOGLE_NAMESPACE_
111
112 void InitGoogleTest(int* argc, char** argv) {}
113
114 // The following is some bare-bones testing infrastructure
115
116 #define EXPECT_TRUE(cond)                               \
117   do {                                                  \
118     if (!(cond)) {                                      \
119       fprintf(stderr, "Check failed: %s\n", #cond);     \
120       exit(1);                                          \
121     }                                                   \
122   } while (0)
123
124 #define EXPECT_FALSE(cond)  EXPECT_TRUE(!(cond))
125
126 #define EXPECT_OP(op, val1, val2)                                       \
127   do {                                                                  \
128     if (!((val1) op (val2))) {                                          \
129       fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2);   \
130       exit(1);                                                          \
131     }                                                                   \
132   } while (0)
133
134 #define EXPECT_EQ(val1, val2)  EXPECT_OP(==, val1, val2)
135 #define EXPECT_NE(val1, val2)  EXPECT_OP(!=, val1, val2)
136 #define EXPECT_GT(val1, val2)  EXPECT_OP(>, val1, val2)
137 #define EXPECT_LT(val1, val2)  EXPECT_OP(<, val1, val2)
138
139 #define EXPECT_NAN(arg)                                         \
140   do {                                                          \
141     if (!isnan(arg)) {                                          \
142       fprintf(stderr, "Check failed: isnan(%s)\n", #arg);       \
143       exit(1);                                                  \
144     }                                                           \
145   } while (0)
146
147 #define EXPECT_INF(arg)                                         \
148   do {                                                          \
149     if (!isinf(arg)) {                                          \
150       fprintf(stderr, "Check failed: isinf(%s)\n", #arg);       \
151       exit(1);                                                  \
152     }                                                           \
153   } while (0)
154
155 #define EXPECT_DOUBLE_EQ(val1, val2)                                    \
156   do {                                                                  \
157     if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) {         \
158       fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2);        \
159       exit(1);                                                          \
160     }                                                                   \
161   } while (0)
162
163 #define EXPECT_STREQ(val1, val2)                                        \
164   do {                                                                  \
165     if (strcmp((val1), (val2)) != 0) {                                  \
166       fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2);   \
167       exit(1);                                                          \
168     }                                                                   \
169   } while (0)
170
171 vector<void (*)()> g_testlist;  // the tests to run
172
173 #define TEST(a, b)                                      \
174   struct Test_##a##_##b {                               \
175     Test_##a##_##b() { g_testlist.push_back(&Run); }    \
176     static void Run() { FlagSaver fs; RunTest(); }      \
177     static void RunTest();                              \
178   };                                                    \
179   static Test_##a##_##b g_test_##a##_##b;               \
180   void Test_##a##_##b::RunTest()
181
182
183 static inline int RUN_ALL_TESTS() {
184   vector<void (*)()>::const_iterator it;
185   for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
186     (*it)();
187   }
188   fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
189   return 0;
190 }
191
192 _END_GOOGLE_NAMESPACE_
193
194 #endif  // ! HAVE_LIB_GTEST
195
196 _START_GOOGLE_NAMESPACE_
197
198 static bool g_called_abort;
199 static jmp_buf g_jmp_buf;
200 static inline void CalledAbort() {
201   g_called_abort = true;
202   longjmp(g_jmp_buf, 1);
203 }
204
205 #ifdef OS_WINDOWS
206 // TODO(hamaji): Death test somehow doesn't work in Windows.
207 #define ASSERT_DEATH(fn, msg)
208 #else
209 #define ASSERT_DEATH(fn, msg)                                           \
210   do {                                                                  \
211     g_called_abort = false;                                             \
212     /* in logging.cc */                                                 \
213     void (*original_logging_fail_func)() = g_logging_fail_func;         \
214     g_logging_fail_func = &CalledAbort;                                 \
215     if (!setjmp(g_jmp_buf)) fn;                                         \
216     /* set back to their default */                                     \
217     g_logging_fail_func = original_logging_fail_func;                   \
218     if (!g_called_abort) {                                              \
219       fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn);      \
220       exit(1);                                                          \
221     }                                                                   \
222   } while (0)
223 #endif
224
225 #ifdef NDEBUG
226 #define ASSERT_DEBUG_DEATH(fn, msg)
227 #else
228 #define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
229 #endif  // NDEBUG
230
231 // Benchmark tools.
232
233 #define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n);
234
235 map<string, void (*)(int)> g_benchlist;  // the benchmarks to run
236
237 class BenchmarkRegisterer {
238  public:
239   BenchmarkRegisterer(const char* name, void (*function)(int iters)) {
240     EXPECT_TRUE(g_benchlist.insert(std::make_pair(name, function)).second);
241   }
242 };
243
244 static inline void RunSpecifiedBenchmarks() {
245   if (!FLAGS_run_benchmark) {
246     return;
247   }
248
249   int iter_cnt = FLAGS_benchmark_iters;
250   puts("Benchmark\tTime(ns)\tIterations");
251   for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
252        iter != g_benchlist.end();
253        ++iter) {
254     clock_t start = clock();
255     iter->second(iter_cnt);
256     double elapsed_ns =
257         ((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
258     printf("%s\t%8.2lf\t%10d\n",
259            iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
260   }
261   puts("");
262 }
263
264 // ----------------------------------------------------------------------
265 // Golden file functions
266 // ----------------------------------------------------------------------
267
268 class CapturedStream {
269  public:
270   CapturedStream(int fd, const string & filename) :
271     fd_(fd),
272     uncaptured_fd_(-1),
273     filename_(filename) {
274     Capture();
275   }
276
277   ~CapturedStream() {
278     if (uncaptured_fd_ != -1) {
279       CHECK(close(uncaptured_fd_) != -1);
280     }
281   }
282
283   // Start redirecting output to a file
284   void Capture() {
285     // Keep original stream for later
286     CHECK(uncaptured_fd_ == -1) << ", Stream " << fd_ << " already captured!";
287     uncaptured_fd_ = dup(fd_);
288     CHECK(uncaptured_fd_ != -1);
289
290     // Open file to save stream to
291     int cap_fd = open(filename_.c_str(),
292                       O_CREAT | O_TRUNC | O_WRONLY,
293                       S_IRUSR | S_IWUSR);
294     CHECK(cap_fd != -1);
295
296     // Send stdout/stderr to this file
297     fflush(NULL);
298     CHECK(dup2(cap_fd, fd_) != -1);
299     CHECK(close(cap_fd) != -1);
300   }
301
302   // Remove output redirection
303   void StopCapture() {
304     // Restore original stream
305     if (uncaptured_fd_ != -1) {
306       fflush(NULL);
307       CHECK(dup2(uncaptured_fd_, fd_) != -1);
308     }
309   }
310
311   const string & filename() const { return filename_; }
312
313  private:
314   int fd_;             // file descriptor being captured
315   int uncaptured_fd_;  // where the stream was originally being sent to
316   string filename_;    // file where stream is being saved
317 };
318 static CapturedStream * s_captured_streams[STDERR_FILENO+1];
319 // Redirect a file descriptor to a file.
320 //   fd       - Should be STDOUT_FILENO or STDERR_FILENO
321 //   filename - File where output should be stored
322 static inline void CaptureTestOutput(int fd, const string & filename) {
323   CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
324   CHECK(s_captured_streams[fd] == NULL);
325   s_captured_streams[fd] = new CapturedStream(fd, filename);
326 }
327 static inline void CaptureTestStderr() {
328   CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
329 }
330 // Return the size (in bytes) of a file
331 static inline size_t GetFileSize(FILE * file) {
332   fseek(file, 0, SEEK_END);
333   return static_cast<size_t>(ftell(file));
334 }
335 // Read the entire content of a file as a string
336 static inline string ReadEntireFile(FILE * file) {
337   const size_t file_size = GetFileSize(file);
338   char * const buffer = new char[file_size];
339
340   size_t bytes_last_read = 0;  // # of bytes read in the last fread()
341   size_t bytes_read = 0;       // # of bytes read so far
342
343   fseek(file, 0, SEEK_SET);
344
345   // Keep reading the file until we cannot read further or the
346   // pre-determined file size is reached.
347   do {
348     bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
349     bytes_read += bytes_last_read;
350   } while (bytes_last_read > 0 && bytes_read < file_size);
351
352   const string content = string(buffer, buffer+bytes_read);
353   delete[] buffer;
354
355   return content;
356 }
357 // Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
358 // fd is STDERR_FILENO) as a string
359 static inline string GetCapturedTestOutput(int fd) {
360   CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
361   CapturedStream * const cap = s_captured_streams[fd];
362   CHECK(cap)
363     << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
364
365   // Make sure everything is flushed.
366   cap->StopCapture();
367
368   // Read the captured file.
369   FILE * const file = fopen(cap->filename().c_str(), "r");
370   const string content = ReadEntireFile(file);
371   fclose(file);
372
373   delete cap;
374   s_captured_streams[fd] = NULL;
375
376   return content;
377 }
378 // Get the captured stderr of a test as a string.
379 static inline string GetCapturedTestStderr() {
380   return GetCapturedTestOutput(STDERR_FILENO);
381 }
382
383 // Check if the string is [IWEF](\d{4}|DATE)
384 static inline bool IsLoggingPrefix(const string& s) {
385   if (s.size() != 5) return false;
386   if (!strchr("IWEF", s[0])) return false;
387   for (int i = 1; i <= 4; ++i) {
388     if (!isdigit(s[i]) && s[i] != "DATE"[i-1]) return false;
389   }
390   return true;
391 }
392
393 // Convert log output into normalized form.
394 //
395 // Example:
396 //     I0102 030405 logging_unittest.cc:345] RAW: vlog -1
397 //  => IDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
398 static inline string MungeLine(const string& line) {
399   std::istringstream iss(line);
400   string before, logcode_date, time, thread_lineinfo;
401   iss >> logcode_date;
402   while (!IsLoggingPrefix(logcode_date)) {
403     before += " " + logcode_date;
404     if (!(iss >> logcode_date)) {
405       // We cannot find the header of log output.
406       return before;
407     }
408   }
409   if (!before.empty()) before += " ";
410   iss >> time;
411   iss >> thread_lineinfo;
412   CHECK(!thread_lineinfo.empty());
413   if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
414     // We found thread ID.
415     string tmp;
416     iss >> tmp;
417     CHECK(!tmp.empty());
418     CHECK_EQ(']', tmp[tmp.size() - 1]);
419     thread_lineinfo = "THREADID " + tmp;
420   }
421   size_t index = thread_lineinfo.find(':');
422   CHECK_NE(string::npos, index);
423   thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
424   string rest;
425   std::getline(iss, rest);
426   return (before + logcode_date[0] + "DATE TIME__ " + thread_lineinfo +
427           MungeLine(rest));
428 }
429
430 static inline void StringReplace(string* str,
431                           const string& oldsub,
432                           const string& newsub) {
433   size_t pos = str->find(oldsub);
434   if (pos != string::npos) {
435     str->replace(pos, oldsub.size(), newsub.c_str());
436   }
437 }
438
439 static inline string Munge(const string& filename) {
440   FILE* fp = fopen(filename.c_str(), "rb");
441   CHECK(fp != NULL) << filename << ": couldn't open";
442   char buf[4096];
443   string result;
444   while (fgets(buf, 4095, fp)) {
445     string line = MungeLine(buf);
446     char null_str[256];
447     sprintf(null_str, "%p", static_cast<void*>(NULL));
448     StringReplace(&line, "__NULLP__", null_str);
449     // Remove 0x prefix produced by %p. VC++ doesn't put the prefix.
450     StringReplace(&line, " 0x", " ");
451
452     char errmsg_buf[100];
453     posix_strerror_r(0, errmsg_buf, sizeof(errmsg_buf));
454     if (*errmsg_buf == '\0') {
455       // MacOSX 10.4 and FreeBSD return empty string for errno=0.
456       // In such case, the we need to remove an extra space.
457       StringReplace(&line, "__SUCCESS__ ", "");
458     } else {
459       StringReplace(&line, "__SUCCESS__", errmsg_buf);
460     }
461     StringReplace(&line, "__ENOENT__", strerror(ENOENT));
462     StringReplace(&line, "__EINTR__", strerror(EINTR));
463     StringReplace(&line, "__ENXIO__", strerror(ENXIO));
464     StringReplace(&line, "__ENOEXEC__", strerror(ENOEXEC));
465     result += line + "\n";
466   }
467   fclose(fp);
468   return result;
469 }
470
471 static inline void WriteToFile(const string& body, const string& file) {
472   FILE* fp = fopen(file.c_str(), "wb");
473   fwrite(body.data(), 1, body.size(), fp);
474   fclose(fp);
475 }
476
477 static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
478   CapturedStream* cap = s_captured_streams[STDERR_FILENO];
479   CHECK(cap) << ": did you forget CaptureTestStderr()?";
480
481   cap->StopCapture();
482
483   // Run munge
484   const string captured = Munge(cap->filename());
485   const string golden = Munge(golden_filename);
486   if (captured != golden) {
487     fprintf(stderr,
488             "Test with golden file failed. We'll try to show the diff:\n");
489     string munged_golden = golden_filename + ".munged";
490     WriteToFile(golden, munged_golden);
491     string munged_captured = cap->filename() + ".munged";
492     WriteToFile(captured, munged_captured);
493     string diffcmd("diff -u " + munged_golden + " " + munged_captured);
494     if (system(diffcmd.c_str()) != 0) {
495       fprintf(stderr, "diff command was failed.\n");
496     }
497     unlink(munged_golden.c_str());
498     unlink(munged_captured.c_str());
499     return false;
500   }
501   LOG(INFO) << "Diff was successful";
502   return true;
503 }
504
505 // Save flags used from logging_unittest.cc.
506 #ifndef HAVE_LIB_GFLAGS
507 struct FlagSaver {
508   FlagSaver()
509       : v_(FLAGS_v),
510         stderrthreshold_(FLAGS_stderrthreshold),
511         logtostderr_(FLAGS_logtostderr),
512         alsologtostderr_(FLAGS_alsologtostderr) {}
513   ~FlagSaver() {
514     FLAGS_v = v_;
515     FLAGS_stderrthreshold = stderrthreshold_;
516     FLAGS_logtostderr = logtostderr_;
517     FLAGS_alsologtostderr = alsologtostderr_;
518   }
519   int v_;
520   int stderrthreshold_;
521   bool logtostderr_;
522   bool alsologtostderr_;
523 };
524 #endif
525
526 class Thread {
527  public:
528   virtual ~Thread() {}
529
530   void SetJoinable(bool joinable) {}
531 #if defined(OS_WINDOWS) || defined(OS_CYGWIN)
532   void Start() {
533     handle_ = CreateThread(NULL,
534                            0,
535                            (LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
536                            (LPVOID)this,
537                            0,
538                            &th_);
539     CHECK(handle_) << "CreateThread";
540   }
541   void Join() {
542     WaitForSingleObject(handle_, INFINITE);
543   }
544 #elif defined(HAVE_PTHREAD)
545   void Start() {
546     pthread_create(&th_, NULL, &Thread::InvokeThread, this);
547   }
548   void Join() {
549     pthread_join(th_, NULL);
550   }
551 #else
552 # error No thread implementation.
553 #endif
554
555  protected:
556   virtual void Run() = 0;
557
558  private:
559   static void* InvokeThread(void* self) {
560     ((Thread*)self)->Run();
561     return NULL;
562   }
563
564 #if defined(OS_WINDOWS) || defined(OS_CYGWIN)
565   HANDLE handle_;
566   DWORD th_;
567 #else
568   pthread_t th_;
569 #endif
570 };
571
572 static inline void SleepForMilliseconds(int t) {
573 #ifndef OS_WINDOWS
574   usleep(t * 1000);
575 #else
576   Sleep(t);
577 #endif
578 }
579
580 // Add hook for operator new to ensure there are no memory allocation.
581
582 void (*g_new_hook)() = NULL;
583
584 _END_GOOGLE_NAMESPACE_
585
586 void* operator new(size_t size) {
587   if (GOOGLE_NAMESPACE::g_new_hook) {
588     GOOGLE_NAMESPACE::g_new_hook();
589   }
590   return malloc(size);
591 }
592
593 void* operator new[](size_t size) {
594   return ::operator new(size);
595 }
596
597 void operator delete(void* p) {
598   free(p);
599 }
600
601 void operator delete[](void* p) {
602   ::operator delete(p);
603 }