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