From 41ca36a861d462e22daf25e8f0fc3e32682ec618 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 27 Jan 2010 22:27:30 +0000 Subject: Implements stdout capturing (by Vlad Losev); fixes compiler error on NVCC (by Zhanyong Wan). git-svn-id: http://googletest.googlecode.com/svn/trunk@368 861a406c-534a-0410-8894-cb66d6ee9925 --- src/gtest-port.cc | 126 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 54 deletions(-) (limited to 'src/gtest-port.cc') diff --git a/src/gtest-port.cc b/src/gtest-port.cc index de169e2..1890a80 100644 --- a/src/gtest-port.cc +++ b/src/gtest-port.cc @@ -68,8 +68,10 @@ namespace internal { #if defined(_MSC_VER) || defined(__BORLANDC__) // MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; const int kStdErrFileno = 2; #else +const int kStdOutFileno = STDOUT_FILENO; const int kStdErrFileno = STDERR_FILENO; #endif // _MSC_VER @@ -439,18 +441,14 @@ GTestLog::~GTestLog() { #pragma warning(disable: 4996) #endif // _MSC_VER -// Defines the stderr capturer. +// Stream capturing is not supported on Windows Mobile. +#if !GTEST_OS_WINDOWS_MOBILE -class CapturedStderr { +// Object that captures an output stream (stdout/stderr). +class CapturedStream { public: - // The ctor redirects stderr to a temporary file. - CapturedStderr() { -#if GTEST_OS_WINDOWS_MOBILE - // Not supported on Windows CE. - posix::Abort(); -#else - uncaptured_fd_ = dup(kStdErrFileno); - + // The ctor redirects the stream to a temporary file. + CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { #if GTEST_OS_WINDOWS char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT @@ -463,57 +461,57 @@ class CapturedStderr { // There's no guarantee that a test has write access to the // current directory, so we create the temporary file in the /tmp // directory instead. - char name_template[] = "/tmp/captured_stderr.XXXXXX"; + char name_template[] = "/tmp/captured_stream.XXXXXX"; const int captured_fd = mkstemp(name_template); filename_ = name_template; #endif // GTEST_OS_WINDOWS fflush(NULL); - dup2(captured_fd, kStdErrFileno); + dup2(captured_fd, fd_); close(captured_fd); -#endif // GTEST_OS_WINDOWS_MOBILE } - ~CapturedStderr() { -#if !GTEST_OS_WINDOWS_MOBILE + ~CapturedStream() { remove(filename_.c_str()); -#endif // !GTEST_OS_WINDOWS_MOBILE } - // Stops redirecting stderr. - void StopCapture() { -#if !GTEST_OS_WINDOWS_MOBILE - // Restores the original stream. - fflush(NULL); - dup2(uncaptured_fd_, kStdErrFileno); - close(uncaptured_fd_); - uncaptured_fd_ = -1; -#endif // !GTEST_OS_WINDOWS_MOBILE - } + String GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } - // Returns the name of the temporary file holding the stderr output. - // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we - // can use it here. - ::std::string filename() const { return filename_; } + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const String content = ReadEntireFile(file); + posix::FClose(file); + return content; + } private: + // Reads the entire content of a file as a String. + static String ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. int uncaptured_fd_; + // Name of the temporary file holding the stderr output. ::std::string filename_; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER -static CapturedStderr* g_captured_stderr = NULL; + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; // Returns the size (in bytes) of a file. -static size_t GetFileSize(FILE * file) { +size_t CapturedStream::GetFileSize(FILE* file) { fseek(file, 0, SEEK_END); return static_cast(ftell(file)); } // Reads the entire content of a file as a string. -static String ReadEntireFile(FILE * file) { +String CapturedStream::ReadEntireFile(FILE* file) { const size_t file_size = GetFileSize(file); char* const buffer = new char[file_size]; @@ -535,30 +533,50 @@ static String ReadEntireFile(FILE * file) { return content; } -// Starts capturing stderr. -void CaptureStderr() { - if (g_captured_stderr != NULL) { - GTEST_LOG_(FATAL) << "Only one stderr capturer can exist at one time."; +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; } - g_captured_stderr = new CapturedStderr; + *stream = new CapturedStream(fd); } -// Stops capturing stderr and returns the captured string. -// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can -// use it here. -String GetCapturedStderr() { - g_captured_stderr->StopCapture(); +// Stops capturing the output stream and returns the captured string. +String GetCapturedStream(CapturedStream** captured_stream) { + const String content = (*captured_stream)->GetCapturedString(); - FILE* const file = posix::FOpen(g_captured_stderr->filename().c_str(), "r"); - const String content = ReadEntireFile(file); - posix::FClose(file); - - delete g_captured_stderr; - g_captured_stderr = NULL; + delete *captured_stream; + *captured_stream = NULL; return content; } +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } + +// Stops capturing stderr and returns the captured string. +String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } + +#endif // !GTEST_OS_WINDOWS_MOBILE + #if GTEST_HAS_DEATH_TEST // A copy of all command line arguments. Set by InitGoogleTest(). -- cgit v1.2.3