+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+// (based on googletest: http://code.google.com/p/googletest/)
+
#ifdef GOOGLETEST_H__
#error You must not include this file twice.
#endif
#define GOOGLETEST_H__
+#include "utilities.h"
+
#include <ctype.h>
#include <setjmp.h>
#include <time.h>
#include <string>
#include <vector>
+#include <stdio.h>
+#include <stdlib.h>
+
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#undef GOOGLE_GLOG_DLL_DECL
#define GOOGLE_GLOG_DLL_DECL
-static string GetTempDir() {
+static inline string GetTempDir() {
#ifndef OS_WINDOWS
return "/tmp";
#else
#endif
}
-#ifdef OS_WINDOWS
+#if defined(OS_WINDOWS) && defined(_MSC_VER)
// The test will run in glog/vsproject/<project name>
// (e.g., glog/vsproject/logging_unittest).
static const char TEST_SRC_DIR[] = "../..";
-#else
+#elif !defined(TEST_SRC_DIR)
+# warning TEST_SRC_DIR should be defined in config.h
static const char TEST_SRC_DIR[] = ".";
#endif
DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
DEFINE_string(test_srcdir, TEST_SRC_DIR,
"Source-dir root, needed to find glog_unittest_flagfile");
+DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
#ifdef NDEBUG
DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
#else
-DEFINE_int32(benchmark_iters, 1000000, "Number of iterations per benchmark");
+DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
#endif
#ifdef HAVE_LIB_GTEST
_START_GOOGLE_NAMESPACE_
-void InitGoogleTest(int* argc, char** argv) {}
+void InitGoogleTest(int*, char**) {}
// The following is some bare-bones testing infrastructure
void Test_##a##_##b::RunTest()
-static int RUN_ALL_TESTS() {
+static inline int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
_END_GOOGLE_NAMESPACE_
-#endif
+#endif // ! HAVE_LIB_GTEST
_START_GOOGLE_NAMESPACE_
static bool g_called_abort;
static jmp_buf g_jmp_buf;
-static void CalledAbort() {
+static inline void CalledAbort() {
g_called_abort = true;
longjmp(g_jmp_buf, 1);
}
}
};
-static void RunSpecifiedBenchmarks() {
+static inline void RunSpecifiedBenchmarks() {
+ if (!FLAGS_run_benchmark) {
+ return;
+ }
+
int iter_cnt = FLAGS_benchmark_iters;
puts("Benchmark\tTime(ns)\tIterations");
for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
// Redirect a file descriptor to a file.
// fd - Should be STDOUT_FILENO or STDERR_FILENO
// filename - File where output should be stored
-static void CaptureTestOutput(int fd, const string & filename) {
+static inline void CaptureTestOutput(int fd, const string & filename) {
CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
CHECK(s_captured_streams[fd] == NULL);
s_captured_streams[fd] = new CapturedStream(fd, filename);
}
-static void CaptureTestStderr() {
+static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
}
// Return the size (in bytes) of a file
-static size_t GetFileSize(FILE * file) {
+static inline size_t GetFileSize(FILE * file) {
fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file));
}
// Read the entire content of a file as a string
-static string ReadEntireFile(FILE * file) {
+static inline string ReadEntireFile(FILE * file) {
const size_t file_size = GetFileSize(file);
char * const buffer = new char[file_size];
}
// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
// fd is STDERR_FILENO) as a string
-static string GetCapturedTestOutput(int fd) {
+static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
CapturedStream * const cap = s_captured_streams[fd];
CHECK(cap)
return content;
}
// Get the captured stderr of a test as a string.
-static string GetCapturedTestStderr() {
+static inline string GetCapturedTestStderr() {
return GetCapturedTestOutput(STDERR_FILENO);
}
// Check if the string is [IWEF](\d{4}|DATE)
-static bool IsLoggingPrefix(const string& s) {
+static inline bool IsLoggingPrefix(const string& s) {
if (s.size() != 5) return false;
if (!strchr("IWEF", s[0])) return false;
for (int i = 1; i <= 4; ++i) {
// Example:
// I0102 030405 logging_unittest.cc:345] RAW: vlog -1
// => IDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
-static string MungeLine(const string& line) {
+static inline string MungeLine(const string& line) {
std::istringstream iss(line);
string before, logcode_date, time, thread_lineinfo;
iss >> logcode_date;
}
if (!before.empty()) before += " ";
iss >> time;
- CHECK_EQ(6, time.size());
iss >> thread_lineinfo;
CHECK(!thread_lineinfo.empty());
if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
MungeLine(rest));
}
-static void StringReplace(string* str,
+static inline void StringReplace(string* str,
const string& oldsub,
const string& newsub) {
size_t pos = str->find(oldsub);
}
}
-static string Munge(const string& filename) {
+static inline string Munge(const string& filename) {
FILE* fp = fopen(filename.c_str(), "rb");
CHECK(fp != NULL) << filename << ": couldn't open";
char buf[4096];
while (fgets(buf, 4095, fp)) {
string line = MungeLine(buf);
char null_str[256];
- sprintf(null_str, "%p", NULL);
+ sprintf(null_str, "%p", static_cast<void*>(NULL));
StringReplace(&line, "__NULLP__", null_str);
// Remove 0x prefix produced by %p. VC++ doesn't put the prefix.
StringReplace(&line, " 0x", " ");
- char errmsg_buf[100];
- posix_strerror_r(0, errmsg_buf, sizeof(errmsg_buf));
- if (*errmsg_buf == '\0') {
- // MacOSX 10.4 and FreeBSD return empty string for errno=0.
- // In such case, the we need to remove an extra space.
- StringReplace(&line, "__SUCCESS__ ", "");
- } else {
- StringReplace(&line, "__SUCCESS__", errmsg_buf);
- }
- StringReplace(&line, "__ENOENT__", strerror(ENOENT));
- StringReplace(&line, "__EINTR__", strerror(EINTR));
- StringReplace(&line, "__ENXIO__", strerror(ENXIO));
- StringReplace(&line, "__ENOEXEC__", strerror(ENOEXEC));
+ StringReplace(&line, "__SUCCESS__", StrError(0));
+ StringReplace(&line, "__ENOENT__", StrError(ENOENT));
+ StringReplace(&line, "__EINTR__", StrError(EINTR));
+ StringReplace(&line, "__ENXIO__", StrError(ENXIO));
+ StringReplace(&line, "__ENOEXEC__", StrError(ENOEXEC));
result += line + "\n";
}
fclose(fp);
return result;
}
-static void WriteToFile(const string& body, const string& file) {
+static inline void WriteToFile(const string& body, const string& file) {
FILE* fp = fopen(file.c_str(), "wb");
fwrite(body.data(), 1, body.size(), fp);
fclose(fp);
}
-static bool MungeAndDiffTestStderr(const string& golden_filename) {
+static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
CapturedStream* cap = s_captured_streams[STDERR_FILENO];
CHECK(cap) << ": did you forget CaptureTestStderr()?";
class Thread {
public:
- void SetJoinable(bool joinable) {}
-#if defined(HAVE_PTHREAD)
- void Start() {
- pthread_create(&th_, NULL, &Thread::InvokeThread, this);
- }
- void Join() {
- pthread_join(th_, NULL);
- }
-#elif defined(OS_WINDOWS)
+ virtual ~Thread() {}
+
+ void SetJoinable(bool) {}
+#if defined(OS_WINDOWS) || defined(OS_CYGWIN)
void Start() {
handle_ = CreateThread(NULL,
0,
void Join() {
WaitForSingleObject(handle_, INFINITE);
}
+#elif defined(HAVE_PTHREAD)
+ void Start() {
+ pthread_create(&th_, NULL, &Thread::InvokeThread, this);
+ }
+ void Join() {
+ pthread_join(th_, NULL);
+ }
#else
# error No thread implementation.
#endif
return NULL;
}
- pthread_t th_;
-#ifdef OS_WINDOWS
+#if defined(OS_WINDOWS) || defined(OS_CYGWIN)
HANDLE handle_;
+ DWORD th_;
+#else
+ pthread_t th_;
#endif
};
-static void SleepForMilliseconds(int t) {
+static inline void SleepForMilliseconds(int t) {
#ifndef OS_WINDOWS
usleep(t * 1000);
#else
_END_GOOGLE_NAMESPACE_
-void* operator new(size_t size) {
+void* operator new(size_t size) throw(std::bad_alloc) {
if (GOOGLE_NAMESPACE::g_new_hook) {
GOOGLE_NAMESPACE::g_new_hook();
}
return malloc(size);
}
-void* operator new[](size_t size) {
+void* operator new[](size_t size) throw(std::bad_alloc) {
return ::operator new(size);
}
-void operator delete(void* p) {
+void operator delete(void* p) throw() {
free(p);
}
-void operator delete[](void* p) {
+void operator delete[](void* p) throw() {
::operator delete(p);
}