1 // Copyright (c) 2009, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
30 // Author: Shinichiro Hamaji
31 // (based on googletest: http://code.google.com/p/googletest/)
34 #error You must not include this file twice.
36 #define GOOGLETEST_H__
38 #include "utilities.h"
52 #include <sys/types.h>
59 #include "base/commandlineflags.h"
65 _START_GOOGLE_NAMESPACE_
67 extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
69 _END_GOOGLE_NAMESPACE_
71 #undef GOOGLE_GLOG_DLL_DECL
72 #define GOOGLE_GLOG_DLL_DECL
74 static inline string GetTempDir() {
79 GetTempPathA(MAX_PATH, tmp);
84 #if defined(OS_WINDOWS) && defined(_MSC_VER) && !defined(TEST_SRC_DIR)
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 #elif !defined(TEST_SRC_DIR)
89 # warning TEST_SRC_DIR should be defined in config.h
90 static const char TEST_SRC_DIR[] = ".";
93 DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
94 DEFINE_string(test_srcdir, TEST_SRC_DIR,
95 "Source-dir root, needed to find glog_unittest_flagfile");
96 DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
98 DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
100 DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
103 #ifdef HAVE_LIB_GTEST
104 # include <gtest/gtest.h>
105 // Use our ASSERT_DEATH implementation.
107 # undef ASSERT_DEBUG_DEATH
108 using testing::InitGoogleTest;
111 _START_GOOGLE_NAMESPACE_
113 void InitGoogleTest(int*, char**) {}
115 // The following is some bare-bones testing infrastructure
117 #define EXPECT_TRUE(cond) \
120 fprintf(stderr, "Check failed: %s\n", #cond); \
125 #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
127 #define EXPECT_OP(op, val1, val2) \
129 if (!((val1) op (val2))) { \
130 fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
135 #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
136 #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
137 #define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
138 #define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
140 #define EXPECT_NAN(arg) \
143 fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
148 #define EXPECT_INF(arg) \
151 fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
156 #define EXPECT_DOUBLE_EQ(val1, val2) \
158 if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
159 fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
164 #define EXPECT_STREQ(val1, val2) \
166 if (strcmp((val1), (val2)) != 0) { \
167 fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
172 vector<void (*)()> g_testlist; // the tests to run
175 struct Test_##a##_##b { \
176 Test_##a##_##b() { g_testlist.push_back(&Run); } \
177 static void Run() { FlagSaver fs; RunTest(); } \
178 static void RunTest(); \
180 static Test_##a##_##b g_test_##a##_##b; \
181 void Test_##a##_##b::RunTest()
184 static inline int RUN_ALL_TESTS() {
185 vector<void (*)()>::const_iterator it;
186 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
189 fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
193 _END_GOOGLE_NAMESPACE_
195 #endif // ! HAVE_LIB_GTEST
197 _START_GOOGLE_NAMESPACE_
199 static bool g_called_abort;
200 static jmp_buf g_jmp_buf;
201 static inline void CalledAbort() {
202 g_called_abort = true;
203 longjmp(g_jmp_buf, 1);
207 // TODO(hamaji): Death test somehow doesn't work in Windows.
208 #define ASSERT_DEATH(fn, msg)
210 #define ASSERT_DEATH(fn, msg) \
212 g_called_abort = false; \
213 /* in logging.cc */ \
214 void (*original_logging_fail_func)() = g_logging_fail_func; \
215 g_logging_fail_func = &CalledAbort; \
216 if (!setjmp(g_jmp_buf)) fn; \
217 /* set back to their default */ \
218 g_logging_fail_func = original_logging_fail_func; \
219 if (!g_called_abort) { \
220 fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
227 #define ASSERT_DEBUG_DEATH(fn, msg)
229 #define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
234 #define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n);
236 map<string, void (*)(int)> g_benchlist; // the benchmarks to run
238 class BenchmarkRegisterer {
240 BenchmarkRegisterer(const char* name, void (*function)(int iters)) {
241 EXPECT_TRUE(g_benchlist.insert(std::make_pair(name, function)).second);
245 static inline void RunSpecifiedBenchmarks() {
246 if (!FLAGS_run_benchmark) {
250 int iter_cnt = FLAGS_benchmark_iters;
251 puts("Benchmark\tTime(ns)\tIterations");
252 for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
253 iter != g_benchlist.end();
255 clock_t start = clock();
256 iter->second(iter_cnt);
258 ((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
259 printf("%s\t%8.2lf\t%10d\n",
260 iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
265 // ----------------------------------------------------------------------
266 // Golden file functions
267 // ----------------------------------------------------------------------
269 class CapturedStream {
271 CapturedStream(int fd, const string & filename) :
274 filename_(filename) {
279 if (uncaptured_fd_ != -1) {
280 CHECK(close(uncaptured_fd_) != -1);
284 // Start redirecting output to a file
286 // Keep original stream for later
287 CHECK(uncaptured_fd_ == -1) << ", Stream " << fd_ << " already captured!";
288 uncaptured_fd_ = dup(fd_);
289 CHECK(uncaptured_fd_ != -1);
291 // Open file to save stream to
292 int cap_fd = open(filename_.c_str(),
293 O_CREAT | O_TRUNC | O_WRONLY,
297 // Send stdout/stderr to this file
299 CHECK(dup2(cap_fd, fd_) != -1);
300 CHECK(close(cap_fd) != -1);
303 // Remove output redirection
305 // Restore original stream
306 if (uncaptured_fd_ != -1) {
308 CHECK(dup2(uncaptured_fd_, fd_) != -1);
312 const string & filename() const { return filename_; }
315 int fd_; // file descriptor being captured
316 int uncaptured_fd_; // where the stream was originally being sent to
317 string filename_; // file where stream is being saved
319 static CapturedStream * s_captured_streams[STDERR_FILENO+1];
320 // Redirect a file descriptor to a file.
321 // fd - Should be STDOUT_FILENO or STDERR_FILENO
322 // filename - File where output should be stored
323 static inline void CaptureTestOutput(int fd, const string & filename) {
324 CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
325 CHECK(s_captured_streams[fd] == NULL);
326 s_captured_streams[fd] = new CapturedStream(fd, filename);
328 static inline void CaptureTestStderr() {
329 CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
331 // Return the size (in bytes) of a file
332 static inline size_t GetFileSize(FILE * file) {
333 fseek(file, 0, SEEK_END);
334 return static_cast<size_t>(ftell(file));
336 // Read the entire content of a file as a string
337 static inline string ReadEntireFile(FILE * file) {
338 const size_t file_size = GetFileSize(file);
339 char * const buffer = new char[file_size];
341 size_t bytes_last_read = 0; // # of bytes read in the last fread()
342 size_t bytes_read = 0; // # of bytes read so far
344 fseek(file, 0, SEEK_SET);
346 // Keep reading the file until we cannot read further or the
347 // pre-determined file size is reached.
349 bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
350 bytes_read += bytes_last_read;
351 } while (bytes_last_read > 0 && bytes_read < file_size);
353 const string content = string(buffer, buffer+bytes_read);
358 // Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
359 // fd is STDERR_FILENO) as a string
360 static inline string GetCapturedTestOutput(int fd) {
361 CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
362 CapturedStream * const cap = s_captured_streams[fd];
364 << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
366 // Make sure everything is flushed.
369 // Read the captured file.
370 FILE * const file = fopen(cap->filename().c_str(), "r");
371 const string content = ReadEntireFile(file);
375 s_captured_streams[fd] = NULL;
379 // Get the captured stderr of a test as a string.
380 static inline string GetCapturedTestStderr() {
381 return GetCapturedTestOutput(STDERR_FILENO);
384 // Check if the string is [IWEF](\d{4}|DATE)
385 static inline bool IsLoggingPrefix(const string& s) {
386 if (s.size() != 5) return false;
387 if (!strchr("IWEF", s[0])) return false;
388 for (int i = 1; i <= 4; ++i) {
389 if (!isdigit(s[i]) && s[i] != "DATE"[i-1]) return false;
394 // Convert log output into normalized form.
397 // I0102 030405 logging_unittest.cc:345] RAW: vlog -1
398 // => IDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
399 static inline string MungeLine(const string& line) {
400 std::istringstream iss(line);
401 string before, logcode_date, time, thread_lineinfo;
403 while (!IsLoggingPrefix(logcode_date)) {
404 before += " " + logcode_date;
405 if (!(iss >> logcode_date)) {
406 // We cannot find the header of log output.
410 if (!before.empty()) before += " ";
412 iss >> thread_lineinfo;
413 CHECK(!thread_lineinfo.empty());
414 if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
415 // We found thread ID.
419 CHECK_EQ(']', tmp[tmp.size() - 1]);
420 thread_lineinfo = "THREADID " + tmp;
422 size_t index = thread_lineinfo.find(':');
423 CHECK_NE(string::npos, index);
424 thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
426 std::getline(iss, rest);
427 return (before + logcode_date[0] + "DATE TIME__ " + thread_lineinfo +
431 static inline void StringReplace(string* str,
432 const string& oldsub,
433 const string& newsub) {
434 size_t pos = str->find(oldsub);
435 if (pos != string::npos) {
436 str->replace(pos, oldsub.size(), newsub.c_str());
440 static inline string Munge(const string& filename) {
441 FILE* fp = fopen(filename.c_str(), "rb");
442 CHECK(fp != NULL) << filename << ": couldn't open";
445 while (fgets(buf, 4095, fp)) {
446 string line = MungeLine(buf);
448 sprintf(null_str, "%p", static_cast<void*>(NULL));
449 StringReplace(&line, "__NULLP__", null_str);
450 // Remove 0x prefix produced by %p. VC++ doesn't put the prefix.
451 StringReplace(&line, " 0x", " ");
453 StringReplace(&line, "__SUCCESS__", StrError(0));
454 StringReplace(&line, "__ENOENT__", StrError(ENOENT));
455 StringReplace(&line, "__EINTR__", StrError(EINTR));
456 StringReplace(&line, "__ENXIO__", StrError(ENXIO));
457 StringReplace(&line, "__ENOEXEC__", StrError(ENOEXEC));
458 result += line + "\n";
464 static inline void WriteToFile(const string& body, const string& file) {
465 FILE* fp = fopen(file.c_str(), "wb");
466 fwrite(body.data(), 1, body.size(), fp);
470 static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
471 CapturedStream* cap = s_captured_streams[STDERR_FILENO];
472 CHECK(cap) << ": did you forget CaptureTestStderr()?";
477 const string captured = Munge(cap->filename());
478 const string golden = Munge(golden_filename);
479 if (captured != golden) {
481 "Test with golden file failed. We'll try to show the diff:\n");
482 string munged_golden = golden_filename + ".munged";
483 WriteToFile(golden, munged_golden);
484 string munged_captured = cap->filename() + ".munged";
485 WriteToFile(captured, munged_captured);
486 string diffcmd("diff -u " + munged_golden + " " + munged_captured);
487 if (system(diffcmd.c_str()) != 0) {
488 fprintf(stderr, "diff command was failed.\n");
490 unlink(munged_golden.c_str());
491 unlink(munged_captured.c_str());
494 LOG(INFO) << "Diff was successful";
498 // Save flags used from logging_unittest.cc.
499 #ifndef HAVE_LIB_GFLAGS
503 stderrthreshold_(FLAGS_stderrthreshold),
504 logtostderr_(FLAGS_logtostderr),
505 alsologtostderr_(FLAGS_alsologtostderr) {}
508 FLAGS_stderrthreshold = stderrthreshold_;
509 FLAGS_logtostderr = logtostderr_;
510 FLAGS_alsologtostderr = alsologtostderr_;
513 int stderrthreshold_;
515 bool alsologtostderr_;
523 void SetJoinable(bool) {}
524 #if defined(OS_WINDOWS) || defined(OS_CYGWIN)
526 handle_ = CreateThread(NULL,
528 (LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
532 CHECK(handle_) << "CreateThread";
535 WaitForSingleObject(handle_, INFINITE);
537 #elif defined(HAVE_PTHREAD)
539 pthread_create(&th_, NULL, &Thread::InvokeThread, this);
542 pthread_join(th_, NULL);
545 # error No thread implementation.
549 virtual void Run() = 0;
552 static void* InvokeThread(void* self) {
553 ((Thread*)self)->Run();
557 #if defined(OS_WINDOWS) || defined(OS_CYGWIN)
565 static inline void SleepForMilliseconds(int t) {
573 // Add hook for operator new to ensure there are no memory allocation.
575 void (*g_new_hook)() = NULL;
577 _END_GOOGLE_NAMESPACE_
579 void* operator new(size_t size) throw(std::bad_alloc) {
580 if (GOOGLE_NAMESPACE::g_new_hook) {
581 GOOGLE_NAMESPACE::g_new_hook();
586 void* operator new[](size_t size) throw(std::bad_alloc) {
587 return ::operator new(size);
590 void operator delete(void* p) throw() {
594 void operator delete[](void* p) throw() {
595 ::operator delete(p);