Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
fd6f2a8a
Commit
fd6f2a8a
authored
Jan 27, 2010
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implements stdout capturing (by Vlad Losev); fixes compiler error on NVCC (by Zhanyong Wan).
parent
27a65a9d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
137 additions
and
61 deletions
+137
-61
gtest-port.h
include/gtest/internal/gtest-port.h
+19
-4
gtest-port.cc
src/gtest-port.cc
+72
-54
gtest.cc
src/gtest.cc
+3
-0
gtest-port_test.cc
test/gtest-port_test.cc
+43
-3
No files found.
include/gtest/internal/gtest-port.h
View file @
fd6f2a8a
...
@@ -132,7 +132,10 @@
...
@@ -132,7 +132,10 @@
// LogToStderr() - directs all log messages to stderr.
// LogToStderr() - directs all log messages to stderr.
// FlushInfoLog() - flushes informational log messages.
// FlushInfoLog() - flushes informational log messages.
//
//
// Stderr capturing:
// Stdout and stderr capturing:
// CaptureStdout() - starts capturing stdout.
// GetCapturedStdout() - stops capturing stdout and returns the captured
// string.
// CaptureStderr() - starts capturing stderr.
// CaptureStderr() - starts capturing stderr.
// GetCapturedStderr() - stops capturing stderr and returns the captured
// GetCapturedStderr() - stops capturing stderr and returns the captured
// string.
// string.
...
@@ -353,12 +356,15 @@
...
@@ -353,12 +356,15 @@
#ifndef GTEST_USE_OWN_TR1_TUPLE
#ifndef GTEST_USE_OWN_TR1_TUPLE
// The user didn't tell us, so we need to figure it out.
// The user didn't tell us, so we need to figure it out.
// We use our own
tr
1 tuple if we aren't sure the user has an
// We use our own
TR
1 tuple if we aren't sure the user has an
// implementation of it already. At this time, GCC 4.0.0+ and MSVC
// implementation of it already. At this time, GCC 4.0.0+ and MSVC
// 2010 are the only mainstream compilers that come with a TR1 tuple
// 2010 are the only mainstream compilers that come with a TR1 tuple
// implementation. NVIDIA's CUDA NVCC compiler pretends to be GCC by
// defining __GNUC__ and friends, but cannot compile GCC's tuple
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// Feature Pack download, which we cannot assume the user has.
// Feature Pack download, which we cannot assume the user has.
#if (defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)) || _MSC_VER >= 1600
#if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
|| _MSC_VER >= 1600
#define GTEST_USE_OWN_TR1_TUPLE 0
#define GTEST_USE_OWN_TR1_TUPLE 0
#else
#else
#define GTEST_USE_OWN_TR1_TUPLE 1
#define GTEST_USE_OWN_TR1_TUPLE 1
...
@@ -690,13 +696,22 @@ class GTestLog {
...
@@ -690,13 +696,22 @@ class GTestLog {
inline
void
LogToStderr
()
{}
inline
void
LogToStderr
()
{}
inline
void
FlushInfoLog
()
{
fflush
(
NULL
);
}
inline
void
FlushInfoLog
()
{
fflush
(
NULL
);
}
#if !GTEST_OS_WINDOWS_MOBILE
// Defines the stderr capturer:
// Defines the stderr capturer:
// CaptureStdout - starts capturing stdout.
// GetCapturedStdout - stops capturing stdout and returns the captured string.
// CaptureStderr - starts capturing stderr.
// CaptureStderr - starts capturing stderr.
// GetCapturedStderr - stops capturing stderr and returns the captured string.
// GetCapturedStderr - stops capturing stderr and returns the captured string.
//
void
CaptureStdout
();
String
GetCapturedStdout
();
void
CaptureStderr
();
void
CaptureStderr
();
String
GetCapturedStderr
();
String
GetCapturedStderr
();
#endif // !GTEST_OS_WINDOWS_MOBILE
#if GTEST_HAS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest().
// A copy of all command line arguments. Set by InitGoogleTest().
...
...
src/gtest-port.cc
View file @
fd6f2a8a
...
@@ -68,8 +68,10 @@ namespace internal {
...
@@ -68,8 +68,10 @@ namespace internal {
#if defined(_MSC_VER) || defined(__BORLANDC__)
#if defined(_MSC_VER) || defined(__BORLANDC__)
// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
const
int
kStdOutFileno
=
1
;
const
int
kStdErrFileno
=
2
;
const
int
kStdErrFileno
=
2
;
#else
#else
const
int
kStdOutFileno
=
STDOUT_FILENO
;
const
int
kStdErrFileno
=
STDERR_FILENO
;
const
int
kStdErrFileno
=
STDERR_FILENO
;
#endif // _MSC_VER
#endif // _MSC_VER
...
@@ -439,18 +441,14 @@ GTestLog::~GTestLog() {
...
@@ -439,18 +441,14 @@ GTestLog::~GTestLog() {
#pragma warning(disable: 4996)
#pragma warning(disable: 4996)
#endif // _MSC_VER
#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
:
public
:
// The ctor redirects stderr to a temporary file.
// The ctor redirects the stream to a temporary file.
CapturedStderr
()
{
CapturedStream
(
int
fd
)
:
fd_
(
fd
),
uncaptured_fd_
(
dup
(
fd
))
{
#if GTEST_OS_WINDOWS_MOBILE
// Not supported on Windows CE.
posix
::
Abort
();
#else
uncaptured_fd_
=
dup
(
kStdErrFileno
);
#if GTEST_OS_WINDOWS
#if GTEST_OS_WINDOWS
char
temp_dir_path
[
MAX_PATH
+
1
]
=
{
'\0'
};
// NOLINT
char
temp_dir_path
[
MAX_PATH
+
1
]
=
{
'\0'
};
// NOLINT
char
temp_file_path
[
MAX_PATH
+
1
]
=
{
'\0'
};
// NOLINT
char
temp_file_path
[
MAX_PATH
+
1
]
=
{
'\0'
};
// NOLINT
...
@@ -463,57 +461,57 @@ class CapturedStderr {
...
@@ -463,57 +461,57 @@ class CapturedStderr {
// There's no guarantee that a test has write access to the
// There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp
// current directory, so we create the temporary file in the /tmp
// directory instead.
// directory instead.
char
name_template
[]
=
"/tmp/captured_st
derr
.XXXXXX"
;
char
name_template
[]
=
"/tmp/captured_st
ream
.XXXXXX"
;
const
int
captured_fd
=
mkstemp
(
name_template
);
const
int
captured_fd
=
mkstemp
(
name_template
);
filename_
=
name_template
;
filename_
=
name_template
;
#endif // GTEST_OS_WINDOWS
#endif // GTEST_OS_WINDOWS
fflush
(
NULL
);
fflush
(
NULL
);
dup2
(
captured_fd
,
kStdErrFileno
);
dup2
(
captured_fd
,
fd_
);
close
(
captured_fd
);
close
(
captured_fd
);
#endif // GTEST_OS_WINDOWS_MOBILE
}
}
~
CapturedStderr
()
{
~
CapturedStream
()
{
#if !GTEST_OS_WINDOWS_MOBILE
remove
(
filename_
.
c_str
());
remove
(
filename_
.
c_str
());
#endif // !GTEST_OS_WINDOWS_MOBILE
}
}
// Stops redirecting stderr.
String
GetCapturedString
()
{
void
StopCapture
()
{
if
(
uncaptured_fd_
!=
-
1
)
{
#if !GTEST_OS_WINDOWS_MOBILE
// Restores the original stream.
// Restores the original stream.
fflush
(
NULL
);
fflush
(
NULL
);
dup2
(
uncaptured_fd_
,
fd_
);
dup2
(
uncaptured_fd_
,
kStdErrFileno
);
close
(
uncaptured_fd_
);
close
(
uncaptured_fd_
);
uncaptured_fd_
=
-
1
;
uncaptured_fd_
=
-
1
;
}
#endif // !GTEST_OS_WINDOWS_MOBILE
}
// Returns the name of the temporary file holding the stderr output.
FILE
*
const
file
=
posix
::
FOpen
(
filename_
.
c_str
(),
"r"
);
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
const
String
content
=
ReadEntireFile
(
file
);
// can use it here.
posix
::
FClose
(
file
);
::
std
::
string
filename
()
const
{
return
filename_
;
}
return
content
;
}
private
:
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_
;
int
uncaptured_fd_
;
// Name of the temporary file holding the stderr output.
::
std
::
string
filename_
;
::
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.
// Returns the size (in bytes) of a file.
s
tatic
size_t
GetFileSize
(
FILE
*
file
)
{
s
ize_t
CapturedStream
::
GetFileSize
(
FILE
*
file
)
{
fseek
(
file
,
0
,
SEEK_END
);
fseek
(
file
,
0
,
SEEK_END
);
return
static_cast
<
size_t
>
(
ftell
(
file
));
return
static_cast
<
size_t
>
(
ftell
(
file
));
}
}
// Reads the entire content of a file as a string.
// 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
);
const
size_t
file_size
=
GetFileSize
(
file
);
char
*
const
buffer
=
new
char
[
file_size
];
char
*
const
buffer
=
new
char
[
file_size
];
...
@@ -535,30 +533,50 @@ static String ReadEntireFile(FILE * file) {
...
@@ -535,30 +533,50 @@ static String ReadEntireFile(FILE * file) {
return
content
;
return
content
;
}
}
// Starts capturing stderr.
#ifdef _MSC_VER
void
CaptureStderr
()
{
#pragma warning(pop)
if
(
g_captured_stderr
!=
NULL
)
{
#endif // _MSC_VER
GTEST_LOG_
(
FATAL
)
<<
"Only one stderr capturer can exist at one time."
;
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.
// Stops capturing the output stream and returns the captured string.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
String
GetCapturedStream
(
CapturedStream
**
captured_stream
)
{
// use it here.
const
String
content
=
(
*
captured_stream
)
->
GetCapturedString
();
String
GetCapturedStderr
()
{
g_captured_stderr
->
StopCapture
();
FILE
*
const
file
=
posix
::
FOpen
(
g_captured_stderr
->
filename
().
c_str
(),
"r"
);
delete
*
captured_stream
;
const
String
content
=
ReadEntireFile
(
file
);
*
captured_stream
=
NULL
;
posix
::
FClose
(
file
);
delete
g_captured_stderr
;
g_captured_stderr
=
NULL
;
return
content
;
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
#if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest().
// A copy of all command line arguments. Set by InitGoogleTest().
...
...
src/gtest.cc
View file @
fd6f2a8a
...
@@ -2634,6 +2634,9 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
...
@@ -2634,6 +2634,9 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
SetConsoleTextAttribute
(
stdout_handle
,
SetConsoleTextAttribute
(
stdout_handle
,
GetColorAttribute
(
color
)
|
FOREGROUND_INTENSITY
);
GetColorAttribute
(
color
)
|
FOREGROUND_INTENSITY
);
vprintf
(
fmt
,
args
);
vprintf
(
fmt
,
args
);
// Unless we flush stream buffers now the next SetConsoleTextAttribute
// call can reset the color before the output reaches the console.
fflush
(
stdout
);
// Restores the text color.
// Restores the text color.
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
...
...
test/gtest-port_test.cc
View file @
fd6f2a8a
...
@@ -33,6 +33,8 @@
...
@@ -33,6 +33,8 @@
#include <gtest/internal/gtest-port.h>
#include <gtest/internal/gtest-port.h>
#include <stdio.h>
#if GTEST_OS_MAC
#if GTEST_OS_MAC
#include <pthread.h>
#include <pthread.h>
#include <time.h>
#include <time.h>
...
@@ -699,11 +701,49 @@ TEST(RETest, PartialMatchWorks) {
...
@@ -699,11 +701,49 @@ TEST(RETest, PartialMatchWorks) {
#endif // GTEST_USES_POSIX_RE
#endif // GTEST_USES_POSIX_RE
TEST
(
CaptureStderrTest
,
CapturesStdErr
)
{
#if !GTEST_OS_WINDOWS_MOBILE
TEST
(
CaptureTest
,
CapturesStdout
)
{
CaptureStdout
();
fprintf
(
stdout
,
"abc"
);
EXPECT_STREQ
(
"abc"
,
GetCapturedStdout
().
c_str
());
CaptureStdout
();
fprintf
(
stdout
,
"def%cghi"
,
'\0'
);
EXPECT_EQ
(
::
std
::
string
(
"def
\0
ghi"
,
7
),
::
std
::
string
(
GetCapturedStdout
()));
}
TEST
(
CaptureTest
,
CapturesStderr
)
{
CaptureStderr
();
fprintf
(
stderr
,
"jkl"
);
EXPECT_STREQ
(
"jkl"
,
GetCapturedStderr
().
c_str
());
CaptureStderr
();
CaptureStderr
();
fprintf
(
stderr
,
"
abc"
);
fprintf
(
stderr
,
"
jkl%cmno"
,
'\0'
);
ASSERT_STREQ
(
"abc"
,
GetCapturedStderr
().
c_str
(
));
EXPECT_EQ
(
::
std
::
string
(
"jkl
\0
mno"
,
7
),
::
std
::
string
(
GetCapturedStderr
()
));
}
}
// Tests that stdout and stderr capture don't interfere with each other.
TEST
(
CaptureTest
,
CapturesStdoutAndStderr
)
{
CaptureStdout
();
CaptureStderr
();
fprintf
(
stdout
,
"pqr"
);
fprintf
(
stderr
,
"stu"
);
EXPECT_STREQ
(
"pqr"
,
GetCapturedStdout
().
c_str
());
EXPECT_STREQ
(
"stu"
,
GetCapturedStderr
().
c_str
());
}
TEST
(
CaptureDeathTest
,
CannotReenterStdoutCapture
)
{
CaptureStdout
();
EXPECT_DEATH_IF_SUPPORTED
(
CaptureStdout
();,
"Only one stdout capturer can exist at a time"
);
GetCapturedStdout
();
// We cannot test stderr capturing using death tests as they use it
// themselves.
}
#endif // !GTEST_OS_WINDOWS_MOBILE
}
// namespace internal
}
// namespace internal
}
// namespace testing
}
// namespace testing
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment