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