Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
yaml-cpp
Commits
db82302e
Commit
db82302e
authored
Mar 22, 2014
by
Jesse Beder
Browse files
Add gtest, as separate set of tests (that just follow the ad-hoc tests that already exist)
parent
32125697
Changes
108
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
7767 additions
and
0 deletions
+7767
-0
test/gtest-1.7.0/src/gtest-typed-test.cc
test/gtest-1.7.0/src/gtest-typed-test.cc
+110
-0
test/gtest-1.7.0/src/gtest.cc
test/gtest-1.7.0/src/gtest.cc
+5015
-0
test/gtest-1.7.0/src/gtest_main.cc
test/gtest-1.7.0/src/gtest_main.cc
+38
-0
test/gtest-1.7.0/test/gtest-death-test_ex_test.cc
test/gtest-1.7.0/test/gtest-death-test_ex_test.cc
+93
-0
test/gtest-1.7.0/test/gtest-death-test_test.cc
test/gtest-1.7.0/test/gtest-death-test_test.cc
+1367
-0
test/gtest-1.7.0/test/gtest-filepath_test.cc
test/gtest-1.7.0/test/gtest-filepath_test.cc
+680
-0
test/gtest-1.7.0/test/gtest-linked_ptr_test.cc
test/gtest-1.7.0/test/gtest-linked_ptr_test.cc
+154
-0
test/gtest-1.7.0/test/gtest-listener_test.cc
test/gtest-1.7.0/test/gtest-listener_test.cc
+310
-0
No files found.
Too many changes to show.
To preserve performance only
108 of 108+
files are displayed.
Plain diff
Email patch
test/gtest-1.7.0/src/gtest-typed-test.cc
0 → 100644
View file @
db82302e
// Copyright 2008 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: wan@google.com (Zhanyong Wan)
#include "gtest/gtest-typed-test.h"
#include "gtest/gtest.h"
namespace
testing
{
namespace
internal
{
#if GTEST_HAS_TYPED_TEST_P
// Skips to the first non-space char in str. Returns an empty string if str
// contains only whitespace characters.
static
const
char
*
SkipSpaces
(
const
char
*
str
)
{
while
(
IsSpace
(
*
str
))
str
++
;
return
str
;
}
// Verifies that registered_tests match the test names in
// defined_test_names_; returns registered_tests if successful, or
// aborts the program otherwise.
const
char
*
TypedTestCasePState
::
VerifyRegisteredTestNames
(
const
char
*
file
,
int
line
,
const
char
*
registered_tests
)
{
typedef
::
std
::
set
<
const
char
*>::
const_iterator
DefinedTestIter
;
registered_
=
true
;
// Skip initial whitespace in registered_tests since some
// preprocessors prefix stringizied literals with whitespace.
registered_tests
=
SkipSpaces
(
registered_tests
);
Message
errors
;
::
std
::
set
<
std
::
string
>
tests
;
for
(
const
char
*
names
=
registered_tests
;
names
!=
NULL
;
names
=
SkipComma
(
names
))
{
const
std
::
string
name
=
GetPrefixUntilComma
(
names
);
if
(
tests
.
count
(
name
)
!=
0
)
{
errors
<<
"Test "
<<
name
<<
" is listed more than once.
\n
"
;
continue
;
}
bool
found
=
false
;
for
(
DefinedTestIter
it
=
defined_test_names_
.
begin
();
it
!=
defined_test_names_
.
end
();
++
it
)
{
if
(
name
==
*
it
)
{
found
=
true
;
break
;
}
}
if
(
found
)
{
tests
.
insert
(
name
);
}
else
{
errors
<<
"No test named "
<<
name
<<
" can be found in this test case.
\n
"
;
}
}
for
(
DefinedTestIter
it
=
defined_test_names_
.
begin
();
it
!=
defined_test_names_
.
end
();
++
it
)
{
if
(
tests
.
count
(
*
it
)
==
0
)
{
errors
<<
"You forgot to list test "
<<
*
it
<<
".
\n
"
;
}
}
const
std
::
string
&
errors_str
=
errors
.
GetString
();
if
(
errors_str
!=
""
)
{
fprintf
(
stderr
,
"%s %s"
,
FormatFileLocation
(
file
,
line
).
c_str
(),
errors_str
.
c_str
());
fflush
(
stderr
);
posix
::
Abort
();
}
return
registered_tests
;
}
#endif // GTEST_HAS_TYPED_TEST_P
}
// namespace internal
}
// namespace testing
test/gtest-1.7.0/src/gtest.cc
0 → 100644
View file @
db82302e
Changes suppressed. Click to show.
// Copyright 2005, 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: wan@google.com (Zhanyong Wan)
//
// The Google C++ Testing Framework (Google Test)
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <wchar.h>
#include <wctype.h>
#include <algorithm>
#include <iomanip>
#include <limits>
#include <ostream> // NOLINT
#include <sstream>
#include <vector>
#if GTEST_OS_LINUX
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
# define GTEST_HAS_GETTIMEOFDAY_ 1
# include <fcntl.h> // NOLINT
# include <limits.h> // NOLINT
# include <sched.h> // NOLINT
// Declares vsnprintf(). This header is not available on Windows.
# include <strings.h> // NOLINT
# include <sys/mman.h> // NOLINT
# include <sys/time.h> // NOLINT
# include <unistd.h> // NOLINT
# include <string>
#elif GTEST_OS_SYMBIAN
# define GTEST_HAS_GETTIMEOFDAY_ 1
# include <sys/time.h> // NOLINT
#elif GTEST_OS_ZOS
# define GTEST_HAS_GETTIMEOFDAY_ 1
# include <sys/time.h> // NOLINT
// On z/OS we additionally need strings.h for strcasecmp.
# include <strings.h> // NOLINT
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS // We are on Windows proper.
# include <io.h> // NOLINT
# include <sys/timeb.h> // NOLINT
# include <sys/types.h> // NOLINT
# include <sys/stat.h> // NOLINT
# if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
// TODO(kenton@google.com): There are other ways to get the time on
// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
// supports these. consider using them instead.
# define GTEST_HAS_GETTIMEOFDAY_ 1
# include <sys/time.h> // NOLINT
# endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
# include <windows.h> // NOLINT
#else
// Assume other platforms have gettimeofday().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
# define GTEST_HAS_GETTIMEOFDAY_ 1
// cpplint thinks that the header is already included, so we want to
// silence it.
# include <sys/time.h> // NOLINT
# include <unistd.h> // NOLINT
#endif // GTEST_OS_LINUX
#if GTEST_HAS_EXCEPTIONS
# include <stdexcept>
#endif
#if GTEST_CAN_STREAM_RESULTS_
# include <arpa/inet.h> // NOLINT
# include <netdb.h> // NOLINT
#endif
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// his code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
# define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
namespace
testing
{
using
internal
::
CountIf
;
using
internal
::
ForEach
;
using
internal
::
GetElementOr
;
using
internal
::
Shuffle
;
// Constants.
// A test whose test case name or test name matches this filter is
// disabled and not run.
static
const
char
kDisableTestFilter
[]
=
"DISABLED_*:*/DISABLED_*"
;
// A test case whose name matches this filter is considered a death
// test case and will be run before test cases whose name doesn't
// match this filter.
static
const
char
kDeathTestCaseFilter
[]
=
"*DeathTest:*DeathTest/*"
;
// A test filter that matches everything.
static
const
char
kUniversalFilter
[]
=
"*"
;
// The default output file for XML output.
static
const
char
kDefaultOutputFile
[]
=
"test_detail.xml"
;
// The environment variable name for the test shard index.
static
const
char
kTestShardIndex
[]
=
"GTEST_SHARD_INDEX"
;
// The environment variable name for the total number of test shards.
static
const
char
kTestTotalShards
[]
=
"GTEST_TOTAL_SHARDS"
;
// The environment variable name for the test shard status file.
static
const
char
kTestShardStatusFile
[]
=
"GTEST_SHARD_STATUS_FILE"
;
namespace
internal
{
// The text used in failure messages to indicate the start of the
// stack trace.
const
char
kStackTraceMarker
[]
=
"
\n
Stack trace:
\n
"
;
// g_help_flag is true iff the --help flag or an equivalent form is
// specified on the command line.
bool
g_help_flag
=
false
;
}
// namespace internal
static
const
char
*
GetDefaultFilter
()
{
return
kUniversalFilter
;
}
GTEST_DEFINE_bool_
(
also_run_disabled_tests
,
internal
::
BoolFromGTestEnv
(
"also_run_disabled_tests"
,
false
),
"Run disabled tests too, in addition to the tests normally being run."
);
GTEST_DEFINE_bool_
(
break_on_failure
,
internal
::
BoolFromGTestEnv
(
"break_on_failure"
,
false
),
"True iff a failed assertion should be a debugger break-point."
);
GTEST_DEFINE_bool_
(
catch_exceptions
,
internal
::
BoolFromGTestEnv
(
"catch_exceptions"
,
true
),
"True iff "
GTEST_NAME_
" should catch exceptions and treat them as test failures."
);
GTEST_DEFINE_string_
(
color
,
internal
::
StringFromGTestEnv
(
"color"
,
"auto"
),
"Whether to use colors in the output. Valid values: yes, no, "
"and auto. 'auto' means to use colors if the output is "
"being sent to a terminal and the TERM environment variable "
"is set to a terminal type that supports colors."
);
GTEST_DEFINE_string_
(
filter
,
internal
::
StringFromGTestEnv
(
"filter"
,
GetDefaultFilter
()),
"A colon-separated list of glob (not regex) patterns "
"for filtering the tests to run, optionally followed by a "
"'-' and a : separated list of negative patterns (tests to "
"exclude). A test is run if it matches one of the positive "
"patterns and does not match any of the negative patterns."
);
GTEST_DEFINE_bool_
(
list_tests
,
false
,
"List all tests without running them."
);
GTEST_DEFINE_string_
(
output
,
internal
::
StringFromGTestEnv
(
"output"
,
""
),
"A format (currently must be
\"
xml
\"
), optionally followed "
"by a colon and an output file name or directory. A directory "
"is indicated by a trailing pathname separator. "
"Examples:
\"
xml:filename.xml
\"
,
\"
xml::directoryname/
\"
. "
"If a directory is specified, output files will be created "
"within that directory, with file-names based on the test "
"executable's name and, if necessary, made unique by adding "
"digits."
);
GTEST_DEFINE_bool_
(
print_time
,
internal
::
BoolFromGTestEnv
(
"print_time"
,
true
),
"True iff "
GTEST_NAME_
" should display elapsed time in text output."
);
GTEST_DEFINE_int32_
(
random_seed
,
internal
::
Int32FromGTestEnv
(
"random_seed"
,
0
),
"Random number seed to use when shuffling test orders. Must be in range "
"[1, 99999], or 0 to use a seed based on the current time."
);
GTEST_DEFINE_int32_
(
repeat
,
internal
::
Int32FromGTestEnv
(
"repeat"
,
1
),
"How many times to repeat each test. Specify a negative number "
"for repeating forever. Useful for shaking out flaky tests."
);
GTEST_DEFINE_bool_
(
show_internal_stack_frames
,
false
,
"True iff "
GTEST_NAME_
" should include internal stack frames when "
"printing test failure stack traces."
);
GTEST_DEFINE_bool_
(
shuffle
,
internal
::
BoolFromGTestEnv
(
"shuffle"
,
false
),
"True iff "
GTEST_NAME_
" should randomize tests' order on every run."
);
GTEST_DEFINE_int32_
(
stack_trace_depth
,
internal
::
Int32FromGTestEnv
(
"stack_trace_depth"
,
kMaxStackTraceDepth
),
"The maximum number of stack frames to print when an "
"assertion fails. The valid range is 0 through 100, inclusive."
);
GTEST_DEFINE_string_
(
stream_result_to
,
internal
::
StringFromGTestEnv
(
"stream_result_to"
,
""
),
"This flag specifies the host name and the port number on which to stream "
"test results. Example:
\"
localhost:555
\"
. The flag is effective only on "
"Linux."
);
GTEST_DEFINE_bool_
(
throw_on_failure
,
internal
::
BoolFromGTestEnv
(
"throw_on_failure"
,
false
),
"When this flag is specified, a failed assertion will throw an exception "
"if exceptions are enabled or exit the program with a non-zero code "
"otherwise."
);
namespace
internal
{
// Generates a random number from [0, range), using a Linear
// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
// than kMaxRange.
UInt32
Random
::
Generate
(
UInt32
range
)
{
// These constants are the same as are used in glibc's rand(3).
state_
=
(
1103515245U
*
state_
+
12345U
)
%
kMaxRange
;
GTEST_CHECK_
(
range
>
0
)
<<
"Cannot generate a number in the range [0, 0)."
;
GTEST_CHECK_
(
range
<=
kMaxRange
)
<<
"Generation of a number in [0, "
<<
range
<<
") was requested, "
<<
"but this can only generate numbers in [0, "
<<
kMaxRange
<<
")."
;
// Converting via modulus introduces a bit of downward bias, but
// it's simple, and a linear congruential generator isn't too good
// to begin with.
return
state_
%
range
;
}
// GTestIsInitialized() returns true iff the user has initialized
// Google Test. Useful for catching the user mistake of not initializing
// Google Test before calling RUN_ALL_TESTS().
//
// A user must call testing::InitGoogleTest() to initialize Google
// Test. g_init_gtest_count is set to the number of times
// InitGoogleTest() has been called. We don't protect this variable
// under a mutex as it is only accessed in the main thread.
GTEST_API_
int
g_init_gtest_count
=
0
;
static
bool
GTestIsInitialized
()
{
return
g_init_gtest_count
!=
0
;
}
// Iterates over a vector of TestCases, keeping a running sum of the
// results of calling a given int-returning method on each.
// Returns the sum.
static
int
SumOverTestCaseList
(
const
std
::
vector
<
TestCase
*>&
case_list
,
int
(
TestCase
::*
method
)()
const
)
{
int
sum
=
0
;
for
(
size_t
i
=
0
;
i
<
case_list
.
size
();
i
++
)
{
sum
+=
(
case_list
[
i
]
->*
method
)();
}
return
sum
;
}
// Returns true iff the test case passed.
static
bool
TestCasePassed
(
const
TestCase
*
test_case
)
{
return
test_case
->
should_run
()
&&
test_case
->
Passed
();
}
// Returns true iff the test case failed.
static
bool
TestCaseFailed
(
const
TestCase
*
test_case
)
{
return
test_case
->
should_run
()
&&
test_case
->
Failed
();
}
// Returns true iff test_case contains at least one test that should
// run.
static
bool
ShouldRunTestCase
(
const
TestCase
*
test_case
)
{
return
test_case
->
should_run
();
}
// AssertHelper constructor.
AssertHelper
::
AssertHelper
(
TestPartResult
::
Type
type
,
const
char
*
file
,
int
line
,
const
char
*
message
)
:
data_
(
new
AssertHelperData
(
type
,
file
,
line
,
message
))
{
}
AssertHelper
::~
AssertHelper
()
{
delete
data_
;
}
// Message assignment, for assertion streaming support.
void
AssertHelper
::
operator
=
(
const
Message
&
message
)
const
{
UnitTest
::
GetInstance
()
->
AddTestPartResult
(
data_
->
type
,
data_
->
file
,
data_
->
line
,
AppendUserMessage
(
data_
->
message
,
message
),
UnitTest
::
GetInstance
()
->
impl
()
->
CurrentOsStackTraceExceptTop
(
1
)
// Skips the stack frame for this function itself.
);
// NOLINT
}
// Mutex for linked pointers.
GTEST_API_
GTEST_DEFINE_STATIC_MUTEX_
(
g_linked_ptr_mutex
);
// Application pathname gotten in InitGoogleTest.
std
::
string
g_executable_path
;
// Returns the current application's name, removing directory path if that
// is present.
FilePath
GetCurrentExecutableName
()
{
FilePath
result
;
#if GTEST_OS_WINDOWS
result
.
Set
(
FilePath
(
g_executable_path
).
RemoveExtension
(
"exe"
));
#else
result
.
Set
(
FilePath
(
g_executable_path
));
#endif // GTEST_OS_WINDOWS
return
result
.
RemoveDirectoryName
();
}
// Functions for processing the gtest_output flag.
// Returns the output format, or "" for normal printed output.
std
::
string
UnitTestOptions
::
GetOutputFormat
()
{
const
char
*
const
gtest_output_flag
=
GTEST_FLAG
(
output
).
c_str
();
if
(
gtest_output_flag
==
NULL
)
return
std
::
string
(
""
);
const
char
*
const
colon
=
strchr
(
gtest_output_flag
,
':'
);
return
(
colon
==
NULL
)
?
std
::
string
(
gtest_output_flag
)
:
std
::
string
(
gtest_output_flag
,
colon
-
gtest_output_flag
);
}
// Returns the name of the requested output file, or the default if none
// was explicitly specified.
std
::
string
UnitTestOptions
::
GetAbsolutePathToOutputFile
()
{
const
char
*
const
gtest_output_flag
=
GTEST_FLAG
(
output
).
c_str
();
if
(
gtest_output_flag
==
NULL
)
return
""
;
const
char
*
const
colon
=
strchr
(
gtest_output_flag
,
':'
);
if
(
colon
==
NULL
)
return
internal
::
FilePath
::
ConcatPaths
(
internal
::
FilePath
(
UnitTest
::
GetInstance
()
->
original_working_dir
()),
internal
::
FilePath
(
kDefaultOutputFile
)).
string
();
internal
::
FilePath
output_name
(
colon
+
1
);
if
(
!
output_name
.
IsAbsolutePath
())
// TODO(wan@google.com): on Windows \some\path is not an absolute
// path (as its meaning depends on the current drive), yet the
// following logic for turning it into an absolute path is wrong.
// Fix it.
output_name
=
internal
::
FilePath
::
ConcatPaths
(
internal
::
FilePath
(
UnitTest
::
GetInstance
()
->
original_working_dir
()),
internal
::
FilePath
(
colon
+
1
));
if
(
!
output_name
.
IsDirectory
())
return
output_name
.
string
();
internal
::
FilePath
result
(
internal
::
FilePath
::
GenerateUniqueFileName
(
output_name
,
internal
::
GetCurrentExecutableName
(),
GetOutputFormat
().
c_str
()));
return
result
.
string
();
}
// Returns true iff the wildcard pattern matches the string. The
// first ':' or '\0' character in pattern marks the end of it.
//
// This recursive algorithm isn't very efficient, but is clear and
// works well enough for matching test names, which are short.
bool
UnitTestOptions
::
PatternMatchesString
(
const
char
*
pattern
,
const
char
*
str
)
{
switch
(
*
pattern
)
{
case
'\0'
:
case
':'
:
// Either ':' or '\0' marks the end of the pattern.
return
*
str
==
'\0'
;
case
'?'
:
// Matches any single character.
return
*
str
!=
'\0'
&&
PatternMatchesString
(
pattern
+
1
,
str
+
1
);
case
'*'
:
// Matches any string (possibly empty) of characters.
return
(
*
str
!=
'\0'
&&
PatternMatchesString
(
pattern
,
str
+
1
))
||
PatternMatchesString
(
pattern
+
1
,
str
);
default:
// Non-special character. Matches itself.
return
*
pattern
==
*
str
&&
PatternMatchesString
(
pattern
+
1
,
str
+
1
);
}
}
bool
UnitTestOptions
::
MatchesFilter
(
const
std
::
string
&
name
,
const
char
*
filter
)
{
const
char
*
cur_pattern
=
filter
;
for
(;;)
{
if
(
PatternMatchesString
(
cur_pattern
,
name
.
c_str
()))
{
return
true
;
}
// Finds the next pattern in the filter.
cur_pattern
=
strchr
(
cur_pattern
,
':'
);
// Returns if no more pattern can be found.
if
(
cur_pattern
==
NULL
)
{
return
false
;
}
// Skips the pattern separater (the ':' character).
cur_pattern
++
;
}
}
// Returns true iff the user-specified filter matches the test case
// name and the test name.
bool
UnitTestOptions
::
FilterMatchesTest
(
const
std
::
string
&
test_case_name
,
const
std
::
string
&
test_name
)
{
const
std
::
string
&
full_name
=
test_case_name
+
"."
+
test_name
.
c_str
();
// Split --gtest_filter at '-', if there is one, to separate into
// positive filter and negative filter portions
const
char
*
const
p
=
GTEST_FLAG
(
filter
).
c_str
();
const
char
*
const
dash
=
strchr
(
p
,
'-'
);
std
::
string
positive
;
std
::
string
negative
;
if
(
dash
==
NULL
)
{
positive
=
GTEST_FLAG
(
filter
).
c_str
();
// Whole string is a positive filter
negative
=
""
;
}
else
{
positive
=
std
::
string
(
p
,
dash
);
// Everything up to the dash
negative
=
std
::
string
(
dash
+
1
);
// Everything after the dash
if
(
positive
.
empty
())
{
// Treat '-test1' as the same as '*-test1'
positive
=
kUniversalFilter
;
}
}
// A filter is a colon-separated list of patterns. It matches a
// test if any pattern in it matches the test.
return
(
MatchesFilter
(
full_name
,
positive
.
c_str
())
&&
!
MatchesFilter
(
full_name
,
negative
.
c_str
()));
}
#if GTEST_HAS_SEH
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
int
UnitTestOptions
::
GTestShouldProcessSEH
(
DWORD
exception_code
)
{
// Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
// 2. this is not a breakpoint exception, AND
// 3. this is not a C++ exception (VC++ implements them via SEH,
// apparently).
//
// SEH exception code for C++ exceptions.
// (see http://support.microsoft.com/kb/185294 for more information).
const
DWORD
kCxxExceptionCode
=
0xe06d7363
;
bool
should_handle
=
true
;
if
(
!
GTEST_FLAG
(
catch_exceptions
))
should_handle
=
false
;
else
if
(
exception_code
==
EXCEPTION_BREAKPOINT
)
should_handle
=
false
;
else
if
(
exception_code
==
kCxxExceptionCode
)
should_handle
=
false
;
return
should_handle
?
EXCEPTION_EXECUTE_HANDLER
:
EXCEPTION_CONTINUE_SEARCH
;
}
#endif // GTEST_HAS_SEH
}
// namespace internal
// The c'tor sets this object as the test part result reporter used by
// Google Test. The 'result' parameter specifies where to report the
// results. Intercepts only failures from the current thread.
ScopedFakeTestPartResultReporter
::
ScopedFakeTestPartResultReporter
(
TestPartResultArray
*
result
)
:
intercept_mode_
(
INTERCEPT_ONLY_CURRENT_THREAD
),
result_
(
result
)
{
Init
();
}
// The c'tor sets this object as the test part result reporter used by
// Google Test. The 'result' parameter specifies where to report the
// results.
ScopedFakeTestPartResultReporter
::
ScopedFakeTestPartResultReporter
(
InterceptMode
intercept_mode
,
TestPartResultArray
*
result
)
:
intercept_mode_
(
intercept_mode
),
result_
(
result
)
{
Init
();
}
void
ScopedFakeTestPartResultReporter
::
Init
()
{
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
if
(
intercept_mode_
==
INTERCEPT_ALL_THREADS
)
{
old_reporter_
=
impl
->
GetGlobalTestPartResultReporter
();
impl
->
SetGlobalTestPartResultReporter
(
this
);
}
else
{
old_reporter_
=
impl
->
GetTestPartResultReporterForCurrentThread
();
impl
->
SetTestPartResultReporterForCurrentThread
(
this
);
}
}
// The d'tor restores the test part result reporter used by Google Test
// before.
ScopedFakeTestPartResultReporter
::~
ScopedFakeTestPartResultReporter
()
{
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
if
(
intercept_mode_
==
INTERCEPT_ALL_THREADS
)
{
impl
->
SetGlobalTestPartResultReporter
(
old_reporter_
);
}
else
{
impl
->
SetTestPartResultReporterForCurrentThread
(
old_reporter_
);
}
}
// Increments the test part result count and remembers the result.
// This method is from the TestPartResultReporterInterface interface.
void
ScopedFakeTestPartResultReporter
::
ReportTestPartResult
(
const
TestPartResult
&
result
)
{
result_
->
Append
(
result
);
}
namespace
internal
{
// Returns the type ID of ::testing::Test. We should always call this
// instead of GetTypeId< ::testing::Test>() to get the type ID of
// testing::Test. This is to work around a suspected linker bug when
// using Google Test as a framework on Mac OS X. The bug causes
// GetTypeId< ::testing::Test>() to return different values depending
// on whether the call is from the Google Test framework itself or
// from user test code. GetTestTypeId() is guaranteed to always
// return the same value, as it always calls GetTypeId<>() from the
// gtest.cc, which is within the Google Test framework.
TypeId
GetTestTypeId
()
{
return
GetTypeId
<
Test
>
();
}
// The value of GetTestTypeId() as seen from within the Google Test
// library. This is solely for testing GetTestTypeId().
extern
const
TypeId
kTestTypeIdInGoogleTest
=
GetTestTypeId
();
// This predicate-formatter checks that 'results' contains a test part
// failure of the given type and that the failure message contains the
// given substring.
AssertionResult
HasOneFailure
(
const
char
*
/* results_expr */
,
const
char
*
/* type_expr */
,
const
char
*
/* substr_expr */
,
const
TestPartResultArray
&
results
,
TestPartResult
::
Type
type
,
const
string
&
substr
)
{
const
std
::
string
expected
(
type
==
TestPartResult
::
kFatalFailure
?
"1 fatal failure"
:
"1 non-fatal failure"
);
Message
msg
;
if
(
results
.
size
()
!=
1
)
{
msg
<<
"Expected: "
<<
expected
<<
"
\n
"
<<
" Actual: "
<<
results
.
size
()
<<
" failures"
;
for
(
int
i
=
0
;
i
<
results
.
size
();
i
++
)
{
msg
<<
"
\n
"
<<
results
.
GetTestPartResult
(
i
);
}
return
AssertionFailure
()
<<
msg
;
}
const
TestPartResult
&
r
=
results
.
GetTestPartResult
(
0
);
if
(
r
.
type
()
!=
type
)
{
return
AssertionFailure
()
<<
"Expected: "
<<
expected
<<
"
\n
"
<<
" Actual:
\n
"
<<
r
;
}
if
(
strstr
(
r
.
message
(),
substr
.
c_str
())
==
NULL
)
{
return
AssertionFailure
()
<<
"Expected: "
<<
expected
<<
" containing
\"
"
<<
substr
<<
"
\"\n
"
<<
" Actual:
\n
"
<<
r
;
}
return
AssertionSuccess
();
}
// The constructor of SingleFailureChecker remembers where to look up
// test part results, what type of failure we expect, and what
// substring the failure message should contain.
SingleFailureChecker
::
SingleFailureChecker
(
const
TestPartResultArray
*
results
,
TestPartResult
::
Type
type
,
const
string
&
substr
)
:
results_
(
results
),
type_
(
type
),
substr_
(
substr
)
{}
// The destructor of SingleFailureChecker verifies that the given
// TestPartResultArray contains exactly one failure that has the given
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
SingleFailureChecker
::~
SingleFailureChecker
()
{
EXPECT_PRED_FORMAT3
(
HasOneFailure
,
*
results_
,
type_
,
substr_
);
}
DefaultGlobalTestPartResultReporter
::
DefaultGlobalTestPartResultReporter
(
UnitTestImpl
*
unit_test
)
:
unit_test_
(
unit_test
)
{}
void
DefaultGlobalTestPartResultReporter
::
ReportTestPartResult
(
const
TestPartResult
&
result
)
{
unit_test_
->
current_test_result
()
->
AddTestPartResult
(
result
);
unit_test_
->
listeners
()
->
repeater
()
->
OnTestPartResult
(
result
);
}
DefaultPerThreadTestPartResultReporter
::
DefaultPerThreadTestPartResultReporter
(
UnitTestImpl
*
unit_test
)
:
unit_test_
(
unit_test
)
{}
void
DefaultPerThreadTestPartResultReporter
::
ReportTestPartResult
(
const
TestPartResult
&
result
)
{
unit_test_
->
GetGlobalTestPartResultReporter
()
->
ReportTestPartResult
(
result
);
}
// Returns the global test part result reporter.
TestPartResultReporterInterface
*
UnitTestImpl
::
GetGlobalTestPartResultReporter
()
{
internal
::
MutexLock
lock
(
&
global_test_part_result_reporter_mutex_
);
return
global_test_part_result_repoter_
;
}
// Sets the global test part result reporter.
void
UnitTestImpl
::
SetGlobalTestPartResultReporter
(
TestPartResultReporterInterface
*
reporter
)
{
internal
::
MutexLock
lock
(
&
global_test_part_result_reporter_mutex_
);
global_test_part_result_repoter_
=
reporter
;
}
// Returns the test part result reporter for the current thread.
TestPartResultReporterInterface
*
UnitTestImpl
::
GetTestPartResultReporterForCurrentThread
()
{
return
per_thread_test_part_result_reporter_
.
get
();
}
// Sets the test part result reporter for the current thread.
void
UnitTestImpl
::
SetTestPartResultReporterForCurrentThread
(
TestPartResultReporterInterface
*
reporter
)
{
per_thread_test_part_result_reporter_
.
set
(
reporter
);
}
// Gets the number of successful test cases.
int
UnitTestImpl
::
successful_test_case_count
()
const
{
return
CountIf
(
test_cases_
,
TestCasePassed
);
}
// Gets the number of failed test cases.
int
UnitTestImpl
::
failed_test_case_count
()
const
{
return
CountIf
(
test_cases_
,
TestCaseFailed
);
}
// Gets the number of all test cases.
int
UnitTestImpl
::
total_test_case_count
()
const
{
return
static_cast
<
int
>
(
test_cases_
.
size
());
}
// Gets the number of all test cases that contain at least one test
// that should run.
int
UnitTestImpl
::
test_case_to_run_count
()
const
{
return
CountIf
(
test_cases_
,
ShouldRunTestCase
);
}
// Gets the number of successful tests.
int
UnitTestImpl
::
successful_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
successful_test_count
);
}
// Gets the number of failed tests.
int
UnitTestImpl
::
failed_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
failed_test_count
);
}
// Gets the number of disabled tests that will be reported in the XML report.
int
UnitTestImpl
::
reportable_disabled_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
reportable_disabled_test_count
);
}
// Gets the number of disabled tests.
int
UnitTestImpl
::
disabled_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
disabled_test_count
);
}
// Gets the number of tests to be printed in the XML report.
int
UnitTestImpl
::
reportable_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
reportable_test_count
);
}
// Gets the number of all tests.
int
UnitTestImpl
::
total_test_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
total_test_count
);
}
// Gets the number of tests that should run.
int
UnitTestImpl
::
test_to_run_count
()
const
{
return
SumOverTestCaseList
(
test_cases_
,
&
TestCase
::
test_to_run_count
);
}
// Returns the current OS stack trace as an std::string.
//
// The maximum number of stack frames to be included is specified by
// the gtest_stack_trace_depth flag. The skip_count parameter
// specifies the number of top frames to be skipped, which doesn't
// count against the number of frames to be included.
//
// For example, if Foo() calls Bar(), which in turn calls
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
std
::
string
UnitTestImpl
::
CurrentOsStackTraceExceptTop
(
int
skip_count
)
{
(
void
)
skip_count
;
return
""
;
}
// Returns the current time in milliseconds.
TimeInMillis
GetTimeInMillis
()
{
#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
// Difference between 1970-01-01 and 1601-01-01 in milliseconds.
// http://analogous.blogspot.com/2005/04/epoch.html
const
TimeInMillis
kJavaEpochToWinFileTimeDelta
=
static_cast
<
TimeInMillis
>
(
116444736UL
)
*
100000UL
;
const
DWORD
kTenthMicrosInMilliSecond
=
10000
;
SYSTEMTIME
now_systime
;
FILETIME
now_filetime
;
ULARGE_INTEGER
now_int64
;
// TODO(kenton@google.com): Shouldn't this just use
// GetSystemTimeAsFileTime()?
GetSystemTime
(
&
now_systime
);
if
(
SystemTimeToFileTime
(
&
now_systime
,
&
now_filetime
))
{
now_int64
.
LowPart
=
now_filetime
.
dwLowDateTime
;
now_int64
.
HighPart
=
now_filetime
.
dwHighDateTime
;
now_int64
.
QuadPart
=
(
now_int64
.
QuadPart
/
kTenthMicrosInMilliSecond
)
-
kJavaEpochToWinFileTimeDelta
;
return
now_int64
.
QuadPart
;
}
return
0
;
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64
now
;
# ifdef _MSC_VER
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there.
// TODO(kenton@google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime()
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64
(
&
now
);
# pragma warning(pop) // Restores the warning state.
# else
_ftime64
(
&
now
);
# endif // _MSC_VER
return
static_cast
<
TimeInMillis
>
(
now
.
time
)
*
1000
+
now
.
millitm
;
#elif GTEST_HAS_GETTIMEOFDAY_
struct
timeval
now
;
gettimeofday
(
&
now
,
NULL
);
return
static_cast
<
TimeInMillis
>
(
now
.
tv_sec
)
*
1000
+
now
.
tv_usec
/
1000
;
#else
# error "Don't know how to get the current time on your system."
#endif
}
// Utilities
// class String.
#if GTEST_OS_WINDOWS_MOBILE
// Creates a UTF-16 wide string from the given ANSI string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the wide string, or NULL if the
// input is NULL.
LPCWSTR
String
::
AnsiToUtf16
(
const
char
*
ansi
)
{
if
(
!
ansi
)
return
NULL
;
const
int
length
=
strlen
(
ansi
);
const
int
unicode_length
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ansi
,
length
,
NULL
,
0
);
WCHAR
*
unicode
=
new
WCHAR
[
unicode_length
+
1
];
MultiByteToWideChar
(
CP_ACP
,
0
,
ansi
,
length
,
unicode
,
unicode_length
);
unicode
[
unicode_length
]
=
0
;
return
unicode
;
}
// Creates an ANSI string from the given wide string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the ANSI string, or NULL if the
// input is NULL.
const
char
*
String
::
Utf16ToAnsi
(
LPCWSTR
utf16_str
)
{
if
(
!
utf16_str
)
return
NULL
;
const
int
ansi_length
=
WideCharToMultiByte
(
CP_ACP
,
0
,
utf16_str
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
char
*
ansi
=
new
char
[
ansi_length
+
1
];
WideCharToMultiByte
(
CP_ACP
,
0
,
utf16_str
,
-
1
,
ansi
,
ansi_length
,
NULL
,
NULL
);
ansi
[
ansi_length
]
=
0
;
return
ansi
;
}
#endif // GTEST_OS_WINDOWS_MOBILE
// Compares two C strings. Returns true iff they have the same content.
//
// Unlike strcmp(), this function can handle NULL argument(s). A NULL
// C string is considered different to any non-NULL C string,
// including the empty string.
bool
String
::
CStringEquals
(
const
char
*
lhs
,
const
char
*
rhs
)
{
if
(
lhs
==
NULL
)
return
rhs
==
NULL
;
if
(
rhs
==
NULL
)
return
false
;
return
strcmp
(
lhs
,
rhs
)
==
0
;
}
#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
// Converts an array of wide chars to a narrow string using the UTF-8
// encoding, and streams the result to the given Message object.
static
void
StreamWideCharsToMessage
(
const
wchar_t
*
wstr
,
size_t
length
,
Message
*
msg
)
{
for
(
size_t
i
=
0
;
i
!=
length
;
)
{
// NOLINT
if
(
wstr
[
i
]
!=
L'\0'
)
{
*
msg
<<
WideStringToUtf8
(
wstr
+
i
,
static_cast
<
int
>
(
length
-
i
));
while
(
i
!=
length
&&
wstr
[
i
]
!=
L'\0'
)
i
++
;
}
else
{
*
msg
<<
'\0'
;
i
++
;
}
}
}
#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
}
// namespace internal
// Constructs an empty Message.
// We allocate the stringstream separately because otherwise each use of
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
// stack frame leading to huge stack frames in some cases; gcc does not reuse
// the stack space.
Message
::
Message
()
:
ss_
(
new
::
std
::
stringstream
)
{
// By default, we want there to be enough precision when printing
// a double to a Message.
*
ss_
<<
std
::
setprecision
(
std
::
numeric_limits
<
double
>::
digits10
+
2
);
}
// These two overloads allow streaming a wide C string to a Message
// using the UTF-8 encoding.
Message
&
Message
::
operator
<<
(
const
wchar_t
*
wide_c_str
)
{
return
*
this
<<
internal
::
String
::
ShowWideCString
(
wide_c_str
);
}
Message
&
Message
::
operator
<<
(
wchar_t
*
wide_c_str
)
{
return
*
this
<<
internal
::
String
::
ShowWideCString
(
wide_c_str
);
}
#if GTEST_HAS_STD_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
Message
&
Message
::
operator
<<
(
const
::
std
::
wstring
&
wstr
)
{
internal
::
StreamWideCharsToMessage
(
wstr
.
c_str
(),
wstr
.
length
(),
this
);
return
*
this
;
}
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_GLOBAL_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
Message
&
Message
::
operator
<<
(
const
::
wstring
&
wstr
)
{
internal
::
StreamWideCharsToMessage
(
wstr
.
c_str
(),
wstr
.
length
(),
this
);
return
*
this
;
}
#endif // GTEST_HAS_GLOBAL_WSTRING
// Gets the text streamed to this object so far as an std::string.
// Each '\0' character in the buffer is replaced with "\\0".
std
::
string
Message
::
GetString
()
const
{
return
internal
::
StringStreamToString
(
ss_
.
get
());
}
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult
::
AssertionResult
(
const
AssertionResult
&
other
)
:
success_
(
other
.
success_
),
message_
(
other
.
message_
.
get
()
!=
NULL
?
new
::
std
::
string
(
*
other
.
message_
)
:
static_cast
<
::
std
::
string
*>
(
NULL
))
{
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
AssertionResult
AssertionResult
::
operator
!
()
const
{
AssertionResult
negation
(
!
success_
);
if
(
message_
.
get
()
!=
NULL
)
negation
<<
*
message_
;
return
negation
;
}
// Makes a successful assertion result.
AssertionResult
AssertionSuccess
()
{
return
AssertionResult
(
true
);
}
// Makes a failed assertion result.
AssertionResult
AssertionFailure
()
{
return
AssertionResult
(
false
);
}
// Makes a failed assertion result with the given failure message.
// Deprecated; use AssertionFailure() << message.
AssertionResult
AssertionFailure
(
const
Message
&
message
)
{
return
AssertionFailure
()
<<
message
;
}
namespace
internal
{
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
// The first four parameters are the expressions used in the assertion
// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
// where foo is 5 and bar is 6, we have:
//
// expected_expression: "foo"
// actual_expression: "bar"
// expected_value: "5"
// actual_value: "6"
//
// The ignoring_case parameter is true iff the assertion is a
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
// be inserted into the message.
AssertionResult
EqFailure
(
const
char
*
expected_expression
,
const
char
*
actual_expression
,
const
std
::
string
&
expected_value
,
const
std
::
string
&
actual_value
,
bool
ignoring_case
)
{
Message
msg
;
msg
<<
"Value of: "
<<
actual_expression
;
if
(
actual_value
!=
actual_expression
)
{
msg
<<
"
\n
Actual: "
<<
actual_value
;
}
msg
<<
"
\n
Expected: "
<<
expected_expression
;
if
(
ignoring_case
)
{
msg
<<
" (ignoring case)"
;
}
if
(
expected_value
!=
expected_expression
)
{
msg
<<
"
\n
Which is: "
<<
expected_value
;
}
return
AssertionFailure
()
<<
msg
;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
std
::
string
GetBoolAssertionFailureMessage
(
const
AssertionResult
&
assertion_result
,
const
char
*
expression_text
,
const
char
*
actual_predicate_value
,
const
char
*
expected_predicate_value
)
{
const
char
*
actual_message
=
assertion_result
.
message
();
Message
msg
;
msg
<<
"Value of: "
<<
expression_text
<<
"
\n
Actual: "
<<
actual_predicate_value
;
if
(
actual_message
[
0
]
!=
'\0'
)
msg
<<
" ("
<<
actual_message
<<
")"
;
msg
<<
"
\n
Expected: "
<<
expected_predicate_value
;
return
msg
.
GetString
();
}
// Helper function for implementing ASSERT_NEAR.
AssertionResult
DoubleNearPredFormat
(
const
char
*
expr1
,
const
char
*
expr2
,
const
char
*
abs_error_expr
,
double
val1
,
double
val2
,
double
abs_error
)
{
const
double
diff
=
fabs
(
val1
-
val2
);
if
(
diff
<=
abs_error
)
return
AssertionSuccess
();
// TODO(wan): do not print the value of an expression if it's
// already a literal.
return
AssertionFailure
()
<<
"The difference between "
<<
expr1
<<
" and "
<<
expr2
<<
" is "
<<
diff
<<
", which exceeds "
<<
abs_error_expr
<<
", where
\n
"
<<
expr1
<<
" evaluates to "
<<
val1
<<
",
\n
"
<<
expr2
<<
" evaluates to "
<<
val2
<<
", and
\n
"
<<
abs_error_expr
<<
" evaluates to "
<<
abs_error
<<
"."
;
}
// Helper template for implementing FloatLE() and DoubleLE().
template
<
typename
RawType
>
AssertionResult
FloatingPointLE
(
const
char
*
expr1
,
const
char
*
expr2
,
RawType
val1
,
RawType
val2
)
{
// Returns success if val1 is less than val2,
if
(
val1
<
val2
)
{
return
AssertionSuccess
();
}
// or if val1 is almost equal to val2.
const
FloatingPoint
<
RawType
>
lhs
(
val1
),
rhs
(
val2
);
if
(
lhs
.
AlmostEquals
(
rhs
))
{
return
AssertionSuccess
();
}
// Note that the above two checks will both fail if either val1 or
// val2 is NaN, as the IEEE floating-point standard requires that
// any predicate involving a NaN must return false.
::
std
::
stringstream
val1_ss
;
val1_ss
<<
std
::
setprecision
(
std
::
numeric_limits
<
RawType
>::
digits10
+
2
)
<<
val1
;
::
std
::
stringstream
val2_ss
;
val2_ss
<<
std
::
setprecision
(
std
::
numeric_limits
<
RawType
>::
digits10
+
2
)
<<
val2
;
return
AssertionFailure
()
<<
"Expected: ("
<<
expr1
<<
") <= ("
<<
expr2
<<
")
\n
"
<<
" Actual: "
<<
StringStreamToString
(
&
val1_ss
)
<<
" vs "
<<
StringStreamToString
(
&
val2_ss
);
}
}
// namespace internal
// Asserts that val1 is less than, or almost equal to, val2. Fails
// otherwise. In particular, it fails if either val1 or val2 is NaN.
AssertionResult
FloatLE
(
const
char
*
expr1
,
const
char
*
expr2
,
float
val1
,
float
val2
)
{
return
internal
::
FloatingPointLE
<
float
>
(
expr1
,
expr2
,
val1
,
val2
);
}
// Asserts that val1 is less than, or almost equal to, val2. Fails
// otherwise. In particular, it fails if either val1 or val2 is NaN.
AssertionResult
DoubleLE
(
const
char
*
expr1
,
const
char
*
expr2
,
double
val1
,
double
val2
)
{
return
internal
::
FloatingPointLE
<
double
>
(
expr1
,
expr2
,
val1
,
val2
);
}
namespace
internal
{
// The helper function for {ASSERT|EXPECT}_EQ with int or enum
// arguments.
AssertionResult
CmpHelperEQ
(
const
char
*
expected_expression
,
const
char
*
actual_expression
,
BiggestInt
expected
,
BiggestInt
actual
)
{
if
(
expected
==
actual
)
{
return
AssertionSuccess
();
}
return
EqFailure
(
expected_expression
,
actual_expression
,
FormatForComparisonFailureMessage
(
expected
,
actual
),
FormatForComparisonFailureMessage
(
actual
,
expected
),
false
);
}
// A macro for implementing the helper functions needed to implement
// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here
// just to avoid copy-and-paste of similar code.
#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
BiggestInt val1, BiggestInt val2) {\
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
return AssertionFailure() \
<< "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
}\
}
// Implements the helper function for {ASSERT|EXPECT}_NE with int or
// enum arguments.
GTEST_IMPL_CMP_HELPER_
(
NE
,
!=
)
// Implements the helper function for {ASSERT|EXPECT}_LE with int or
// enum arguments.
GTEST_IMPL_CMP_HELPER_
(
LE
,
<=
)
// Implements the helper function for {ASSERT|EXPECT}_LT with int or
// enum arguments.
GTEST_IMPL_CMP_HELPER_
(
LT
,
<
)
// Implements the helper function for {ASSERT|EXPECT}_GE with int or
// enum arguments.
GTEST_IMPL_CMP_HELPER_
(
GE
,
>=
)
// Implements the helper function for {ASSERT|EXPECT}_GT with int or
// enum arguments.
GTEST_IMPL_CMP_HELPER_
(
GT
,
>
)
#undef GTEST_IMPL_CMP_HELPER_
// The helper function for {ASSERT|EXPECT}_STREQ.
AssertionResult
CmpHelperSTREQ
(
const
char
*
expected_expression
,
const
char
*
actual_expression
,
const
char
*
expected
,
const
char
*
actual
)
{
if
(
String
::
CStringEquals
(
expected
,
actual
))
{
return
AssertionSuccess
();
}
return
EqFailure
(
expected_expression
,
actual_expression
,
PrintToString
(
expected
),
PrintToString
(
actual
),
false
);
}
// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
AssertionResult
CmpHelperSTRCASEEQ
(
const
char
*
expected_expression
,
const
char
*
actual_expression
,
const
char
*
expected
,
const
char
*
actual
)
{
if
(
String
::
CaseInsensitiveCStringEquals
(
expected
,
actual
))
{
return
AssertionSuccess
();
}
return
EqFailure
(
expected_expression
,
actual_expression
,
PrintToString
(
expected
),
PrintToString
(
actual
),
true
);
}
// The helper function for {ASSERT|EXPECT}_STRNE.
AssertionResult
CmpHelperSTRNE
(
const
char
*
s1_expression
,
const
char
*
s2_expression
,
const
char
*
s1
,
const
char
*
s2
)
{
if
(
!
String
::
CStringEquals
(
s1
,
s2
))
{
return
AssertionSuccess
();
}
else
{
return
AssertionFailure
()
<<
"Expected: ("
<<
s1_expression
<<
") != ("
<<
s2_expression
<<
"), actual:
\"
"
<<
s1
<<
"
\"
vs
\"
"
<<
s2
<<
"
\"
"
;
}
}
// The helper function for {ASSERT|EXPECT}_STRCASENE.
AssertionResult
CmpHelperSTRCASENE
(
const
char
*
s1_expression
,
const
char
*
s2_expression
,
const
char
*
s1
,
const
char
*
s2
)
{
if
(
!
String
::
CaseInsensitiveCStringEquals
(
s1
,
s2
))
{
return
AssertionSuccess
();
}
else
{
return
AssertionFailure
()
<<
"Expected: ("
<<
s1_expression
<<
") != ("
<<
s2_expression
<<
") (ignoring case), actual:
\"
"
<<
s1
<<
"
\"
vs
\"
"
<<
s2
<<
"
\"
"
;
}
}
}
// namespace internal
namespace
{
// Helper functions for implementing IsSubString() and IsNotSubstring().
// This group of overloaded functions return true iff needle is a
// substring of haystack. NULL is considered a substring of itself
// only.
bool
IsSubstringPred
(
const
char
*
needle
,
const
char
*
haystack
)
{
if
(
needle
==
NULL
||
haystack
==
NULL
)
return
needle
==
haystack
;
return
strstr
(
haystack
,
needle
)
!=
NULL
;
}
bool
IsSubstringPred
(
const
wchar_t
*
needle
,
const
wchar_t
*
haystack
)
{
if
(
needle
==
NULL
||
haystack
==
NULL
)
return
needle
==
haystack
;
return
wcsstr
(
haystack
,
needle
)
!=
NULL
;
}
// StringType here can be either ::std::string or ::std::wstring.
template
<
typename
StringType
>
bool
IsSubstringPred
(
const
StringType
&
needle
,
const
StringType
&
haystack
)
{
return
haystack
.
find
(
needle
)
!=
StringType
::
npos
;
}
// This function implements either IsSubstring() or IsNotSubstring(),
// depending on the value of the expected_to_be_substring parameter.
// StringType here can be const char*, const wchar_t*, ::std::string,
// or ::std::wstring.
template
<
typename
StringType
>
AssertionResult
IsSubstringImpl
(
bool
expected_to_be_substring
,
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
StringType
&
needle
,
const
StringType
&
haystack
)
{
if
(
IsSubstringPred
(
needle
,
haystack
)
==
expected_to_be_substring
)
return
AssertionSuccess
();
const
bool
is_wide_string
=
sizeof
(
needle
[
0
])
>
1
;
const
char
*
const
begin_string_quote
=
is_wide_string
?
"L
\"
"
:
"
\"
"
;
return
AssertionFailure
()
<<
"Value of: "
<<
needle_expr
<<
"
\n
"
<<
" Actual: "
<<
begin_string_quote
<<
needle
<<
"
\"\n
"
<<
"Expected: "
<<
(
expected_to_be_substring
?
""
:
"not "
)
<<
"a substring of "
<<
haystack_expr
<<
"
\n
"
<<
"Which is: "
<<
begin_string_quote
<<
haystack
<<
"
\"
"
;
}
}
// namespace
// IsSubstring() and IsNotSubstring() check whether needle is a
// substring of haystack (NULL is considered a substring of itself
// only), and return an appropriate error message when they fail.
AssertionResult
IsSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
char
*
needle
,
const
char
*
haystack
)
{
return
IsSubstringImpl
(
true
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
wchar_t
*
needle
,
const
wchar_t
*
haystack
)
{
return
IsSubstringImpl
(
true
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsNotSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
char
*
needle
,
const
char
*
haystack
)
{
return
IsSubstringImpl
(
false
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsNotSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
wchar_t
*
needle
,
const
wchar_t
*
haystack
)
{
return
IsSubstringImpl
(
false
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
::
std
::
string
&
needle
,
const
::
std
::
string
&
haystack
)
{
return
IsSubstringImpl
(
true
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsNotSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
::
std
::
string
&
needle
,
const
::
std
::
string
&
haystack
)
{
return
IsSubstringImpl
(
false
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
#if GTEST_HAS_STD_WSTRING
AssertionResult
IsSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
::
std
::
wstring
&
needle
,
const
::
std
::
wstring
&
haystack
)
{
return
IsSubstringImpl
(
true
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
AssertionResult
IsNotSubstring
(
const
char
*
needle_expr
,
const
char
*
haystack_expr
,
const
::
std
::
wstring
&
needle
,
const
::
std
::
wstring
&
haystack
)
{
return
IsSubstringImpl
(
false
,
needle_expr
,
haystack_expr
,
needle
,
haystack
);
}
#endif // GTEST_HAS_STD_WSTRING
namespace
internal
{
#if GTEST_OS_WINDOWS
namespace
{
// Helper function for IsHRESULT{SuccessFailure} predicates
AssertionResult
HRESULTFailureHelper
(
const
char
*
expr
,
const
char
*
expected
,
long
hr
)
{
// NOLINT
# if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't support FormatMessage.
const
char
error_text
[]
=
""
;
# else
// Looks up the human-readable system message for the HRESULT code
// and since we're not passing any params to FormatMessage, we don't
// want inserts expanded.
const
DWORD
kFlags
=
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
;
const
DWORD
kBufSize
=
4096
;
// Gets the system's human readable message string for this HRESULT.
char
error_text
[
kBufSize
]
=
{
'\0'
};
DWORD
message_length
=
::
FormatMessageA
(
kFlags
,
0
,
// no source, we're asking system
hr
,
// the error
0
,
// no line width restrictions
error_text
,
// output buffer
kBufSize
,
// buf size
NULL
);
// no arguments for inserts
// Trims tailing white space (FormatMessage leaves a trailing CR-LF)
for
(;
message_length
&&
IsSpace
(
error_text
[
message_length
-
1
]);
--
message_length
)
{
error_text
[
message_length
-
1
]
=
'\0'
;
}
# endif // GTEST_OS_WINDOWS_MOBILE
const
std
::
string
error_hex
(
"0x"
+
String
::
FormatHexInt
(
hr
));
return
::
testing
::
AssertionFailure
()
<<
"Expected: "
<<
expr
<<
" "
<<
expected
<<
".
\n
"
<<
" Actual: "
<<
error_hex
<<
" "
<<
error_text
<<
"
\n
"
;
}
}
// namespace
AssertionResult
IsHRESULTSuccess
(
const
char
*
expr
,
long
hr
)
{
// NOLINT
if
(
SUCCEEDED
(
hr
))
{
return
AssertionSuccess
();
}
return
HRESULTFailureHelper
(
expr
,
"succeeds"
,
hr
);
}
AssertionResult
IsHRESULTFailure
(
const
char
*
expr
,
long
hr
)
{
// NOLINT
if
(
FAILED
(
hr
))
{
return
AssertionSuccess
();
}
return
HRESULTFailureHelper
(
expr
,
"fails"
,
hr
);
}
#endif // GTEST_OS_WINDOWS
// Utility functions for encoding Unicode text (wide strings) in
// UTF-8.
// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
// like this:
//
// Code-point length Encoding
// 0 - 7 bits 0xxxxxxx
// 8 - 11 bits 110xxxxx 10xxxxxx
// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx
// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// The maximum code-point a one-byte UTF-8 sequence can represent.
const
UInt32
kMaxCodePoint1
=
(
static_cast
<
UInt32
>
(
1
)
<<
7
)
-
1
;
// The maximum code-point a two-byte UTF-8 sequence can represent.
const
UInt32
kMaxCodePoint2
=
(
static_cast
<
UInt32
>
(
1
)
<<
(
5
+
6
))
-
1
;
// The maximum code-point a three-byte UTF-8 sequence can represent.
const
UInt32
kMaxCodePoint3
=
(
static_cast
<
UInt32
>
(
1
)
<<
(
4
+
2
*
6
))
-
1
;
// The maximum code-point a four-byte UTF-8 sequence can represent.
const
UInt32
kMaxCodePoint4
=
(
static_cast
<
UInt32
>
(
1
)
<<
(
3
+
3
*
6
))
-
1
;
// Chops off the n lowest bits from a bit pattern. Returns the n
// lowest bits. As a side effect, the original bit pattern will be
// shifted to the right by n bits.
inline
UInt32
ChopLowBits
(
UInt32
*
bits
,
int
n
)
{
const
UInt32
low_bits
=
*
bits
&
((
static_cast
<
UInt32
>
(
1
)
<<
n
)
-
1
);
*
bits
>>=
n
;
return
low_bits
;
}
// Converts a Unicode code point to a narrow string in UTF-8 encoding.
// code_point parameter is of type UInt32 because wchar_t may not be
// wide enough to contain a code point.
// If the code_point is not a valid Unicode code point
// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
// to "(Invalid Unicode 0xXXXXXXXX)".
std
::
string
CodePointToUtf8
(
UInt32
code_point
)
{
if
(
code_point
>
kMaxCodePoint4
)
{
return
"(Invalid Unicode 0x"
+
String
::
FormatHexInt
(
code_point
)
+
")"
;
}
char
str
[
5
];
// Big enough for the largest valid code point.
if
(
code_point
<=
kMaxCodePoint1
)
{
str
[
1
]
=
'\0'
;
str
[
0
]
=
static_cast
<
char
>
(
code_point
);
// 0xxxxxxx
}
else
if
(
code_point
<=
kMaxCodePoint2
)
{
str
[
2
]
=
'\0'
;
str
[
1
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
0
]
=
static_cast
<
char
>
(
0xC0
|
code_point
);
// 110xxxxx
}
else
if
(
code_point
<=
kMaxCodePoint3
)
{
str
[
3
]
=
'\0'
;
str
[
2
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
1
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
0
]
=
static_cast
<
char
>
(
0xE0
|
code_point
);
// 1110xxxx
}
else
{
// code_point <= kMaxCodePoint4
str
[
4
]
=
'\0'
;
str
[
3
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
2
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
1
]
=
static_cast
<
char
>
(
0x80
|
ChopLowBits
(
&
code_point
,
6
));
// 10xxxxxx
str
[
0
]
=
static_cast
<
char
>
(
0xF0
|
code_point
);
// 11110xxx
}
return
str
;
}
// The following two functions only make sense if the the system
// uses UTF-16 for wide string encoding. All supported systems
// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
// Determines if the arguments constitute UTF-16 surrogate pair
// and thus should be combined into a single Unicode code point
// using CreateCodePointFromUtf16SurrogatePair.
inline
bool
IsUtf16SurrogatePair
(
wchar_t
first
,
wchar_t
second
)
{
return
sizeof
(
wchar_t
)
==
2
&&
(
first
&
0xFC00
)
==
0xD800
&&
(
second
&
0xFC00
)
==
0xDC00
;
}
// Creates a Unicode code point from UTF16 surrogate pair.
inline
UInt32
CreateCodePointFromUtf16SurrogatePair
(
wchar_t
first
,
wchar_t
second
)
{
const
UInt32
mask
=
(
1
<<
10
)
-
1
;
return
(
sizeof
(
wchar_t
)
==
2
)
?
(((
first
&
mask
)
<<
10
)
|
(
second
&
mask
))
+
0x10000
:
// This function should not be called when the condition is
// false, but we provide a sensible default in case it is.
static_cast
<
UInt32
>
(
first
);
}
// Converts a wide string to a narrow string in UTF-8 encoding.
// The wide string is assumed to have the following encoding:
// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
// Parameter str points to a null-terminated wide string.
// Parameter num_chars may additionally limit the number
// of wchar_t characters processed. -1 is used when the entire string
// should be processed.
// If the string contains code points that are not valid Unicode code points
// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
// and contains invalid UTF-16 surrogate pairs, values in those pairs
// will be encoded as individual Unicode characters from Basic Normal Plane.
std
::
string
WideStringToUtf8
(
const
wchar_t
*
str
,
int
num_chars
)
{
if
(
num_chars
==
-
1
)
num_chars
=
static_cast
<
int
>
(
wcslen
(
str
));
::
std
::
stringstream
stream
;
for
(
int
i
=
0
;
i
<
num_chars
;
++
i
)
{
UInt32
unicode_code_point
;
if
(
str
[
i
]
==
L'\0'
)
{
break
;
}
else
if
(
i
+
1
<
num_chars
&&
IsUtf16SurrogatePair
(
str
[
i
],
str
[
i
+
1
]))
{
unicode_code_point
=
CreateCodePointFromUtf16SurrogatePair
(
str
[
i
],
str
[
i
+
1
]);
i
++
;
}
else
{
unicode_code_point
=
static_cast
<
UInt32
>
(
str
[
i
]);
}
stream
<<
CodePointToUtf8
(
unicode_code_point
);
}
return
StringStreamToString
(
&
stream
);
}
// Converts a wide C string to an std::string using the UTF-8 encoding.
// NULL will be converted to "(null)".
std
::
string
String
::
ShowWideCString
(
const
wchar_t
*
wide_c_str
)
{
if
(
wide_c_str
==
NULL
)
return
"(null)"
;
return
internal
::
WideStringToUtf8
(
wide_c_str
,
-
1
);
}
// Compares two wide C strings. Returns true iff they have the same
// content.
//
// Unlike wcscmp(), this function can handle NULL argument(s). A NULL
// C string is considered different to any non-NULL C string,
// including the empty string.
bool
String
::
WideCStringEquals
(
const
wchar_t
*
lhs
,
const
wchar_t
*
rhs
)
{
if
(
lhs
==
NULL
)
return
rhs
==
NULL
;
if
(
rhs
==
NULL
)
return
false
;
return
wcscmp
(
lhs
,
rhs
)
==
0
;
}
// Helper function for *_STREQ on wide strings.
AssertionResult
CmpHelperSTREQ
(
const
char
*
expected_expression
,
const
char
*
actual_expression
,
const
wchar_t
*
expected
,
const
wchar_t
*
actual
)
{
if
(
String
::
WideCStringEquals
(
expected
,
actual
))
{
return
AssertionSuccess
();
}
return
EqFailure
(
expected_expression
,
actual_expression
,
PrintToString
(
expected
),
PrintToString
(
actual
),
false
);
}
// Helper function for *_STRNE on wide strings.
AssertionResult
CmpHelperSTRNE
(
const
char
*
s1_expression
,
const
char
*
s2_expression
,
const
wchar_t
*
s1
,
const
wchar_t
*
s2
)
{
if
(
!
String
::
WideCStringEquals
(
s1
,
s2
))
{
return
AssertionSuccess
();
}
return
AssertionFailure
()
<<
"Expected: ("
<<
s1_expression
<<
") != ("
<<
s2_expression
<<
"), actual: "
<<
PrintToString
(
s1
)
<<
" vs "
<<
PrintToString
(
s2
);
}
// Compares two C strings, ignoring case. Returns true iff they have
// the same content.
//
// Unlike strcasecmp(), this function can handle NULL argument(s). A
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
bool
String
::
CaseInsensitiveCStringEquals
(
const
char
*
lhs
,
const
char
*
rhs
)
{
if
(
lhs
==
NULL
)
return
rhs
==
NULL
;
if
(
rhs
==
NULL
)
return
false
;
return
posix
::
StrCaseCmp
(
lhs
,
rhs
)
==
0
;
}
// Compares two wide C strings, ignoring case. Returns true iff they
// have the same content.
//
// Unlike wcscasecmp(), this function can handle NULL argument(s).
// A NULL C string is considered different to any non-NULL wide C string,
// including the empty string.
// NB: The implementations on different platforms slightly differ.
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
// environment variable. On GNU platform this method uses wcscasecmp
// which compares according to LC_CTYPE category of the current locale.
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
// current locale.
bool
String
::
CaseInsensitiveWideCStringEquals
(
const
wchar_t
*
lhs
,
const
wchar_t
*
rhs
)
{
if
(
lhs
==
NULL
)
return
rhs
==
NULL
;
if
(
rhs
==
NULL
)
return
false
;
#if GTEST_OS_WINDOWS
return
_wcsicmp
(
lhs
,
rhs
)
==
0
;
#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
return
wcscasecmp
(
lhs
,
rhs
)
==
0
;
#else
// Android, Mac OS X and Cygwin don't define wcscasecmp.
// Other unknown OSes may not define it either.
wint_t
left
,
right
;
do
{
left
=
towlower
(
*
lhs
++
);
right
=
towlower
(
*
rhs
++
);
}
while
(
left
&&
left
==
right
);
return
left
==
right
;
#endif // OS selector
}
// Returns true iff str ends with the given suffix, ignoring case.
// Any string is considered to end with an empty suffix.
bool
String
::
EndsWithCaseInsensitive
(
const
std
::
string
&
str
,
const
std
::
string
&
suffix
)
{
const
size_t
str_len
=
str
.
length
();
const
size_t
suffix_len
=
suffix
.
length
();
return
(
str_len
>=
suffix_len
)
&&
CaseInsensitiveCStringEquals
(
str
.
c_str
()
+
str_len
-
suffix_len
,
suffix
.
c_str
());
}
// Formats an int value as "%02d".
std
::
string
String
::
FormatIntWidth2
(
int
value
)
{
std
::
stringstream
ss
;
ss
<<
std
::
setfill
(
'0'
)
<<
std
::
setw
(
2
)
<<
value
;
return
ss
.
str
();
}
// Formats an int value as "%X".
std
::
string
String
::
FormatHexInt
(
int
value
)
{
std
::
stringstream
ss
;
ss
<<
std
::
hex
<<
std
::
uppercase
<<
value
;
return
ss
.
str
();
}
// Formats a byte as "%02X".
std
::
string
String
::
FormatByte
(
unsigned
char
value
)
{
std
::
stringstream
ss
;
ss
<<
std
::
setfill
(
'0'
)
<<
std
::
setw
(
2
)
<<
std
::
hex
<<
std
::
uppercase
<<
static_cast
<
unsigned
int
>
(
value
);
return
ss
.
str
();
}
// Converts the buffer in a stringstream to an std::string, converting NUL
// bytes to "\\0" along the way.
std
::
string
StringStreamToString
(
::
std
::
stringstream
*
ss
)
{
const
::
std
::
string
&
str
=
ss
->
str
();
const
char
*
const
start
=
str
.
c_str
();
const
char
*
const
end
=
start
+
str
.
length
();
std
::
string
result
;
result
.
reserve
(
2
*
(
end
-
start
));
for
(
const
char
*
ch
=
start
;
ch
!=
end
;
++
ch
)
{
if
(
*
ch
==
'\0'
)
{
result
+=
"
\\
0"
;
// Replaces NUL with "\\0";
}
else
{
result
+=
*
ch
;
}
}
return
result
;
}
// Appends the user-supplied message to the Google-Test-generated message.
std
::
string
AppendUserMessage
(
const
std
::
string
&
gtest_msg
,
const
Message
&
user_msg
)
{
// Appends the user message if it's non-empty.
const
std
::
string
user_msg_string
=
user_msg
.
GetString
();
if
(
user_msg_string
.
empty
())
{
return
gtest_msg
;
}
return
gtest_msg
+
"
\n
"
+
user_msg_string
;
}
}
// namespace internal
// class TestResult
// Creates an empty TestResult.
TestResult
::
TestResult
()
:
death_test_count_
(
0
),
elapsed_time_
(
0
)
{
}
// D'tor.
TestResult
::~
TestResult
()
{
}
// Returns the i-th test part result among all the results. i can
// range from 0 to total_part_count() - 1. If i is not in that range,
// aborts the program.
const
TestPartResult
&
TestResult
::
GetTestPartResult
(
int
i
)
const
{
if
(
i
<
0
||
i
>=
total_part_count
())
internal
::
posix
::
Abort
();
return
test_part_results_
.
at
(
i
);
}
// Returns the i-th test property. i can range from 0 to
// test_property_count() - 1. If i is not in that range, aborts the
// program.
const
TestProperty
&
TestResult
::
GetTestProperty
(
int
i
)
const
{
if
(
i
<
0
||
i
>=
test_property_count
())
internal
::
posix
::
Abort
();
return
test_properties_
.
at
(
i
);
}
// Clears the test part results.
void
TestResult
::
ClearTestPartResults
()
{
test_part_results_
.
clear
();
}
// Adds a test part result to the list.
void
TestResult
::
AddTestPartResult
(
const
TestPartResult
&
test_part_result
)
{
test_part_results_
.
push_back
(
test_part_result
);
}
// Adds a test property to the list. If a property with the same key as the
// supplied property is already represented, the value of this test_property
// replaces the old value for that key.
void
TestResult
::
RecordProperty
(
const
std
::
string
&
xml_element
,
const
TestProperty
&
test_property
)
{
if
(
!
ValidateTestProperty
(
xml_element
,
test_property
))
{
return
;
}
internal
::
MutexLock
lock
(
&
test_properites_mutex_
);
const
std
::
vector
<
TestProperty
>::
iterator
property_with_matching_key
=
std
::
find_if
(
test_properties_
.
begin
(),
test_properties_
.
end
(),
internal
::
TestPropertyKeyIs
(
test_property
.
key
()));
if
(
property_with_matching_key
==
test_properties_
.
end
())
{
test_properties_
.
push_back
(
test_property
);
return
;
}
property_with_matching_key
->
SetValue
(
test_property
.
value
());
}
// The list of reserved attributes used in the <testsuites> element of XML
// output.
static
const
char
*
const
kReservedTestSuitesAttributes
[]
=
{
"disabled"
,
"errors"
,
"failures"
,
"name"
,
"random_seed"
,
"tests"
,
"time"
,
"timestamp"
};
// The list of reserved attributes used in the <testsuite> element of XML
// output.
static
const
char
*
const
kReservedTestSuiteAttributes
[]
=
{
"disabled"
,
"errors"
,
"failures"
,
"name"
,
"tests"
,
"time"
};
// The list of reserved attributes used in the <testcase> element of XML output.
static
const
char
*
const
kReservedTestCaseAttributes
[]
=
{
"classname"
,
"name"
,
"status"
,
"time"
,
"type_param"
,
"value_param"
};
template
<
int
kSize
>
std
::
vector
<
std
::
string
>
ArrayAsVector
(
const
char
*
const
(
&
array
)[
kSize
])
{
return
std
::
vector
<
std
::
string
>
(
array
,
array
+
kSize
);
}
static
std
::
vector
<
std
::
string
>
GetReservedAttributesForElement
(
const
std
::
string
&
xml_element
)
{
if
(
xml_element
==
"testsuites"
)
{
return
ArrayAsVector
(
kReservedTestSuitesAttributes
);
}
else
if
(
xml_element
==
"testsuite"
)
{
return
ArrayAsVector
(
kReservedTestSuiteAttributes
);
}
else
if
(
xml_element
==
"testcase"
)
{
return
ArrayAsVector
(
kReservedTestCaseAttributes
);
}
else
{
GTEST_CHECK_
(
false
)
<<
"Unrecognized xml_element provided: "
<<
xml_element
;
}
// This code is unreachable but some compilers may not realizes that.
return
std
::
vector
<
std
::
string
>
();
}
static
std
::
string
FormatWordList
(
const
std
::
vector
<
std
::
string
>&
words
)
{
Message
word_list
;
for
(
size_t
i
=
0
;
i
<
words
.
size
();
++
i
)
{
if
(
i
>
0
&&
words
.
size
()
>
2
)
{
word_list
<<
", "
;
}
if
(
i
==
words
.
size
()
-
1
)
{
word_list
<<
"and "
;
}
word_list
<<
"'"
<<
words
[
i
]
<<
"'"
;
}
return
word_list
.
GetString
();
}
bool
ValidateTestPropertyName
(
const
std
::
string
&
property_name
,
const
std
::
vector
<
std
::
string
>&
reserved_names
)
{
if
(
std
::
find
(
reserved_names
.
begin
(),
reserved_names
.
end
(),
property_name
)
!=
reserved_names
.
end
())
{
ADD_FAILURE
()
<<
"Reserved key used in RecordProperty(): "
<<
property_name
<<
" ("
<<
FormatWordList
(
reserved_names
)
<<
" are reserved by "
<<
GTEST_NAME_
<<
")"
;
return
false
;
}
return
true
;
}
// Adds a failure if the key is a reserved attribute of the element named
// xml_element. Returns true if the property is valid.
bool
TestResult
::
ValidateTestProperty
(
const
std
::
string
&
xml_element
,
const
TestProperty
&
test_property
)
{
return
ValidateTestPropertyName
(
test_property
.
key
(),
GetReservedAttributesForElement
(
xml_element
));
}
// Clears the object.
void
TestResult
::
Clear
()
{
test_part_results_
.
clear
();
test_properties_
.
clear
();
death_test_count_
=
0
;
elapsed_time_
=
0
;
}
// Returns true iff the test failed.
bool
TestResult
::
Failed
()
const
{
for
(
int
i
=
0
;
i
<
total_part_count
();
++
i
)
{
if
(
GetTestPartResult
(
i
).
failed
())
return
true
;
}
return
false
;
}
// Returns true iff the test part fatally failed.
static
bool
TestPartFatallyFailed
(
const
TestPartResult
&
result
)
{
return
result
.
fatally_failed
();
}
// Returns true iff the test fatally failed.
bool
TestResult
::
HasFatalFailure
()
const
{
return
CountIf
(
test_part_results_
,
TestPartFatallyFailed
)
>
0
;
}
// Returns true iff the test part non-fatally failed.
static
bool
TestPartNonfatallyFailed
(
const
TestPartResult
&
result
)
{
return
result
.
nonfatally_failed
();
}
// Returns true iff the test has a non-fatal failure.
bool
TestResult
::
HasNonfatalFailure
()
const
{
return
CountIf
(
test_part_results_
,
TestPartNonfatallyFailed
)
>
0
;
}
// Gets the number of all test parts. This is the sum of the number
// of successful test parts and the number of failed test parts.
int
TestResult
::
total_part_count
()
const
{
return
static_cast
<
int
>
(
test_part_results_
.
size
());
}
// Returns the number of the test properties.
int
TestResult
::
test_property_count
()
const
{
return
static_cast
<
int
>
(
test_properties_
.
size
());
}
// class Test
// Creates a Test object.
// The c'tor saves the values of all Google Test flags.
Test
::
Test
()
:
gtest_flag_saver_
(
new
internal
::
GTestFlagSaver
)
{
}
// The d'tor restores the values of all Google Test flags.
Test
::~
Test
()
{
delete
gtest_flag_saver_
;
}
// Sets up the test fixture.
//
// A sub-class may override this.
void
Test
::
SetUp
()
{
}
// Tears down the test fixture.
//
// A sub-class may override this.
void
Test
::
TearDown
()
{
}
// Allows user supplied key value pairs to be recorded for later output.
void
Test
::
RecordProperty
(
const
std
::
string
&
key
,
const
std
::
string
&
value
)
{
UnitTest
::
GetInstance
()
->
RecordProperty
(
key
,
value
);
}
// Allows user supplied key value pairs to be recorded for later output.
void
Test
::
RecordProperty
(
const
std
::
string
&
key
,
int
value
)
{
Message
value_message
;
value_message
<<
value
;
RecordProperty
(
key
,
value_message
.
GetString
().
c_str
());
}
namespace
internal
{
void
ReportFailureInUnknownLocation
(
TestPartResult
::
Type
result_type
,
const
std
::
string
&
message
)
{
// This function is a friend of UnitTest and as such has access to
// AddTestPartResult.
UnitTest
::
GetInstance
()
->
AddTestPartResult
(
result_type
,
NULL
,
// No info about the source file where the exception occurred.
-
1
,
// We have no info on which line caused the exception.
message
,
""
);
// No stack trace, either.
}
}
// namespace internal
// Google Test requires all tests in the same test case to use the same test
// fixture class. This function checks if the current test has the
// same fixture class as the first test in the current test case. If
// yes, it returns true; otherwise it generates a Google Test failure and
// returns false.
bool
Test
::
HasSameFixtureClass
()
{
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
const
TestCase
*
const
test_case
=
impl
->
current_test_case
();
// Info about the first test in the current test case.
const
TestInfo
*
const
first_test_info
=
test_case
->
test_info_list
()[
0
];
const
internal
::
TypeId
first_fixture_id
=
first_test_info
->
fixture_class_id_
;
const
char
*
const
first_test_name
=
first_test_info
->
name
();
// Info about the current test.
const
TestInfo
*
const
this_test_info
=
impl
->
current_test_info
();
const
internal
::
TypeId
this_fixture_id
=
this_test_info
->
fixture_class_id_
;
const
char
*
const
this_test_name
=
this_test_info
->
name
();
if
(
this_fixture_id
!=
first_fixture_id
)
{
// Is the first test defined using TEST?
const
bool
first_is_TEST
=
first_fixture_id
==
internal
::
GetTestTypeId
();
// Is this test defined using TEST?
const
bool
this_is_TEST
=
this_fixture_id
==
internal
::
GetTestTypeId
();
if
(
first_is_TEST
||
this_is_TEST
)
{
// The user mixed TEST and TEST_F in this test case - we'll tell
// him/her how to fix it.
// Gets the name of the TEST and the name of the TEST_F. Note
// that first_is_TEST and this_is_TEST cannot both be true, as
// the fixture IDs are different for the two tests.
const
char
*
const
TEST_name
=
first_is_TEST
?
first_test_name
:
this_test_name
;
const
char
*
const
TEST_F_name
=
first_is_TEST
?
this_test_name
:
first_test_name
;
ADD_FAILURE
()
<<
"All tests in the same test case must use the same test fixture
\n
"
<<
"class, so mixing TEST_F and TEST in the same test case is
\n
"
<<
"illegal. In test case "
<<
this_test_info
->
test_case_name
()
<<
",
\n
"
<<
"test "
<<
TEST_F_name
<<
" is defined using TEST_F but
\n
"
<<
"test "
<<
TEST_name
<<
" is defined using TEST. You probably
\n
"
<<
"want to change the TEST to TEST_F or move it to another test
\n
"
<<
"case."
;
}
else
{
// The user defined two fixture classes with the same name in
// two namespaces - we'll tell him/her how to fix it.
ADD_FAILURE
()
<<
"All tests in the same test case must use the same test fixture
\n
"
<<
"class. However, in test case "
<<
this_test_info
->
test_case_name
()
<<
",
\n
"
<<
"you defined test "
<<
first_test_name
<<
" and test "
<<
this_test_name
<<
"
\n
"
<<
"using two different test fixture classes. This can happen if
\n
"
<<
"the two classes are from different namespaces or translation
\n
"
<<
"units and have the same name. You should probably rename one
\n
"
<<
"of the classes to put the tests into different test cases."
;
}
return
false
;
}
return
true
;
}
#if GTEST_HAS_SEH
// Adds an "exception thrown" fatal failure to the current test. This
// function returns its result via an output parameter pointer because VC++
// prohibits creation of objects with destructors on stack in functions
// using __try (see error C2712).
static
std
::
string
*
FormatSehExceptionMessage
(
DWORD
exception_code
,
const
char
*
location
)
{
Message
message
;
message
<<
"SEH exception with code 0x"
<<
std
::
setbase
(
16
)
<<
exception_code
<<
std
::
setbase
(
10
)
<<
" thrown in "
<<
location
<<
"."
;
return
new
std
::
string
(
message
.
GetString
());
}
#endif // GTEST_HAS_SEH
namespace
internal
{
#if GTEST_HAS_EXCEPTIONS
// Adds an "exception thrown" fatal failure to the current test.
static
std
::
string
FormatCxxExceptionMessage
(
const
char
*
description
,
const
char
*
location
)
{
Message
message
;
if
(
description
!=
NULL
)
{
message
<<
"C++ exception with description
\"
"
<<
description
<<
"
\"
"
;
}
else
{
message
<<
"Unknown C++ exception"
;
}
message
<<
" thrown in "
<<
location
<<
"."
;
return
message
.
GetString
();
}
static
std
::
string
PrintTestPartResultToString
(
const
TestPartResult
&
test_part_result
);
GoogleTestFailureException
::
GoogleTestFailureException
(
const
TestPartResult
&
failure
)
:
::
std
::
runtime_error
(
PrintTestPartResultToString
(
failure
).
c_str
())
{}
#endif // GTEST_HAS_EXCEPTIONS
// We put these helper functions in the internal namespace as IBM's xlC
// compiler rejects the code if they were declared static.
// Runs the given method and handles SEH exceptions it throws, when
// SEH is supported; returns the 0-value for type Result in case of an
// SEH exception. (Microsoft compilers cannot handle SEH and C++
// exceptions in the same function. Therefore, we provide a separate
// wrapper function for handling SEH exceptions.)
template
<
class
T
,
typename
Result
>
Result
HandleSehExceptionsInMethodIfSupported
(
T
*
object
,
Result
(
T
::*
method
)(),
const
char
*
location
)
{
#if GTEST_HAS_SEH
__try
{
return
(
object
->*
method
)();
}
__except
(
internal
::
UnitTestOptions
::
GTestShouldProcessSEH
(
// NOLINT
GetExceptionCode
()))
{
// We create the exception message on the heap because VC++ prohibits
// creation of objects with destructors on stack in functions using __try
// (see error C2712).
std
::
string
*
exception_message
=
FormatSehExceptionMessage
(
GetExceptionCode
(),
location
);
internal
::
ReportFailureInUnknownLocation
(
TestPartResult
::
kFatalFailure
,
*
exception_message
);
delete
exception_message
;
return
static_cast
<
Result
>
(
0
);
}
#else
(
void
)
location
;
return
(
object
->*
method
)();
#endif // GTEST_HAS_SEH
}
// Runs the given method and catches and reports C++ and/or SEH-style
// exceptions, if they are supported; returns the 0-value for type
// Result in case of an SEH exception.
template
<
class
T
,
typename
Result
>
Result
HandleExceptionsInMethodIfSupported
(
T
*
object
,
Result
(
T
::*
method
)(),
const
char
*
location
)
{
// NOTE: The user code can affect the way in which Google Test handles
// exceptions by setting GTEST_FLAG(catch_exceptions), but only before
// RUN_ALL_TESTS() starts. It is technically possible to check the flag
// after the exception is caught and either report or re-throw the
// exception based on the flag's value:
//
// try {
// // Perform the test method.
// } catch (...) {
// if (GTEST_FLAG(catch_exceptions))
// // Report the exception as failure.
// else
// throw; // Re-throws the original exception.
// }
//
// However, the purpose of this flag is to allow the program to drop into
// the debugger when the exception is thrown. On most platforms, once the
// control enters the catch block, the exception origin information is
// lost and the debugger will stop the program at the point of the
// re-throw in this function -- instead of at the point of the original
// throw statement in the code under test. For this reason, we perform
// the check early, sacrificing the ability to affect Google Test's
// exception handling in the method where the exception is thrown.
if
(
internal
::
GetUnitTestImpl
()
->
catch_exceptions
())
{
#if GTEST_HAS_EXCEPTIONS
try
{
return
HandleSehExceptionsInMethodIfSupported
(
object
,
method
,
location
);
}
catch
(
const
internal
::
GoogleTestFailureException
&
)
{
// NOLINT
// This exception type can only be thrown by a failed Google
// Test assertion with the intention of letting another testing
// framework catch it. Therefore we just re-throw it.
throw
;
}
catch
(
const
std
::
exception
&
e
)
{
// NOLINT
internal
::
ReportFailureInUnknownLocation
(
TestPartResult
::
kFatalFailure
,
FormatCxxExceptionMessage
(
e
.
what
(),
location
));
}
catch
(...)
{
// NOLINT
internal
::
ReportFailureInUnknownLocation
(
TestPartResult
::
kFatalFailure
,
FormatCxxExceptionMessage
(
NULL
,
location
));
}
return
static_cast
<
Result
>
(
0
);
#else
return
HandleSehExceptionsInMethodIfSupported
(
object
,
method
,
location
);
#endif // GTEST_HAS_EXCEPTIONS
}
else
{
return
(
object
->*
method
)();
}
}
}
// namespace internal
// Runs the test and updates the test result.
void
Test
::
Run
()
{
if
(
!
HasSameFixtureClass
())
return
;
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
this
,
&
Test
::
SetUp
,
"SetUp()"
);
// We will run the test only if SetUp() was successful.
if
(
!
HasFatalFailure
())
{
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
this
,
&
Test
::
TestBody
,
"the test body"
);
}
// However, we want to clean up as much as possible. Hence we will
// always call TearDown(), even if SetUp() or the test body has
// failed.
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
this
,
&
Test
::
TearDown
,
"TearDown()"
);
}
// Returns true iff the current test has a fatal failure.
bool
Test
::
HasFatalFailure
()
{
return
internal
::
GetUnitTestImpl
()
->
current_test_result
()
->
HasFatalFailure
();
}
// Returns true iff the current test has a non-fatal failure.
bool
Test
::
HasNonfatalFailure
()
{
return
internal
::
GetUnitTestImpl
()
->
current_test_result
()
->
HasNonfatalFailure
();
}
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
// object.
TestInfo
::
TestInfo
(
const
std
::
string
&
a_test_case_name
,
const
std
::
string
&
a_name
,
const
char
*
a_type_param
,
const
char
*
a_value_param
,
internal
::
TypeId
fixture_class_id
,
internal
::
TestFactoryBase
*
factory
)
:
test_case_name_
(
a_test_case_name
),
name_
(
a_name
),
type_param_
(
a_type_param
?
new
std
::
string
(
a_type_param
)
:
NULL
),
value_param_
(
a_value_param
?
new
std
::
string
(
a_value_param
)
:
NULL
),
fixture_class_id_
(
fixture_class_id
),
should_run_
(
false
),
is_disabled_
(
false
),
matches_filter_
(
false
),
factory_
(
factory
),
result_
()
{}
// Destructs a TestInfo object.
TestInfo
::~
TestInfo
()
{
delete
factory_
;
}
namespace
internal
{
// Creates a new TestInfo object and registers it with Google Test;
// returns the created object.
//
// Arguments:
//
// test_case_name: name of the test case
// name: name of the test
// type_param: the name of the test's type parameter, or NULL if
// this is not a typed or a type-parameterized test.
// value_param: text representation of the test's value parameter,
// or NULL if this is not a value-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
// factory: pointer to the factory that creates a test object.
// The newly created TestInfo instance will assume
// ownership of the factory object.
TestInfo
*
MakeAndRegisterTestInfo
(
const
char
*
test_case_name
,
const
char
*
name
,
const
char
*
type_param
,
const
char
*
value_param
,
TypeId
fixture_class_id
,
SetUpTestCaseFunc
set_up_tc
,
TearDownTestCaseFunc
tear_down_tc
,
TestFactoryBase
*
factory
)
{
TestInfo
*
const
test_info
=
new
TestInfo
(
test_case_name
,
name
,
type_param
,
value_param
,
fixture_class_id
,
factory
);
GetUnitTestImpl
()
->
AddTestInfo
(
set_up_tc
,
tear_down_tc
,
test_info
);
return
test_info
;
}
#if GTEST_HAS_PARAM_TEST
void
ReportInvalidTestCaseType
(
const
char
*
test_case_name
,
const
char
*
file
,
int
line
)
{
Message
errors
;
errors
<<
"Attempted redefinition of test case "
<<
test_case_name
<<
".
\n
"
<<
"All tests in the same test case must use the same test fixture
\n
"
<<
"class. However, in test case "
<<
test_case_name
<<
", you tried
\n
"
<<
"to define a test using a fixture class different from the one
\n
"
<<
"used earlier. This can happen if the two fixture classes are
\n
"
<<
"from different namespaces and have the same name. You should
\n
"
<<
"probably rename one of the classes to put the tests into different
\n
"
<<
"test cases."
;
fprintf
(
stderr
,
"%s %s"
,
FormatFileLocation
(
file
,
line
).
c_str
(),
errors
.
GetString
().
c_str
());
}
#endif // GTEST_HAS_PARAM_TEST
}
// namespace internal
namespace
{
// A predicate that checks the test name of a TestInfo against a known
// value.
//
// This is used for implementation of the TestCase class only. We put
// it in the anonymous namespace to prevent polluting the outer
// namespace.
//
// TestNameIs is copyable.
class
TestNameIs
{
public:
// Constructor.
//
// TestNameIs has NO default constructor.
explicit
TestNameIs
(
const
char
*
name
)
:
name_
(
name
)
{}
// Returns true iff the test name of test_info matches name_.
bool
operator
()(
const
TestInfo
*
test_info
)
const
{
return
test_info
&&
test_info
->
name
()
==
name_
;
}
private:
std
::
string
name_
;
};
}
// namespace
namespace
internal
{
// This method expands all parameterized tests registered with macros TEST_P
// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
// This will be done just once during the program runtime.
void
UnitTestImpl
::
RegisterParameterizedTests
()
{
#if GTEST_HAS_PARAM_TEST
if
(
!
parameterized_tests_registered_
)
{
parameterized_test_registry_
.
RegisterTests
();
parameterized_tests_registered_
=
true
;
}
#endif
}
}
// namespace internal
// Creates the test object, runs it, records its result, and then
// deletes it.
void
TestInfo
::
Run
()
{
if
(
!
should_run_
)
return
;
// Tells UnitTest where to store test result.
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
impl
->
set_current_test_info
(
this
);
TestEventListener
*
repeater
=
UnitTest
::
GetInstance
()
->
listeners
().
repeater
();
// Notifies the unit test event listeners that a test is about to start.
repeater
->
OnTestStart
(
*
this
);
const
TimeInMillis
start
=
internal
::
GetTimeInMillis
();
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
// Creates the test object.
Test
*
const
test
=
internal
::
HandleExceptionsInMethodIfSupported
(
factory_
,
&
internal
::
TestFactoryBase
::
CreateTest
,
"the test fixture's constructor"
);
// Runs the test only if the test object was created and its
// constructor didn't generate a fatal failure.
if
((
test
!=
NULL
)
&&
!
Test
::
HasFatalFailure
())
{
// This doesn't throw as all user code that can throw are wrapped into
// exception handling code.
test
->
Run
();
}
// Deletes the test object.
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
test
,
&
Test
::
DeleteSelf_
,
"the test fixture's destructor"
);
result_
.
set_elapsed_time
(
internal
::
GetTimeInMillis
()
-
start
);
// Notifies the unit test event listener that a test has just finished.
repeater
->
OnTestEnd
(
*
this
);
// Tells UnitTest to stop associating assertion results to this
// test.
impl
->
set_current_test_info
(
NULL
);
}
// class TestCase
// Gets the number of successful tests in this test case.
int
TestCase
::
successful_test_count
()
const
{
return
CountIf
(
test_info_list_
,
TestPassed
);
}
// Gets the number of failed tests in this test case.
int
TestCase
::
failed_test_count
()
const
{
return
CountIf
(
test_info_list_
,
TestFailed
);
}
// Gets the number of disabled tests that will be reported in the XML report.
int
TestCase
::
reportable_disabled_test_count
()
const
{
return
CountIf
(
test_info_list_
,
TestReportableDisabled
);
}
// Gets the number of disabled tests in this test case.
int
TestCase
::
disabled_test_count
()
const
{
return
CountIf
(
test_info_list_
,
TestDisabled
);
}
// Gets the number of tests to be printed in the XML report.
int
TestCase
::
reportable_test_count
()
const
{
return
CountIf
(
test_info_list_
,
TestReportable
);
}
// Get the number of tests in this test case that should run.
int
TestCase
::
test_to_run_count
()
const
{
return
CountIf
(
test_info_list_
,
ShouldRunTest
);
}
// Gets the number of all tests.
int
TestCase
::
total_test_count
()
const
{
return
static_cast
<
int
>
(
test_info_list_
.
size
());
}
// Creates a TestCase with the given name.
//
// Arguments:
//
// name: name of the test case
// a_type_param: the name of the test case's type parameter, or NULL if
// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase
::
TestCase
(
const
char
*
a_name
,
const
char
*
a_type_param
,
Test
::
SetUpTestCaseFunc
set_up_tc
,
Test
::
TearDownTestCaseFunc
tear_down_tc
)
:
name_
(
a_name
),
type_param_
(
a_type_param
?
new
std
::
string
(
a_type_param
)
:
NULL
),
set_up_tc_
(
set_up_tc
),
tear_down_tc_
(
tear_down_tc
),
should_run_
(
false
),
elapsed_time_
(
0
)
{
}
// Destructor of TestCase.
TestCase
::~
TestCase
()
{
// Deletes every Test in the collection.
ForEach
(
test_info_list_
,
internal
::
Delete
<
TestInfo
>
);
}
// Returns the i-th test among all the tests. i can range from 0 to
// total_test_count() - 1. If i is not in that range, returns NULL.
const
TestInfo
*
TestCase
::
GetTestInfo
(
int
i
)
const
{
const
int
index
=
GetElementOr
(
test_indices_
,
i
,
-
1
);
return
index
<
0
?
NULL
:
test_info_list_
[
index
];
}
// Returns the i-th test among all the tests. i can range from 0 to
// total_test_count() - 1. If i is not in that range, returns NULL.
TestInfo
*
TestCase
::
GetMutableTestInfo
(
int
i
)
{
const
int
index
=
GetElementOr
(
test_indices_
,
i
,
-
1
);
return
index
<
0
?
NULL
:
test_info_list_
[
index
];
}
// Adds a test to this test case. Will delete the test upon
// destruction of the TestCase object.
void
TestCase
::
AddTestInfo
(
TestInfo
*
test_info
)
{
test_info_list_
.
push_back
(
test_info
);
test_indices_
.
push_back
(
static_cast
<
int
>
(
test_indices_
.
size
()));
}
// Runs every test in this TestCase.
void
TestCase
::
Run
()
{
if
(
!
should_run_
)
return
;
internal
::
UnitTestImpl
*
const
impl
=
internal
::
GetUnitTestImpl
();
impl
->
set_current_test_case
(
this
);
TestEventListener
*
repeater
=
UnitTest
::
GetInstance
()
->
listeners
().
repeater
();
repeater
->
OnTestCaseStart
(
*
this
);
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
this
,
&
TestCase
::
RunSetUpTestCase
,
"SetUpTestCase()"
);
const
internal
::
TimeInMillis
start
=
internal
::
GetTimeInMillis
();
for
(
int
i
=
0
;
i
<
total_test_count
();
i
++
)
{
GetMutableTestInfo
(
i
)
->
Run
();
}
elapsed_time_
=
internal
::
GetTimeInMillis
()
-
start
;
impl
->
os_stack_trace_getter
()
->
UponLeavingGTest
();
internal
::
HandleExceptionsInMethodIfSupported
(
this
,
&
TestCase
::
RunTearDownTestCase
,
"TearDownTestCase()"
);
repeater
->
OnTestCaseEnd
(
*
this
);
impl
->
set_current_test_case
(
NULL
);
}
// Clears the results of all tests in this test case.
void
TestCase
::
ClearResult
()
{
ad_hoc_test_result_
.
Clear
();
ForEach
(
test_info_list_
,
TestInfo
::
ClearTestResult
);
}
// Shuffles the tests in this test case.
void
TestCase
::
ShuffleTests
(
internal
::
Random
*
random
)
{
Shuffle
(
random
,
&
test_indices_
);
}
// Restores the test order to before the first shuffle.
void
TestCase
::
UnshuffleTests
()
{
for
(
size_t
i
=
0
;
i
<
test_indices_
.
size
();
i
++
)
{
test_indices_
[
i
]
=
static_cast
<
int
>
(
i
);
}
}
// Formats a countable noun. Depending on its quantity, either the
// singular form or the plural form is used. e.g.
//
// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
// FormatCountableNoun(5, "book", "books") returns "5 books".
static
std
::
string
FormatCountableNoun
(
int
count
,
const
char
*
singular_form
,
const
char
*
plural_form
)
{
return
internal
::
StreamableToString
(
count
)
+
" "
+
(
count
==
1
?
singular_form
:
plural_form
);
}
// Formats the count of tests.
static
std
::
string
FormatTestCount
(
int
test_count
)
{
return
FormatCountableNoun
(
test_count
,
"test"
,
"tests"
);
}
// Formats the count of test cases.
static
std
::
string
FormatTestCaseCount
(
int
test_case_count
)
{
return
FormatCountableNoun
(
test_case_count
,
"test case"
,
"test cases"
);
}
// Converts a TestPartResult::Type enum to human-friendly string
// representation. Both kNonFatalFailure and kFatalFailure are translated
// to "Failure", as the user usually doesn't care about the difference
// between the two when viewing the test result.
static
const
char
*
TestPartResultTypeToString
(
TestPartResult
::
Type
type
)
{
switch
(
type
)
{
case
TestPartResult
::
kSuccess
:
return
"Success"
;
case
TestPartResult
::
kNonFatalFailure
:
case
TestPartResult
::
kFatalFailure
:
#ifdef _MSC_VER
return
"error: "
;
#else
return
"Failure
\n
"
;
#endif
default:
return
"Unknown result type"
;
}
}
namespace
internal
{
// Prints a TestPartResult to an std::string.
static
std
::
string
PrintTestPartResultToString
(
const
TestPartResult
&
test_part_result
)
{
return
(
Message
()
<<
internal
::
FormatFileLocation
(
test_part_result
.
file_name
(),
test_part_result
.
line_number
())
<<
" "
<<
TestPartResultTypeToString
(
test_part_result
.
type
())
<<
test_part_result
.
message
()).
GetString
();
}
// Prints a TestPartResult.
static
void
PrintTestPartResult
(
const
TestPartResult
&
test_part_result
)
{
const
std
::
string
&
result
=
PrintTestPartResultToString
(
test_part_result
);
printf
(
"%s
\n
"
,
result
.
c_str
());
fflush
(
stdout
);
// If the test program runs in Visual Studio or a debugger, the
// following statements add the test part result message to the Output
// window such that the user can double-click on it to jump to the
// corresponding source code location; otherwise they do nothing.
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
// We don't call OutputDebugString*() on Windows Mobile, as printing
// to stdout is done by OutputDebugString() there already - we don't
// want the same message printed twice.
::
OutputDebugStringA
(
result
.
c_str
());
::
OutputDebugStringA
(
"
\n
"
);
#endif
}
// class PrettyUnitTestResultPrinter
enum
GTestColor
{
COLOR_DEFAULT
,
COLOR_RED
,
COLOR_GREEN
,
COLOR_YELLOW
};
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
// Returns the character attribute for the given color.
WORD
GetColorAttribute
(
GTestColor
color
)
{
switch
(
color
)
{
case
COLOR_RED
:
return
FOREGROUND_RED
;
case
COLOR_GREEN
:
return
FOREGROUND_GREEN
;
case
COLOR_YELLOW
:
return
FOREGROUND_RED
|
FOREGROUND_GREEN
;
default:
return
0
;
}
}
#else
// Returns the ANSI color code for the given color. COLOR_DEFAULT is
// an invalid input.
const
char
*
GetAnsiColorCode
(
GTestColor
color
)
{
switch
(
color
)
{
case
COLOR_RED
:
return
"1"
;
case
COLOR_GREEN
:
return
"2"
;
case
COLOR_YELLOW
:
return
"3"
;
default:
return
NULL
;
};
}
#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
// Returns true iff Google Test should use colors in the output.
bool
ShouldUseColor
(
bool
stdout_is_tty
)
{
const
char
*
const
gtest_color
=
GTEST_FLAG
(
color
).
c_str
();
if
(
String
::
CaseInsensitiveCStringEquals
(
gtest_color
,
"auto"
))
{
#if GTEST_OS_WINDOWS
// On Windows the TERM variable is usually not set, but the
// console there does support colors.
return
stdout_is_tty
;
#else
// On non-Windows platforms, we rely on the TERM variable.
const
char
*
const
term
=
posix
::
GetEnv
(
"TERM"
);
const
bool
term_supports_color
=
String
::
CStringEquals
(
term
,
"xterm"
)
||
String
::
CStringEquals
(
term
,
"xterm-color"
)
||
String
::
CStringEquals
(
term
,
"xterm-256color"
)
||
String
::
CStringEquals
(
term
,
"screen"
)
||
String
::
CStringEquals
(
term
,
"screen-256color"
)
||
String
::
CStringEquals
(
term
,
"linux"
)
||
String
::
CStringEquals
(
term
,
"cygwin"
);
return
stdout_is_tty
&&
term_supports_color
;
#endif // GTEST_OS_WINDOWS
}
return
String
::
CaseInsensitiveCStringEquals
(
gtest_color
,
"yes"
)
||
String
::
CaseInsensitiveCStringEquals
(
gtest_color
,
"true"
)
||
String
::
CaseInsensitiveCStringEquals
(
gtest_color
,
"t"
)
||
String
::
CStringEquals
(
gtest_color
,
"1"
);
// We take "yes", "true", "t", and "1" as meaning "yes". If the
// value is neither one of these nor "auto", we treat it as "no" to
// be conservative.
}
// Helpers for printing colored strings to stdout. Note that on Windows, we
// cannot simply emit special characters and have the terminal change colors.
// This routine must actually emit the characters rather than return a string
// that would be colored when printed, as can be done on Linux.
void
ColoredPrintf
(
GTestColor
color
,
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS
const
bool
use_color
=
false
;
#else
static
const
bool
in_color_mode
=
ShouldUseColor
(
posix
::
IsATTY
(
posix
::
FileNo
(
stdout
))
!=
0
);
const
bool
use_color
=
in_color_mode
&&
(
color
!=
COLOR_DEFAULT
);
#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
// The '!= 0' comparison is necessary to satisfy MSVC 7.1.
if
(
!
use_color
)
{
vprintf
(
fmt
,
args
);
va_end
(
args
);
return
;
}
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
const
HANDLE
stdout_handle
=
GetStdHandle
(
STD_OUTPUT_HANDLE
);
// Gets the current text color.
CONSOLE_SCREEN_BUFFER_INFO
buffer_info
;
GetConsoleScreenBufferInfo
(
stdout_handle
,
&
buffer_info
);
const
WORD
old_color_attrs
=
buffer_info
.
wAttributes
;
// We need to flush the stream buffers into the console before each
// SetConsoleTextAttribute call lest it affect the text that is already
// printed but has not yet reached the console.
fflush
(
stdout
);
SetConsoleTextAttribute
(
stdout_handle
,
GetColorAttribute
(
color
)
|
FOREGROUND_INTENSITY
);
vprintf
(
fmt
,
args
);
fflush
(
stdout
);
// Restores the text color.
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
#else
printf
(
"
\033
[0;3%sm"
,
GetAnsiColorCode
(
color
));
vprintf
(
fmt
,
args
);
printf
(
"
\033
[m"
);
// Resets the terminal to default.
#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
va_end
(
args
);
}
// Text printed in Google Test's text output and --gunit_list_tests
// output to label the type parameter and value parameter for a test.
static
const
char
kTypeParamLabel
[]
=
"TypeParam"
;
static
const
char
kValueParamLabel
[]
=
"GetParam()"
;
void
PrintFullTestCommentIfPresent
(
const
TestInfo
&
test_info
)
{
const
char
*
const
type_param
=
test_info
.
type_param
();
const
char
*
const
value_param
=
test_info
.
value_param
();
if
(
type_param
!=
NULL
||
value_param
!=
NULL
)
{
printf
(
", where "
);
if
(
type_param
!=
NULL
)
{
printf
(
"%s = %s"
,
kTypeParamLabel
,
type_param
);
if
(
value_param
!=
NULL
)
printf
(
" and "
);
}
if
(
value_param
!=
NULL
)
{
printf
(
"%s = %s"
,
kValueParamLabel
,
value_param
);
}
}
}
// This class implements the TestEventListener interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
class
PrettyUnitTestResultPrinter
:
public
TestEventListener
{
public:
PrettyUnitTestResultPrinter
()
{}
static
void
PrintTestName
(
const
char
*
test_case
,
const
char
*
test
)
{
printf
(
"%s.%s"
,
test_case
,
test
);
}
// The following methods override what's in the TestEventListener class.
virtual
void
OnTestProgramStart
(
const
UnitTest
&
/*unit_test*/
)
{}
virtual
void
OnTestIterationStart
(
const
UnitTest
&
unit_test
,
int
iteration
);
virtual
void
OnEnvironmentsSetUpStart
(
const
UnitTest
&
unit_test
);
virtual
void
OnEnvironmentsSetUpEnd
(
const
UnitTest
&
/*unit_test*/
)
{}
virtual
void
OnTestCaseStart
(
const
TestCase
&
test_case
);
virtual
void
OnTestStart
(
const
TestInfo
&
test_info
);
virtual
void
OnTestPartResult
(
const
TestPartResult
&
result
);
virtual
void
OnTestEnd
(
const
TestInfo
&
test_info
);
virtual
void
OnTestCaseEnd
(
const
TestCase
&
test_case
);
virtual
void
OnEnvironmentsTearDownStart
(
const
UnitTest
&
unit_test
);
virtual
void
OnEnvironmentsTearDownEnd
(
const
UnitTest
&
/*unit_test*/
)
{}
virtual
void
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
iteration
);
virtual
void
OnTestProgramEnd
(
const
UnitTest
&
/*unit_test*/
)
{}
private:
static
void
PrintFailedTests
(
const
UnitTest
&
unit_test
);
};
// Fired before each iteration of tests starts.
void
PrettyUnitTestResultPrinter
::
OnTestIterationStart
(
const
UnitTest
&
unit_test
,
int
iteration
)
{
if
(
GTEST_FLAG
(
repeat
)
!=
1
)
printf
(
"
\n
Repeating all tests (iteration %d) . . .
\n\n
"
,
iteration
+
1
);
const
char
*
const
filter
=
GTEST_FLAG
(
filter
).
c_str
();
// Prints the filter if it's not *. This reminds the user that some
// tests may be skipped.
if
(
!
String
::
CStringEquals
(
filter
,
kUniversalFilter
))
{
ColoredPrintf
(
COLOR_YELLOW
,
"Note: %s filter = %s
\n
"
,
GTEST_NAME_
,
filter
);
}
if
(
internal
::
ShouldShard
(
kTestTotalShards
,
kTestShardIndex
,
false
))
{
const
Int32
shard_index
=
Int32FromEnvOrDie
(
kTestShardIndex
,
-
1
);
ColoredPrintf
(
COLOR_YELLOW
,
"Note: This is test shard %d of %s.
\n
"
,
static_cast
<
int
>
(
shard_index
)
+
1
,
internal
::
posix
::
GetEnv
(
kTestTotalShards
));
}
if
(
GTEST_FLAG
(
shuffle
))
{
ColoredPrintf
(
COLOR_YELLOW
,
"Note: Randomizing tests' orders with a seed of %d .
\n
"
,
unit_test
.
random_seed
());
}
ColoredPrintf
(
COLOR_GREEN
,
"[==========] "
);
printf
(
"Running %s from %s.
\n
"
,
FormatTestCount
(
unit_test
.
test_to_run_count
()).
c_str
(),
FormatTestCaseCount
(
unit_test
.
test_case_to_run_count
()).
c_str
());
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnEnvironmentsSetUpStart
(
const
UnitTest
&
/*unit_test*/
)
{
ColoredPrintf
(
COLOR_GREEN
,
"[----------] "
);
printf
(
"Global test environment set-up.
\n
"
);
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnTestCaseStart
(
const
TestCase
&
test_case
)
{
const
std
::
string
counts
=
FormatCountableNoun
(
test_case
.
test_to_run_count
(),
"test"
,
"tests"
);
ColoredPrintf
(
COLOR_GREEN
,
"[----------] "
);
printf
(
"%s from %s"
,
counts
.
c_str
(),
test_case
.
name
());
if
(
test_case
.
type_param
()
==
NULL
)
{
printf
(
"
\n
"
);
}
else
{
printf
(
", where %s = %s
\n
"
,
kTypeParamLabel
,
test_case
.
type_param
());
}
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnTestStart
(
const
TestInfo
&
test_info
)
{
ColoredPrintf
(
COLOR_GREEN
,
"[ RUN ] "
);
PrintTestName
(
test_info
.
test_case_name
(),
test_info
.
name
());
printf
(
"
\n
"
);
fflush
(
stdout
);
}
// Called after an assertion failure.
void
PrettyUnitTestResultPrinter
::
OnTestPartResult
(
const
TestPartResult
&
result
)
{
// If the test part succeeded, we don't need to do anything.
if
(
result
.
type
()
==
TestPartResult
::
kSuccess
)
return
;
// Print failure message from the assertion (e.g. expected this and got that).
PrintTestPartResult
(
result
);
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnTestEnd
(
const
TestInfo
&
test_info
)
{
if
(
test_info
.
result
()
->
Passed
())
{
ColoredPrintf
(
COLOR_GREEN
,
"[ OK ] "
);
}
else
{
ColoredPrintf
(
COLOR_RED
,
"[ FAILED ] "
);
}
PrintTestName
(
test_info
.
test_case_name
(),
test_info
.
name
());
if
(
test_info
.
result
()
->
Failed
())
PrintFullTestCommentIfPresent
(
test_info
);
if
(
GTEST_FLAG
(
print_time
))
{
printf
(
" (%s ms)
\n
"
,
internal
::
StreamableToString
(
test_info
.
result
()
->
elapsed_time
()).
c_str
());
}
else
{
printf
(
"
\n
"
);
}
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnTestCaseEnd
(
const
TestCase
&
test_case
)
{
if
(
!
GTEST_FLAG
(
print_time
))
return
;
const
std
::
string
counts
=
FormatCountableNoun
(
test_case
.
test_to_run_count
(),
"test"
,
"tests"
);
ColoredPrintf
(
COLOR_GREEN
,
"[----------] "
);
printf
(
"%s from %s (%s ms total)
\n\n
"
,
counts
.
c_str
(),
test_case
.
name
(),
internal
::
StreamableToString
(
test_case
.
elapsed_time
()).
c_str
());
fflush
(
stdout
);
}
void
PrettyUnitTestResultPrinter
::
OnEnvironmentsTearDownStart
(
const
UnitTest
&
/*unit_test*/
)
{
ColoredPrintf
(
COLOR_GREEN
,
"[----------] "
);
printf
(
"Global test environment tear-down
\n
"
);
fflush
(
stdout
);
}
// Internal helper for printing the list of failed tests.
void
PrettyUnitTestResultPrinter
::
PrintFailedTests
(
const
UnitTest
&
unit_test
)
{
const
int
failed_test_count
=
unit_test
.
failed_test_count
();
if
(
failed_test_count
==
0
)
{
return
;
}
for
(
int
i
=
0
;
i
<
unit_test
.
total_test_case_count
();
++
i
)
{
const
TestCase
&
test_case
=
*
unit_test
.
GetTestCase
(
i
);
if
(
!
test_case
.
should_run
()
||
(
test_case
.
failed_test_count
()
==
0
))
{
continue
;
}
for
(
int
j
=
0
;
j
<
test_case
.
total_test_count
();
++
j
)
{
const
TestInfo
&
test_info
=
*
test_case
.
GetTestInfo
(
j
);
if
(
!
test_info
.
should_run
()
||
test_info
.
result
()
->
Passed
())
{
continue
;
}
ColoredPrintf
(
COLOR_RED
,
"[ FAILED ] "
);
printf
(
"%s.%s"
,
test_case
.
name
(),
test_info
.
name
());
PrintFullTestCommentIfPresent
(
test_info
);
printf
(
"
\n
"
);
}
}
}
void
PrettyUnitTestResultPrinter
::
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
/*iteration*/
)
{
ColoredPrintf
(
COLOR_GREEN
,
"[==========] "
);
printf
(
"%s from %s ran."
,
FormatTestCount
(
unit_test
.
test_to_run_count
()).
c_str
(),
FormatTestCaseCount
(
unit_test
.
test_case_to_run_count
()).
c_str
());
if
(
GTEST_FLAG
(
print_time
))
{
printf
(
" (%s ms total)"
,
internal
::
StreamableToString
(
unit_test
.
elapsed_time
()).
c_str
());
}
printf
(
"
\n
"
);
ColoredPrintf
(
COLOR_GREEN
,
"[ PASSED ] "
);
printf
(
"%s.
\n
"
,
FormatTestCount
(
unit_test
.
successful_test_count
()).
c_str
());
int
num_failures
=
unit_test
.
failed_test_count
();
if
(
!
unit_test
.
Passed
())
{
const
int
failed_test_count
=
unit_test
.
failed_test_count
();
ColoredPrintf
(
COLOR_RED
,
"[ FAILED ] "
);
printf
(
"%s, listed below:
\n
"
,
FormatTestCount
(
failed_test_count
).
c_str
());
PrintFailedTests
(
unit_test
);
printf
(
"
\n
%2d FAILED %s
\n
"
,
num_failures
,
num_failures
==
1
?
"TEST"
:
"TESTS"
);
}
int
num_disabled
=
unit_test
.
reportable_disabled_test_count
();
if
(
num_disabled
&&
!
GTEST_FLAG
(
also_run_disabled_tests
))
{
if
(
!
num_failures
)
{
printf
(
"
\n
"
);
// Add a spacer if no FAILURE banner is displayed.
}
ColoredPrintf
(
COLOR_YELLOW
,
" YOU HAVE %d DISABLED %s
\n\n
"
,
num_disabled
,
num_disabled
==
1
?
"TEST"
:
"TESTS"
);
}
// Ensure that Google Test output is printed before, e.g., heapchecker output.
fflush
(
stdout
);
}
// End PrettyUnitTestResultPrinter
// class TestEventRepeater
//
// This class forwards events to other event listeners.
class
TestEventRepeater
:
public
TestEventListener
{
public:
TestEventRepeater
()
:
forwarding_enabled_
(
true
)
{}
virtual
~
TestEventRepeater
();
void
Append
(
TestEventListener
*
listener
);
TestEventListener
*
Release
(
TestEventListener
*
listener
);
// Controls whether events will be forwarded to listeners_. Set to false
// in death test child processes.
bool
forwarding_enabled
()
const
{
return
forwarding_enabled_
;
}
void
set_forwarding_enabled
(
bool
enable
)
{
forwarding_enabled_
=
enable
;
}
virtual
void
OnTestProgramStart
(
const
UnitTest
&
unit_test
);
virtual
void
OnTestIterationStart
(
const
UnitTest
&
unit_test
,
int
iteration
);
virtual
void
OnEnvironmentsSetUpStart
(
const
UnitTest
&
unit_test
);
virtual
void
OnEnvironmentsSetUpEnd
(
const
UnitTest
&
unit_test
);
virtual
void
OnTestCaseStart
(
const
TestCase
&
test_case
);
virtual
void
OnTestStart
(
const
TestInfo
&
test_info
);
virtual
void
OnTestPartResult
(
const
TestPartResult
&
result
);
virtual
void
OnTestEnd
(
const
TestInfo
&
test_info
);
virtual
void
OnTestCaseEnd
(
const
TestCase
&
test_case
);
virtual
void
OnEnvironmentsTearDownStart
(
const
UnitTest
&
unit_test
);
virtual
void
OnEnvironmentsTearDownEnd
(
const
UnitTest
&
unit_test
);
virtual
void
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
iteration
);
virtual
void
OnTestProgramEnd
(
const
UnitTest
&
unit_test
);
private:
// Controls whether events will be forwarded to listeners_. Set to false
// in death test child processes.
bool
forwarding_enabled_
;
// The list of listeners that receive events.
std
::
vector
<
TestEventListener
*>
listeners_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
TestEventRepeater
);
};
TestEventRepeater
::~
TestEventRepeater
()
{
ForEach
(
listeners_
,
Delete
<
TestEventListener
>
);
}
void
TestEventRepeater
::
Append
(
TestEventListener
*
listener
)
{
listeners_
.
push_back
(
listener
);
}
// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
TestEventListener
*
TestEventRepeater
::
Release
(
TestEventListener
*
listener
)
{
for
(
size_t
i
=
0
;
i
<
listeners_
.
size
();
++
i
)
{
if
(
listeners_
[
i
]
==
listener
)
{
listeners_
.
erase
(
listeners_
.
begin
()
+
i
);
return
listener
;
}
}
return
NULL
;
}
// Since most methods are very similar, use macros to reduce boilerplate.
// This defines a member that forwards the call to all listeners.
#define GTEST_REPEATER_METHOD_(Name, Type) \
void TestEventRepeater::Name(const Type& parameter) { \
if (forwarding_enabled_) { \
for (size_t i = 0; i < listeners_.size(); i++) { \
listeners_[i]->Name(parameter); \
} \
} \
}
// This defines a member that forwards the call to all listeners in reverse
// order.
#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
void TestEventRepeater::Name(const Type& parameter) { \
if (forwarding_enabled_) { \
for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
listeners_[i]->Name(parameter); \
} \
} \
}
GTEST_REPEATER_METHOD_
(
OnTestProgramStart
,
UnitTest
)
GTEST_REPEATER_METHOD_
(
OnEnvironmentsSetUpStart
,
UnitTest
)
GTEST_REPEATER_METHOD_
(
OnTestCaseStart
,
TestCase
)
GTEST_REPEATER_METHOD_
(
OnTestStart
,
TestInfo
)
GTEST_REPEATER_METHOD_
(
OnTestPartResult
,
TestPartResult
)
GTEST_REPEATER_METHOD_
(
OnEnvironmentsTearDownStart
,
UnitTest
)
GTEST_REVERSE_REPEATER_METHOD_
(
OnEnvironmentsSetUpEnd
,
UnitTest
)
GTEST_REVERSE_REPEATER_METHOD_
(
OnEnvironmentsTearDownEnd
,
UnitTest
)
GTEST_REVERSE_REPEATER_METHOD_
(
OnTestEnd
,
TestInfo
)
GTEST_REVERSE_REPEATER_METHOD_
(
OnTestCaseEnd
,
TestCase
)
GTEST_REVERSE_REPEATER_METHOD_
(
OnTestProgramEnd
,
UnitTest
)
#undef GTEST_REPEATER_METHOD_
#undef GTEST_REVERSE_REPEATER_METHOD_
void
TestEventRepeater
::
OnTestIterationStart
(
const
UnitTest
&
unit_test
,
int
iteration
)
{
if
(
forwarding_enabled_
)
{
for
(
size_t
i
=
0
;
i
<
listeners_
.
size
();
i
++
)
{
listeners_
[
i
]
->
OnTestIterationStart
(
unit_test
,
iteration
);
}
}
}
void
TestEventRepeater
::
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
iteration
)
{
if
(
forwarding_enabled_
)
{
for
(
int
i
=
static_cast
<
int
>
(
listeners_
.
size
())
-
1
;
i
>=
0
;
i
--
)
{
listeners_
[
i
]
->
OnTestIterationEnd
(
unit_test
,
iteration
);
}
}
}
// End TestEventRepeater
// This class generates an XML output file.
class
XmlUnitTestResultPrinter
:
public
EmptyTestEventListener
{
public:
explicit
XmlUnitTestResultPrinter
(
const
char
*
output_file
);
virtual
void
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
iteration
);
private:
// Is c a whitespace character that is normalized to a space character
// when it appears in an XML attribute value?
static
bool
IsNormalizableWhitespace
(
char
c
)
{
return
c
==
0x9
||
c
==
0xA
||
c
==
0xD
;
}
// May c appear in a well-formed XML document?
static
bool
IsValidXmlCharacter
(
char
c
)
{
return
IsNormalizableWhitespace
(
c
)
||
c
>=
0x20
;
}
// Returns an XML-escaped copy of the input string str. If
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// with character references.
static
std
::
string
EscapeXml
(
const
std
::
string
&
str
,
bool
is_attribute
);
// Returns the given string with all characters invalid in XML removed.
static
std
::
string
RemoveInvalidXmlCharacters
(
const
std
::
string
&
str
);
// Convenience wrapper around EscapeXml when str is an attribute value.
static
std
::
string
EscapeXmlAttribute
(
const
std
::
string
&
str
)
{
return
EscapeXml
(
str
,
true
);
}
// Convenience wrapper around EscapeXml when str is not an attribute value.
static
std
::
string
EscapeXmlText
(
const
char
*
str
)
{
return
EscapeXml
(
str
,
false
);
}
// Verifies that the given attribute belongs to the given element and
// streams the attribute as XML.
static
void
OutputXmlAttribute
(
std
::
ostream
*
stream
,
const
std
::
string
&
element_name
,
const
std
::
string
&
name
,
const
std
::
string
&
value
);
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
static
void
OutputXmlCDataSection
(
::
std
::
ostream
*
stream
,
const
char
*
data
);
// Streams an XML representation of a TestInfo object.
static
void
OutputXmlTestInfo
(
::
std
::
ostream
*
stream
,
const
char
*
test_case_name
,
const
TestInfo
&
test_info
);
// Prints an XML representation of a TestCase object
static
void
PrintXmlTestCase
(
::
std
::
ostream
*
stream
,
const
TestCase
&
test_case
);
// Prints an XML summary of unit_test to output stream out.
static
void
PrintXmlUnitTest
(
::
std
::
ostream
*
stream
,
const
UnitTest
&
unit_test
);
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
// When the std::string is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static
std
::
string
TestPropertiesAsXmlAttributes
(
const
TestResult
&
result
);
// The output file.
const
std
::
string
output_file_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
XmlUnitTestResultPrinter
);
};
// Creates a new XmlUnitTestResultPrinter.
XmlUnitTestResultPrinter
::
XmlUnitTestResultPrinter
(
const
char
*
output_file
)
:
output_file_
(
output_file
)
{
if
(
output_file_
.
c_str
()
==
NULL
||
output_file_
.
empty
())
{
fprintf
(
stderr
,
"XML output file may not be null
\n
"
);
fflush
(
stderr
);
exit
(
EXIT_FAILURE
);
}
}
// Called after the unit test ends.
void
XmlUnitTestResultPrinter
::
OnTestIterationEnd
(
const
UnitTest
&
unit_test
,
int
/*iteration*/
)
{
FILE
*
xmlout
=
NULL
;
FilePath
output_file
(
output_file_
);
FilePath
output_dir
(
output_file
.
RemoveFileName
());
if
(
output_dir
.
CreateDirectoriesRecursively
())
{
xmlout
=
posix
::
FOpen
(
output_file_
.
c_str
(),
"w"
);
}
if
(
xmlout
==
NULL
)
{
// TODO(wan): report the reason of the failure.
//
// We don't do it for now as:
//
// 1. There is no urgent need for it.
// 2. It's a bit involved to make the errno variable thread-safe on
// all three operating systems (Linux, Windows, and Mac OS).
// 3. To interpret the meaning of errno in a thread-safe way,
// we need the strerror_r() function, which is not available on
// Windows.
fprintf
(
stderr
,
"Unable to open file
\"
%s
\"\n
"
,
output_file_
.
c_str
());
fflush
(
stderr
);
exit
(
EXIT_FAILURE
);
}
std
::
stringstream
stream
;
PrintXmlUnitTest
(
&
stream
,
unit_test
);
fprintf
(
xmlout
,
"%s"
,
StringStreamToString
(
&
stream
).
c_str
());
fclose
(
xmlout
);
}
// Returns an XML-escaped copy of the input string str. If is_attribute
// is true, the text is meant to appear as an attribute value, and
// normalizable whitespace is preserved by replacing it with character
// references.
//
// Invalid XML characters in str, if any, are stripped from the output.
// It is expected that most, if not all, of the text processed by this
// module will consist of ordinary English text.
// If this module is ever modified to produce version 1.1 XML output,
// most invalid characters can be retained using character references.
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
std
::
string
XmlUnitTestResultPrinter
::
EscapeXml
(
const
std
::
string
&
str
,
bool
is_attribute
)
{
Message
m
;
for
(
size_t
i
=
0
;
i
<
str
.
size
();
++
i
)
{
const
char
ch
=
str
[
i
];
switch
(
ch
)
{
case
'<'
:
m
<<
"<"
;
break
;
case
'>'
:
m
<<
">"
;
break
;
case
'&'
:
m
<<
"&"
;
break
;
case
'\''
:
if
(
is_attribute
)
m
<<
"'"
;
else
m
<<
'\''
;
break
;
case
'"'
:
if
(
is_attribute
)
m
<<
"""
;
else
m
<<
'"'
;
break
;
default:
if
(
IsValidXmlCharacter
(
ch
))
{
if
(
is_attribute
&&
IsNormalizableWhitespace
(
ch
))
m
<<
"&#x"
<<
String
::
FormatByte
(
static_cast
<
unsigned
char
>
(
ch
))
<<
";"
;
else
m
<<
ch
;
}
break
;
}
}
return
m
.
GetString
();
}
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
std
::
string
XmlUnitTestResultPrinter
::
RemoveInvalidXmlCharacters
(
const
std
::
string
&
str
)
{
std
::
string
output
;
output
.
reserve
(
str
.
size
());
for
(
std
::
string
::
const_iterator
it
=
str
.
begin
();
it
!=
str
.
end
();
++
it
)
if
(
IsValidXmlCharacter
(
*
it
))
output
.
push_back
(
*
it
);
return
output
;
}
// The following routines generate an XML representation of a UnitTest
// object.
//
// This is how Google Test concepts map to the DTD:
//
// <testsuites name="AllTests"> <-- corresponds to a UnitTest object
// <testsuite name="testcase-name"> <-- corresponds to a TestCase object
// <testcase name="test-name"> <-- corresponds to a TestInfo object
// <failure message="...">...</failure>
// <failure message="...">...</failure>
// <failure message="...">...</failure>
// <-- individual assertion failures
// </testcase>
// </testsuite>
// </testsuites>
// Formats the given time in milliseconds as seconds.
std
::
string
FormatTimeInMillisAsSeconds
(
TimeInMillis
ms
)
{
::
std
::
stringstream
ss
;
ss
<<
ms
/
1000.0
;
return
ss
.
str
();
}
// Converts the given epoch time in milliseconds to a date string in the ISO
// 8601 format, without the timezone information.
std
::
string
FormatEpochTimeInMillisAsIso8601
(
TimeInMillis
ms
)
{
// Using non-reentrant version as localtime_r is not portable.
time_t
seconds
=
static_cast
<
time_t
>
(
ms
/
1000
);
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4996) // Temporarily disables warning 4996
// (function or variable may be unsafe).
const
struct
tm
*
const
time_struct
=
localtime
(
&
seconds
);
// NOLINT
# pragma warning(pop) // Restores the warning state again.
#else
const
struct
tm
*
const
time_struct
=
localtime
(
&
seconds
);
// NOLINT
#endif
if
(
time_struct
==
NULL
)
return
""
;
// Invalid ms value
// YYYY-MM-DDThh:mm:ss
return
StreamableToString
(
time_struct
->
tm_year
+
1900
)
+
"-"
+
String
::
FormatIntWidth2
(
time_struct
->
tm_mon
+
1
)
+
"-"
+
String
::
FormatIntWidth2
(
time_struct
->
tm_mday
)
+
"T"
+
String
::
FormatIntWidth2
(
time_struct
->
tm_hour
)
+
":"
+
String
::
FormatIntWidth2
(
time_struct
->
tm_min
)
+
":"
+
String
::
FormatIntWidth2
(
time_struct
->
tm_sec
);
}
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
void
XmlUnitTestResultPrinter
::
OutputXmlCDataSection
(
::
std
::
ostream
*
stream
,
const
char
*
data
)
{
const
char
*
segment
=
data
;
*
stream
<<
"<![CDATA["
;
for
(;;)
{
const
char
*
const
next_segment
=
strstr
(
segment
,
"]]>"
);
if
(
next_segment
!=
NULL
)
{
stream
->
write
(
segment
,
static_cast
<
std
::
streamsize
>
(
next_segment
-
segment
));
*
stream
<<
"]]>]]><![CDATA["
;
segment
=
next_segment
+
strlen
(
"]]>"
);
}
else
{
*
stream
<<
segment
;
break
;
}
}
*
stream
<<
"]]>"
;
}
void
XmlUnitTestResultPrinter
::
OutputXmlAttribute
(
std
::
ostream
*
stream
,
const
std
::
string
&
element_name
,
const
std
::
string
&
name
,
const
std
::
string
&
value
)
{
const
std
::
vector
<
std
::
string
>&
allowed_names
=
GetReservedAttributesForElement
(
element_name
);
GTEST_CHECK_
(
std
::
find
(
allowed_names
.
begin
(),
allowed_names
.
end
(),
name
)
!=
allowed_names
.
end
())
<<
"Attribute "
<<
name
<<
" is not allowed for element <"
<<
element_name
<<
">."
;
*
stream
<<
" "
<<
name
<<
"=
\"
"
<<
EscapeXmlAttribute
(
value
)
<<
"
\"
"
;
}
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
void
XmlUnitTestResultPrinter
::
OutputXmlTestInfo
(
::
std
::
ostream
*
stream
,
const
char
*
test_case_name
,
const
TestInfo
&
test_info
)
{
const
TestResult
&
result
=
*
test_info
.
result
();
const
std
::
string
kTestcase
=
"testcase"
;
*
stream
<<
" <testcase"
;
OutputXmlAttribute
(
stream
,
kTestcase
,
"name"
,
test_info
.
name
());
if
(
test_info
.
value_param
()
!=
NULL
)
{
OutputXmlAttribute
(
stream
,
kTestcase
,
"value_param"
,
test_info
.
value_param
());
}
if
(
test_info
.
type_param
()
!=
NULL
)
{
OutputXmlAttribute
(
stream
,
kTestcase
,
"type_param"
,
test_info
.
type_param
());
}
OutputXmlAttribute
(
stream
,
kTestcase
,
"status"
,
test_info
.
should_run
()
?
"run"
:
"notrun"
);
OutputXmlAttribute
(
stream
,
kTestcase
,
"time"
,
FormatTimeInMillisAsSeconds
(
result
.
elapsed_time
()));
OutputXmlAttribute
(
stream
,
kTestcase
,
"classname"
,
test_case_name
);
*
stream
<<
TestPropertiesAsXmlAttributes
(
result
);
int
failures
=
0
;
for
(
int
i
=
0
;
i
<
result
.
total_part_count
();
++
i
)
{
const
TestPartResult
&
part
=
result
.
GetTestPartResult
(
i
);
if
(
part
.
failed
())
{
if
(
++
failures
==
1
)
{
*
stream
<<
">
\n
"
;
}
const
string
location
=
internal
::
FormatCompilerIndependentFileLocation
(
part
.
file_name
(),
part
.
line_number
());
const
string
summary
=
location
+
"
\n
"
+
part
.
summary
();
*
stream
<<
" <failure message=
\"
"
<<
EscapeXmlAttribute
(
summary
.
c_str
())
<<
"
\"
type=
\"\"
>"
;
const
string
detail
=
location
+
"
\n
"
+
part
.
message
();
OutputXmlCDataSection
(
stream
,
RemoveInvalidXmlCharacters
(
detail
).
c_str
());
*
stream
<<
"</failure>
\n
"
;
}
}
if
(
failures
==
0
)
*
stream
<<
" />
\n
"
;
else
*
stream
<<
" </testcase>
\n
"
;
}
// Prints an XML representation of a TestCase object
void
XmlUnitTestResultPrinter
::
PrintXmlTestCase
(
std
::
ostream
*
stream
,
const
TestCase
&
test_case
)
{
const
std
::
string
kTestsuite
=
"testsuite"
;
*
stream
<<
" <"
<<
kTestsuite
;
OutputXmlAttribute
(
stream
,
kTestsuite
,
"name"
,
test_case
.
name
());
OutputXmlAttribute
(
stream
,
kTestsuite
,
"tests"
,
StreamableToString
(
test_case
.
reportable_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuite
,
"failures"
,
StreamableToString
(
test_case
.
failed_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuite
,
"disabled"
,
StreamableToString
(
test_case
.
reportable_disabled_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuite
,
"errors"
,
"0"
);
OutputXmlAttribute
(
stream
,
kTestsuite
,
"time"
,
FormatTimeInMillisAsSeconds
(
test_case
.
elapsed_time
()));
*
stream
<<
TestPropertiesAsXmlAttributes
(
test_case
.
ad_hoc_test_result
())
<<
">
\n
"
;
for
(
int
i
=
0
;
i
<
test_case
.
total_test_count
();
++
i
)
{
if
(
test_case
.
GetTestInfo
(
i
)
->
is_reportable
())
OutputXmlTestInfo
(
stream
,
test_case
.
name
(),
*
test_case
.
GetTestInfo
(
i
));
}
*
stream
<<
" </"
<<
kTestsuite
<<
">
\n
"
;
}
// Prints an XML summary of unit_test to output stream out.
void
XmlUnitTestResultPrinter
::
PrintXmlUnitTest
(
std
::
ostream
*
stream
,
const
UnitTest
&
unit_test
)
{
const
std
::
string
kTestsuites
=
"testsuites"
;
*
stream
<<
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?>
\n
"
;
*
stream
<<
"<"
<<
kTestsuites
;
OutputXmlAttribute
(
stream
,
kTestsuites
,
"tests"
,
StreamableToString
(
unit_test
.
reportable_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuites
,
"failures"
,
StreamableToString
(
unit_test
.
failed_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuites
,
"disabled"
,
StreamableToString
(
unit_test
.
reportable_disabled_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuites
,
"errors"
,
"0"
);
OutputXmlAttribute
(
stream
,
kTestsuites
,
"timestamp"
,
FormatEpochTimeInMillisAsIso8601
(
unit_test
.
start_timestamp
()));
OutputXmlAttribute
(
stream
,
kTestsuites
,
"time"
,
FormatTimeInMillisAsSeconds
(
unit_test
.
elapsed_time
()));
if
(
GTEST_FLAG
(
shuffle
))
{
OutputXmlAttribute
(
stream
,
kTestsuites
,
"random_seed"
,
StreamableToString
(
unit_test
.
random_seed
()));
}
*
stream
<<
TestPropertiesAsXmlAttributes
(
unit_test
.
ad_hoc_test_result
());
OutputXmlAttribute
(
stream
,
kTestsuites
,
"name"
,
"AllTests"
);
*
stream
<<
">
\n
"
;
for
(
int
i
=
0
;
i
<
unit_test
.
total_test_case_count
();
++
i
)
{
if
(
unit_test
.
GetTestCase
(
i
)
->
reportable_test_count
()
>
0
)
PrintXmlTestCase
(
stream
,
*
unit_test
.
GetTestCase
(
i
));
}
*
stream
<<
"</"
<<
kTestsuites
<<
">
\n
"
;
}
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
std
::
string
XmlUnitTestResultPrinter
::
TestPropertiesAsXmlAttributes
(
const
TestResult
&
result
)
{
Message
attributes
;
for
(
int
i
=
0
;
i
<
result
.
test_property_count
();
++
i
)
{
const
TestProperty
&
property
=
result
.
GetTestProperty
(
i
);
attributes
<<
" "
<<
property
.
key
()
<<
"="
<<
"
\"
"
<<
EscapeXmlAttribute
(
property
.
value
())
<<
"
\"
"
;
}
return
attributes
.
GetString
();
}
// End XmlUnitTestResultPrinter
#if GTEST_CAN_STREAM_RESULTS_
// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
// replaces them by "%xx" where xx is their hexadecimal value. For
// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
// in both time and space -- important as the input str may contain an
// arbitrarily long test failure message and stack trace.
string
StreamingListener
::
UrlEncode
(
const
char
*
str
)
{
string
result
;
result
.
reserve
(
strlen
(
str
)
+
1
);
for
(
char
ch
=
*
str
;
ch
!=
'\0'
;
ch
=
*++
str
)
{
switch
(
ch
)
{
case
'%'
:
case
'='
:
case
'&'
:
case
'\n'
:
result
.
append
(
"%"
+
String
::
FormatByte
(
static_cast
<
unsigned
char
>
(
ch
)));
break
;
default:
result
.
push_back
(
ch
);
break
;
}
}
return
result
;
}
void
StreamingListener
::
SocketWriter
::
MakeConnection
()
{
GTEST_CHECK_
(
sockfd_
==
-
1
)
<<
"MakeConnection() can't be called when there is already a connection."
;
addrinfo
hints
;
memset
(
&
hints
,
0
,
sizeof
(
hints
));
hints
.
ai_family
=
AF_UNSPEC
;
// To allow both IPv4 and IPv6 addresses.
hints
.
ai_socktype
=
SOCK_STREAM
;
addrinfo
*
servinfo
=
NULL
;
// Use the getaddrinfo() to get a linked list of IP addresses for
// the given host name.
const
int
error_num
=
getaddrinfo
(
host_name_
.
c_str
(),
port_num_
.
c_str
(),
&
hints
,
&
servinfo
);
if
(
error_num
!=
0
)
{
GTEST_LOG_
(
WARNING
)
<<
"stream_result_to: getaddrinfo() failed: "
<<
gai_strerror
(
error_num
);
}
// Loop through all the results and connect to the first we can.
for
(
addrinfo
*
cur_addr
=
servinfo
;
sockfd_
==
-
1
&&
cur_addr
!=
NULL
;
cur_addr
=
cur_addr
->
ai_next
)
{
sockfd_
=
socket
(
cur_addr
->
ai_family
,
cur_addr
->
ai_socktype
,
cur_addr
->
ai_protocol
);
if
(
sockfd_
!=
-
1
)
{
// Connect the client socket to the server socket.
if
(
connect
(
sockfd_
,
cur_addr
->
ai_addr
,
cur_addr
->
ai_addrlen
)
==
-
1
)
{
close
(
sockfd_
);
sockfd_
=
-
1
;
}
}
}
freeaddrinfo
(
servinfo
);
// all done with this structure
if
(
sockfd_
==
-
1
)
{
GTEST_LOG_
(
WARNING
)
<<
"stream_result_to: failed to connect to "
<<
host_name_
<<
":"
<<
port_num_
;
}
}
// End of class Streaming Listener
#endif // GTEST_CAN_STREAM_RESULTS__
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
// trace stack maintained by Google Test.
ScopedTrace
::
ScopedTrace
(
const
char
*
file
,
int
line
,
const
Message
&
message
)
GTEST_LOCK_EXCLUDED_
(
&
UnitTest
::
mutex_
)
{
TraceInfo
trace
;
trace
.
file
=
file
;
trace
.
line
=
line
;
trace
.
message
=
message
.
GetString
();
UnitTest
::
GetInstance
()
->
PushGTestTrace
(
trace
);
}
// Pops the info pushed by the c'tor.
ScopedTrace
::~
ScopedTrace
()
GTEST_LOCK_EXCLUDED_
(
&
UnitTest
::
mutex_
)
{
UnitTest
::
GetInstance
()
->
PopGTestTrace
();
}
// class OsStackTraceGetter
// Returns the current OS stack trace as an std::string. Parameters:
//
// max_depth - the maximum number of stack frames to be included
// in the trace.
// skip_count - the number of top frames to be skipped; doesn't count
// against max_depth.
//
string
OsStackTraceGetter
::
CurrentStackTrace
(
int
/* max_depth */
,
int
/* skip_count */
)
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
return
""
;
}
void
OsStackTraceGetter
::
UponLeavingGTest
()
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
}
const
char
*
const
OsStackTraceGetter
::
kElidedFramesMarker
=
"... "
GTEST_NAME_
" internal frames ..."
;
// A helper class that creates the premature-exit file in its
// constructor and deletes the file in its destructor.
class
ScopedPrematureExitFile
{
public:
explicit
ScopedPrematureExitFile
(
const
char
*
premature_exit_filepath
)
:
premature_exit_filepath_
(
premature_exit_filepath
)
{
// If a path to the premature-exit file is specified...
if
(
premature_exit_filepath
!=
NULL
&&
*
premature_exit_filepath
!=
'\0'
)
{
// create the file with a single "0" character in it. I/O
// errors are ignored as there's nothing better we can do and we
// don't want to fail the test because of this.
FILE
*
pfile
=
posix
::
FOpen
(
premature_exit_filepath
,
"w"
);
fwrite
(
"0"
,
1
,
1
,
pfile
);
fclose
(
pfile
);
}
}
~
ScopedPrematureExitFile
()
{
if
(
premature_exit_filepath_
!=
NULL
&&
*
premature_exit_filepath_
!=
'\0'
)
{
remove
(
premature_exit_filepath_
);
}
}
private:
const
char
*
const
premature_exit_filepath_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ScopedPrematureExitFile
);
};
}
// namespace internal
// class TestEventListeners
TestEventListeners
::
TestEventListeners
()
:
repeater_
(
new
internal
::
TestEventRepeater
()),
default_result_printer_
(
NULL
),
default_xml_generator_
(
NULL
)
{
}
TestEventListeners
::~
TestEventListeners
()
{
delete
repeater_
;
}
// Returns the standard listener responsible for the default console
// output. Can be removed from the listeners list to shut down default
// console output. Note that removing this object from the listener list
// with Release transfers its ownership to the user.
void
TestEventListeners
::
Append
(
TestEventListener
*
listener
)
{
repeater_
->
Append
(
listener
);
}
// Removes the given event listener from the list and returns it. It then
// becomes the caller's responsibility to delete the listener. Returns
// NULL if the listener is not found in the list.
TestEventListener
*
TestEventListeners
::
Release
(
TestEventListener
*
listener
)
{
if
(
listener
==
default_result_printer_
)
default_result_printer_
=
NULL
;
else
if
(
listener
==
default_xml_generator_
)
default_xml_generator_
=
NULL
;
return
repeater_
->
Release
(
listener
);
}
// Returns repeater that broadcasts the TestEventListener events to all
// subscribers.
TestEventListener
*
TestEventListeners
::
repeater
()
{
return
repeater_
;
}
// Sets the default_result_printer attribute to the provided listener.
// The listener is also added to the listener list and previous
// default_result_printer is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void
TestEventListeners
::
SetDefaultResultPrinter
(
TestEventListener
*
listener
)
{
if
(
default_result_printer_
!=
listener
)
{
// It is an error to pass this method a listener that is already in the
// list.
delete
Release
(
default_result_printer_
);
default_result_printer_
=
listener
;
if
(
listener
!=
NULL
)
Append
(
listener
);
}
}
// Sets the default_xml_generator attribute to the provided listener. The
// listener is also added to the listener list and previous
// default_xml_generator is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void
TestEventListeners
::
SetDefaultXmlGenerator
(
TestEventListener
*
listener
)
{
if
(
default_xml_generator_
!=
listener
)
{
// It is an error to pass this method a listener that is already in the
// list.
delete
Release
(
default_xml_generator_
);
default_xml_generator_
=
listener
;
if
(
listener
!=
NULL
)
Append
(
listener
);
}
}
// Controls whether events will be forwarded by the repeater to the
// listeners in the list.
bool
TestEventListeners
::
EventForwardingEnabled
()
const
{
return
repeater_
->
forwarding_enabled
();
}
void
TestEventListeners
::
SuppressEventForwarding
()
{
repeater_
->
set_forwarding_enabled
(
false
);
}
// class UnitTest
// Gets the singleton UnitTest object. The first time this method is
// called, a UnitTest object is constructed and returned. Consecutive
// calls will return the same object.
//
// We don't protect this under mutex_ as a user is not supposed to
// call this before main() starts, from which point on the return
// value will never change.
UnitTest
*
UnitTest
::
GetInstance
()
{
// When compiled with MSVC 7.1 in optimized mode, destroying the
// UnitTest object upon exiting the program messes up the exit code,
// causing successful tests to appear failed. We have to use a
// different implementation in this case to bypass the compiler bug.
// This implementation makes the compiler happy, at the cost of
// leaking the UnitTest object.
// CodeGear C++Builder insists on a public destructor for the
// default implementation. Use this implementation to keep good OO
// design with private destructor.
#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
static
UnitTest
*
const
instance
=
new
UnitTest
;
return
instance
;
#else
static
UnitTest
instance
;
return
&
instance
;
#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
}
// Gets the number of successful test cases.
int
UnitTest
::
successful_test_case_count
()
const
{
return
impl
()
->
successful_test_case_count
();
}
// Gets the number of failed test cases.
int
UnitTest
::
failed_test_case_count
()
const
{
return
impl
()
->
failed_test_case_count
();
}
// Gets the number of all test cases.
int
UnitTest
::
total_test_case_count
()
const
{
return
impl
()
->
total_test_case_count
();
}
// Gets the number of all test cases that contain at least one test
// that should run.
int
UnitTest
::
test_case_to_run_count
()
const
{
return
impl
()
->
test_case_to_run_count
();
}
// Gets the number of successful tests.
int
UnitTest
::
successful_test_count
()
const
{
return
impl
()
->
successful_test_count
();
}
// Gets the number of failed tests.
int
UnitTest
::
failed_test_count
()
const
{
return
impl
()
->
failed_test_count
();
}
// Gets the number of disabled tests that will be reported in the XML report.
int
UnitTest
::
reportable_disabled_test_count
()
const
{
return
impl
()
->
reportable_disabled_test_count
();
}
// Gets the number of disabled tests.
int
UnitTest
::
disabled_test_count
()
const
{
return
impl
()
->
disabled_test_count
();
}
// Gets the number of tests to be printed in the XML report.
int
UnitTest
::
reportable_test_count
()
const
{
return
impl
()
->
reportable_test_count
();
}
// Gets the number of all tests.
int
UnitTest
::
total_test_count
()
const
{
return
impl
()
->
total_test_count
();
}
// Gets the number of tests that should run.
int
UnitTest
::
test_to_run_count
()
const
{
return
impl
()
->
test_to_run_count
();
}
// Gets the time of the test program start, in ms from the start of the
// UNIX epoch.
internal
::
TimeInMillis
UnitTest
::
start_timestamp
()
const
{
return
impl
()
->
start_timestamp
();
}
// Gets the elapsed time, in milliseconds.
internal
::
TimeInMillis
UnitTest
::
elapsed_time
()
const
{
return
impl
()
->
elapsed_time
();
}
// Returns true iff the unit test passed (i.e. all test cases passed).
bool
UnitTest
::
Passed
()
const
{
return
impl
()
->
Passed
();
}
// Returns true iff the unit test failed (i.e. some test case failed
// or something outside of all tests failed).
bool
UnitTest
::
Failed
()
const
{
return
impl
()
->
Failed
();
}
// Gets the i-th test case among all the test cases. i can range from 0 to
// total_test_case_count() - 1. If i is not in that range, returns NULL.
const
TestCase
*
UnitTest
::
GetTestCase
(
int
i
)
const
{
return
impl
()
->
GetTestCase
(
i
);
}
// Returns the TestResult containing information on test failures and
// properties logged outside of individual test cases.
const
TestResult
&
UnitTest
::
ad_hoc_test_result
()
const
{
return
*
impl
()
->
ad_hoc_test_result
();
}
// Gets the i-th test case among all the test cases. i can range from 0 to
// total_test_case_count() - 1. If i is not in that range, returns NULL.
TestCase
*
UnitTest
::
GetMutableTestCase
(
int
i
)
{
return
impl
()
->
GetMutableTestCase
(
i
);
}
// Returns the list of event listeners that can be used to track events
// inside Google Test.
TestEventListeners
&
UnitTest
::
listeners
()
{
return
*
impl
()
->
listeners
();
}
// Registers and returns a global test environment. When a test
// program is run, all global test environments will be set-up in the
// order they were registered. After all tests in the program have
// finished, all global test environments will be torn-down in the
// *reverse* order they were registered.
//
// The UnitTest object takes ownership of the given environment.
//
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
Environment
*
UnitTest
::
AddEnvironment
(
Environment
*
env
)
{
if
(
env
==
NULL
)
{
return
NULL
;
}
impl_
->
environments
().
push_back
(
env
);
return
env
;
}
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
// assertion macros instead of calling this directly.
void
UnitTest
::
AddTestPartResult
(
TestPartResult
::
Type
result_type
,
const
char
*
file_name
,
int
line_number
,
const
std
::
string
&
message
,
const
std
::
string
&
os_stack_trace
)
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
Message
msg
;
msg
<<
message
;
internal
::
MutexLock
lock
(
&
mutex_
);
if
(
impl_
->
gtest_trace_stack
().
size
()
>
0
)
{
msg
<<
"
\n
"
<<
GTEST_NAME_
<<
" trace:"
;
for
(
int
i
=
static_cast
<
int
>
(
impl_
->
gtest_trace_stack
().
size
());
i
>
0
;
--
i
)
{
const
internal
::
TraceInfo
&
trace
=
impl_
->
gtest_trace_stack
()[
i
-
1
];
msg
<<
"
\n
"
<<
internal
::
FormatFileLocation
(
trace
.
file
,
trace
.
line
)
<<
" "
<<
trace
.
message
;
}
}
if
(
os_stack_trace
.
c_str
()
!=
NULL
&&
!
os_stack_trace
.
empty
())
{
msg
<<
internal
::
kStackTraceMarker
<<
os_stack_trace
;
}
const
TestPartResult
result
=
TestPartResult
(
result_type
,
file_name
,
line_number
,
msg
.
GetString
().
c_str
());
impl_
->
GetTestPartResultReporterForCurrentThread
()
->
ReportTestPartResult
(
result
);
if
(
result_type
!=
TestPartResult
::
kSuccess
)
{
// gtest_break_on_failure takes precedence over
// gtest_throw_on_failure. This allows a user to set the latter
// in the code (perhaps in order to use Google Test assertions
// with another testing framework) and specify the former on the
// command line for debugging.
if
(
GTEST_FLAG
(
break_on_failure
))
{
#if GTEST_OS_WINDOWS
// Using DebugBreak on Windows allows gtest to still break into a debugger
// when a failure happens and both the --gtest_break_on_failure and
// the --gtest_catch_exceptions flags are specified.
DebugBreak
();
#else
// Dereference NULL through a volatile pointer to prevent the compiler
// from removing. We use this rather than abort() or __builtin_trap() for
// portability: Symbian doesn't implement abort() well, and some debuggers
// don't correctly trap abort().
*
static_cast
<
volatile
int
*>
(
NULL
)
=
1
;
#endif // GTEST_OS_WINDOWS
}
else
if
(
GTEST_FLAG
(
throw_on_failure
))
{
#if GTEST_HAS_EXCEPTIONS
throw
internal
::
GoogleTestFailureException
(
result
);
#else
// We cannot call abort() as it generates a pop-up in debug mode
// that cannot be suppressed in VC 7.1 or below.
exit
(
1
);
#endif
}
}
}
// Adds a TestProperty to the current TestResult object when invoked from
// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
// from SetUpTestCase or TearDownTestCase, or to the global property set
// when invoked elsewhere. If the result already contains a property with
// the same key, the value will be updated.
void
UnitTest
::
RecordProperty
(
const
std
::
string
&
key
,
const
std
::
string
&
value
)
{
impl_
->
RecordProperty
(
TestProperty
(
key
,
value
));
}
// Runs all tests in this UnitTest object and prints the result.
// Returns 0 if successful, or 1 otherwise.
//
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
int
UnitTest
::
Run
()
{
const
bool
in_death_test_child_process
=
internal
::
GTEST_FLAG
(
internal_run_death_test
).
length
()
>
0
;
// Google Test implements this protocol for catching that a test
// program exits before returning control to Google Test:
//
// 1. Upon start, Google Test creates a file whose absolute path
// is specified by the environment variable
// TEST_PREMATURE_EXIT_FILE.
// 2. When Google Test has finished its work, it deletes the file.
//
// This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
// running a Google-Test-based test program and check the existence
// of the file at the end of the test execution to see if it has
// exited prematurely.
// If we are in the child process of a death test, don't
// create/delete the premature exit file, as doing so is unnecessary
// and will confuse the parent process. Otherwise, create/delete
// the file upon entering/leaving this function. If the program
// somehow exits before this function has a chance to return, the
// premature-exit file will be left undeleted, causing a test runner
// that understands the premature-exit-file protocol to report the
// test as having failed.
const
internal
::
ScopedPrematureExitFile
premature_exit_file
(
in_death_test_child_process
?
NULL
:
internal
::
posix
::
GetEnv
(
"TEST_PREMATURE_EXIT_FILE"
));
// Captures the value of GTEST_FLAG(catch_exceptions). This value will be
// used for the duration of the program.
impl
()
->
set_catch_exceptions
(
GTEST_FLAG
(
catch_exceptions
));
#if GTEST_HAS_SEH
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// process. In either case the user does not want to see pop-up dialogs
// about crashes - they are expected.
if
(
impl
()
->
catch_exceptions
()
||
in_death_test_child_process
)
{
# if !GTEST_OS_WINDOWS_MOBILE
// SetErrorMode doesn't exist on CE.
SetErrorMode
(
SEM_FAILCRITICALERRORS
|
SEM_NOALIGNMENTFAULTEXCEPT
|
SEM_NOGPFAULTERRORBOX
|
SEM_NOOPENFILEERRORBOX
);
# endif // !GTEST_OS_WINDOWS_MOBILE
# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
// Death test children can be terminated with _abort(). On Windows,
// _abort() can show a dialog with a warning message. This forces the
// abort message to go to stderr instead.
_set_error_mode
(
_OUT_TO_STDERR
);
# endif
# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
// In the debug version, Visual Studio pops up a separate dialog
// offering a choice to debug the aborted program. We need to suppress
// this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
// executed. Google Test will notify the user of any unexpected
// failure via stderr.
//
// VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
// Users of prior VC versions shall suffer the agony and pain of
// clicking through the countless debug dialogs.
// TODO(vladl@google.com): find a way to suppress the abort dialog() in the
// debug mode when compiled with VC 7.1 or lower.
if
(
!
GTEST_FLAG
(
break_on_failure
))
_set_abort_behavior
(
0x0
,
// Clear the following flags:
_WRITE_ABORT_MSG
|
_CALL_REPORTFAULT
);
// pop-up window, core dump.
# endif
}
#endif // GTEST_HAS_SEH
return
internal
::
HandleExceptionsInMethodIfSupported
(
impl
(),
&
internal
::
UnitTestImpl
::
RunAllTests
,
"auxiliary test code (environments or event listeners)"
)
?
0
:
1
;
}
// Returns the working directory when the first TEST() or TEST_F() was
// executed.
const
char
*
UnitTest
::
original_working_dir
()
const
{
return
impl_
->
original_working_dir_
.
c_str
();
}
// Returns the TestCase object for the test that's currently running,
// or NULL if no test is running.
const
TestCase
*
UnitTest
::
current_test_case
()
const
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
internal
::
MutexLock
lock
(
&
mutex_
);
return
impl_
->
current_test_case
();
}
// Returns the TestInfo object for the test that's currently running,
// or NULL if no test is running.
const
TestInfo
*
UnitTest
::
current_test_info
()
const
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
internal
::
MutexLock
lock
(
&
mutex_
);
return
impl_
->
current_test_info
();
}
// Returns the random seed used at the start of the current test run.
int
UnitTest
::
random_seed
()
const
{
return
impl_
->
random_seed
();
}
#if GTEST_HAS_PARAM_TEST
// Returns ParameterizedTestCaseRegistry object used to keep track of
// value-parameterized tests and instantiate and register them.
internal
::
ParameterizedTestCaseRegistry
&
UnitTest
::
parameterized_test_registry
()
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
return
impl_
->
parameterized_test_registry
();
}
#endif // GTEST_HAS_PARAM_TEST
// Creates an empty UnitTest.
UnitTest
::
UnitTest
()
{
impl_
=
new
internal
::
UnitTestImpl
(
this
);
}
// Destructor of UnitTest.
UnitTest
::~
UnitTest
()
{
delete
impl_
;
}
// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
// Google Test trace stack.
void
UnitTest
::
PushGTestTrace
(
const
internal
::
TraceInfo
&
trace
)
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
internal
::
MutexLock
lock
(
&
mutex_
);
impl_
->
gtest_trace_stack
().
push_back
(
trace
);
}
// Pops a trace from the per-thread Google Test trace stack.
void
UnitTest
::
PopGTestTrace
()
GTEST_LOCK_EXCLUDED_
(
mutex_
)
{
internal
::
MutexLock
lock
(
&
mutex_
);
impl_
->
gtest_trace_stack
().
pop_back
();
}
namespace
internal
{
UnitTestImpl
::
UnitTestImpl
(
UnitTest
*
parent
)
:
parent_
(
parent
),
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4355) // Temporarily disables warning 4355
// (using this in initializer).
default_global_test_part_result_reporter_
(
this
),
default_per_thread_test_part_result_reporter_
(
this
),
# pragma warning(pop) // Restores the warning state again.
#else
default_global_test_part_result_reporter_
(
this
),
default_per_thread_test_part_result_reporter_
(
this
),
#endif // _MSC_VER
global_test_part_result_repoter_
(
&
default_global_test_part_result_reporter_
),
per_thread_test_part_result_reporter_
(
&
default_per_thread_test_part_result_reporter_
),
#if GTEST_HAS_PARAM_TEST
parameterized_test_registry_
(),
parameterized_tests_registered_
(
false
),
#endif // GTEST_HAS_PARAM_TEST
last_death_test_case_
(
-
1
),
current_test_case_
(
NULL
),
current_test_info_
(
NULL
),
ad_hoc_test_result_
(),
os_stack_trace_getter_
(
NULL
),
post_flag_parse_init_performed_
(
false
),
random_seed_
(
0
),
// Will be overridden by the flag before first use.
random_
(
0
),
// Will be reseeded before first use.
start_timestamp_
(
0
),
elapsed_time_
(
0
),
#if GTEST_HAS_DEATH_TEST
death_test_factory_
(
new
DefaultDeathTestFactory
),
#endif
// Will be overridden by the flag before first use.
catch_exceptions_
(
false
)
{
listeners
()
->
SetDefaultResultPrinter
(
new
PrettyUnitTestResultPrinter
);
}
UnitTestImpl
::~
UnitTestImpl
()
{
// Deletes every TestCase.
ForEach
(
test_cases_
,
internal
::
Delete
<
TestCase
>
);
// Deletes every Environment.
ForEach
(
environments_
,
internal
::
Delete
<
Environment
>
);
delete
os_stack_trace_getter_
;
}
// Adds a TestProperty to the current TestResult object when invoked in a
// context of a test, to current test case's ad_hoc_test_result when invoke
// from SetUpTestCase/TearDownTestCase, or to the global property set
// otherwise. If the result already contains a property with the same key,
// the value will be updated.
void
UnitTestImpl
::
RecordProperty
(
const
TestProperty
&
test_property
)
{
std
::
string
xml_element
;
TestResult
*
test_result
;
// TestResult appropriate for property recording.
if
(
current_test_info_
!=
NULL
)
{
xml_element
=
"testcase"
;
test_result
=
&
(
current_test_info_
->
result_
);
}
else
if
(
current_test_case_
!=
NULL
)
{
xml_element
=
"testsuite"
;
test_result
=
&
(
current_test_case_
->
ad_hoc_test_result_
);
}
else
{
xml_element
=
"testsuites"
;
test_result
=
&
ad_hoc_test_result_
;
}
test_result
->
RecordProperty
(
xml_element
,
test_property
);
}
#if GTEST_HAS_DEATH_TEST
// Disables event forwarding if the control is currently in a death test
// subprocess. Must not be called before InitGoogleTest.
void
UnitTestImpl
::
SuppressTestEventsIfInSubprocess
()
{
if
(
internal_run_death_test_flag_
.
get
()
!=
NULL
)
listeners
()
->
SuppressEventForwarding
();
}
#endif // GTEST_HAS_DEATH_TEST
// Initializes event listeners performing XML output as specified by
// UnitTestOptions. Must not be called before InitGoogleTest.
void
UnitTestImpl
::
ConfigureXmlOutput
()
{
const
std
::
string
&
output_format
=
UnitTestOptions
::
GetOutputFormat
();
if
(
output_format
==
"xml"
)
{
listeners
()
->
SetDefaultXmlGenerator
(
new
XmlUnitTestResultPrinter
(
UnitTestOptions
::
GetAbsolutePathToOutputFile
().
c_str
()));
}
else
if
(
output_format
!=
""
)
{
printf
(
"WARNING: unrecognized output format
\"
%s
\"
ignored.
\n
"
,
output_format
.
c_str
());
fflush
(
stdout
);
}
}
#if GTEST_CAN_STREAM_RESULTS_
// Initializes event listeners for streaming test results in string form.
// Must not be called before InitGoogleTest.
void
UnitTestImpl
::
ConfigureStreamingOutput
()
{
const
std
::
string
&
target
=
GTEST_FLAG
(
stream_result_to
);
if
(
!
target
.
empty
())
{
const
size_t
pos
=
target
.
find
(
':'
);
if
(
pos
!=
std
::
string
::
npos
)
{
listeners
()
->
Append
(
new
StreamingListener
(
target
.
substr
(
0
,
pos
),
target
.
substr
(
pos
+
1
)));
}
else
{
printf
(
"WARNING: unrecognized streaming target
\"
%s
\"
ignored.
\n
"
,
target
.
c_str
());
fflush
(
stdout
);
}
}
}
#endif // GTEST_CAN_STREAM_RESULTS_
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
// this function is also called from RunAllTests. Since this function can be
// called more than once, it has to be idempotent.
void
UnitTestImpl
::
PostFlagParsingInit
()
{
// Ensures that this function does not execute more than once.
if
(
!
post_flag_parse_init_performed_
)
{
post_flag_parse_init_performed_
=
true
;
#if GTEST_HAS_DEATH_TEST
InitDeathTestSubprocessControlInfo
();
SuppressTestEventsIfInSubprocess
();
#endif // GTEST_HAS_DEATH_TEST
// Registers parameterized tests. This makes parameterized tests
// available to the UnitTest reflection API without running
// RUN_ALL_TESTS.
RegisterParameterizedTests
();
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput
();
#if GTEST_CAN_STREAM_RESULTS_
// Configures listeners for streaming test results to the specified server.
ConfigureStreamingOutput
();
#endif // GTEST_CAN_STREAM_RESULTS_
}
}
// A predicate that checks the name of a TestCase against a known
// value.
//
// This is used for implementation of the UnitTest class only. We put
// it in the anonymous namespace to prevent polluting the outer
// namespace.
//
// TestCaseNameIs is copyable.
class
TestCaseNameIs
{
public:
// Constructor.
explicit
TestCaseNameIs
(
const
std
::
string
&
name
)
:
name_
(
name
)
{}
// Returns true iff the name of test_case matches name_.
bool
operator
()(
const
TestCase
*
test_case
)
const
{
return
test_case
!=
NULL
&&
strcmp
(
test_case
->
name
(),
name_
.
c_str
())
==
0
;
}
private:
std
::
string
name_
;
};
// Finds and returns a TestCase with the given name. If one doesn't
// exist, creates one and returns it. It's the CALLER'S
// RESPONSIBILITY to ensure that this function is only called WHEN THE
// TESTS ARE NOT SHUFFLED.
//
// Arguments:
//
// test_case_name: name of the test case
// type_param: the name of the test case's type parameter, or NULL if
// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase
*
UnitTestImpl
::
GetTestCase
(
const
char
*
test_case_name
,
const
char
*
type_param
,
Test
::
SetUpTestCaseFunc
set_up_tc
,
Test
::
TearDownTestCaseFunc
tear_down_tc
)
{
// Can we find a TestCase with the given name?
const
std
::
vector
<
TestCase
*>::
const_iterator
test_case
=
std
::
find_if
(
test_cases_
.
begin
(),
test_cases_
.
end
(),
TestCaseNameIs
(
test_case_name
));
if
(
test_case
!=
test_cases_
.
end
())
return
*
test_case
;
// No. Let's create one.
TestCase
*
const
new_test_case
=
new
TestCase
(
test_case_name
,
type_param
,
set_up_tc
,
tear_down_tc
);
// Is this a death test case?
if
(
internal
::
UnitTestOptions
::
MatchesFilter
(
test_case_name
,
kDeathTestCaseFilter
))
{
// Yes. Inserts the test case after the last death test case
// defined so far. This only works when the test cases haven't
// been shuffled. Otherwise we may end up running a death test
// after a non-death test.
++
last_death_test_case_
;
test_cases_
.
insert
(
test_cases_
.
begin
()
+
last_death_test_case_
,
new_test_case
);
}
else
{
// No. Appends to the end of the list.
test_cases_
.
push_back
(
new_test_case
);
}
test_case_indices_
.
push_back
(
static_cast
<
int
>
(
test_case_indices_
.
size
()));
return
new_test_case
;
}
// Helpers for setting up / tearing down the given environment. They
// are for use in the ForEach() function.
static
void
SetUpEnvironment
(
Environment
*
env
)
{
env
->
SetUp
();
}
static
void
TearDownEnvironment
(
Environment
*
env
)
{
env
->
TearDown
();
}
// Runs all tests in this UnitTest object, prints the result, and
// returns true if all tests are successful. If any exception is
// thrown during a test, the test is considered to be failed, but the
// rest of the tests will still be run.
//
// When parameterized tests are enabled, it expands and registers
// parameterized tests first in RegisterParameterizedTests().
// All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run.
bool
UnitTestImpl
::
RunAllTests
()
{
// Makes sure InitGoogleTest() was called.
if
(
!
GTestIsInitialized
())
{
printf
(
"%s"
,
"
\n
This test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.
\n
"
);
return
false
;
}
// Do not run any test if the --help flag was specified.
if
(
g_help_flag
)
return
true
;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
PostFlagParsingInit
();
// Even if sharding is not on, test runners may want to use the
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
// protocol.
internal
::
WriteToShardStatusFileIfNeeded
();
// True iff we are in a subprocess for running a thread-safe-style
// death test.
bool
in_subprocess_for_death_test
=
false
;
#if GTEST_HAS_DEATH_TEST
in_subprocess_for_death_test
=
(
internal_run_death_test_flag_
.
get
()
!=
NULL
);
#endif // GTEST_HAS_DEATH_TEST
const
bool
should_shard
=
ShouldShard
(
kTestTotalShards
,
kTestShardIndex
,
in_subprocess_for_death_test
);
// Compares the full test names with the filter to decide which
// tests to run.
const
bool
has_tests_to_run
=
FilterTests
(
should_shard
?
HONOR_SHARDING_PROTOCOL
:
IGNORE_SHARDING_PROTOCOL
)
>
0
;
// Lists the tests and exits if the --gtest_list_tests flag was specified.
if
(
GTEST_FLAG
(
list_tests
))
{
// This must be called *after* FilterTests() has been called.
ListTestsMatchingFilter
();
return
true
;
}
random_seed_
=
GTEST_FLAG
(
shuffle
)
?
GetRandomSeedFromFlag
(
GTEST_FLAG
(
random_seed
))
:
0
;
// True iff at least one test has failed.
bool
failed
=
false
;
TestEventListener
*
repeater
=
listeners
()
->
repeater
();
start_timestamp_
=
GetTimeInMillis
();
repeater
->
OnTestProgramStart
(
*
parent_
);
// How many times to repeat the tests? We don't want to repeat them
// when we are inside the subprocess of a death test.
const
int
repeat
=
in_subprocess_for_death_test
?
1
:
GTEST_FLAG
(
repeat
);
// Repeats forever if the repeat count is negative.
const
bool
forever
=
repeat
<
0
;
for
(
int
i
=
0
;
forever
||
i
!=
repeat
;
i
++
)
{
// We want to preserve failures generated by ad-hoc test
// assertions executed before RUN_ALL_TESTS().
ClearNonAdHocTestResult
();
const
TimeInMillis
start
=
GetTimeInMillis
();
// Shuffles test cases and tests if requested.
if
(
has_tests_to_run
&&
GTEST_FLAG
(
shuffle
))
{
random
()
->
Reseed
(
random_seed_
);
// This should be done before calling OnTestIterationStart(),
// such that a test event listener can see the actual test order
// in the event.
ShuffleTests
();
}
// Tells the unit test event listeners that the tests are about to start.
repeater
->
OnTestIterationStart
(
*
parent_
,
i
);
// Runs each test case if there is at least one test to run.
if
(
has_tests_to_run
)
{
// Sets up all environments beforehand.
repeater
->
OnEnvironmentsSetUpStart
(
*
parent_
);
ForEach
(
environments_
,
SetUpEnvironment
);
repeater
->
OnEnvironmentsSetUpEnd
(
*
parent_
);
// Runs the tests only if there was no fatal failure during global
// set-up.
if
(
!
Test
::
HasFatalFailure
())
{
for
(
int
test_index
=
0
;
test_index
<
total_test_case_count
();
test_index
++
)
{
GetMutableTestCase
(
test_index
)
->
Run
();
}
}
// Tears down all environments in reverse order afterwards.
repeater
->
OnEnvironmentsTearDownStart
(
*
parent_
);
std
::
for_each
(
environments_
.
rbegin
(),
environments_
.
rend
(),
TearDownEnvironment
);
repeater
->
OnEnvironmentsTearDownEnd
(
*
parent_
);
}
elapsed_time_
=
GetTimeInMillis
()
-
start
;
// Tells the unit test event listener that the tests have just finished.
repeater
->
OnTestIterationEnd
(
*
parent_
,
i
);
// Gets the result and clears it.
if
(
!
Passed
())
{
failed
=
true
;
}
// Restores the original test order after the iteration. This
// allows the user to quickly repro a failure that happens in the
// N-th iteration without repeating the first (N - 1) iterations.
// This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
// case the user somehow changes the value of the flag somewhere
// (it's always safe to unshuffle the tests).
UnshuffleTests
();
if
(
GTEST_FLAG
(
shuffle
))
{
// Picks a new random seed for each iteration.
random_seed_
=
GetNextRandomSeed
(
random_seed_
);
}
}
repeater
->
OnTestProgramEnd
(
*
parent_
);
return
!
failed
;
}
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
// if the variable is present. If a file already exists at this location, this
// function will write over it. If the variable is present, but the file cannot
// be created, prints an error and exits.
void
WriteToShardStatusFileIfNeeded
()
{
const
char
*
const
test_shard_file
=
posix
::
GetEnv
(
kTestShardStatusFile
);
if
(
test_shard_file
!=
NULL
)
{
FILE
*
const
file
=
posix
::
FOpen
(
test_shard_file
,
"w"
);
if
(
file
==
NULL
)
{
ColoredPrintf
(
COLOR_RED
,
"Could not write to the test shard status file
\"
%s
\"
"
"specified by the %s environment variable.
\n
"
,
test_shard_file
,
kTestShardStatusFile
);
fflush
(
stdout
);
exit
(
EXIT_FAILURE
);
}
fclose
(
file
);
}
}
// Checks whether sharding is enabled by examining the relevant
// environment variable values. If the variables are present,
// but inconsistent (i.e., shard_index >= total_shards), prints
// an error and exits. If in_subprocess_for_death_test, sharding is
// disabled because it must only be applied to the original test
// process. Otherwise, we could filter out death tests we intended to execute.
bool
ShouldShard
(
const
char
*
total_shards_env
,
const
char
*
shard_index_env
,
bool
in_subprocess_for_death_test
)
{
if
(
in_subprocess_for_death_test
)
{
return
false
;
}
const
Int32
total_shards
=
Int32FromEnvOrDie
(
total_shards_env
,
-
1
);
const
Int32
shard_index
=
Int32FromEnvOrDie
(
shard_index_env
,
-
1
);
if
(
total_shards
==
-
1
&&
shard_index
==
-
1
)
{
return
false
;
}
else
if
(
total_shards
==
-
1
&&
shard_index
!=
-
1
)
{
const
Message
msg
=
Message
()
<<
"Invalid environment variables: you have "
<<
kTestShardIndex
<<
" = "
<<
shard_index
<<
", but have left "
<<
kTestTotalShards
<<
" unset.
\n
"
;
ColoredPrintf
(
COLOR_RED
,
msg
.
GetString
().
c_str
());
fflush
(
stdout
);
exit
(
EXIT_FAILURE
);
}
else
if
(
total_shards
!=
-
1
&&
shard_index
==
-
1
)
{
const
Message
msg
=
Message
()
<<
"Invalid environment variables: you have "
<<
kTestTotalShards
<<
" = "
<<
total_shards
<<
", but have left "
<<
kTestShardIndex
<<
" unset.
\n
"
;
ColoredPrintf
(
COLOR_RED
,
msg
.
GetString
().
c_str
());
fflush
(
stdout
);
exit
(
EXIT_FAILURE
);
}
else
if
(
shard_index
<
0
||
shard_index
>=
total_shards
)
{
const
Message
msg
=
Message
()
<<
"Invalid environment variables: we require 0 <= "
<<
kTestShardIndex
<<
" < "
<<
kTestTotalShards
<<
", but you have "
<<
kTestShardIndex
<<
"="
<<
shard_index
<<
", "
<<
kTestTotalShards
<<
"="
<<
total_shards
<<
".
\n
"
;
ColoredPrintf
(
COLOR_RED
,
msg
.
GetString
().
c_str
());
fflush
(
stdout
);
exit
(
EXIT_FAILURE
);
}
return
total_shards
>
1
;
}
// Parses the environment variable var as an Int32. If it is unset,
// returns default_val. If it is not an Int32, prints an error
// and aborts.
Int32
Int32FromEnvOrDie
(
const
char
*
var
,
Int32
default_val
)
{
const
char
*
str_val
=
posix
::
GetEnv
(
var
);
if
(
str_val
==
NULL
)
{
return
default_val
;
}
Int32
result
;
if
(
!
ParseInt32
(
Message
()
<<
"The value of environment variable "
<<
var
,
str_val
,
&
result
))
{
exit
(
EXIT_FAILURE
);
}
return
result
;
}
// Given the total number of shards, the shard index, and the test id,
// returns true iff the test should be run on this shard. The test id is
// some arbitrary but unique non-negative integer assigned to each test
// method. Assumes that 0 <= shard_index < total_shards.
bool
ShouldRunTestOnShard
(
int
total_shards
,
int
shard_index
,
int
test_id
)
{
return
(
test_id
%
total_shards
)
==
shard_index
;
}
// Compares the name of each test with the user-specified filter to
// decide whether the test should be run, then records the result in
// each TestCase and TestInfo object.
// If shard_tests == true, further filters tests based on sharding
// variables in the environment - see
// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
// Returns the number of tests that should run.
int
UnitTestImpl
::
FilterTests
(
ReactionToSharding
shard_tests
)
{
const
Int32
total_shards
=
shard_tests
==
HONOR_SHARDING_PROTOCOL
?
Int32FromEnvOrDie
(
kTestTotalShards
,
-
1
)
:
-
1
;
const
Int32
shard_index
=
shard_tests
==
HONOR_SHARDING_PROTOCOL
?
Int32FromEnvOrDie
(
kTestShardIndex
,
-
1
)
:
-
1
;
// num_runnable_tests are the number of tests that will
// run across all shards (i.e., match filter and are not disabled).
// num_selected_tests are the number of tests to be run on
// this shard.
int
num_runnable_tests
=
0
;
int
num_selected_tests
=
0
;
for
(
size_t
i
=
0
;
i
<
test_cases_
.
size
();
i
++
)
{
TestCase
*
const
test_case
=
test_cases_
[
i
];
const
std
::
string
&
test_case_name
=
test_case
->
name
();
test_case
->
set_should_run
(
false
);
for
(
size_t
j
=
0
;
j
<
test_case
->
test_info_list
().
size
();
j
++
)
{
TestInfo
*
const
test_info
=
test_case
->
test_info_list
()[
j
];
const
std
::
string
test_name
(
test_info
->
name
());
// A test is disabled if test case name or test name matches
// kDisableTestFilter.
const
bool
is_disabled
=
internal
::
UnitTestOptions
::
MatchesFilter
(
test_case_name
,
kDisableTestFilter
)
||
internal
::
UnitTestOptions
::
MatchesFilter
(
test_name
,
kDisableTestFilter
);
test_info
->
is_disabled_
=
is_disabled
;
const
bool
matches_filter
=
internal
::
UnitTestOptions
::
FilterMatchesTest
(
test_case_name
,
test_name
);
test_info
->
matches_filter_
=
matches_filter
;
const
bool
is_runnable
=
(
GTEST_FLAG
(
also_run_disabled_tests
)
||
!
is_disabled
)
&&
matches_filter
;
const
bool
is_selected
=
is_runnable
&&
(
shard_tests
==
IGNORE_SHARDING_PROTOCOL
||
ShouldRunTestOnShard
(
total_shards
,
shard_index
,
num_runnable_tests
));
num_runnable_tests
+=
is_runnable
;
num_selected_tests
+=
is_selected
;
test_info
->
should_run_
=
is_selected
;
test_case
->
set_should_run
(
test_case
->
should_run
()
||
is_selected
);
}
}
return
num_selected_tests
;
}
// Prints the given C-string on a single line by replacing all '\n'
// characters with string "\\n". If the output takes more than
// max_length characters, only prints the first max_length characters
// and "...".
static
void
PrintOnOneLine
(
const
char
*
str
,
int
max_length
)
{
if
(
str
!=
NULL
)
{
for
(
int
i
=
0
;
*
str
!=
'\0'
;
++
str
)
{
if
(
i
>=
max_length
)
{
printf
(
"..."
);
break
;
}
if
(
*
str
==
'\n'
)
{
printf
(
"
\\
n"
);
i
+=
2
;
}
else
{
printf
(
"%c"
,
*
str
);
++
i
;
}
}
}
}
// Prints the names of the tests matching the user-specified filter flag.
void
UnitTestImpl
::
ListTestsMatchingFilter
()
{
// Print at most this many characters for each type/value parameter.
const
int
kMaxParamLength
=
250
;
for
(
size_t
i
=
0
;
i
<
test_cases_
.
size
();
i
++
)
{
const
TestCase
*
const
test_case
=
test_cases_
[
i
];
bool
printed_test_case_name
=
false
;
for
(
size_t
j
=
0
;
j
<
test_case
->
test_info_list
().
size
();
j
++
)
{
const
TestInfo
*
const
test_info
=
test_case
->
test_info_list
()[
j
];
if
(
test_info
->
matches_filter_
)
{
if
(
!
printed_test_case_name
)
{
printed_test_case_name
=
true
;
printf
(
"%s."
,
test_case
->
name
());
if
(
test_case
->
type_param
()
!=
NULL
)
{
printf
(
" # %s = "
,
kTypeParamLabel
);
// We print the type parameter on a single line to make
// the output easy to parse by a program.
PrintOnOneLine
(
test_case
->
type_param
(),
kMaxParamLength
);
}
printf
(
"
\n
"
);
}
printf
(
" %s"
,
test_info
->
name
());
if
(
test_info
->
value_param
()
!=
NULL
)
{
printf
(
" # %s = "
,
kValueParamLabel
);
// We print the value parameter on a single line to make the
// output easy to parse by a program.
PrintOnOneLine
(
test_info
->
value_param
(),
kMaxParamLength
);
}
printf
(
"
\n
"
);
}
}
}
fflush
(
stdout
);
}
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter are
// the same; otherwise, deletes the old getter and makes the input the
// current getter.
void
UnitTestImpl
::
set_os_stack_trace_getter
(
OsStackTraceGetterInterface
*
getter
)
{
if
(
os_stack_trace_getter_
!=
getter
)
{
delete
os_stack_trace_getter_
;
os_stack_trace_getter_
=
getter
;
}
}
// Returns the current OS stack trace getter if it is not NULL;
// otherwise, creates an OsStackTraceGetter, makes it the current
// getter, and returns it.
OsStackTraceGetterInterface
*
UnitTestImpl
::
os_stack_trace_getter
()
{
if
(
os_stack_trace_getter_
==
NULL
)
{
os_stack_trace_getter_
=
new
OsStackTraceGetter
;
}
return
os_stack_trace_getter_
;
}
// Returns the TestResult for the test that's currently running, or
// the TestResult for the ad hoc test if no test is running.
TestResult
*
UnitTestImpl
::
current_test_result
()
{
return
current_test_info_
?
&
(
current_test_info_
->
result_
)
:
&
ad_hoc_test_result_
;
}
// Shuffles all test cases, and the tests within each test case,
// making sure that death tests are still run first.
void
UnitTestImpl
::
ShuffleTests
()
{
// Shuffles the death test cases.
ShuffleRange
(
random
(),
0
,
last_death_test_case_
+
1
,
&
test_case_indices_
);
// Shuffles the non-death test cases.
ShuffleRange
(
random
(),
last_death_test_case_
+
1
,
static_cast
<
int
>
(
test_cases_
.
size
()),
&
test_case_indices_
);
// Shuffles the tests inside each test case.
for
(
size_t
i
=
0
;
i
<
test_cases_
.
size
();
i
++
)
{
test_cases_
[
i
]
->
ShuffleTests
(
random
());
}
}
// Restores the test cases and tests to their order before the first shuffle.
void
UnitTestImpl
::
UnshuffleTests
()
{
for
(
size_t
i
=
0
;
i
<
test_cases_
.
size
();
i
++
)
{
// Unshuffles the tests in each test case.
test_cases_
[
i
]
->
UnshuffleTests
();
// Resets the index of each test case.
test_case_indices_
[
i
]
=
static_cast
<
int
>
(
i
);
}
}
// Returns the current OS stack trace as an std::string.
//
// The maximum number of stack frames to be included is specified by
// the gtest_stack_trace_depth flag. The skip_count parameter
// specifies the number of top frames to be skipped, which doesn't
// count against the number of frames to be included.
//
// For example, if Foo() calls Bar(), which in turn calls
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
std
::
string
GetCurrentOsStackTraceExceptTop
(
UnitTest
*
/*unit_test*/
,
int
skip_count
)
{
// We pass skip_count + 1 to skip this wrapper function in addition
// to what the user really wants to skip.
return
GetUnitTestImpl
()
->
CurrentOsStackTraceExceptTop
(
skip_count
+
1
);
}
// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
// suppress unreachable code warnings.
namespace
{
class
ClassUniqueToAlwaysTrue
{};
}
bool
IsTrue
(
bool
condition
)
{
return
condition
;
}
bool
AlwaysTrue
()
{
#if GTEST_HAS_EXCEPTIONS
// This condition is always false so AlwaysTrue() never actually throws,
// but it makes the compiler think that it may throw.
if
(
IsTrue
(
false
))
throw
ClassUniqueToAlwaysTrue
();
#endif // GTEST_HAS_EXCEPTIONS
return
true
;
}
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
// and returns false. None of pstr, *pstr, and prefix can be NULL.
bool
SkipPrefix
(
const
char
*
prefix
,
const
char
**
pstr
)
{
const
size_t
prefix_len
=
strlen
(
prefix
);
if
(
strncmp
(
*
pstr
,
prefix
,
prefix_len
)
==
0
)
{
*
pstr
+=
prefix_len
;
return
true
;
}
return
false
;
}
// Parses a string as a command line flag. The string should have
// the format "--flag=value". When def_optional is true, the "=value"
// part can be omitted.
//
// Returns the value of the flag, or NULL if the parsing failed.
const
char
*
ParseFlagValue
(
const
char
*
str
,
const
char
*
flag
,
bool
def_optional
)
{
// str and flag must not be NULL.
if
(
str
==
NULL
||
flag
==
NULL
)
return
NULL
;
// The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
const
std
::
string
flag_str
=
std
::
string
(
"--"
)
+
GTEST_FLAG_PREFIX_
+
flag
;
const
size_t
flag_len
=
flag_str
.
length
();
if
(
strncmp
(
str
,
flag_str
.
c_str
(),
flag_len
)
!=
0
)
return
NULL
;
// Skips the flag name.
const
char
*
flag_end
=
str
+
flag_len
;
// When def_optional is true, it's OK to not have a "=value" part.
if
(
def_optional
&&
(
flag_end
[
0
]
==
'\0'
))
{
return
flag_end
;
}
// If def_optional is true and there are more characters after the
// flag name, or if def_optional is false, there must be a '=' after
// the flag name.
if
(
flag_end
[
0
]
!=
'='
)
return
NULL
;
// Returns the string after "=".
return
flag_end
+
1
;
}
// Parses a string for a bool flag, in the form of either
// "--flag=value" or "--flag".
//
// In the former case, the value is taken as true as long as it does
// not start with '0', 'f', or 'F'.
//
// In the latter case, the value is taken as true.
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
bool
ParseBoolFlag
(
const
char
*
str
,
const
char
*
flag
,
bool
*
value
)
{
// Gets the value of the flag as a string.
const
char
*
const
value_str
=
ParseFlagValue
(
str
,
flag
,
true
);
// Aborts if the parsing failed.
if
(
value_str
==
NULL
)
return
false
;
// Converts the string value to a bool.
*
value
=
!
(
*
value_str
==
'0'
||
*
value_str
==
'f'
||
*
value_str
==
'F'
);
return
true
;
}
// Parses a string for an Int32 flag, in the form of
// "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
bool
ParseInt32Flag
(
const
char
*
str
,
const
char
*
flag
,
Int32
*
value
)
{
// Gets the value of the flag as a string.
const
char
*
const
value_str
=
ParseFlagValue
(
str
,
flag
,
false
);
// Aborts if the parsing failed.
if
(
value_str
==
NULL
)
return
false
;
// Sets *value to the value of the flag.
return
ParseInt32
(
Message
()
<<
"The value of flag --"
<<
flag
,
value_str
,
value
);
}
// Parses a string for a string flag, in the form of
// "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
bool
ParseStringFlag
(
const
char
*
str
,
const
char
*
flag
,
std
::
string
*
value
)
{
// Gets the value of the flag as a string.
const
char
*
const
value_str
=
ParseFlagValue
(
str
,
flag
,
false
);
// Aborts if the parsing failed.
if
(
value_str
==
NULL
)
return
false
;
// Sets *value to the value of the flag.
*
value
=
value_str
;
return
true
;
}
// Determines whether a string has a prefix that Google Test uses for its
// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
// If Google Test detects that a command line flag has its prefix but is not
// recognized, it will print its help message. Flags starting with
// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
// internal flags and do not trigger the help message.
static
bool
HasGoogleTestFlagPrefix
(
const
char
*
str
)
{
return
(
SkipPrefix
(
"--"
,
&
str
)
||
SkipPrefix
(
"-"
,
&
str
)
||
SkipPrefix
(
"/"
,
&
str
))
&&
!
SkipPrefix
(
GTEST_FLAG_PREFIX_
"internal_"
,
&
str
)
&&
(
SkipPrefix
(
GTEST_FLAG_PREFIX_
,
&
str
)
||
SkipPrefix
(
GTEST_FLAG_PREFIX_DASH_
,
&
str
));
}
// Prints a string containing code-encoded text. The following escape
// sequences can be used in the string to control the text color:
//
// @@ prints a single '@' character.
// @R changes the color to red.
// @G changes the color to green.
// @Y changes the color to yellow.
// @D changes to the default terminal text color.
//
// TODO(wan@google.com): Write tests for this once we add stdout
// capturing to Google Test.
static
void
PrintColorEncoded
(
const
char
*
str
)
{
GTestColor
color
=
COLOR_DEFAULT
;
// The current color.
// Conceptually, we split the string into segments divided by escape
// sequences. Then we print one segment at a time. At the end of
// each iteration, the str pointer advances to the beginning of the
// next segment.
for
(;;)
{
const
char
*
p
=
strchr
(
str
,
'@'
);
if
(
p
==
NULL
)
{
ColoredPrintf
(
color
,
"%s"
,
str
);
return
;
}
ColoredPrintf
(
color
,
"%s"
,
std
::
string
(
str
,
p
).
c_str
());
const
char
ch
=
p
[
1
];
str
=
p
+
2
;
if
(
ch
==
'@'
)
{
ColoredPrintf
(
color
,
"@"
);
}
else
if
(
ch
==
'D'
)
{
color
=
COLOR_DEFAULT
;
}
else
if
(
ch
==
'R'
)
{
color
=
COLOR_RED
;
}
else
if
(
ch
==
'G'
)
{
color
=
COLOR_GREEN
;
}
else
if
(
ch
==
'Y'
)
{
color
=
COLOR_YELLOW
;
}
else
{
--
str
;
}
}
}
static
const
char
kColorEncodedHelpMessage
[]
=
"This program contains tests written using "
GTEST_NAME_
". You can use the
\n
"
"following command line flags to control its behavior:
\n
"
"
\n
"
"Test Selection:
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"list_tests@D
\n
"
" List the names of all tests instead of running them. The name of
\n
"
" TEST(Foo, Bar) is
\"
Foo.Bar
\"
.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"filter=@YPOSTIVE_PATTERNS"
"[@G-@YNEGATIVE_PATTERNS]@D
\n
"
" Run only the tests whose name matches one of the positive patterns but
\n
"
" none of the negative patterns. '?' matches any single character; '*'
\n
"
" matches any substring; ':' separates two patterns.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"also_run_disabled_tests@D
\n
"
" Run all disabled tests too.
\n
"
"
\n
"
"Test Execution:
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"repeat=@Y[COUNT]@D
\n
"
" Run the tests repeatedly; use a negative count to repeat forever.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"shuffle@D
\n
"
" Randomize tests' orders on every iteration.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"random_seed=@Y[NUMBER]@D
\n
"
" Random number seed to use for shuffling test orders (between 1 and
\n
"
" 99999, or 0 to use a seed based on the current time).
\n
"
"
\n
"
"Test Output:
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D
\n
"
" Enable/disable colored output. The default is @Gauto@D.
\n
"
" -@G-"
GTEST_FLAG_PREFIX_
"print_time=0@D
\n
"
" Don't print the elapsed time of each test.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"output=xml@Y[@G:@YDIRECTORY_PATH@G"
GTEST_PATH_SEP_
"@Y|@G:@YFILE_PATH]@D
\n
"
" Generate an XML report in the given directory or with the given file
\n
"
" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.
\n
"
#if GTEST_CAN_STREAM_RESULTS_
" @G--"
GTEST_FLAG_PREFIX_
"stream_result_to=@YHOST@G:@YPORT@D
\n
"
" Stream test results to the given server.
\n
"
#endif // GTEST_CAN_STREAM_RESULTS_
"
\n
"
"Assertion Behavior:
\n
"
#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
" @G--"
GTEST_FLAG_PREFIX_
"death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D
\n
"
" Set the default death test style.
\n
"
#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
" @G--"
GTEST_FLAG_PREFIX_
"break_on_failure@D
\n
"
" Turn assertion failures into debugger break-points.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"throw_on_failure@D
\n
"
" Turn assertion failures into C++ exceptions.
\n
"
" @G--"
GTEST_FLAG_PREFIX_
"catch_exceptions=0@D
\n
"
" Do not report exceptions as test failures. Instead, allow them
\n
"
" to crash the program or throw a pop-up (on Windows).
\n
"
"
\n
"
"Except for @G--"
GTEST_FLAG_PREFIX_
"list_tests@D, you can alternatively set "
"the corresponding
\n
"
"environment variable of a flag (all letters in upper-case). For example, to
\n
"
"disable colored text output, you can either specify @G--"
GTEST_FLAG_PREFIX_
"color=no@D or set
\n
"
"the @G"
GTEST_FLAG_PREFIX_UPPER_
"COLOR@D environment variable to @Gno@D.
\n
"
"
\n
"
"For more information, please read the "
GTEST_NAME_
" documentation at
\n
"
"@G"
GTEST_PROJECT_URL_
"@D. If you find a bug in "
GTEST_NAME_
"
\n
"
"(not one in your own code or tests), please report it to
\n
"
"@G<"
GTEST_DEV_EMAIL_
">@D.
\n
"
;
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test. The type parameter CharType can be
// instantiated to either char or wchar_t.
template
<
typename
CharType
>
void
ParseGoogleTestFlagsOnlyImpl
(
int
*
argc
,
CharType
**
argv
)
{
for
(
int
i
=
1
;
i
<
*
argc
;
i
++
)
{
const
std
::
string
arg_string
=
StreamableToString
(
argv
[
i
]);
const
char
*
const
arg
=
arg_string
.
c_str
();
using
internal
::
ParseBoolFlag
;
using
internal
::
ParseInt32Flag
;
using
internal
::
ParseStringFlag
;
// Do we see a Google Test flag?
if
(
ParseBoolFlag
(
arg
,
kAlsoRunDisabledTestsFlag
,
&
GTEST_FLAG
(
also_run_disabled_tests
))
||
ParseBoolFlag
(
arg
,
kBreakOnFailureFlag
,
&
GTEST_FLAG
(
break_on_failure
))
||
ParseBoolFlag
(
arg
,
kCatchExceptionsFlag
,
&
GTEST_FLAG
(
catch_exceptions
))
||
ParseStringFlag
(
arg
,
kColorFlag
,
&
GTEST_FLAG
(
color
))
||
ParseStringFlag
(
arg
,
kDeathTestStyleFlag
,
&
GTEST_FLAG
(
death_test_style
))
||
ParseBoolFlag
(
arg
,
kDeathTestUseFork
,
&
GTEST_FLAG
(
death_test_use_fork
))
||
ParseStringFlag
(
arg
,
kFilterFlag
,
&
GTEST_FLAG
(
filter
))
||
ParseStringFlag
(
arg
,
kInternalRunDeathTestFlag
,
&
GTEST_FLAG
(
internal_run_death_test
))
||
ParseBoolFlag
(
arg
,
kListTestsFlag
,
&
GTEST_FLAG
(
list_tests
))
||
ParseStringFlag
(
arg
,
kOutputFlag
,
&
GTEST_FLAG
(
output
))
||
ParseBoolFlag
(
arg
,
kPrintTimeFlag
,
&
GTEST_FLAG
(
print_time
))
||
ParseInt32Flag
(
arg
,
kRandomSeedFlag
,
&
GTEST_FLAG
(
random_seed
))
||
ParseInt32Flag
(
arg
,
kRepeatFlag
,
&
GTEST_FLAG
(
repeat
))
||
ParseBoolFlag
(
arg
,
kShuffleFlag
,
&
GTEST_FLAG
(
shuffle
))
||
ParseInt32Flag
(
arg
,
kStackTraceDepthFlag
,
&
GTEST_FLAG
(
stack_trace_depth
))
||
ParseStringFlag
(
arg
,
kStreamResultToFlag
,
&
GTEST_FLAG
(
stream_result_to
))
||
ParseBoolFlag
(
arg
,
kThrowOnFailureFlag
,
&
GTEST_FLAG
(
throw_on_failure
))
)
{
// Yes. Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being
// NULL. The following loop moves the trailing NULL element as
// well.
for
(
int
j
=
i
;
j
!=
*
argc
;
j
++
)
{
argv
[
j
]
=
argv
[
j
+
1
];
}
// Decrements the argument count.
(
*
argc
)
--
;
// We also need to decrement the iterator as we just removed
// an element.
i
--
;
}
else
if
(
arg_string
==
"--help"
||
arg_string
==
"-h"
||
arg_string
==
"-?"
||
arg_string
==
"/?"
||
HasGoogleTestFlagPrefix
(
arg
))
{
// Both help flag and unrecognized Google Test flags (excluding
// internal ones) trigger help display.
g_help_flag
=
true
;
}
}
if
(
g_help_flag
)
{
// We print the help here instead of in RUN_ALL_TESTS(), as the
// latter may not be called at all if the user is using Google
// Test with another testing framework.
PrintColorEncoded
(
kColorEncodedHelpMessage
);
}
}
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test.
void
ParseGoogleTestFlagsOnly
(
int
*
argc
,
char
**
argv
)
{
ParseGoogleTestFlagsOnlyImpl
(
argc
,
argv
);
}
void
ParseGoogleTestFlagsOnly
(
int
*
argc
,
wchar_t
**
argv
)
{
ParseGoogleTestFlagsOnlyImpl
(
argc
,
argv
);
}
// The internal implementation of InitGoogleTest().
//
// The type parameter CharType can be instantiated to either char or
// wchar_t.
template
<
typename
CharType
>
void
InitGoogleTestImpl
(
int
*
argc
,
CharType
**
argv
)
{
g_init_gtest_count
++
;
// We don't want to run the initialization code twice.
if
(
g_init_gtest_count
!=
1
)
return
;
if
(
*
argc
<=
0
)
return
;
internal
::
g_executable_path
=
internal
::
StreamableToString
(
argv
[
0
]);
#if GTEST_HAS_DEATH_TEST
g_argvs
.
clear
();
for
(
int
i
=
0
;
i
!=
*
argc
;
i
++
)
{
g_argvs
.
push_back
(
StreamableToString
(
argv
[
i
]));
}
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly
(
argc
,
argv
);
GetUnitTestImpl
()
->
PostFlagParsingInit
();
}
}
// namespace internal
// Initializes Google Test. This must be called before calling
// RUN_ALL_TESTS(). In particular, it parses a command line for the
// flags that Google Test recognizes. Whenever a Google Test flag is
// seen, it is removed from argv, and *argc is decremented.
//
// No value is returned. Instead, the Google Test flag variables are
// updated.
//
// Calling the function for the second time has no user-visible effect.
void
InitGoogleTest
(
int
*
argc
,
char
**
argv
)
{
internal
::
InitGoogleTestImpl
(
argc
,
argv
);
}
// This overloaded version can be used in Windows programs compiled in
// UNICODE mode.
void
InitGoogleTest
(
int
*
argc
,
wchar_t
**
argv
)
{
internal
::
InitGoogleTestImpl
(
argc
,
argv
);
}
}
// namespace testing
test/gtest-1.7.0/src/gtest_main.cc
0 → 100644
View file @
db82302e
// Copyright 2006, 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.
#include <stdio.h>
#include "gtest/gtest.h"
GTEST_API_
int
main
(
int
argc
,
char
**
argv
)
{
printf
(
"Running main() from gtest_main.cc
\n
"
);
testing
::
InitGoogleTest
(
&
argc
,
argv
);
return
RUN_ALL_TESTS
();
}
test/gtest-1.7.0/test/gtest-death-test_ex_test.cc
0 → 100644
View file @
db82302e
// Copyright 2010, 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: vladl@google.com (Vlad Losev)
//
// Tests that verify interaction of exceptions and death tests.
#include "gtest/gtest-death-test.h"
#include "gtest/gtest.h"
#if GTEST_HAS_DEATH_TEST
# if GTEST_HAS_SEH
# include <windows.h> // For RaiseException().
# endif
# include "gtest/gtest-spi.h"
# if GTEST_HAS_EXCEPTIONS
# include <exception> // For std::exception.
// Tests that death tests report thrown exceptions as failures and that the
// exceptions do not escape death test macros.
TEST
(
CxxExceptionDeathTest
,
ExceptionIsFailure
)
{
try
{
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
1
,
""
),
"threw an exception"
);
}
catch
(...)
{
// NOLINT
FAIL
()
<<
"An exception escaped a death test macro invocation "
<<
"with catch_exceptions "
<<
(
testing
::
GTEST_FLAG
(
catch_exceptions
)
?
"enabled"
:
"disabled"
);
}
}
class
TestException
:
public
std
::
exception
{
public:
virtual
const
char
*
what
()
const
throw
()
{
return
"exceptional message"
;
}
};
TEST
(
CxxExceptionDeathTest
,
PrintsMessageForStdExceptions
)
{
// Verifies that the exception message is quoted in the failure text.
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
TestException
(),
""
),
"exceptional message"
);
// Verifies that the location is mentioned in the failure text.
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
TestException
(),
""
),
"gtest-death-test_ex_test.cc"
);
}
# endif // GTEST_HAS_EXCEPTIONS
# if GTEST_HAS_SEH
// Tests that enabling interception of SEH exceptions with the
// catch_exceptions flag does not interfere with SEH exceptions being
// treated as death by death tests.
TEST
(
SehExceptionDeasTest
,
CatchExceptionsDoesNotInterfere
)
{
EXPECT_DEATH
(
RaiseException
(
42
,
0x0
,
0
,
NULL
),
""
)
<<
"with catch_exceptions "
<<
(
testing
::
GTEST_FLAG
(
catch_exceptions
)
?
"enabled"
:
"disabled"
);
}
# endif
#endif // GTEST_HAS_DEATH_TEST
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
testing
::
GTEST_FLAG
(
catch_exceptions
)
=
GTEST_ENABLE_CATCH_EXCEPTIONS_
!=
0
;
return
RUN_ALL_TESTS
();
}
test/gtest-1.7.0/test/gtest-death-test_test.cc
0 → 100644
View file @
db82302e
// Copyright 2005, 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: wan@google.com (Zhanyong Wan)
//
// Tests for death tests.
#include "gtest/gtest-death-test.h"
#include "gtest/gtest.h"
#include "gtest/internal/gtest-filepath.h"
using
testing
::
internal
::
AlwaysFalse
;
using
testing
::
internal
::
AlwaysTrue
;
#if GTEST_HAS_DEATH_TEST
# if GTEST_OS_WINDOWS
# include <direct.h> // For chdir().
# else
# include <unistd.h>
# include <sys/wait.h> // For waitpid.
# endif // GTEST_OS_WINDOWS
# include <limits.h>
# include <signal.h>
# include <stdio.h>
# if GTEST_OS_LINUX
# include <sys/time.h>
# endif // GTEST_OS_LINUX
# include "gtest/gtest-spi.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// his code.
# define GTEST_IMPLEMENTATION_ 1
# include "src/gtest-internal-inl.h"
# undef GTEST_IMPLEMENTATION_
namespace
posix
=
::
testing
::
internal
::
posix
;
using
testing
::
Message
;
using
testing
::
internal
::
DeathTest
;
using
testing
::
internal
::
DeathTestFactory
;
using
testing
::
internal
::
FilePath
;
using
testing
::
internal
::
GetLastErrnoDescription
;
using
testing
::
internal
::
GetUnitTestImpl
;
using
testing
::
internal
::
InDeathTestChild
;
using
testing
::
internal
::
ParseNaturalNumber
;
namespace
testing
{
namespace
internal
{
// A helper class whose objects replace the death test factory for a
// single UnitTest object during their lifetimes.
class
ReplaceDeathTestFactory
{
public:
explicit
ReplaceDeathTestFactory
(
DeathTestFactory
*
new_factory
)
:
unit_test_impl_
(
GetUnitTestImpl
())
{
old_factory_
=
unit_test_impl_
->
death_test_factory_
.
release
();
unit_test_impl_
->
death_test_factory_
.
reset
(
new_factory
);
}
~
ReplaceDeathTestFactory
()
{
unit_test_impl_
->
death_test_factory_
.
release
();
unit_test_impl_
->
death_test_factory_
.
reset
(
old_factory_
);
}
private:
// Prevents copying ReplaceDeathTestFactory objects.
ReplaceDeathTestFactory
(
const
ReplaceDeathTestFactory
&
);
void
operator
=
(
const
ReplaceDeathTestFactory
&
);
UnitTestImpl
*
unit_test_impl_
;
DeathTestFactory
*
old_factory_
;
};
}
// namespace internal
}
// namespace testing
void
DieWithMessage
(
const
::
std
::
string
&
message
)
{
fprintf
(
stderr
,
"%s"
,
message
.
c_str
());
fflush
(
stderr
);
// Make sure the text is printed before the process exits.
// We call _exit() instead of exit(), as the former is a direct
// system call and thus safer in the presence of threads. exit()
// will invoke user-defined exit-hooks, which may do dangerous
// things that conflict with death tests.
//
// Some compilers can recognize that _exit() never returns and issue the
// 'unreachable code' warning for code following this function, unless
// fooled by a fake condition.
if
(
AlwaysTrue
())
_exit
(
1
);
}
void
DieInside
(
const
::
std
::
string
&
function
)
{
DieWithMessage
(
"death inside "
+
function
+
"()."
);
}
// Tests that death tests work.
class
TestForDeathTest
:
public
testing
::
Test
{
protected:
TestForDeathTest
()
:
original_dir_
(
FilePath
::
GetCurrentDir
())
{}
virtual
~
TestForDeathTest
()
{
posix
::
ChDir
(
original_dir_
.
c_str
());
}
// A static member function that's expected to die.
static
void
StaticMemberFunction
()
{
DieInside
(
"StaticMemberFunction"
);
}
// A method of the test fixture that may die.
void
MemberFunction
()
{
if
(
should_die_
)
DieInside
(
"MemberFunction"
);
}
// True iff MemberFunction() should die.
bool
should_die_
;
const
FilePath
original_dir_
;
};
// A class with a member function that may die.
class
MayDie
{
public:
explicit
MayDie
(
bool
should_die
)
:
should_die_
(
should_die
)
{}
// A member function that may die.
void
MemberFunction
()
const
{
if
(
should_die_
)
DieInside
(
"MayDie::MemberFunction"
);
}
private:
// True iff MemberFunction() should die.
bool
should_die_
;
};
// A global function that's expected to die.
void
GlobalFunction
()
{
DieInside
(
"GlobalFunction"
);
}
// A non-void function that's expected to die.
int
NonVoidFunction
()
{
DieInside
(
"NonVoidFunction"
);
return
1
;
}
// A unary function that may die.
void
DieIf
(
bool
should_die
)
{
if
(
should_die
)
DieInside
(
"DieIf"
);
}
// A binary function that may die.
bool
DieIfLessThan
(
int
x
,
int
y
)
{
if
(
x
<
y
)
{
DieInside
(
"DieIfLessThan"
);
}
return
true
;
}
// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
void
DeathTestSubroutine
()
{
EXPECT_DEATH
(
GlobalFunction
(),
"death.*GlobalFunction"
);
ASSERT_DEATH
(
GlobalFunction
(),
"death.*GlobalFunction"
);
}
// Death in dbg, not opt.
int
DieInDebugElse12
(
int
*
sideeffect
)
{
if
(
sideeffect
)
*
sideeffect
=
12
;
# ifndef NDEBUG
DieInside
(
"DieInDebugElse12"
);
# endif // NDEBUG
return
12
;
}
# if GTEST_OS_WINDOWS
// Tests the ExitedWithCode predicate.
TEST
(
ExitStatusPredicateTest
,
ExitedWithCode
)
{
// On Windows, the process's exit code is the same as its exit status,
// so the predicate just compares the its input with its parameter.
EXPECT_TRUE
(
testing
::
ExitedWithCode
(
0
)(
0
));
EXPECT_TRUE
(
testing
::
ExitedWithCode
(
1
)(
1
));
EXPECT_TRUE
(
testing
::
ExitedWithCode
(
42
)(
42
));
EXPECT_FALSE
(
testing
::
ExitedWithCode
(
0
)(
1
));
EXPECT_FALSE
(
testing
::
ExitedWithCode
(
1
)(
0
));
}
# else
// Returns the exit status of a process that calls _exit(2) with a
// given exit code. This is a helper function for the
// ExitStatusPredicateTest test suite.
static
int
NormalExitStatus
(
int
exit_code
)
{
pid_t
child_pid
=
fork
();
if
(
child_pid
==
0
)
{
_exit
(
exit_code
);
}
int
status
;
waitpid
(
child_pid
,
&
status
,
0
);
return
status
;
}
// Returns the exit status of a process that raises a given signal.
// If the signal does not cause the process to die, then it returns
// instead the exit status of a process that exits normally with exit
// code 1. This is a helper function for the ExitStatusPredicateTest
// test suite.
static
int
KilledExitStatus
(
int
signum
)
{
pid_t
child_pid
=
fork
();
if
(
child_pid
==
0
)
{
raise
(
signum
);
_exit
(
1
);
}
int
status
;
waitpid
(
child_pid
,
&
status
,
0
);
return
status
;
}
// Tests the ExitedWithCode predicate.
TEST
(
ExitStatusPredicateTest
,
ExitedWithCode
)
{
const
int
status0
=
NormalExitStatus
(
0
);
const
int
status1
=
NormalExitStatus
(
1
);
const
int
status42
=
NormalExitStatus
(
42
);
const
testing
::
ExitedWithCode
pred0
(
0
);
const
testing
::
ExitedWithCode
pred1
(
1
);
const
testing
::
ExitedWithCode
pred42
(
42
);
EXPECT_PRED1
(
pred0
,
status0
);
EXPECT_PRED1
(
pred1
,
status1
);
EXPECT_PRED1
(
pred42
,
status42
);
EXPECT_FALSE
(
pred0
(
status1
));
EXPECT_FALSE
(
pred42
(
status0
));
EXPECT_FALSE
(
pred1
(
status42
));
}
// Tests the KilledBySignal predicate.
TEST
(
ExitStatusPredicateTest
,
KilledBySignal
)
{
const
int
status_segv
=
KilledExitStatus
(
SIGSEGV
);
const
int
status_kill
=
KilledExitStatus
(
SIGKILL
);
const
testing
::
KilledBySignal
pred_segv
(
SIGSEGV
);
const
testing
::
KilledBySignal
pred_kill
(
SIGKILL
);
EXPECT_PRED1
(
pred_segv
,
status_segv
);
EXPECT_PRED1
(
pred_kill
,
status_kill
);
EXPECT_FALSE
(
pred_segv
(
status_kill
));
EXPECT_FALSE
(
pred_kill
(
status_segv
));
}
# endif // GTEST_OS_WINDOWS
// Tests that the death test macros expand to code which may or may not
// be followed by operator<<, and that in either case the complete text
// comprises only a single C++ statement.
TEST_F
(
TestForDeathTest
,
SingleStatement
)
{
if
(
AlwaysFalse
())
// This would fail if executed; this is a compilation test only
ASSERT_DEATH
(
return
,
""
);
if
(
AlwaysTrue
())
EXPECT_DEATH
(
_exit
(
1
),
""
);
else
// This empty "else" branch is meant to ensure that EXPECT_DEATH
// doesn't expand into an "if" statement without an "else"
;
if
(
AlwaysFalse
())
ASSERT_DEATH
(
return
,
""
)
<<
"did not die"
;
if
(
AlwaysFalse
())
;
else
EXPECT_DEATH
(
_exit
(
1
),
""
)
<<
1
<<
2
<<
3
;
}
void
DieWithEmbeddedNul
()
{
fprintf
(
stderr
,
"Hello%cmy null world.
\n
"
,
'\0'
);
fflush
(
stderr
);
_exit
(
1
);
}
# if GTEST_USES_PCRE
// Tests that EXPECT_DEATH and ASSERT_DEATH work when the error
// message has a NUL character in it.
TEST_F
(
TestForDeathTest
,
EmbeddedNulInMessage
)
{
// TODO(wan@google.com): <regex.h> doesn't support matching strings
// with embedded NUL characters - find a way to workaround it.
EXPECT_DEATH
(
DieWithEmbeddedNul
(),
"my null world"
);
ASSERT_DEATH
(
DieWithEmbeddedNul
(),
"my null world"
);
}
# endif // GTEST_USES_PCRE
// Tests that death test macros expand to code which interacts well with switch
// statements.
TEST_F
(
TestForDeathTest
,
SwitchStatement
)
{
// Microsoft compiler usually complains about switch statements without
// case labels. We suppress that warning for this test.
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4065)
# endif // _MSC_VER
switch
(
0
)
default:
ASSERT_DEATH
(
_exit
(
1
),
""
)
<<
"exit in default switch handler"
;
switch
(
0
)
case
0
:
EXPECT_DEATH
(
_exit
(
1
),
""
)
<<
"exit in switch case"
;
# ifdef _MSC_VER
# pragma warning(pop)
# endif // _MSC_VER
}
// Tests that a static member function can be used in a "fast" style
// death test.
TEST_F
(
TestForDeathTest
,
StaticMemberFunctionFastStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
ASSERT_DEATH
(
StaticMemberFunction
(),
"death.*StaticMember"
);
}
// Tests that a method of the test fixture can be used in a "fast"
// style death test.
TEST_F
(
TestForDeathTest
,
MemberFunctionFastStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
should_die_
=
true
;
EXPECT_DEATH
(
MemberFunction
(),
"inside.*MemberFunction"
);
}
void
ChangeToRootDir
()
{
posix
::
ChDir
(
GTEST_PATH_SEP_
);
}
// Tests that death tests work even if the current directory has been
// changed.
TEST_F
(
TestForDeathTest
,
FastDeathTestInChangedDir
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
ChangeToRootDir
();
EXPECT_EXIT
(
_exit
(
1
),
testing
::
ExitedWithCode
(
1
),
""
);
ChangeToRootDir
();
ASSERT_DEATH
(
_exit
(
1
),
""
);
}
# if GTEST_OS_LINUX
void
SigprofAction
(
int
,
siginfo_t
*
,
void
*
)
{
/* no op */
}
// Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms).
void
SetSigprofActionAndTimer
()
{
struct
itimerval
timer
;
timer
.
it_interval
.
tv_sec
=
0
;
timer
.
it_interval
.
tv_usec
=
1
;
timer
.
it_value
=
timer
.
it_interval
;
ASSERT_EQ
(
0
,
setitimer
(
ITIMER_PROF
,
&
timer
,
NULL
));
struct
sigaction
signal_action
;
memset
(
&
signal_action
,
0
,
sizeof
(
signal_action
));
sigemptyset
(
&
signal_action
.
sa_mask
);
signal_action
.
sa_sigaction
=
SigprofAction
;
signal_action
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
;
ASSERT_EQ
(
0
,
sigaction
(
SIGPROF
,
&
signal_action
,
NULL
));
}
// Disables ITIMER_PROF timer and ignores SIGPROF signal.
void
DisableSigprofActionAndTimer
(
struct
sigaction
*
old_signal_action
)
{
struct
itimerval
timer
;
timer
.
it_interval
.
tv_sec
=
0
;
timer
.
it_interval
.
tv_usec
=
0
;
timer
.
it_value
=
timer
.
it_interval
;
ASSERT_EQ
(
0
,
setitimer
(
ITIMER_PROF
,
&
timer
,
NULL
));
struct
sigaction
signal_action
;
memset
(
&
signal_action
,
0
,
sizeof
(
signal_action
));
sigemptyset
(
&
signal_action
.
sa_mask
);
signal_action
.
sa_handler
=
SIG_IGN
;
ASSERT_EQ
(
0
,
sigaction
(
SIGPROF
,
&
signal_action
,
old_signal_action
));
}
// Tests that death tests work when SIGPROF handler and timer are set.
TEST_F
(
TestForDeathTest
,
FastSigprofActionSet
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
SetSigprofActionAndTimer
();
EXPECT_DEATH
(
_exit
(
1
),
""
);
struct
sigaction
old_signal_action
;
DisableSigprofActionAndTimer
(
&
old_signal_action
);
EXPECT_TRUE
(
old_signal_action
.
sa_sigaction
==
SigprofAction
);
}
TEST_F
(
TestForDeathTest
,
ThreadSafeSigprofActionSet
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
SetSigprofActionAndTimer
();
EXPECT_DEATH
(
_exit
(
1
),
""
);
struct
sigaction
old_signal_action
;
DisableSigprofActionAndTimer
(
&
old_signal_action
);
EXPECT_TRUE
(
old_signal_action
.
sa_sigaction
==
SigprofAction
);
}
# endif // GTEST_OS_LINUX
// Repeats a representative sample of death tests in the "threadsafe" style:
TEST_F
(
TestForDeathTest
,
StaticMemberFunctionThreadsafeStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
ASSERT_DEATH
(
StaticMemberFunction
(),
"death.*StaticMember"
);
}
TEST_F
(
TestForDeathTest
,
MemberFunctionThreadsafeStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
should_die_
=
true
;
EXPECT_DEATH
(
MemberFunction
(),
"inside.*MemberFunction"
);
}
TEST_F
(
TestForDeathTest
,
ThreadsafeDeathTestInLoop
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
EXPECT_EXIT
(
_exit
(
i
),
testing
::
ExitedWithCode
(
i
),
""
)
<<
": i = "
<<
i
;
}
TEST_F
(
TestForDeathTest
,
ThreadsafeDeathTestInChangedDir
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
ChangeToRootDir
();
EXPECT_EXIT
(
_exit
(
1
),
testing
::
ExitedWithCode
(
1
),
""
);
ChangeToRootDir
();
ASSERT_DEATH
(
_exit
(
1
),
""
);
}
TEST_F
(
TestForDeathTest
,
MixedStyles
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
EXPECT_DEATH
(
_exit
(
1
),
""
);
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_DEATH
(
_exit
(
1
),
""
);
}
# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
namespace
{
bool
pthread_flag
;
void
SetPthreadFlag
()
{
pthread_flag
=
true
;
}
}
// namespace
TEST_F
(
TestForDeathTest
,
DoesNotExecuteAtforkHooks
)
{
if
(
!
testing
::
GTEST_FLAG
(
death_test_use_fork
))
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
pthread_flag
=
false
;
ASSERT_EQ
(
0
,
pthread_atfork
(
&
SetPthreadFlag
,
NULL
,
NULL
));
ASSERT_DEATH
(
_exit
(
1
),
""
);
ASSERT_FALSE
(
pthread_flag
);
}
}
# endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
// Tests that a method of another class can be used in a death test.
TEST_F
(
TestForDeathTest
,
MethodOfAnotherClass
)
{
const
MayDie
x
(
true
);
ASSERT_DEATH
(
x
.
MemberFunction
(),
"MayDie
\\
:
\\
:MemberFunction"
);
}
// Tests that a global function can be used in a death test.
TEST_F
(
TestForDeathTest
,
GlobalFunction
)
{
EXPECT_DEATH
(
GlobalFunction
(),
"GlobalFunction"
);
}
// Tests that any value convertible to an RE works as a second
// argument to EXPECT_DEATH.
TEST_F
(
TestForDeathTest
,
AcceptsAnythingConvertibleToRE
)
{
static
const
char
regex_c_str
[]
=
"GlobalFunction"
;
EXPECT_DEATH
(
GlobalFunction
(),
regex_c_str
);
const
testing
::
internal
::
RE
regex
(
regex_c_str
);
EXPECT_DEATH
(
GlobalFunction
(),
regex
);
# if GTEST_HAS_GLOBAL_STRING
const
string
regex_str
(
regex_c_str
);
EXPECT_DEATH
(
GlobalFunction
(),
regex_str
);
# endif // GTEST_HAS_GLOBAL_STRING
const
::
std
::
string
regex_std_str
(
regex_c_str
);
EXPECT_DEATH
(
GlobalFunction
(),
regex_std_str
);
}
// Tests that a non-void function can be used in a death test.
TEST_F
(
TestForDeathTest
,
NonVoidFunction
)
{
ASSERT_DEATH
(
NonVoidFunction
(),
"NonVoidFunction"
);
}
// Tests that functions that take parameter(s) can be used in a death test.
TEST_F
(
TestForDeathTest
,
FunctionWithParameter
)
{
EXPECT_DEATH
(
DieIf
(
true
),
"DieIf
\\
(
\\
)"
);
EXPECT_DEATH
(
DieIfLessThan
(
2
,
3
),
"DieIfLessThan"
);
}
// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
TEST_F
(
TestForDeathTest
,
OutsideFixture
)
{
DeathTestSubroutine
();
}
// Tests that death tests can be done inside a loop.
TEST_F
(
TestForDeathTest
,
InsideLoop
)
{
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
EXPECT_DEATH
(
DieIfLessThan
(
-
1
,
i
),
"DieIfLessThan"
)
<<
"where i == "
<<
i
;
}
}
// Tests that a compound statement can be used in a death test.
TEST_F
(
TestForDeathTest
,
CompoundStatement
)
{
EXPECT_DEATH
({
// NOLINT
const
int
x
=
2
;
const
int
y
=
x
+
1
;
DieIfLessThan
(
x
,
y
);
},
"DieIfLessThan"
);
}
// Tests that code that doesn't die causes a death test to fail.
TEST_F
(
TestForDeathTest
,
DoesNotDie
)
{
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
DieIf
(
false
),
"DieIf"
),
"failed to die"
);
}
// Tests that a death test fails when the error message isn't expected.
TEST_F
(
TestForDeathTest
,
ErrorMessageMismatch
)
{
EXPECT_NONFATAL_FAILURE
({
// NOLINT
EXPECT_DEATH
(
DieIf
(
true
),
"DieIfLessThan"
)
<<
"End of death test message."
;
},
"died but not with expected error"
);
}
// On exit, *aborted will be true iff the EXPECT_DEATH() statement
// aborted the function.
void
ExpectDeathTestHelper
(
bool
*
aborted
)
{
*
aborted
=
true
;
EXPECT_DEATH
(
DieIf
(
false
),
"DieIf"
);
// This assertion should fail.
*
aborted
=
false
;
}
// Tests that EXPECT_DEATH doesn't abort the test on failure.
TEST_F
(
TestForDeathTest
,
EXPECT_DEATH
)
{
bool
aborted
=
true
;
EXPECT_NONFATAL_FAILURE
(
ExpectDeathTestHelper
(
&
aborted
),
"failed to die"
);
EXPECT_FALSE
(
aborted
);
}
// Tests that ASSERT_DEATH does abort the test on failure.
TEST_F
(
TestForDeathTest
,
ASSERT_DEATH
)
{
static
bool
aborted
;
EXPECT_FATAL_FAILURE
({
// NOLINT
aborted
=
true
;
ASSERT_DEATH
(
DieIf
(
false
),
"DieIf"
);
// This assertion should fail.
aborted
=
false
;
},
"failed to die"
);
EXPECT_TRUE
(
aborted
);
}
// Tests that EXPECT_DEATH evaluates the arguments exactly once.
TEST_F
(
TestForDeathTest
,
SingleEvaluation
)
{
int
x
=
3
;
EXPECT_DEATH
(
DieIf
((
++
x
)
==
4
),
"DieIf"
);
const
char
*
regex
=
"DieIf"
;
const
char
*
regex_save
=
regex
;
EXPECT_DEATH
(
DieIfLessThan
(
3
,
4
),
regex
++
);
EXPECT_EQ
(
regex_save
+
1
,
regex
);
}
// Tests that run-away death tests are reported as failures.
TEST_F
(
TestForDeathTest
,
RunawayIsFailure
)
{
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
static_cast
<
void
>
(
0
),
"Foo"
),
"failed to die."
);
}
// Tests that death tests report executing 'return' in the statement as
// failure.
TEST_F
(
TestForDeathTest
,
ReturnIsFailure
)
{
EXPECT_FATAL_FAILURE
(
ASSERT_DEATH
(
return
,
"Bar"
),
"illegal return in test statement."
);
}
// Tests that EXPECT_DEBUG_DEATH works as expected, that is, you can stream a
// message to it, and in debug mode it:
// 1. Asserts on death.
// 2. Has no side effect.
//
// And in opt mode, it:
// 1. Has side effects but does not assert.
TEST_F
(
TestForDeathTest
,
TestExpectDebugDeath
)
{
int
sideeffect
=
0
;
EXPECT_DEBUG_DEATH
(
DieInDebugElse12
(
&
sideeffect
),
"death.*DieInDebugElse12"
)
<<
"Must accept a streamed message"
;
# ifdef NDEBUG
// Checks that the assignment occurs in opt mode (sideeffect).
EXPECT_EQ
(
12
,
sideeffect
);
# else
// Checks that the assignment does not occur in dbg mode (no sideeffect).
EXPECT_EQ
(
0
,
sideeffect
);
# endif
}
// Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a
// message to it, and in debug mode it:
// 1. Asserts on death.
// 2. Has no side effect.
//
// And in opt mode, it:
// 1. Has side effects but does not assert.
TEST_F
(
TestForDeathTest
,
TestAssertDebugDeath
)
{
int
sideeffect
=
0
;
ASSERT_DEBUG_DEATH
(
DieInDebugElse12
(
&
sideeffect
),
"death.*DieInDebugElse12"
)
<<
"Must accept a streamed message"
;
# ifdef NDEBUG
// Checks that the assignment occurs in opt mode (sideeffect).
EXPECT_EQ
(
12
,
sideeffect
);
# else
// Checks that the assignment does not occur in dbg mode (no sideeffect).
EXPECT_EQ
(
0
,
sideeffect
);
# endif
}
# ifndef NDEBUG
void
ExpectDebugDeathHelper
(
bool
*
aborted
)
{
*
aborted
=
true
;
EXPECT_DEBUG_DEATH
(
return
,
""
)
<<
"This is expected to fail."
;
*
aborted
=
false
;
}
# if GTEST_OS_WINDOWS
TEST
(
PopUpDeathTest
,
DoesNotShowPopUpOnAbort
)
{
printf
(
"This test should be considered failing if it shows "
"any pop-up dialogs.
\n
"
);
fflush
(
stdout
);
EXPECT_DEATH
({
testing
::
GTEST_FLAG
(
catch_exceptions
)
=
false
;
abort
();
},
""
);
}
# endif // GTEST_OS_WINDOWS
// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
// the function.
TEST_F
(
TestForDeathTest
,
ExpectDebugDeathDoesNotAbort
)
{
bool
aborted
=
true
;
EXPECT_NONFATAL_FAILURE
(
ExpectDebugDeathHelper
(
&
aborted
),
""
);
EXPECT_FALSE
(
aborted
);
}
void
AssertDebugDeathHelper
(
bool
*
aborted
)
{
*
aborted
=
true
;
ASSERT_DEBUG_DEATH
(
return
,
""
)
<<
"This is expected to fail."
;
*
aborted
=
false
;
}
// Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on
// failure.
TEST_F
(
TestForDeathTest
,
AssertDebugDeathAborts
)
{
static
bool
aborted
;
aborted
=
false
;
EXPECT_FATAL_FAILURE
(
AssertDebugDeathHelper
(
&
aborted
),
""
);
EXPECT_TRUE
(
aborted
);
}
# endif // _NDEBUG
// Tests the *_EXIT family of macros, using a variety of predicates.
static
void
TestExitMacros
()
{
EXPECT_EXIT
(
_exit
(
1
),
testing
::
ExitedWithCode
(
1
),
""
);
ASSERT_EXIT
(
_exit
(
42
),
testing
::
ExitedWithCode
(
42
),
""
);
# if GTEST_OS_WINDOWS
// Of all signals effects on the process exit code, only those of SIGABRT
// are documented on Windows.
// See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx.
EXPECT_EXIT
(
raise
(
SIGABRT
),
testing
::
ExitedWithCode
(
3
),
""
)
<<
"b_ar"
;
# else
EXPECT_EXIT
(
raise
(
SIGKILL
),
testing
::
KilledBySignal
(
SIGKILL
),
""
)
<<
"foo"
;
ASSERT_EXIT
(
raise
(
SIGUSR2
),
testing
::
KilledBySignal
(
SIGUSR2
),
""
)
<<
"bar"
;
EXPECT_FATAL_FAILURE
({
// NOLINT
ASSERT_EXIT
(
_exit
(
0
),
testing
::
KilledBySignal
(
SIGSEGV
),
""
)
<<
"This failure is expected, too."
;
},
"This failure is expected, too."
);
# endif // GTEST_OS_WINDOWS
EXPECT_NONFATAL_FAILURE
({
// NOLINT
EXPECT_EXIT
(
raise
(
SIGSEGV
),
testing
::
ExitedWithCode
(
0
),
""
)
<<
"This failure is expected."
;
},
"This failure is expected."
);
}
TEST_F
(
TestForDeathTest
,
ExitMacros
)
{
TestExitMacros
();
}
TEST_F
(
TestForDeathTest
,
ExitMacrosUsingFork
)
{
testing
::
GTEST_FLAG
(
death_test_use_fork
)
=
true
;
TestExitMacros
();
}
TEST_F
(
TestForDeathTest
,
InvalidStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"rococo"
;
EXPECT_NONFATAL_FAILURE
({
// NOLINT
EXPECT_DEATH
(
_exit
(
0
),
""
)
<<
"This failure is expected."
;
},
"This failure is expected."
);
}
TEST_F
(
TestForDeathTest
,
DeathTestFailedOutput
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
DieWithMessage
(
"death
\n
"
),
"expected message"
),
"Actual msg:
\n
"
"[ DEATH ] death
\n
"
);
}
TEST_F
(
TestForDeathTest
,
DeathTestUnexpectedReturnOutput
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
({
fprintf
(
stderr
,
"returning
\n
"
);
fflush
(
stderr
);
return
;
},
""
),
" Result: illegal return in test statement.
\n
"
" Error msg:
\n
"
"[ DEATH ] returning
\n
"
);
}
TEST_F
(
TestForDeathTest
,
DeathTestBadExitCodeOutput
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_NONFATAL_FAILURE
(
EXPECT_EXIT
(
DieWithMessage
(
"exiting with rc 1
\n
"
),
testing
::
ExitedWithCode
(
3
),
"expected message"
),
" Result: died but not with expected exit code:
\n
"
" Exited with exit status 1
\n
"
"Actual msg:
\n
"
"[ DEATH ] exiting with rc 1
\n
"
);
}
TEST_F
(
TestForDeathTest
,
DeathTestMultiLineMatchFail
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
DieWithMessage
(
"line 1
\n
line 2
\n
line 3
\n
"
),
"line 1
\n
xyz
\n
line 3
\n
"
),
"Actual msg:
\n
"
"[ DEATH ] line 1
\n
"
"[ DEATH ] line 2
\n
"
"[ DEATH ] line 3
\n
"
);
}
TEST_F
(
TestForDeathTest
,
DeathTestMultiLineMatchPass
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_DEATH
(
DieWithMessage
(
"line 1
\n
line 2
\n
line 3
\n
"
),
"line 1
\n
line 2
\n
line 3
\n
"
);
}
// A DeathTestFactory that returns MockDeathTests.
class
MockDeathTestFactory
:
public
DeathTestFactory
{
public:
MockDeathTestFactory
();
virtual
bool
Create
(
const
char
*
statement
,
const
::
testing
::
internal
::
RE
*
regex
,
const
char
*
file
,
int
line
,
DeathTest
**
test
);
// Sets the parameters for subsequent calls to Create.
void
SetParameters
(
bool
create
,
DeathTest
::
TestRole
role
,
int
status
,
bool
passed
);
// Accessors.
int
AssumeRoleCalls
()
const
{
return
assume_role_calls_
;
}
int
WaitCalls
()
const
{
return
wait_calls_
;
}
int
PassedCalls
()
const
{
return
passed_args_
.
size
();
}
bool
PassedArgument
(
int
n
)
const
{
return
passed_args_
[
n
];
}
int
AbortCalls
()
const
{
return
abort_args_
.
size
();
}
DeathTest
::
AbortReason
AbortArgument
(
int
n
)
const
{
return
abort_args_
[
n
];
}
bool
TestDeleted
()
const
{
return
test_deleted_
;
}
private:
friend
class
MockDeathTest
;
// If true, Create will return a MockDeathTest; otherwise it returns
// NULL.
bool
create_
;
// The value a MockDeathTest will return from its AssumeRole method.
DeathTest
::
TestRole
role_
;
// The value a MockDeathTest will return from its Wait method.
int
status_
;
// The value a MockDeathTest will return from its Passed method.
bool
passed_
;
// Number of times AssumeRole was called.
int
assume_role_calls_
;
// Number of times Wait was called.
int
wait_calls_
;
// The arguments to the calls to Passed since the last call to
// SetParameters.
std
::
vector
<
bool
>
passed_args_
;
// The arguments to the calls to Abort since the last call to
// SetParameters.
std
::
vector
<
DeathTest
::
AbortReason
>
abort_args_
;
// True if the last MockDeathTest returned by Create has been
// deleted.
bool
test_deleted_
;
};
// A DeathTest implementation useful in testing. It returns values set
// at its creation from its various inherited DeathTest methods, and
// reports calls to those methods to its parent MockDeathTestFactory
// object.
class
MockDeathTest
:
public
DeathTest
{
public:
MockDeathTest
(
MockDeathTestFactory
*
parent
,
TestRole
role
,
int
status
,
bool
passed
)
:
parent_
(
parent
),
role_
(
role
),
status_
(
status
),
passed_
(
passed
)
{
}
virtual
~
MockDeathTest
()
{
parent_
->
test_deleted_
=
true
;
}
virtual
TestRole
AssumeRole
()
{
++
parent_
->
assume_role_calls_
;
return
role_
;
}
virtual
int
Wait
()
{
++
parent_
->
wait_calls_
;
return
status_
;
}
virtual
bool
Passed
(
bool
exit_status_ok
)
{
parent_
->
passed_args_
.
push_back
(
exit_status_ok
);
return
passed_
;
}
virtual
void
Abort
(
AbortReason
reason
)
{
parent_
->
abort_args_
.
push_back
(
reason
);
}
private:
MockDeathTestFactory
*
const
parent_
;
const
TestRole
role_
;
const
int
status_
;
const
bool
passed_
;
};
// MockDeathTestFactory constructor.
MockDeathTestFactory
::
MockDeathTestFactory
()
:
create_
(
true
),
role_
(
DeathTest
::
OVERSEE_TEST
),
status_
(
0
),
passed_
(
true
),
assume_role_calls_
(
0
),
wait_calls_
(
0
),
passed_args_
(),
abort_args_
()
{
}
// Sets the parameters for subsequent calls to Create.
void
MockDeathTestFactory
::
SetParameters
(
bool
create
,
DeathTest
::
TestRole
role
,
int
status
,
bool
passed
)
{
create_
=
create
;
role_
=
role
;
status_
=
status
;
passed_
=
passed
;
assume_role_calls_
=
0
;
wait_calls_
=
0
;
passed_args_
.
clear
();
abort_args_
.
clear
();
}
// Sets test to NULL (if create_ is false) or to the address of a new
// MockDeathTest object with parameters taken from the last call
// to SetParameters (if create_ is true). Always returns true.
bool
MockDeathTestFactory
::
Create
(
const
char
*
/*statement*/
,
const
::
testing
::
internal
::
RE
*
/*regex*/
,
const
char
*
/*file*/
,
int
/*line*/
,
DeathTest
**
test
)
{
test_deleted_
=
false
;
if
(
create_
)
{
*
test
=
new
MockDeathTest
(
this
,
role_
,
status_
,
passed_
);
}
else
{
*
test
=
NULL
;
}
return
true
;
}
// A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro.
// It installs a MockDeathTestFactory that is used for the duration
// of the test case.
class
MacroLogicDeathTest
:
public
testing
::
Test
{
protected:
static
testing
::
internal
::
ReplaceDeathTestFactory
*
replacer_
;
static
MockDeathTestFactory
*
factory_
;
static
void
SetUpTestCase
()
{
factory_
=
new
MockDeathTestFactory
;
replacer_
=
new
testing
::
internal
::
ReplaceDeathTestFactory
(
factory_
);
}
static
void
TearDownTestCase
()
{
delete
replacer_
;
replacer_
=
NULL
;
delete
factory_
;
factory_
=
NULL
;
}
// Runs a death test that breaks the rules by returning. Such a death
// test cannot be run directly from a test routine that uses a
// MockDeathTest, or the remainder of the routine will not be executed.
static
void
RunReturningDeathTest
(
bool
*
flag
)
{
ASSERT_DEATH
({
// NOLINT
*
flag
=
true
;
return
;
},
""
);
}
};
testing
::
internal
::
ReplaceDeathTestFactory
*
MacroLogicDeathTest
::
replacer_
=
NULL
;
MockDeathTestFactory
*
MacroLogicDeathTest
::
factory_
=
NULL
;
// Test that nothing happens when the factory doesn't return a DeathTest:
TEST_F
(
MacroLogicDeathTest
,
NothingHappens
)
{
bool
flag
=
false
;
factory_
->
SetParameters
(
false
,
DeathTest
::
OVERSEE_TEST
,
0
,
true
);
EXPECT_DEATH
(
flag
=
true
,
""
);
EXPECT_FALSE
(
flag
);
EXPECT_EQ
(
0
,
factory_
->
AssumeRoleCalls
());
EXPECT_EQ
(
0
,
factory_
->
WaitCalls
());
EXPECT_EQ
(
0
,
factory_
->
PassedCalls
());
EXPECT_EQ
(
0
,
factory_
->
AbortCalls
());
EXPECT_FALSE
(
factory_
->
TestDeleted
());
}
// Test that the parent process doesn't run the death test code,
// and that the Passed method returns false when the (simulated)
// child process exits with status 0:
TEST_F
(
MacroLogicDeathTest
,
ChildExitsSuccessfully
)
{
bool
flag
=
false
;
factory_
->
SetParameters
(
true
,
DeathTest
::
OVERSEE_TEST
,
0
,
true
);
EXPECT_DEATH
(
flag
=
true
,
""
);
EXPECT_FALSE
(
flag
);
EXPECT_EQ
(
1
,
factory_
->
AssumeRoleCalls
());
EXPECT_EQ
(
1
,
factory_
->
WaitCalls
());
ASSERT_EQ
(
1
,
factory_
->
PassedCalls
());
EXPECT_FALSE
(
factory_
->
PassedArgument
(
0
));
EXPECT_EQ
(
0
,
factory_
->
AbortCalls
());
EXPECT_TRUE
(
factory_
->
TestDeleted
());
}
// Tests that the Passed method was given the argument "true" when
// the (simulated) child process exits with status 1:
TEST_F
(
MacroLogicDeathTest
,
ChildExitsUnsuccessfully
)
{
bool
flag
=
false
;
factory_
->
SetParameters
(
true
,
DeathTest
::
OVERSEE_TEST
,
1
,
true
);
EXPECT_DEATH
(
flag
=
true
,
""
);
EXPECT_FALSE
(
flag
);
EXPECT_EQ
(
1
,
factory_
->
AssumeRoleCalls
());
EXPECT_EQ
(
1
,
factory_
->
WaitCalls
());
ASSERT_EQ
(
1
,
factory_
->
PassedCalls
());
EXPECT_TRUE
(
factory_
->
PassedArgument
(
0
));
EXPECT_EQ
(
0
,
factory_
->
AbortCalls
());
EXPECT_TRUE
(
factory_
->
TestDeleted
());
}
// Tests that the (simulated) child process executes the death test
// code, and is aborted with the correct AbortReason if it
// executes a return statement.
TEST_F
(
MacroLogicDeathTest
,
ChildPerformsReturn
)
{
bool
flag
=
false
;
factory_
->
SetParameters
(
true
,
DeathTest
::
EXECUTE_TEST
,
0
,
true
);
RunReturningDeathTest
(
&
flag
);
EXPECT_TRUE
(
flag
);
EXPECT_EQ
(
1
,
factory_
->
AssumeRoleCalls
());
EXPECT_EQ
(
0
,
factory_
->
WaitCalls
());
EXPECT_EQ
(
0
,
factory_
->
PassedCalls
());
EXPECT_EQ
(
1
,
factory_
->
AbortCalls
());
EXPECT_EQ
(
DeathTest
::
TEST_ENCOUNTERED_RETURN_STATEMENT
,
factory_
->
AbortArgument
(
0
));
EXPECT_TRUE
(
factory_
->
TestDeleted
());
}
// Tests that the (simulated) child process is aborted with the
// correct AbortReason if it does not die.
TEST_F
(
MacroLogicDeathTest
,
ChildDoesNotDie
)
{
bool
flag
=
false
;
factory_
->
SetParameters
(
true
,
DeathTest
::
EXECUTE_TEST
,
0
,
true
);
EXPECT_DEATH
(
flag
=
true
,
""
);
EXPECT_TRUE
(
flag
);
EXPECT_EQ
(
1
,
factory_
->
AssumeRoleCalls
());
EXPECT_EQ
(
0
,
factory_
->
WaitCalls
());
EXPECT_EQ
(
0
,
factory_
->
PassedCalls
());
// This time there are two calls to Abort: one since the test didn't
// die, and another from the ReturnSentinel when it's destroyed. The
// sentinel normally isn't destroyed if a test doesn't die, since
// _exit(2) is called in that case by ForkingDeathTest, but not by
// our MockDeathTest.
ASSERT_EQ
(
2
,
factory_
->
AbortCalls
());
EXPECT_EQ
(
DeathTest
::
TEST_DID_NOT_DIE
,
factory_
->
AbortArgument
(
0
));
EXPECT_EQ
(
DeathTest
::
TEST_ENCOUNTERED_RETURN_STATEMENT
,
factory_
->
AbortArgument
(
1
));
EXPECT_TRUE
(
factory_
->
TestDeleted
());
}
// Tests that a successful death test does not register a successful
// test part.
TEST
(
SuccessRegistrationDeathTest
,
NoSuccessPart
)
{
EXPECT_DEATH
(
_exit
(
1
),
""
);
EXPECT_EQ
(
0
,
GetUnitTestImpl
()
->
current_test_result
()
->
total_part_count
());
}
TEST
(
StreamingAssertionsDeathTest
,
DeathTest
)
{
EXPECT_DEATH
(
_exit
(
1
),
""
)
<<
"unexpected failure"
;
ASSERT_DEATH
(
_exit
(
1
),
""
)
<<
"unexpected failure"
;
EXPECT_NONFATAL_FAILURE
({
// NOLINT
EXPECT_DEATH
(
_exit
(
0
),
""
)
<<
"expected failure"
;
},
"expected failure"
);
EXPECT_FATAL_FAILURE
({
// NOLINT
ASSERT_DEATH
(
_exit
(
0
),
""
)
<<
"expected failure"
;
},
"expected failure"
);
}
// Tests that GetLastErrnoDescription returns an empty string when the
// last error is 0 and non-empty string when it is non-zero.
TEST
(
GetLastErrnoDescription
,
GetLastErrnoDescriptionWorks
)
{
errno
=
ENOENT
;
EXPECT_STRNE
(
""
,
GetLastErrnoDescription
().
c_str
());
errno
=
0
;
EXPECT_STREQ
(
""
,
GetLastErrnoDescription
().
c_str
());
}
# if GTEST_OS_WINDOWS
TEST
(
AutoHandleTest
,
AutoHandleWorks
)
{
HANDLE
handle
=
::
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ASSERT_NE
(
INVALID_HANDLE_VALUE
,
handle
);
// Tests that the AutoHandle is correctly initialized with a handle.
testing
::
internal
::
AutoHandle
auto_handle
(
handle
);
EXPECT_EQ
(
handle
,
auto_handle
.
Get
());
// Tests that Reset assigns INVALID_HANDLE_VALUE.
// Note that this cannot verify whether the original handle is closed.
auto_handle
.
Reset
();
EXPECT_EQ
(
INVALID_HANDLE_VALUE
,
auto_handle
.
Get
());
// Tests that Reset assigns the new handle.
// Note that this cannot verify whether the original handle is closed.
handle
=
::
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ASSERT_NE
(
INVALID_HANDLE_VALUE
,
handle
);
auto_handle
.
Reset
(
handle
);
EXPECT_EQ
(
handle
,
auto_handle
.
Get
());
// Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
testing
::
internal
::
AutoHandle
auto_handle2
;
EXPECT_EQ
(
INVALID_HANDLE_VALUE
,
auto_handle2
.
Get
());
}
# endif // GTEST_OS_WINDOWS
# if GTEST_OS_WINDOWS
typedef
unsigned
__int64
BiggestParsable
;
typedef
signed
__int64
BiggestSignedParsable
;
# else
typedef
unsigned
long
long
BiggestParsable
;
typedef
signed
long
long
BiggestSignedParsable
;
# endif // GTEST_OS_WINDOWS
// We cannot use std::numeric_limits<T>::max() as it clashes with the
// max() macro defined by <windows.h>.
const
BiggestParsable
kBiggestParsableMax
=
ULLONG_MAX
;
const
BiggestSignedParsable
kBiggestSignedParsableMax
=
LLONG_MAX
;
TEST
(
ParseNaturalNumberTest
,
RejectsInvalidFormat
)
{
BiggestParsable
result
=
0
;
// Rejects non-numbers.
EXPECT_FALSE
(
ParseNaturalNumber
(
"non-number string"
,
&
result
));
// Rejects numbers with whitespace prefix.
EXPECT_FALSE
(
ParseNaturalNumber
(
" 123"
,
&
result
));
// Rejects negative numbers.
EXPECT_FALSE
(
ParseNaturalNumber
(
"-123"
,
&
result
));
// Rejects numbers starting with a plus sign.
EXPECT_FALSE
(
ParseNaturalNumber
(
"+123"
,
&
result
));
errno
=
0
;
}
TEST
(
ParseNaturalNumberTest
,
RejectsOverflownNumbers
)
{
BiggestParsable
result
=
0
;
EXPECT_FALSE
(
ParseNaturalNumber
(
"99999999999999999999999"
,
&
result
));
signed
char
char_result
=
0
;
EXPECT_FALSE
(
ParseNaturalNumber
(
"200"
,
&
char_result
));
errno
=
0
;
}
TEST
(
ParseNaturalNumberTest
,
AcceptsValidNumbers
)
{
BiggestParsable
result
=
0
;
result
=
0
;
ASSERT_TRUE
(
ParseNaturalNumber
(
"123"
,
&
result
));
EXPECT_EQ
(
123U
,
result
);
// Check 0 as an edge case.
result
=
1
;
ASSERT_TRUE
(
ParseNaturalNumber
(
"0"
,
&
result
));
EXPECT_EQ
(
0U
,
result
);
result
=
1
;
ASSERT_TRUE
(
ParseNaturalNumber
(
"00000"
,
&
result
));
EXPECT_EQ
(
0U
,
result
);
}
TEST
(
ParseNaturalNumberTest
,
AcceptsTypeLimits
)
{
Message
msg
;
msg
<<
kBiggestParsableMax
;
BiggestParsable
result
=
0
;
EXPECT_TRUE
(
ParseNaturalNumber
(
msg
.
GetString
(),
&
result
));
EXPECT_EQ
(
kBiggestParsableMax
,
result
);
Message
msg2
;
msg2
<<
kBiggestSignedParsableMax
;
BiggestSignedParsable
signed_result
=
0
;
EXPECT_TRUE
(
ParseNaturalNumber
(
msg2
.
GetString
(),
&
signed_result
));
EXPECT_EQ
(
kBiggestSignedParsableMax
,
signed_result
);
Message
msg3
;
msg3
<<
INT_MAX
;
int
int_result
=
0
;
EXPECT_TRUE
(
ParseNaturalNumber
(
msg3
.
GetString
(),
&
int_result
));
EXPECT_EQ
(
INT_MAX
,
int_result
);
Message
msg4
;
msg4
<<
UINT_MAX
;
unsigned
int
uint_result
=
0
;
EXPECT_TRUE
(
ParseNaturalNumber
(
msg4
.
GetString
(),
&
uint_result
));
EXPECT_EQ
(
UINT_MAX
,
uint_result
);
}
TEST
(
ParseNaturalNumberTest
,
WorksForShorterIntegers
)
{
short
short_result
=
0
;
ASSERT_TRUE
(
ParseNaturalNumber
(
"123"
,
&
short_result
));
EXPECT_EQ
(
123
,
short_result
);
signed
char
char_result
=
0
;
ASSERT_TRUE
(
ParseNaturalNumber
(
"123"
,
&
char_result
));
EXPECT_EQ
(
123
,
char_result
);
}
# if GTEST_OS_WINDOWS
TEST
(
EnvironmentTest
,
HandleFitsIntoSizeT
)
{
// TODO(vladl@google.com): Remove this test after this condition is verified
// in a static assertion in gtest-death-test.cc in the function
// GetStatusFileDescriptor.
ASSERT_TRUE
(
sizeof
(
HANDLE
)
<=
sizeof
(
size_t
));
}
# endif // GTEST_OS_WINDOWS
// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
// failures when death tests are available on the system.
TEST
(
ConditionalDeathMacrosDeathTest
,
ExpectsDeathWhenDeathTestsAvailable
)
{
EXPECT_DEATH_IF_SUPPORTED
(
DieInside
(
"CondDeathTestExpectMacro"
),
"death inside CondDeathTestExpectMacro"
);
ASSERT_DEATH_IF_SUPPORTED
(
DieInside
(
"CondDeathTestAssertMacro"
),
"death inside CondDeathTestAssertMacro"
);
// Empty statement will not crash, which must trigger a failure.
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH_IF_SUPPORTED
(;,
""
),
""
);
EXPECT_FATAL_FAILURE
(
ASSERT_DEATH_IF_SUPPORTED
(;,
""
),
""
);
}
#else
using
testing
::
internal
::
CaptureStderr
;
using
testing
::
internal
::
GetCapturedStderr
;
// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
// defined but do not trigger failures when death tests are not available on
// the system.
TEST
(
ConditionalDeathMacrosTest
,
WarnsWhenDeathTestsNotAvailable
)
{
// Empty statement will not crash, but that should not trigger a failure
// when death tests are not supported.
CaptureStderr
();
EXPECT_DEATH_IF_SUPPORTED
(;,
""
);
std
::
string
output
=
GetCapturedStderr
();
ASSERT_TRUE
(
NULL
!=
strstr
(
output
.
c_str
(),
"Death tests are not supported on this platform"
));
ASSERT_TRUE
(
NULL
!=
strstr
(
output
.
c_str
(),
";"
));
// The streamed message should not be printed as there is no test failure.
CaptureStderr
();
EXPECT_DEATH_IF_SUPPORTED
(;,
""
)
<<
"streamed message"
;
output
=
GetCapturedStderr
();
ASSERT_TRUE
(
NULL
==
strstr
(
output
.
c_str
(),
"streamed message"
));
CaptureStderr
();
ASSERT_DEATH_IF_SUPPORTED
(;,
""
);
// NOLINT
output
=
GetCapturedStderr
();
ASSERT_TRUE
(
NULL
!=
strstr
(
output
.
c_str
(),
"Death tests are not supported on this platform"
));
ASSERT_TRUE
(
NULL
!=
strstr
(
output
.
c_str
(),
";"
));
CaptureStderr
();
ASSERT_DEATH_IF_SUPPORTED
(;,
""
)
<<
"streamed message"
;
// NOLINT
output
=
GetCapturedStderr
();
ASSERT_TRUE
(
NULL
==
strstr
(
output
.
c_str
(),
"streamed message"
));
}
void
FuncWithAssert
(
int
*
n
)
{
ASSERT_DEATH_IF_SUPPORTED
(
return
;,
""
);
(
*
n
)
++
;
}
// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
// function (as ASSERT_DEATH does) if death tests are not supported.
TEST
(
ConditionalDeathMacrosTest
,
AssertDeatDoesNotReturnhIfUnsupported
)
{
int
n
=
0
;
FuncWithAssert
(
&
n
);
EXPECT_EQ
(
1
,
n
);
}
TEST
(
InDeathTestChildDeathTest
,
ReportsDeathTestCorrectlyInFastStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"fast"
;
EXPECT_FALSE
(
InDeathTestChild
());
EXPECT_DEATH
({
fprintf
(
stderr
,
InDeathTestChild
()
?
"Inside"
:
"Outside"
);
fflush
(
stderr
);
_exit
(
1
);
},
"Inside"
);
}
TEST
(
InDeathTestChildDeathTest
,
ReportsDeathTestCorrectlyInThreadSafeStyle
)
{
testing
::
GTEST_FLAG
(
death_test_style
)
=
"threadsafe"
;
EXPECT_FALSE
(
InDeathTestChild
());
EXPECT_DEATH
({
fprintf
(
stderr
,
InDeathTestChild
()
?
"Inside"
:
"Outside"
);
fflush
(
stderr
);
_exit
(
1
);
},
"Inside"
);
}
#endif // GTEST_HAS_DEATH_TEST
// Tests that the death test macros expand to code which may or may not
// be followed by operator<<, and that in either case the complete text
// comprises only a single C++ statement.
//
// The syntax should work whether death tests are available or not.
TEST
(
ConditionalDeathMacrosSyntaxDeathTest
,
SingleStatement
)
{
if
(
AlwaysFalse
())
// This would fail if executed; this is a compilation test only
ASSERT_DEATH_IF_SUPPORTED
(
return
,
""
);
if
(
AlwaysTrue
())
EXPECT_DEATH_IF_SUPPORTED
(
_exit
(
1
),
""
);
else
// This empty "else" branch is meant to ensure that EXPECT_DEATH
// doesn't expand into an "if" statement without an "else"
;
// NOLINT
if
(
AlwaysFalse
())
ASSERT_DEATH_IF_SUPPORTED
(
return
,
""
)
<<
"did not die"
;
if
(
AlwaysFalse
())
;
// NOLINT
else
EXPECT_DEATH_IF_SUPPORTED
(
_exit
(
1
),
""
)
<<
1
<<
2
<<
3
;
}
// Tests that conditional death test macros expand to code which interacts
// well with switch statements.
TEST
(
ConditionalDeathMacrosSyntaxDeathTest
,
SwitchStatement
)
{
// Microsoft compiler usually complains about switch statements without
// case labels. We suppress that warning for this test.
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4065)
#endif // _MSC_VER
switch
(
0
)
default:
ASSERT_DEATH_IF_SUPPORTED
(
_exit
(
1
),
""
)
<<
"exit in default switch handler"
;
switch
(
0
)
case
0
:
EXPECT_DEATH_IF_SUPPORTED
(
_exit
(
1
),
""
)
<<
"exit in switch case"
;
#ifdef _MSC_VER
# pragma warning(pop)
#endif // _MSC_VER
}
// Tests that a test case whose name ends with "DeathTest" works fine
// on Windows.
TEST
(
NotADeathTest
,
Test
)
{
SUCCEED
();
}
test/gtest-1.7.0/test/gtest-filepath_test.cc
0 → 100644
View file @
db82302e
// Copyright 2008, 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.
//
// Authors: keith.ray@gmail.com (Keith Ray)
//
// Google Test filepath utilities
//
// This file tests classes and functions used internally by
// Google Test. They are subject to change without notice.
//
// This file is #included from gtest_unittest.cc, to avoid changing
// build or make-files for some existing Google Test clients. Do not
// #include this file anywhere else!
#include "gtest/internal/gtest-filepath.h"
#include "gtest/gtest.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// his code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS_MOBILE
# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS
# include <direct.h> // NOLINT
#endif // GTEST_OS_WINDOWS_MOBILE
namespace
testing
{
namespace
internal
{
namespace
{
#if GTEST_OS_WINDOWS_MOBILE
// TODO(wan@google.com): Move these to the POSIX adapter section in
// gtest-port.h.
// Windows CE doesn't have the remove C function.
int
remove
(
const
char
*
path
)
{
LPCWSTR
wpath
=
String
::
AnsiToUtf16
(
path
);
int
ret
=
DeleteFile
(
wpath
)
?
0
:
-
1
;
delete
[]
wpath
;
return
ret
;
}
// Windows CE doesn't have the _rmdir C function.
int
_rmdir
(
const
char
*
path
)
{
FilePath
filepath
(
path
);
LPCWSTR
wpath
=
String
::
AnsiToUtf16
(
filepath
.
RemoveTrailingPathSeparator
().
c_str
());
int
ret
=
RemoveDirectory
(
wpath
)
?
0
:
-
1
;
delete
[]
wpath
;
return
ret
;
}
#else
TEST
(
GetCurrentDirTest
,
ReturnsCurrentDir
)
{
const
FilePath
original_dir
=
FilePath
::
GetCurrentDir
();
EXPECT_FALSE
(
original_dir
.
IsEmpty
());
posix
::
ChDir
(
GTEST_PATH_SEP_
);
const
FilePath
cwd
=
FilePath
::
GetCurrentDir
();
posix
::
ChDir
(
original_dir
.
c_str
());
# if GTEST_OS_WINDOWS
// Skips the ":".
const
char
*
const
cwd_without_drive
=
strchr
(
cwd
.
c_str
(),
':'
);
ASSERT_TRUE
(
cwd_without_drive
!=
NULL
);
EXPECT_STREQ
(
GTEST_PATH_SEP_
,
cwd_without_drive
+
1
);
# else
EXPECT_EQ
(
GTEST_PATH_SEP_
,
cwd
.
string
());
# endif
}
#endif // GTEST_OS_WINDOWS_MOBILE
TEST
(
IsEmptyTest
,
ReturnsTrueForEmptyPath
)
{
EXPECT_TRUE
(
FilePath
(
""
).
IsEmpty
());
}
TEST
(
IsEmptyTest
,
ReturnsFalseForNonEmptyPath
)
{
EXPECT_FALSE
(
FilePath
(
"a"
).
IsEmpty
());
EXPECT_FALSE
(
FilePath
(
"."
).
IsEmpty
());
EXPECT_FALSE
(
FilePath
(
"a/b"
).
IsEmpty
());
EXPECT_FALSE
(
FilePath
(
"a
\\
b
\\
"
).
IsEmpty
());
}
// RemoveDirectoryName "" -> ""
TEST
(
RemoveDirectoryNameTest
,
WhenEmptyName
)
{
EXPECT_EQ
(
""
,
FilePath
(
""
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName "afile" -> "afile"
TEST
(
RemoveDirectoryNameTest
,
ButNoDirectory
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"afile"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName "/afile" -> "afile"
TEST
(
RemoveDirectoryNameTest
,
RootFileShouldGiveFileName
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
GTEST_PATH_SEP_
"afile"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName "adir/" -> ""
TEST
(
RemoveDirectoryNameTest
,
WhereThereIsNoFileName
)
{
EXPECT_EQ
(
""
,
FilePath
(
"adir"
GTEST_PATH_SEP_
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName "adir/afile" -> "afile"
TEST
(
RemoveDirectoryNameTest
,
ShouldGiveFileName
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"adir"
GTEST_PATH_SEP_
"afile"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName "adir/subdir/afile" -> "afile"
TEST
(
RemoveDirectoryNameTest
,
ShouldAlsoGiveFileName
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"adir"
GTEST_PATH_SEP_
"subdir"
GTEST_PATH_SEP_
"afile"
)
.
RemoveDirectoryName
().
string
());
}
#if GTEST_HAS_ALT_PATH_SEP_
// Tests that RemoveDirectoryName() works with the alternate separator
// on Windows.
// RemoveDirectoryName("/afile") -> "afile"
TEST
(
RemoveDirectoryNameTest
,
RootFileShouldGiveFileNameForAlternateSeparator
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"/afile"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName("adir/") -> ""
TEST
(
RemoveDirectoryNameTest
,
WhereThereIsNoFileNameForAlternateSeparator
)
{
EXPECT_EQ
(
""
,
FilePath
(
"adir/"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName("adir/afile") -> "afile"
TEST
(
RemoveDirectoryNameTest
,
ShouldGiveFileNameForAlternateSeparator
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"adir/afile"
).
RemoveDirectoryName
().
string
());
}
// RemoveDirectoryName("adir/subdir/afile") -> "afile"
TEST
(
RemoveDirectoryNameTest
,
ShouldAlsoGiveFileNameForAlternateSeparator
)
{
EXPECT_EQ
(
"afile"
,
FilePath
(
"adir/subdir/afile"
).
RemoveDirectoryName
().
string
());
}
#endif
// RemoveFileName "" -> "./"
TEST
(
RemoveFileNameTest
,
EmptyName
)
{
#if GTEST_OS_WINDOWS_MOBILE
// On Windows CE, we use the root as the current directory.
EXPECT_EQ
(
GTEST_PATH_SEP_
,
FilePath
(
""
).
RemoveFileName
().
string
());
#else
EXPECT_EQ
(
"."
GTEST_PATH_SEP_
,
FilePath
(
""
).
RemoveFileName
().
string
());
#endif
}
// RemoveFileName "adir/" -> "adir/"
TEST
(
RemoveFileNameTest
,
ButNoFile
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
,
FilePath
(
"adir"
GTEST_PATH_SEP_
).
RemoveFileName
().
string
());
}
// RemoveFileName "adir/afile" -> "adir/"
TEST
(
RemoveFileNameTest
,
GivesDirName
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
,
FilePath
(
"adir"
GTEST_PATH_SEP_
"afile"
).
RemoveFileName
().
string
());
}
// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
TEST
(
RemoveFileNameTest
,
GivesDirAndSubDirName
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
"subdir"
GTEST_PATH_SEP_
,
FilePath
(
"adir"
GTEST_PATH_SEP_
"subdir"
GTEST_PATH_SEP_
"afile"
)
.
RemoveFileName
().
string
());
}
// RemoveFileName "/afile" -> "/"
TEST
(
RemoveFileNameTest
,
GivesRootDir
)
{
EXPECT_EQ
(
GTEST_PATH_SEP_
,
FilePath
(
GTEST_PATH_SEP_
"afile"
).
RemoveFileName
().
string
());
}
#if GTEST_HAS_ALT_PATH_SEP_
// Tests that RemoveFileName() works with the alternate separator on
// Windows.
// RemoveFileName("adir/") -> "adir/"
TEST
(
RemoveFileNameTest
,
ButNoFileForAlternateSeparator
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
,
FilePath
(
"adir/"
).
RemoveFileName
().
string
());
}
// RemoveFileName("adir/afile") -> "adir/"
TEST
(
RemoveFileNameTest
,
GivesDirNameForAlternateSeparator
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
,
FilePath
(
"adir/afile"
).
RemoveFileName
().
string
());
}
// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
TEST
(
RemoveFileNameTest
,
GivesDirAndSubDirNameForAlternateSeparator
)
{
EXPECT_EQ
(
"adir"
GTEST_PATH_SEP_
"subdir"
GTEST_PATH_SEP_
,
FilePath
(
"adir/subdir/afile"
).
RemoveFileName
().
string
());
}
// RemoveFileName("/afile") -> "\"
TEST
(
RemoveFileNameTest
,
GivesRootDirForAlternateSeparator
)
{
EXPECT_EQ
(
GTEST_PATH_SEP_
,
FilePath
(
"/afile"
).
RemoveFileName
().
string
());
}
#endif
TEST
(
MakeFileNameTest
,
GenerateWhenNumberIsZero
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
"foo"
),
FilePath
(
"bar"
),
0
,
"xml"
);
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar.xml"
,
actual
.
string
());
}
TEST
(
MakeFileNameTest
,
GenerateFileNameNumberGtZero
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
"foo"
),
FilePath
(
"bar"
),
12
,
"xml"
);
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar_12.xml"
,
actual
.
string
());
}
TEST
(
MakeFileNameTest
,
GenerateFileNameWithSlashNumberIsZero
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
"foo"
GTEST_PATH_SEP_
),
FilePath
(
"bar"
),
0
,
"xml"
);
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar.xml"
,
actual
.
string
());
}
TEST
(
MakeFileNameTest
,
GenerateFileNameWithSlashNumberGtZero
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
"foo"
GTEST_PATH_SEP_
),
FilePath
(
"bar"
),
12
,
"xml"
);
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar_12.xml"
,
actual
.
string
());
}
TEST
(
MakeFileNameTest
,
GenerateWhenNumberIsZeroAndDirIsEmpty
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
""
),
FilePath
(
"bar"
),
0
,
"xml"
);
EXPECT_EQ
(
"bar.xml"
,
actual
.
string
());
}
TEST
(
MakeFileNameTest
,
GenerateWhenNumberIsNotZeroAndDirIsEmpty
)
{
FilePath
actual
=
FilePath
::
MakeFileName
(
FilePath
(
""
),
FilePath
(
"bar"
),
14
,
"xml"
);
EXPECT_EQ
(
"bar_14.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
WorksWhenDirDoesNotEndWithPathSep
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
),
FilePath
(
"bar.xml"
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
WorksWhenPath1EndsWithPathSep
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
GTEST_PATH_SEP_
),
FilePath
(
"bar.xml"
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
Path1BeingEmpty
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
""
),
FilePath
(
"bar.xml"
));
EXPECT_EQ
(
"bar.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
Path2BeingEmpty
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
),
FilePath
(
""
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
BothPathBeingEmpty
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
""
),
FilePath
(
""
));
EXPECT_EQ
(
""
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
Path1ContainsPathSep
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
GTEST_PATH_SEP_
"bar"
),
FilePath
(
"foobar.xml"
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
GTEST_PATH_SEP_
"foobar.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
Path2ContainsPathSep
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
GTEST_PATH_SEP_
),
FilePath
(
"bar"
GTEST_PATH_SEP_
"bar.xml"
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
GTEST_PATH_SEP_
"bar.xml"
,
actual
.
string
());
}
TEST
(
ConcatPathsTest
,
Path2EndsWithPathSep
)
{
FilePath
actual
=
FilePath
::
ConcatPaths
(
FilePath
(
"foo"
),
FilePath
(
"bar"
GTEST_PATH_SEP_
));
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
GTEST_PATH_SEP_
,
actual
.
string
());
}
// RemoveTrailingPathSeparator "" -> ""
TEST
(
RemoveTrailingPathSeparatorTest
,
EmptyString
)
{
EXPECT_EQ
(
""
,
FilePath
(
""
).
RemoveTrailingPathSeparator
().
string
());
}
// RemoveTrailingPathSeparator "foo" -> "foo"
TEST
(
RemoveTrailingPathSeparatorTest
,
FileNoSlashString
)
{
EXPECT_EQ
(
"foo"
,
FilePath
(
"foo"
).
RemoveTrailingPathSeparator
().
string
());
}
// RemoveTrailingPathSeparator "foo/" -> "foo"
TEST
(
RemoveTrailingPathSeparatorTest
,
ShouldRemoveTrailingSeparator
)
{
EXPECT_EQ
(
"foo"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
).
RemoveTrailingPathSeparator
().
string
());
#if GTEST_HAS_ALT_PATH_SEP_
EXPECT_EQ
(
"foo"
,
FilePath
(
"foo/"
).
RemoveTrailingPathSeparator
().
string
());
#endif
}
// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
TEST
(
RemoveTrailingPathSeparatorTest
,
ShouldRemoveLastSeparator
)
{
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
"bar"
GTEST_PATH_SEP_
)
.
RemoveTrailingPathSeparator
().
string
());
}
// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
TEST
(
RemoveTrailingPathSeparatorTest
,
ShouldReturnUnmodified
)
{
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
"bar"
)
.
RemoveTrailingPathSeparator
().
string
());
}
TEST
(
DirectoryTest
,
RootDirectoryExists
)
{
#if GTEST_OS_WINDOWS // We are on Windows.
char
current_drive
[
_MAX_PATH
];
// NOLINT
current_drive
[
0
]
=
static_cast
<
char
>
(
_getdrive
()
+
'A'
-
1
);
current_drive
[
1
]
=
':'
;
current_drive
[
2
]
=
'\\'
;
current_drive
[
3
]
=
'\0'
;
EXPECT_TRUE
(
FilePath
(
current_drive
).
DirectoryExists
());
#else
EXPECT_TRUE
(
FilePath
(
"/"
).
DirectoryExists
());
#endif // GTEST_OS_WINDOWS
}
#if GTEST_OS_WINDOWS
TEST
(
DirectoryTest
,
RootOfWrongDriveDoesNotExists
)
{
const
int
saved_drive_
=
_getdrive
();
// Find a drive that doesn't exist. Start with 'Z' to avoid common ones.
for
(
char
drive
=
'Z'
;
drive
>=
'A'
;
drive
--
)
if
(
_chdrive
(
drive
-
'A'
+
1
)
==
-
1
)
{
char
non_drive
[
_MAX_PATH
];
// NOLINT
non_drive
[
0
]
=
drive
;
non_drive
[
1
]
=
':'
;
non_drive
[
2
]
=
'\\'
;
non_drive
[
3
]
=
'\0'
;
EXPECT_FALSE
(
FilePath
(
non_drive
).
DirectoryExists
());
break
;
}
_chdrive
(
saved_drive_
);
}
#endif // GTEST_OS_WINDOWS
#if !GTEST_OS_WINDOWS_MOBILE
// Windows CE _does_ consider an empty directory to exist.
TEST
(
DirectoryTest
,
EmptyPathDirectoryDoesNotExist
)
{
EXPECT_FALSE
(
FilePath
(
""
).
DirectoryExists
());
}
#endif // !GTEST_OS_WINDOWS_MOBILE
TEST
(
DirectoryTest
,
CurrentDirectoryExists
)
{
#if GTEST_OS_WINDOWS // We are on Windows.
# ifndef _WIN32_CE // Windows CE doesn't have a current directory.
EXPECT_TRUE
(
FilePath
(
"."
).
DirectoryExists
());
EXPECT_TRUE
(
FilePath
(
".
\\
"
).
DirectoryExists
());
# endif // _WIN32_CE
#else
EXPECT_TRUE
(
FilePath
(
"."
).
DirectoryExists
());
EXPECT_TRUE
(
FilePath
(
"./"
).
DirectoryExists
());
#endif // GTEST_OS_WINDOWS
}
// "foo/bar" == foo//bar" == "foo///bar"
TEST
(
NormalizeTest
,
MultipleConsecutiveSepaparatorsInMidstring
)
{
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
"bar"
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
GTEST_PATH_SEP_
"bar"
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
"bar"
,
FilePath
(
"foo"
GTEST_PATH_SEP_
GTEST_PATH_SEP_
GTEST_PATH_SEP_
"bar"
).
string
());
}
// "/bar" == //bar" == "///bar"
TEST
(
NormalizeTest
,
MultipleConsecutiveSepaparatorsAtStringStart
)
{
EXPECT_EQ
(
GTEST_PATH_SEP_
"bar"
,
FilePath
(
GTEST_PATH_SEP_
"bar"
).
string
());
EXPECT_EQ
(
GTEST_PATH_SEP_
"bar"
,
FilePath
(
GTEST_PATH_SEP_
GTEST_PATH_SEP_
"bar"
).
string
());
EXPECT_EQ
(
GTEST_PATH_SEP_
"bar"
,
FilePath
(
GTEST_PATH_SEP_
GTEST_PATH_SEP_
GTEST_PATH_SEP_
"bar"
).
string
());
}
// "foo/" == foo//" == "foo///"
TEST
(
NormalizeTest
,
MultipleConsecutiveSepaparatorsAtStringEnd
)
{
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo"
GTEST_PATH_SEP_
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo"
GTEST_PATH_SEP_
GTEST_PATH_SEP_
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo"
GTEST_PATH_SEP_
GTEST_PATH_SEP_
GTEST_PATH_SEP_
).
string
());
}
#if GTEST_HAS_ALT_PATH_SEP_
// Tests that separators at the end of the string are normalized
// regardless of their combination (e.g. "foo\" =="foo/\" ==
// "foo\\/").
TEST
(
NormalizeTest
,
MixAlternateSeparatorAtStringEnd
)
{
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo/"
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo"
GTEST_PATH_SEP_
"/"
).
string
());
EXPECT_EQ
(
"foo"
GTEST_PATH_SEP_
,
FilePath
(
"foo//"
GTEST_PATH_SEP_
).
string
());
}
#endif
TEST
(
AssignmentOperatorTest
,
DefaultAssignedToNonDefault
)
{
FilePath
default_path
;
FilePath
non_default_path
(
"path"
);
non_default_path
=
default_path
;
EXPECT_EQ
(
""
,
non_default_path
.
string
());
EXPECT_EQ
(
""
,
default_path
.
string
());
// RHS var is unchanged.
}
TEST
(
AssignmentOperatorTest
,
NonDefaultAssignedToDefault
)
{
FilePath
non_default_path
(
"path"
);
FilePath
default_path
;
default_path
=
non_default_path
;
EXPECT_EQ
(
"path"
,
default_path
.
string
());
EXPECT_EQ
(
"path"
,
non_default_path
.
string
());
// RHS var is unchanged.
}
TEST
(
AssignmentOperatorTest
,
ConstAssignedToNonConst
)
{
const
FilePath
const_default_path
(
"const_path"
);
FilePath
non_default_path
(
"path"
);
non_default_path
=
const_default_path
;
EXPECT_EQ
(
"const_path"
,
non_default_path
.
string
());
}
class
DirectoryCreationTest
:
public
Test
{
protected:
virtual
void
SetUp
()
{
testdata_path_
.
Set
(
FilePath
(
TempDir
()
+
GetCurrentExecutableName
().
string
()
+
"_directory_creation"
GTEST_PATH_SEP_
"test"
GTEST_PATH_SEP_
));
testdata_file_
.
Set
(
testdata_path_
.
RemoveTrailingPathSeparator
());
unique_file0_
.
Set
(
FilePath
::
MakeFileName
(
testdata_path_
,
FilePath
(
"unique"
),
0
,
"txt"
));
unique_file1_
.
Set
(
FilePath
::
MakeFileName
(
testdata_path_
,
FilePath
(
"unique"
),
1
,
"txt"
));
remove
(
testdata_file_
.
c_str
());
remove
(
unique_file0_
.
c_str
());
remove
(
unique_file1_
.
c_str
());
posix
::
RmDir
(
testdata_path_
.
c_str
());
}
virtual
void
TearDown
()
{
remove
(
testdata_file_
.
c_str
());
remove
(
unique_file0_
.
c_str
());
remove
(
unique_file1_
.
c_str
());
posix
::
RmDir
(
testdata_path_
.
c_str
());
}
std
::
string
TempDir
()
const
{
#if GTEST_OS_WINDOWS_MOBILE
return
"
\\
temp
\\
"
;
#elif GTEST_OS_WINDOWS
const
char
*
temp_dir
=
posix
::
GetEnv
(
"TEMP"
);
if
(
temp_dir
==
NULL
||
temp_dir
[
0
]
==
'\0'
)
return
"
\\
temp
\\
"
;
else
if
(
temp_dir
[
strlen
(
temp_dir
)
-
1
]
==
'\\'
)
return
temp_dir
;
else
return
std
::
string
(
temp_dir
)
+
"
\\
"
;
#elif GTEST_OS_LINUX_ANDROID
return
"/sdcard/"
;
#else
return
"/tmp/"
;
#endif // GTEST_OS_WINDOWS_MOBILE
}
void
CreateTextFile
(
const
char
*
filename
)
{
FILE
*
f
=
posix
::
FOpen
(
filename
,
"w"
);
fprintf
(
f
,
"text
\n
"
);
fclose
(
f
);
}
// Strings representing a directory and a file, with identical paths
// except for the trailing separator character that distinquishes
// a directory named 'test' from a file named 'test'. Example names:
FilePath
testdata_path_
;
// "/tmp/directory_creation/test/"
FilePath
testdata_file_
;
// "/tmp/directory_creation/test"
FilePath
unique_file0_
;
// "/tmp/directory_creation/test/unique.txt"
FilePath
unique_file1_
;
// "/tmp/directory_creation/test/unique_1.txt"
};
TEST_F
(
DirectoryCreationTest
,
CreateDirectoriesRecursively
)
{
EXPECT_FALSE
(
testdata_path_
.
DirectoryExists
())
<<
testdata_path_
.
string
();
EXPECT_TRUE
(
testdata_path_
.
CreateDirectoriesRecursively
());
EXPECT_TRUE
(
testdata_path_
.
DirectoryExists
());
}
TEST_F
(
DirectoryCreationTest
,
CreateDirectoriesForAlreadyExistingPath
)
{
EXPECT_FALSE
(
testdata_path_
.
DirectoryExists
())
<<
testdata_path_
.
string
();
EXPECT_TRUE
(
testdata_path_
.
CreateDirectoriesRecursively
());
// Call 'create' again... should still succeed.
EXPECT_TRUE
(
testdata_path_
.
CreateDirectoriesRecursively
());
}
TEST_F
(
DirectoryCreationTest
,
CreateDirectoriesAndUniqueFilename
)
{
FilePath
file_path
(
FilePath
::
GenerateUniqueFileName
(
testdata_path_
,
FilePath
(
"unique"
),
"txt"
));
EXPECT_EQ
(
unique_file0_
.
string
(),
file_path
.
string
());
EXPECT_FALSE
(
file_path
.
FileOrDirectoryExists
());
// file not there
testdata_path_
.
CreateDirectoriesRecursively
();
EXPECT_FALSE
(
file_path
.
FileOrDirectoryExists
());
// file still not there
CreateTextFile
(
file_path
.
c_str
());
EXPECT_TRUE
(
file_path
.
FileOrDirectoryExists
());
FilePath
file_path2
(
FilePath
::
GenerateUniqueFileName
(
testdata_path_
,
FilePath
(
"unique"
),
"txt"
));
EXPECT_EQ
(
unique_file1_
.
string
(),
file_path2
.
string
());
EXPECT_FALSE
(
file_path2
.
FileOrDirectoryExists
());
// file not there
CreateTextFile
(
file_path2
.
c_str
());
EXPECT_TRUE
(
file_path2
.
FileOrDirectoryExists
());
}
TEST_F
(
DirectoryCreationTest
,
CreateDirectoriesFail
)
{
// force a failure by putting a file where we will try to create a directory.
CreateTextFile
(
testdata_file_
.
c_str
());
EXPECT_TRUE
(
testdata_file_
.
FileOrDirectoryExists
());
EXPECT_FALSE
(
testdata_file_
.
DirectoryExists
());
EXPECT_FALSE
(
testdata_file_
.
CreateDirectoriesRecursively
());
}
TEST
(
NoDirectoryCreationTest
,
CreateNoDirectoriesForDefaultXmlFile
)
{
const
FilePath
test_detail_xml
(
"test_detail.xml"
);
EXPECT_FALSE
(
test_detail_xml
.
CreateDirectoriesRecursively
());
}
TEST
(
FilePathTest
,
DefaultConstructor
)
{
FilePath
fp
;
EXPECT_EQ
(
""
,
fp
.
string
());
}
TEST
(
FilePathTest
,
CharAndCopyConstructors
)
{
const
FilePath
fp
(
"spicy"
);
EXPECT_EQ
(
"spicy"
,
fp
.
string
());
const
FilePath
fp_copy
(
fp
);
EXPECT_EQ
(
"spicy"
,
fp_copy
.
string
());
}
TEST
(
FilePathTest
,
StringConstructor
)
{
const
FilePath
fp
(
std
::
string
(
"cider"
));
EXPECT_EQ
(
"cider"
,
fp
.
string
());
}
TEST
(
FilePathTest
,
Set
)
{
const
FilePath
apple
(
"apple"
);
FilePath
mac
(
"mac"
);
mac
.
Set
(
apple
);
// Implement Set() since overloading operator= is forbidden.
EXPECT_EQ
(
"apple"
,
mac
.
string
());
EXPECT_EQ
(
"apple"
,
apple
.
string
());
}
TEST
(
FilePathTest
,
ToString
)
{
const
FilePath
file
(
"drink"
);
EXPECT_EQ
(
"drink"
,
file
.
string
());
}
TEST
(
FilePathTest
,
RemoveExtension
)
{
EXPECT_EQ
(
"app"
,
FilePath
(
"app.cc"
).
RemoveExtension
(
"cc"
).
string
());
EXPECT_EQ
(
"app"
,
FilePath
(
"app.exe"
).
RemoveExtension
(
"exe"
).
string
());
EXPECT_EQ
(
"APP"
,
FilePath
(
"APP.EXE"
).
RemoveExtension
(
"exe"
).
string
());
}
TEST
(
FilePathTest
,
RemoveExtensionWhenThereIsNoExtension
)
{
EXPECT_EQ
(
"app"
,
FilePath
(
"app"
).
RemoveExtension
(
"exe"
).
string
());
}
TEST
(
FilePathTest
,
IsDirectory
)
{
EXPECT_FALSE
(
FilePath
(
"cola"
).
IsDirectory
());
EXPECT_TRUE
(
FilePath
(
"koala"
GTEST_PATH_SEP_
).
IsDirectory
());
#if GTEST_HAS_ALT_PATH_SEP_
EXPECT_TRUE
(
FilePath
(
"koala/"
).
IsDirectory
());
#endif
}
TEST
(
FilePathTest
,
IsAbsolutePath
)
{
EXPECT_FALSE
(
FilePath
(
"is"
GTEST_PATH_SEP_
"relative"
).
IsAbsolutePath
());
EXPECT_FALSE
(
FilePath
(
""
).
IsAbsolutePath
());
#if GTEST_OS_WINDOWS
EXPECT_TRUE
(
FilePath
(
"c:
\\
"
GTEST_PATH_SEP_
"is_not"
GTEST_PATH_SEP_
"relative"
).
IsAbsolutePath
());
EXPECT_FALSE
(
FilePath
(
"c:foo"
GTEST_PATH_SEP_
"bar"
).
IsAbsolutePath
());
EXPECT_TRUE
(
FilePath
(
"c:/"
GTEST_PATH_SEP_
"is_not"
GTEST_PATH_SEP_
"relative"
).
IsAbsolutePath
());
#else
EXPECT_TRUE
(
FilePath
(
GTEST_PATH_SEP_
"is_not"
GTEST_PATH_SEP_
"relative"
)
.
IsAbsolutePath
());
#endif // GTEST_OS_WINDOWS
}
TEST
(
FilePathTest
,
IsRootDirectory
)
{
#if GTEST_OS_WINDOWS
EXPECT_TRUE
(
FilePath
(
"a:
\\
"
).
IsRootDirectory
());
EXPECT_TRUE
(
FilePath
(
"Z:/"
).
IsRootDirectory
());
EXPECT_TRUE
(
FilePath
(
"e://"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
""
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"b:"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"b:a"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"8:/"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"c|/"
).
IsRootDirectory
());
#else
EXPECT_TRUE
(
FilePath
(
"/"
).
IsRootDirectory
());
EXPECT_TRUE
(
FilePath
(
"//"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
""
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"
\\
"
).
IsRootDirectory
());
EXPECT_FALSE
(
FilePath
(
"/x"
).
IsRootDirectory
());
#endif
}
}
// namespace
}
// namespace internal
}
// namespace testing
test/gtest-1.7.0/test/gtest-linked_ptr_test.cc
0 → 100644
View file @
db82302e
// Copyright 2003, 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.
//
// Authors: Dan Egnor (egnor@google.com)
// Ported to Windows: Vadim Berman (vadimb@google.com)
#include "gtest/internal/gtest-linked_ptr.h"
#include <stdlib.h>
#include "gtest/gtest.h"
namespace
{
using
testing
::
Message
;
using
testing
::
internal
::
linked_ptr
;
int
num
;
Message
*
history
=
NULL
;
// Class which tracks allocation/deallocation
class
A
{
public:
A
()
:
mynum
(
num
++
)
{
*
history
<<
"A"
<<
mynum
<<
" ctor
\n
"
;
}
virtual
~
A
()
{
*
history
<<
"A"
<<
mynum
<<
" dtor
\n
"
;
}
virtual
void
Use
()
{
*
history
<<
"A"
<<
mynum
<<
" use
\n
"
;
}
protected:
int
mynum
;
};
// Subclass
class
B
:
public
A
{
public:
B
()
{
*
history
<<
"B"
<<
mynum
<<
" ctor
\n
"
;
}
~
B
()
{
*
history
<<
"B"
<<
mynum
<<
" dtor
\n
"
;
}
virtual
void
Use
()
{
*
history
<<
"B"
<<
mynum
<<
" use
\n
"
;
}
};
class
LinkedPtrTest
:
public
testing
::
Test
{
public:
LinkedPtrTest
()
{
num
=
0
;
history
=
new
Message
;
}
virtual
~
LinkedPtrTest
()
{
delete
history
;
history
=
NULL
;
}
};
TEST_F
(
LinkedPtrTest
,
GeneralTest
)
{
{
linked_ptr
<
A
>
a0
,
a1
,
a2
;
// Use explicit function call notation here to suppress self-assign warning.
a0
.
operator
=
(
a0
);
a1
=
a2
;
ASSERT_EQ
(
a0
.
get
(),
static_cast
<
A
*>
(
NULL
));
ASSERT_EQ
(
a1
.
get
(),
static_cast
<
A
*>
(
NULL
));
ASSERT_EQ
(
a2
.
get
(),
static_cast
<
A
*>
(
NULL
));
ASSERT_TRUE
(
a0
==
NULL
);
ASSERT_TRUE
(
a1
==
NULL
);
ASSERT_TRUE
(
a2
==
NULL
);
{
linked_ptr
<
A
>
a3
(
new
A
);
a0
=
a3
;
ASSERT_TRUE
(
a0
==
a3
);
ASSERT_TRUE
(
a0
!=
NULL
);
ASSERT_TRUE
(
a0
.
get
()
==
a3
);
ASSERT_TRUE
(
a0
==
a3
.
get
());
linked_ptr
<
A
>
a4
(
a0
);
a1
=
a4
;
linked_ptr
<
A
>
a5
(
new
A
);
ASSERT_TRUE
(
a5
.
get
()
!=
a3
);
ASSERT_TRUE
(
a5
!=
a3
.
get
());
a2
=
a5
;
linked_ptr
<
B
>
b0
(
new
B
);
linked_ptr
<
A
>
a6
(
b0
);
ASSERT_TRUE
(
b0
==
a6
);
ASSERT_TRUE
(
a6
==
b0
);
ASSERT_TRUE
(
b0
!=
NULL
);
a5
=
b0
;
a5
=
b0
;
a3
->
Use
();
a4
->
Use
();
a5
->
Use
();
a6
->
Use
();
b0
->
Use
();
(
*
b0
).
Use
();
b0
.
get
()
->
Use
();
}
a0
->
Use
();
a1
->
Use
();
a2
->
Use
();
a1
=
a2
;
a2
.
reset
(
new
A
);
a0
.
reset
();
linked_ptr
<
A
>
a7
;
}
ASSERT_STREQ
(
"A0 ctor
\n
"
"A1 ctor
\n
"
"A2 ctor
\n
"
"B2 ctor
\n
"
"A0 use
\n
"
"A0 use
\n
"
"B2 use
\n
"
"B2 use
\n
"
"B2 use
\n
"
"B2 use
\n
"
"B2 use
\n
"
"B2 dtor
\n
"
"A2 dtor
\n
"
"A0 use
\n
"
"A0 use
\n
"
"A1 use
\n
"
"A3 ctor
\n
"
"A0 dtor
\n
"
"A3 dtor
\n
"
"A1 dtor
\n
"
,
history
->
GetString
().
c_str
());
}
}
// Unnamed namespace
test/gtest-1.7.0/test/gtest-listener_test.cc
0 → 100644
View file @
db82302e
// Copyright 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: vladl@google.com (Vlad Losev)
//
// The Google C++ Testing Framework (Google Test)
//
// This file verifies Google Test event listeners receive events at the
// right times.
#include "gtest/gtest.h"
#include <vector>
using
::
testing
::
AddGlobalTestEnvironment
;
using
::
testing
::
Environment
;
using
::
testing
::
InitGoogleTest
;
using
::
testing
::
Test
;
using
::
testing
::
TestCase
;
using
::
testing
::
TestEventListener
;
using
::
testing
::
TestInfo
;
using
::
testing
::
TestPartResult
;
using
::
testing
::
UnitTest
;
// Used by tests to register their events.
std
::
vector
<
std
::
string
>*
g_events
=
NULL
;
namespace
testing
{
namespace
internal
{
class
EventRecordingListener
:
public
TestEventListener
{
public:
explicit
EventRecordingListener
(
const
char
*
name
)
:
name_
(
name
)
{}
protected:
virtual
void
OnTestProgramStart
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestProgramStart"
));
}
virtual
void
OnTestIterationStart
(
const
UnitTest
&
/*unit_test*/
,
int
iteration
)
{
Message
message
;
message
<<
GetFullMethodName
(
"OnTestIterationStart"
)
<<
"("
<<
iteration
<<
")"
;
g_events
->
push_back
(
message
.
GetString
());
}
virtual
void
OnEnvironmentsSetUpStart
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnEnvironmentsSetUpStart"
));
}
virtual
void
OnEnvironmentsSetUpEnd
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnEnvironmentsSetUpEnd"
));
}
virtual
void
OnTestCaseStart
(
const
TestCase
&
/*test_case*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestCaseStart"
));
}
virtual
void
OnTestStart
(
const
TestInfo
&
/*test_info*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestStart"
));
}
virtual
void
OnTestPartResult
(
const
TestPartResult
&
/*test_part_result*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestPartResult"
));
}
virtual
void
OnTestEnd
(
const
TestInfo
&
/*test_info*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestEnd"
));
}
virtual
void
OnTestCaseEnd
(
const
TestCase
&
/*test_case*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestCaseEnd"
));
}
virtual
void
OnEnvironmentsTearDownStart
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnEnvironmentsTearDownStart"
));
}
virtual
void
OnEnvironmentsTearDownEnd
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnEnvironmentsTearDownEnd"
));
}
virtual
void
OnTestIterationEnd
(
const
UnitTest
&
/*unit_test*/
,
int
iteration
)
{
Message
message
;
message
<<
GetFullMethodName
(
"OnTestIterationEnd"
)
<<
"("
<<
iteration
<<
")"
;
g_events
->
push_back
(
message
.
GetString
());
}
virtual
void
OnTestProgramEnd
(
const
UnitTest
&
/*unit_test*/
)
{
g_events
->
push_back
(
GetFullMethodName
(
"OnTestProgramEnd"
));
}
private:
std
::
string
GetFullMethodName
(
const
char
*
name
)
{
return
name_
+
"."
+
name
;
}
std
::
string
name_
;
};
class
EnvironmentInvocationCatcher
:
public
Environment
{
protected:
virtual
void
SetUp
()
{
g_events
->
push_back
(
"Environment::SetUp"
);
}
virtual
void
TearDown
()
{
g_events
->
push_back
(
"Environment::TearDown"
);
}
};
class
ListenerTest
:
public
Test
{
protected:
static
void
SetUpTestCase
()
{
g_events
->
push_back
(
"ListenerTest::SetUpTestCase"
);
}
static
void
TearDownTestCase
()
{
g_events
->
push_back
(
"ListenerTest::TearDownTestCase"
);
}
virtual
void
SetUp
()
{
g_events
->
push_back
(
"ListenerTest::SetUp"
);
}
virtual
void
TearDown
()
{
g_events
->
push_back
(
"ListenerTest::TearDown"
);
}
};
TEST_F
(
ListenerTest
,
DoesFoo
)
{
// Test execution order within a test case is not guaranteed so we are not
// recording the test name.
g_events
->
push_back
(
"ListenerTest::* Test Body"
);
SUCCEED
();
// Triggers OnTestPartResult.
}
TEST_F
(
ListenerTest
,
DoesBar
)
{
g_events
->
push_back
(
"ListenerTest::* Test Body"
);
SUCCEED
();
// Triggers OnTestPartResult.
}
}
// namespace internal
}
// namespace testing
using
::
testing
::
internal
::
EnvironmentInvocationCatcher
;
using
::
testing
::
internal
::
EventRecordingListener
;
void
VerifyResults
(
const
std
::
vector
<
std
::
string
>&
data
,
const
char
*
const
*
expected_data
,
int
expected_data_size
)
{
const
int
actual_size
=
data
.
size
();
// If the following assertion fails, a new entry will be appended to
// data. Hence we save data.size() first.
EXPECT_EQ
(
expected_data_size
,
actual_size
);
// Compares the common prefix.
const
int
shorter_size
=
expected_data_size
<=
actual_size
?
expected_data_size
:
actual_size
;
int
i
=
0
;
for
(;
i
<
shorter_size
;
++
i
)
{
ASSERT_STREQ
(
expected_data
[
i
],
data
[
i
].
c_str
())
<<
"at position "
<<
i
;
}
// Prints extra elements in the actual data.
for
(;
i
<
actual_size
;
++
i
)
{
printf
(
" Actual event #%d: %s
\n
"
,
i
,
data
[
i
].
c_str
());
}
}
int
main
(
int
argc
,
char
**
argv
)
{
std
::
vector
<
std
::
string
>
events
;
g_events
=
&
events
;
InitGoogleTest
(
&
argc
,
argv
);
UnitTest
::
GetInstance
()
->
listeners
().
Append
(
new
EventRecordingListener
(
"1st"
));
UnitTest
::
GetInstance
()
->
listeners
().
Append
(
new
EventRecordingListener
(
"2nd"
));
AddGlobalTestEnvironment
(
new
EnvironmentInvocationCatcher
);
GTEST_CHECK_
(
events
.
size
()
==
0
)
<<
"AddGlobalTestEnvironment should not generate any events itself."
;
::
testing
::
GTEST_FLAG
(
repeat
)
=
2
;
int
ret_val
=
RUN_ALL_TESTS
();
const
char
*
const
expected_events
[]
=
{
"1st.OnTestProgramStart"
,
"2nd.OnTestProgramStart"
,
"1st.OnTestIterationStart(0)"
,
"2nd.OnTestIterationStart(0)"
,
"1st.OnEnvironmentsSetUpStart"
,
"2nd.OnEnvironmentsSetUpStart"
,
"Environment::SetUp"
,
"2nd.OnEnvironmentsSetUpEnd"
,
"1st.OnEnvironmentsSetUpEnd"
,
"1st.OnTestCaseStart"
,
"2nd.OnTestCaseStart"
,
"ListenerTest::SetUpTestCase"
,
"1st.OnTestStart"
,
"2nd.OnTestStart"
,
"ListenerTest::SetUp"
,
"ListenerTest::* Test Body"
,
"1st.OnTestPartResult"
,
"2nd.OnTestPartResult"
,
"ListenerTest::TearDown"
,
"2nd.OnTestEnd"
,
"1st.OnTestEnd"
,
"1st.OnTestStart"
,
"2nd.OnTestStart"
,
"ListenerTest::SetUp"
,
"ListenerTest::* Test Body"
,
"1st.OnTestPartResult"
,
"2nd.OnTestPartResult"
,
"ListenerTest::TearDown"
,
"2nd.OnTestEnd"
,
"1st.OnTestEnd"
,
"ListenerTest::TearDownTestCase"
,
"2nd.OnTestCaseEnd"
,
"1st.OnTestCaseEnd"
,
"1st.OnEnvironmentsTearDownStart"
,
"2nd.OnEnvironmentsTearDownStart"
,
"Environment::TearDown"
,
"2nd.OnEnvironmentsTearDownEnd"
,
"1st.OnEnvironmentsTearDownEnd"
,
"2nd.OnTestIterationEnd(0)"
,
"1st.OnTestIterationEnd(0)"
,
"1st.OnTestIterationStart(1)"
,
"2nd.OnTestIterationStart(1)"
,
"1st.OnEnvironmentsSetUpStart"
,
"2nd.OnEnvironmentsSetUpStart"
,
"Environment::SetUp"
,
"2nd.OnEnvironmentsSetUpEnd"
,
"1st.OnEnvironmentsSetUpEnd"
,
"1st.OnTestCaseStart"
,
"2nd.OnTestCaseStart"
,
"ListenerTest::SetUpTestCase"
,
"1st.OnTestStart"
,
"2nd.OnTestStart"
,
"ListenerTest::SetUp"
,
"ListenerTest::* Test Body"
,
"1st.OnTestPartResult"
,
"2nd.OnTestPartResult"
,
"ListenerTest::TearDown"
,
"2nd.OnTestEnd"
,
"1st.OnTestEnd"
,
"1st.OnTestStart"
,
"2nd.OnTestStart"
,
"ListenerTest::SetUp"
,
"ListenerTest::* Test Body"
,
"1st.OnTestPartResult"
,
"2nd.OnTestPartResult"
,
"ListenerTest::TearDown"
,
"2nd.OnTestEnd"
,
"1st.OnTestEnd"
,
"ListenerTest::TearDownTestCase"
,
"2nd.OnTestCaseEnd"
,
"1st.OnTestCaseEnd"
,
"1st.OnEnvironmentsTearDownStart"
,
"2nd.OnEnvironmentsTearDownStart"
,
"Environment::TearDown"
,
"2nd.OnEnvironmentsTearDownEnd"
,
"1st.OnEnvironmentsTearDownEnd"
,
"2nd.OnTestIterationEnd(1)"
,
"1st.OnTestIterationEnd(1)"
,
"2nd.OnTestProgramEnd"
,
"1st.OnTestProgramEnd"
};
VerifyResults
(
events
,
expected_events
,
sizeof
(
expected_events
)
/
sizeof
(
expected_events
[
0
]));
// We need to check manually for ad hoc test failures that happen after
// RUN_ALL_TESTS finishes.
if
(
UnitTest
::
GetInstance
()
->
Failed
())
ret_val
=
1
;
return
ret_val
;
}
Prev
1
2
3
4
5
6
Next
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