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 @@
// LogToStderr() - directs all log messages to stderr.
// 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.
// GetCapturedStderr() - stops capturing stderr and returns the captured
// string.
...
...
@@ -353,12 +356,15 @@
#ifndef GTEST_USE_OWN_TR1_TUPLE
// 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
// 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
// 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
#else
#define GTEST_USE_OWN_TR1_TUPLE 1
...
...
@@ -690,13 +696,22 @@ class GTestLog {
inline
void
LogToStderr
()
{}
inline
void
FlushInfoLog
()
{
fflush
(
NULL
);
}
#if !GTEST_OS_WINDOWS_MOBILE
// Defines the stderr capturer:
// CaptureStdout - starts capturing stdout.
// GetCapturedStdout - stops capturing stdout and returns the captured string.
// CaptureStderr - starts capturing stderr.
// GetCapturedStderr - stops capturing stderr and returns the captured string.
//
void
CaptureStdout
();
String
GetCapturedStdout
();
void
CaptureStderr
();
String
GetCapturedStderr
();
#endif // !GTEST_OS_WINDOWS_MOBILE
#if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest().
...
...
src/gtest-port.cc
View file @
fd6f2a8a
...
...
@@ -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_st
derr
.XXXXXX"
;
char
name_template
[]
=
"/tmp/captured_st
ream
.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.
s
tatic
size_t
GetFileSize
(
FILE
*
file
)
{
s
ize_t
CapturedStream
::
GetFileSize
(
FILE
*
file
)
{
fseek
(
file
,
0
,
SEEK_END
);
return
static_cast
<
size_t
>
(
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().
...
...
src/gtest.cc
View file @
fd6f2a8a
...
...
@@ -2634,6 +2634,9 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
SetConsoleTextAttribute
(
stdout_handle
,
GetColorAttribute
(
color
)
|
FOREGROUND_INTENSITY
);
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.
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
...
...
test/gtest-port_test.cc
View file @
fd6f2a8a
...
...
@@ -33,6 +33,8 @@
#include <gtest/internal/gtest-port.h>
#include <stdio.h>
#if GTEST_OS_MAC
#include <pthread.h>
#include <time.h>
...
...
@@ -699,11 +701,49 @@ TEST(RETest, PartialMatchWorks) {
#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
();
fprintf
(
stderr
,
"
abc"
);
ASSERT_STREQ
(
"abc"
,
GetCapturedStderr
().
c_str
(
));
fprintf
(
stderr
,
"
jkl%cmno"
,
'\0'
);
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 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