Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
f5fa71f7
Commit
f5fa71f7
authored
Apr 05, 2013
by
vladlosev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implements support for calling Test::RecordProperty() outside of a test.
parent
5f18b68b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
512 additions
and
187 deletions
+512
-187
gtest.h
include/gtest/gtest.h
+43
-22
gtest-internal-inl.h
src/gtest-internal-inl.h
+9
-3
gtest.cc
src/gtest.cc
+261
-109
gtest_unittest.cc
test/gtest_unittest.cc
+187
-47
gtest_xml_output_unittest.py
test/gtest_xml_output_unittest.py
+2
-2
gtest_xml_output_unittest_.cc
test/gtest_xml_output_unittest_.cc
+7
-3
gtest_xml_test_utils.py
test/gtest_xml_test_utils.py
+3
-1
No files found.
include/gtest/gtest.h
View file @
f5fa71f7
...
@@ -158,6 +158,7 @@ class StreamingListenerTest;
...
@@ -158,6 +158,7 @@ class StreamingListenerTest;
class
TestResultAccessor
;
class
TestResultAccessor
;
class
TestEventListenersAccessor
;
class
TestEventListenersAccessor
;
class
TestEventRepeater
;
class
TestEventRepeater
;
class
UnitTestRecordPropertyTestHelper
;
class
WindowsDeathTest
;
class
WindowsDeathTest
;
class
UnitTestImpl
*
GetUnitTestImpl
();
class
UnitTestImpl
*
GetUnitTestImpl
();
void
ReportFailureInUnknownLocation
(
TestPartResult
::
Type
result_type
,
void
ReportFailureInUnknownLocation
(
TestPartResult
::
Type
result_type
,
...
@@ -381,20 +382,21 @@ class GTEST_API_ Test {
...
@@ -381,20 +382,21 @@ class GTEST_API_ Test {
// non-fatal) failure.
// non-fatal) failure.
static
bool
HasFailure
()
{
return
HasFatalFailure
()
||
HasNonfatalFailure
();
}
static
bool
HasFailure
()
{
return
HasFatalFailure
()
||
HasNonfatalFailure
();
}
// Logs a property for the current test. Only the last value for a given
// Logs a property for the current test, test case, or for the entire
// key is remembered.
// invocation of the test program when used outside of the context of a
// These are public static so they can be called from utility functions
// test case. Only the last value for a given key is remembered. These
// that are not members of the test fixture.
// are public static so they can be called from utility functions that are
// The arguments are const char* instead strings, as Google Test is used
// not members of the test fixture. Calls to RecordProperty made during
// on platforms where string doesn't compile.
// lifespan of the test (from the moment its constructor starts to the
//
// moment its destructor finishes) will be output in XML as attributes of
// Note that a driving consideration for these RecordProperty methods
// the <testcase> element. Properties recorded from fixture's
// was to produce xml output suited to the Greenspan charting utility,
// SetUpTestCase or TearDownTestCase are logged as attributes of the
// which at present will only chart values that fit in a 32-bit int. It
// corresponding <testsuite> element. Calls to RecordProperty made in the
// is the user's responsibility to restrict their values to 32-bit ints
// global context (before or after invocation of RUN_ALL_TESTS and from
// if they intend them to be used with Greenspan.
// SetUp/TearDown method of Environment objects registered with Google
static
void
RecordProperty
(
const
char
*
key
,
const
char
*
value
);
// Test) will be output as attributes of the <testsuites> element.
static
void
RecordProperty
(
const
char
*
key
,
int
value
);
static
void
RecordProperty
(
const
std
::
string
&
key
,
const
std
::
string
&
value
);
static
void
RecordProperty
(
const
std
::
string
&
key
,
int
value
);
protected
:
protected
:
// Creates a Test object.
// Creates a Test object.
...
@@ -463,7 +465,7 @@ class TestProperty {
...
@@ -463,7 +465,7 @@ class TestProperty {
// C'tor. TestProperty does NOT have a default constructor.
// C'tor. TestProperty does NOT have a default constructor.
// Always use this constructor (with parameters) to create a
// Always use this constructor (with parameters) to create a
// TestProperty object.
// TestProperty object.
TestProperty
(
const
char
*
a_key
,
const
char
*
a_value
)
:
TestProperty
(
const
std
::
string
&
a_key
,
const
std
::
string
&
a_value
)
:
key_
(
a_key
),
value_
(
a_value
)
{
key_
(
a_key
),
value_
(
a_value
)
{
}
}
...
@@ -478,7 +480,7 @@ class TestProperty {
...
@@ -478,7 +480,7 @@ class TestProperty {
}
}
// Sets a new value, overriding the one supplied in the constructor.
// Sets a new value, overriding the one supplied in the constructor.
void
SetValue
(
const
char
*
new_value
)
{
void
SetValue
(
const
std
::
string
&
new_value
)
{
value_
=
new_value
;
value_
=
new_value
;
}
}
...
@@ -537,6 +539,7 @@ class GTEST_API_ TestResult {
...
@@ -537,6 +539,7 @@ class GTEST_API_ TestResult {
private
:
private
:
friend
class
TestInfo
;
friend
class
TestInfo
;
friend
class
TestCase
;
friend
class
UnitTest
;
friend
class
UnitTest
;
friend
class
internal
::
DefaultGlobalTestPartResultReporter
;
friend
class
internal
::
DefaultGlobalTestPartResultReporter
;
friend
class
internal
::
ExecDeathTest
;
friend
class
internal
::
ExecDeathTest
;
...
@@ -561,13 +564,16 @@ class GTEST_API_ TestResult {
...
@@ -561,13 +564,16 @@ class GTEST_API_ TestResult {
// a non-fatal failure if invalid (e.g., if it conflicts with reserved
// a non-fatal failure if invalid (e.g., if it conflicts with reserved
// key names). If a property is already recorded for the same key, the
// key names). If a property is already recorded for the same key, the
// value will be updated, rather than storing multiple values for the same
// value will be updated, rather than storing multiple values for the same
// key.
// key. xml_element specifies the element for which the property is being
void
RecordProperty
(
const
TestProperty
&
test_property
);
// recorded and is used for validation.
void
RecordProperty
(
const
std
::
string
&
xml_element
,
const
TestProperty
&
test_property
);
// Adds a failure if the key is a reserved attribute of Google Test
// Adds a failure if the key is a reserved attribute of Google Test
// testcase tags. Returns true if the property is valid.
// testcase tags. Returns true if the property is valid.
// TODO(russr): Validate attribute names are legal and human readable.
// TODO(russr): Validate attribute names are legal and human readable.
static
bool
ValidateTestProperty
(
const
TestProperty
&
test_property
);
static
bool
ValidateTestProperty
(
const
std
::
string
&
xml_element
,
const
TestProperty
&
test_property
);
// Adds a test part result to the list.
// Adds a test part result to the list.
void
AddTestPartResult
(
const
TestPartResult
&
test_part_result
);
void
AddTestPartResult
(
const
TestPartResult
&
test_part_result
);
...
@@ -792,6 +798,10 @@ class GTEST_API_ TestCase {
...
@@ -792,6 +798,10 @@ class GTEST_API_ TestCase {
// total_test_count() - 1. If i is not in that range, returns NULL.
// total_test_count() - 1. If i is not in that range, returns NULL.
const
TestInfo
*
GetTestInfo
(
int
i
)
const
;
const
TestInfo
*
GetTestInfo
(
int
i
)
const
;
// Returns the TestResult that holds test properties recorded during
// execution of SetUpTestCase and TearDownTestCase.
const
TestResult
&
ad_hoc_test_result
()
const
{
return
ad_hoc_test_result_
;
}
private
:
private
:
friend
class
Test
;
friend
class
Test
;
friend
class
internal
::
UnitTestImpl
;
friend
class
internal
::
UnitTestImpl
;
...
@@ -880,6 +890,9 @@ class GTEST_API_ TestCase {
...
@@ -880,6 +890,9 @@ class GTEST_API_ TestCase {
bool
should_run_
;
bool
should_run_
;
// Elapsed time, in milliseconds.
// Elapsed time, in milliseconds.
TimeInMillis
elapsed_time_
;
TimeInMillis
elapsed_time_
;
// Holds test properties recorded during execution of SetUpTestCase and
// TearDownTestCase.
TestResult
ad_hoc_test_result_
;
// We disallow copying TestCases.
// We disallow copying TestCases.
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
TestCase
);
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
TestCase
);
...
@@ -1165,6 +1178,10 @@ class GTEST_API_ UnitTest {
...
@@ -1165,6 +1178,10 @@ class GTEST_API_ UnitTest {
// total_test_case_count() - 1. If i is not in that range, returns NULL.
// total_test_case_count() - 1. If i is not in that range, returns NULL.
const
TestCase
*
GetTestCase
(
int
i
)
const
;
const
TestCase
*
GetTestCase
(
int
i
)
const
;
// Returns the TestResult containing information on test failures and
// properties logged outside of individual test cases.
const
TestResult
&
ad_hoc_test_result
()
const
;
// Returns the list of event listeners that can be used to track events
// Returns the list of event listeners that can be used to track events
// inside Google Test.
// inside Google Test.
TestEventListeners
&
listeners
();
TestEventListeners
&
listeners
();
...
@@ -1192,9 +1209,12 @@ class GTEST_API_ UnitTest {
...
@@ -1192,9 +1209,12 @@ class GTEST_API_ UnitTest {
const
std
::
string
&
os_stack_trace
)
const
std
::
string
&
os_stack_trace
)
GTEST_LOCK_EXCLUDED_
(
mutex_
);
GTEST_LOCK_EXCLUDED_
(
mutex_
);
// Adds a TestProperty to the current TestResult object. If the result already
// Adds a TestProperty to the current TestResult object when invoked from
// contains a property with the same key, the value will be updated.
// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
void
RecordPropertyForCurrentTest
(
const
char
*
key
,
const
char
*
value
);
// 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
RecordProperty
(
const
std
::
string
&
key
,
const
std
::
string
&
value
);
// Gets the i-th test case among all the test cases. i can range from 0 to
// 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.
// total_test_case_count() - 1. If i is not in that range, returns NULL.
...
@@ -1210,6 +1230,7 @@ class GTEST_API_ UnitTest {
...
@@ -1210,6 +1230,7 @@ class GTEST_API_ UnitTest {
friend
class
internal
::
AssertHelper
;
friend
class
internal
::
AssertHelper
;
friend
class
internal
::
ScopedTrace
;
friend
class
internal
::
ScopedTrace
;
friend
class
internal
::
StreamingListenerTest
;
friend
class
internal
::
StreamingListenerTest
;
friend
class
internal
::
UnitTestRecordPropertyTestHelper
;
friend
Environment
*
AddGlobalTestEnvironment
(
Environment
*
env
);
friend
Environment
*
AddGlobalTestEnvironment
(
Environment
*
env
);
friend
internal
::
UnitTestImpl
*
internal
::
GetUnitTestImpl
();
friend
internal
::
UnitTestImpl
*
internal
::
GetUnitTestImpl
();
friend
void
internal
::
ReportFailureInUnknownLocation
(
friend
void
internal
::
ReportFailureInUnknownLocation
(
...
...
src/gtest-internal-inl.h
View file @
f5fa71f7
...
@@ -348,8 +348,7 @@ class TestPropertyKeyIs {
...
@@ -348,8 +348,7 @@ class TestPropertyKeyIs {
// Constructor.
// Constructor.
//
//
// TestPropertyKeyIs has NO default constructor.
// TestPropertyKeyIs has NO default constructor.
explicit
TestPropertyKeyIs
(
const
char
*
key
)
explicit
TestPropertyKeyIs
(
const
std
::
string
&
key
)
:
key_
(
key
)
{}
:
key_
(
key
)
{}
// Returns true iff the test name of test property matches on key_.
// Returns true iff the test name of test property matches on key_.
bool
operator
()(
const
TestProperty
&
test_property
)
const
{
bool
operator
()(
const
TestProperty
&
test_property
)
const
{
...
@@ -712,6 +711,12 @@ class GTEST_API_ UnitTestImpl {
...
@@ -712,6 +711,12 @@ class GTEST_API_ UnitTestImpl {
ad_hoc_test_result_
.
Clear
();
ad_hoc_test_result_
.
Clear
();
}
}
// Adds a TestProperty to the current TestResult object when invoked in a
// context of a test or a test case, or to the global property set. If the
// result already contains a property with the same key, the value will be
// updated.
void
RecordProperty
(
const
TestProperty
&
test_property
);
enum
ReactionToSharding
{
enum
ReactionToSharding
{
HONOR_SHARDING_PROTOCOL
,
HONOR_SHARDING_PROTOCOL
,
IGNORE_SHARDING_PROTOCOL
IGNORE_SHARDING_PROTOCOL
...
@@ -1038,8 +1043,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
...
@@ -1038,8 +1043,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
class
TestResultAccessor
{
class
TestResultAccessor
{
public
:
public
:
static
void
RecordProperty
(
TestResult
*
test_result
,
static
void
RecordProperty
(
TestResult
*
test_result
,
const
std
::
string
&
xml_element
,
const
TestProperty
&
property
)
{
const
TestProperty
&
property
)
{
test_result
->
RecordProperty
(
property
);
test_result
->
RecordProperty
(
xml_element
,
property
);
}
}
static
void
ClearTestPartResults
(
TestResult
*
test_result
)
{
static
void
ClearTestPartResults
(
TestResult
*
test_result
)
{
...
...
src/gtest.cc
View file @
f5fa71f7
...
@@ -1716,8 +1716,9 @@ void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
...
@@ -1716,8 +1716,9 @@ void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
// Adds a test property to the list. If a property with the same key as the
// 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
// supplied property is already represented, the value of this test_property
// replaces the old value for that key.
// replaces the old value for that key.
void
TestResult
::
RecordProperty
(
const
TestProperty
&
test_property
)
{
void
TestResult
::
RecordProperty
(
const
std
::
string
&
xml_element
,
if
(
!
ValidateTestProperty
(
test_property
))
{
const
TestProperty
&
test_property
)
{
if
(
!
ValidateTestProperty
(
xml_element
,
test_property
))
{
return
;
return
;
}
}
internal
::
MutexLock
lock
(
&
test_properites_mutex_
);
internal
::
MutexLock
lock
(
&
test_properites_mutex_
);
...
@@ -1731,21 +1732,94 @@ void TestResult::RecordProperty(const TestProperty& test_property) {
...
@@ -1731,21 +1732,94 @@ void TestResult::RecordProperty(const TestProperty& test_property) {
property_with_matching_key
->
SetValue
(
test_property
.
value
());
property_with_matching_key
->
SetValue
(
test_property
.
value
());
}
}
// Adds a failure if the key is a reserved attribute of Google Test
// The list of reserved attributes used in the <testsuites> element of XML
// testcase tags. Returns true if the property is valid.
// output.
bool
TestResult
::
ValidateTestProperty
(
const
TestProperty
&
test_property
)
{
static
const
char
*
const
kReservedTestSuitesAttributes
[]
=
{
const
std
::
string
&
key
=
test_property
.
key
();
"disabled"
,
if
(
key
==
"name"
||
key
==
"status"
||
key
==
"time"
||
key
==
"classname"
)
{
"errors"
,
ADD_FAILURE
()
"failures"
,
<<
"Reserved key used in RecordProperty(): "
"name"
,
<<
key
"random_seed"
,
<<
" ('name', 'status', 'time', and 'classname' are reserved by "
"tests"
,
<<
GTEST_NAME_
<<
")"
;
"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
false
;
}
}
return
true
;
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.
// Clears the object.
void
TestResult
::
Clear
()
{
void
TestResult
::
Clear
()
{
test_part_results_
.
clear
();
test_part_results_
.
clear
();
...
@@ -1821,12 +1895,12 @@ void Test::TearDown() {
...
@@ -1821,12 +1895,12 @@ void Test::TearDown() {
}
}
// Allows user supplied key value pairs to be recorded for later output.
// Allows user supplied key value pairs to be recorded for later output.
void
Test
::
RecordProperty
(
const
char
*
key
,
const
char
*
value
)
{
void
Test
::
RecordProperty
(
const
std
::
string
&
key
,
const
std
::
string
&
value
)
{
UnitTest
::
GetInstance
()
->
RecordProperty
ForCurrentTest
(
key
,
value
);
UnitTest
::
GetInstance
()
->
RecordProperty
(
key
,
value
);
}
}
// Allows user supplied key value pairs to be recorded for later output.
// Allows user supplied key value pairs to be recorded for later output.
void
Test
::
RecordProperty
(
const
char
*
key
,
int
value
)
{
void
Test
::
RecordProperty
(
const
std
::
string
&
key
,
int
value
)
{
Message
value_message
;
Message
value_message
;
value_message
<<
value
;
value_message
<<
value
;
RecordProperty
(
key
,
value_message
.
GetString
().
c_str
());
RecordProperty
(
key
,
value_message
.
GetString
().
c_str
());
...
@@ -2355,6 +2429,7 @@ void TestCase::Run() {
...
@@ -2355,6 +2429,7 @@ void TestCase::Run() {
// Clears the results of all tests in this test case.
// Clears the results of all tests in this test case.
void
TestCase
::
ClearResult
()
{
void
TestCase
::
ClearResult
()
{
ad_hoc_test_result_
.
Clear
();
ForEach
(
test_info_list_
,
TestInfo
::
ClearTestResult
);
ForEach
(
test_info_list_
,
TestInfo
::
ClearTestResult
);
}
}
...
@@ -2925,13 +3000,13 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
...
@@ -2925,13 +3000,13 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// is_attribute is true, the text is meant to appear as an attribute
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// value, and normalizable whitespace is preserved by replacing it
// with character references.
// with character references.
static
std
::
string
EscapeXml
(
const
char
*
str
,
bool
is_attribute
);
static
std
::
string
EscapeXml
(
const
std
::
string
&
str
,
bool
is_attribute
);
// Returns the given string with all characters invalid in XML removed.
// Returns the given string with all characters invalid in XML removed.
static
st
ring
RemoveInvalidXmlCharacters
(
const
string
&
str
);
static
st
d
::
string
RemoveInvalidXmlCharacters
(
const
std
::
string
&
str
);
// Convenience wrapper around EscapeXml when str is an attribute value.
// Convenience wrapper around EscapeXml when str is an attribute value.
static
std
::
string
EscapeXmlAttribute
(
const
char
*
str
)
{
static
std
::
string
EscapeXmlAttribute
(
const
std
::
string
&
str
)
{
return
EscapeXml
(
str
,
true
);
return
EscapeXml
(
str
,
true
);
}
}
...
@@ -2940,6 +3015,13 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
...
@@ -2940,6 +3015,13 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
return
EscapeXml
(
str
,
false
);
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.
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
static
void
OutputXmlCDataSection
(
::
std
::
ostream
*
stream
,
const
char
*
data
);
static
void
OutputXmlCDataSection
(
::
std
::
ostream
*
stream
,
const
char
*
data
);
...
@@ -2949,10 +3031,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
...
@@ -2949,10 +3031,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
const
TestInfo
&
test_info
);
const
TestInfo
&
test_info
);
// Prints an XML representation of a TestCase object
// Prints an XML representation of a TestCase object
static
void
PrintXmlTestCase
(
FILE
*
out
,
const
TestCase
&
test_case
);
static
void
PrintXmlTestCase
(
::
std
::
ostream
*
stream
,
const
TestCase
&
test_case
);
// Prints an XML summary of unit_test to output stream out.
// Prints an XML summary of unit_test to output stream out.
static
void
PrintXmlUnitTest
(
FILE
*
out
,
const
UnitTest
&
unit_test
);
static
void
PrintXmlUnitTest
(
::
std
::
ostream
*
stream
,
const
UnitTest
&
unit_test
);
// Produces a string representing the test properties in a result as space
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
// delimited XML attributes based on the property key="value" pairs.
...
@@ -3003,7 +3087,9 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
...
@@ -3003,7 +3087,9 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
fflush
(
stderr
);
fflush
(
stderr
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
PrintXmlUnitTest
(
xmlout
,
unit_test
);
std
::
stringstream
stream
;
PrintXmlUnitTest
(
&
stream
,
unit_test
);
fprintf
(
xmlout
,
"%s"
,
StringStreamToString
(
&
stream
).
c_str
());
fclose
(
xmlout
);
fclose
(
xmlout
);
}
}
...
@@ -3020,43 +3106,42 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
...
@@ -3020,43 +3106,42 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
// escaping scheme for invalid characters, rather than dropping them.
std
::
string
XmlUnitTestResultPrinter
::
EscapeXml
(
std
::
string
XmlUnitTestResultPrinter
::
EscapeXml
(
const
char
*
str
,
bool
is_attribute
)
{
const
std
::
string
&
str
,
bool
is_attribute
)
{
Message
m
;
Message
m
;
if
(
str
!=
NULL
)
{
for
(
size_t
i
=
0
;
i
<
str
.
size
();
++
i
)
{
for
(
const
char
*
src
=
str
;
*
src
;
++
src
)
{
const
char
ch
=
str
[
i
];
switch
(
*
src
)
{
switch
(
ch
)
{
case
'<'
:
case
'<'
:
m
<<
"<"
;
m
<<
"<"
;
break
;
break
;
case
'>'
:
case
'>'
:
m
<<
">"
;
m
<<
">"
;
break
;
break
;
case
'&'
:
case
'&'
:
m
<<
"&"
;
m
<<
"&"
;
break
;
break
;
case
'\''
:
case
'\''
:
if
(
is_attribute
)
if
(
is_attribute
)
m
<<
"'"
;
m
<<
"'"
;
else
else
m
<<
'\''
;
m
<<
'\''
;
break
;
break
;
case
'"'
:
case
'"'
:
if
(
is_attribute
)
if
(
is_attribute
)
m
<<
"""
;
m
<<
"""
;
else
m
<<
'"'
;
break
;
default
:
if
(
IsValidXmlCharacter
(
ch
))
{
if
(
is_attribute
&&
IsNormalizableWhitespace
(
ch
))
m
<<
"&#x"
<<
String
::
FormatByte
(
static_cast
<
unsigned
char
>
(
ch
))
<<
";"
;
else
else
m
<<
'"'
;
m
<<
ch
;
break
;
}
default
:
break
;
if
(
IsValidXmlCharacter
(
*
src
))
{
if
(
is_attribute
&&
IsNormalizableWhitespace
(
*
src
))
m
<<
"&#x"
<<
String
::
FormatByte
(
static_cast
<
unsigned
char
>
(
*
src
))
<<
";"
;
else
m
<<
*
src
;
}
break
;
}
}
}
}
}
...
@@ -3066,10 +3151,11 @@ std::string XmlUnitTestResultPrinter::EscapeXml(
...
@@ -3066,10 +3151,11 @@ std::string XmlUnitTestResultPrinter::EscapeXml(
// Returns the given string with all characters invalid in XML removed.
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
// alternative is to replace them with certain characters such as . or ?.
string
XmlUnitTestResultPrinter
::
RemoveInvalidXmlCharacters
(
const
string
&
str
)
{
std
::
string
XmlUnitTestResultPrinter
::
RemoveInvalidXmlCharacters
(
string
output
;
const
std
::
string
&
str
)
{
std
::
string
output
;
output
.
reserve
(
str
.
size
());
output
.
reserve
(
str
.
size
());
for
(
string
::
const_iterator
it
=
str
.
begin
();
it
!=
str
.
end
();
++
it
)
for
(
st
d
::
st
ring
::
const_iterator
it
=
str
.
begin
();
it
!=
str
.
end
();
++
it
)
if
(
IsValidXmlCharacter
(
*
it
))
if
(
IsValidXmlCharacter
(
*
it
))
output
.
push_back
(
*
it
);
output
.
push_back
(
*
it
);
...
@@ -3145,30 +3231,47 @@ void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
...
@@ -3145,30 +3231,47 @@ void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
*
stream
<<
"]]>"
;
*
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.
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
// TODO(wan): There is also value in printing properties with the plain printer.
void
XmlUnitTestResultPrinter
::
OutputXmlTestInfo
(
::
std
::
ostream
*
stream
,
void
XmlUnitTestResultPrinter
::
OutputXmlTestInfo
(
::
std
::
ostream
*
stream
,
const
char
*
test_case_name
,
const
char
*
test_case_name
,
const
TestInfo
&
test_info
)
{
const
TestInfo
&
test_info
)
{
const
TestResult
&
result
=
*
test_info
.
result
();
const
TestResult
&
result
=
*
test_info
.
result
();
*
stream
<<
" <testcase name=
\"
"
const
std
::
string
kTestcase
=
"testcase"
;
<<
EscapeXmlAttribute
(
test_info
.
name
()).
c_str
()
<<
"
\"
"
;
*
stream
<<
" <testcase"
;
OutputXmlAttribute
(
stream
,
kTestcase
,
"name"
,
test_info
.
name
());
if
(
test_info
.
value_param
()
!=
NULL
)
{
if
(
test_info
.
value_param
()
!=
NULL
)
{
*
stream
<<
" value_param=
\"
"
<<
EscapeXmlAttribute
(
test_info
.
value_param
())
OutputXmlAttribute
(
stream
,
kTestcase
,
"value_param"
,
<<
"
\"
"
;
test_info
.
value_param
())
;
}
}
if
(
test_info
.
type_param
()
!=
NULL
)
{
if
(
test_info
.
type_param
()
!=
NULL
)
{
*
stream
<<
" type_param=
\"
"
<<
EscapeXmlAttribute
(
test_info
.
type_param
())
OutputXmlAttribute
(
stream
,
kTestcase
,
"type_param"
,
test_info
.
type_param
());
<<
"
\"
"
;
}
}
*
stream
<<
" status=
\"
"
OutputXmlAttribute
(
stream
,
kTestcase
,
"status"
,
<<
(
test_info
.
should_run
()
?
"run"
:
"notrun"
)
test_info
.
should_run
()
?
"run"
:
"notrun"
);
<<
"
\"
time=
\"
"
OutputXmlAttribute
(
stream
,
kTestcase
,
"time"
,
<<
FormatTimeInMillisAsSeconds
(
result
.
elapsed_time
())
FormatTimeInMillisAsSeconds
(
result
.
elapsed_time
()));
<<
"
\"
classname=
\"
"
<<
EscapeXmlAttribute
(
test_case_name
).
c_str
()
OutputXmlAttribute
(
stream
,
kTestcase
,
"classname"
,
test_case_name
);
<<
"
\"
"
<<
TestPropertiesAsXmlAttributes
(
result
).
c_str
(
);
*
stream
<<
TestPropertiesAsXmlAttributes
(
result
);
int
failures
=
0
;
int
failures
=
0
;
for
(
int
i
=
0
;
i
<
result
.
total_part_count
();
++
i
)
{
for
(
int
i
=
0
;
i
<
result
.
total_part_count
();
++
i
)
{
...
@@ -3196,45 +3299,64 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
...
@@ -3196,45 +3299,64 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
}
}
// Prints an XML representation of a TestCase object
// Prints an XML representation of a TestCase object
void
XmlUnitTestResultPrinter
::
PrintXmlTestCase
(
FILE
*
out
,
void
XmlUnitTestResultPrinter
::
PrintXmlTestCase
(
std
::
ostream
*
stream
,
const
TestCase
&
test_case
)
{
const
TestCase
&
test_case
)
{
fprintf
(
out
,
const
std
::
string
kTestsuite
=
"testsuite"
;
" <testsuite name=
\"
%s
\"
tests=
\"
%d
\"
failures=
\"
%d
\"
"
*
stream
<<
" <"
<<
kTestsuite
;
"disabled=
\"
%d
\"
"
,
OutputXmlAttribute
(
stream
,
kTestsuite
,
"name"
,
test_case
.
name
());
EscapeXmlAttribute
(
test_case
.
name
()).
c_str
(),
OutputXmlAttribute
(
stream
,
kTestsuite
,
"tests"
,
test_case
.
total_test_count
(),
StreamableToString
(
test_case
.
total_test_count
()));
test_case
.
failed_test_count
(),
OutputXmlAttribute
(
stream
,
kTestsuite
,
"failures"
,
test_case
.
disabled_test_count
());
StreamableToString
(
test_case
.
failed_test_count
()));
fprintf
(
out
,
OutputXmlAttribute
(
stream
,
kTestsuite
,
"disabled"
,
"errors=
\"
0
\"
time=
\"
%s
\"
>
\n
"
,
StreamableToString
(
test_case
.
disabled_test_count
()));
FormatTimeInMillisAsSeconds
(
test_case
.
elapsed_time
()).
c_str
());
OutputXmlAttribute
(
stream
,
kTestsuite
,
"errors"
,
"0"
);
for
(
int
i
=
0
;
i
<
test_case
.
total_test_count
();
++
i
)
{
OutputXmlAttribute
(
stream
,
kTestsuite
,
"time"
,
::
std
::
stringstream
stream
;
FormatTimeInMillisAsSeconds
(
test_case
.
elapsed_time
()));
OutputXmlTestInfo
(
&
stream
,
test_case
.
name
(),
*
test_case
.
GetTestInfo
(
i
));
*
stream
<<
TestPropertiesAsXmlAttributes
(
test_case
.
ad_hoc_test_result
())
fprintf
(
out
,
"%s"
,
StringStreamToString
(
&
stream
).
c_str
());
<<
">
\n
"
;
}
fprintf
(
out
,
" </testsuite>
\n
"
);
for
(
int
i
=
0
;
i
<
test_case
.
total_test_count
();
++
i
)
OutputXmlTestInfo
(
stream
,
test_case
.
name
(),
*
test_case
.
GetTestInfo
(
i
));
*
stream
<<
" </"
<<
kTestsuite
<<
">
\n
"
;
}
}
// Prints an XML summary of unit_test to output stream out.
// Prints an XML summary of unit_test to output stream out.
void
XmlUnitTestResultPrinter
::
PrintXmlUnitTest
(
FILE
*
out
,
void
XmlUnitTestResultPrinter
::
PrintXmlUnitTest
(
std
::
ostream
*
stream
,
const
UnitTest
&
unit_test
)
{
const
UnitTest
&
unit_test
)
{
fprintf
(
out
,
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?>
\n
"
);
const
std
::
string
kTestsuites
=
"testsuites"
;
fprintf
(
out
,
"<testsuites tests=
\"
%d
\"
failures=
\"
%d
\"
disabled=
\"
%d
\"
"
*
stream
<<
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?>
\n
"
;
"errors=
\"
0
\"
timestamp=
\"
%s
\"
time=
\"
%s
\"
"
,
*
stream
<<
"<"
<<
kTestsuites
;
unit_test
.
total_test_count
(),
unit_test
.
failed_test_count
(),
OutputXmlAttribute
(
stream
,
kTestsuites
,
"tests"
,
unit_test
.
disabled_test_count
(),
StreamableToString
(
unit_test
.
total_test_count
()));
FormatEpochTimeInMillisAsIso8601
(
unit_test
.
start_timestamp
()).
c_str
(),
OutputXmlAttribute
(
stream
,
kTestsuites
,
"failures"
,
FormatTimeInMillisAsSeconds
(
unit_test
.
elapsed_time
()).
c_str
());
StreamableToString
(
unit_test
.
failed_test_count
()));
OutputXmlAttribute
(
stream
,
kTestsuites
,
"disabled"
,
StreamableToString
(
unit_test
.
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
))
{
if
(
GTEST_FLAG
(
shuffle
))
{
fprintf
(
out
,
"random_seed=
\"
%d
\"
"
,
unit_test
.
random_seed
());
OutputXmlAttribute
(
stream
,
kTestsuites
,
"random_seed"
,
StreamableToString
(
unit_test
.
random_seed
()));
}
}
fprintf
(
out
,
"name=
\"
AllTests
\"
>
\n
"
);
for
(
int
i
=
0
;
i
<
unit_test
.
total_test_case_count
();
++
i
)
*
stream
<<
TestPropertiesAsXmlAttributes
(
unit_test
.
ad_hoc_test_result
());
PrintXmlTestCase
(
out
,
*
unit_test
.
GetTestCase
(
i
));
fprintf
(
out
,
"</testsuites>
\n
"
);
OutputXmlAttribute
(
stream
,
kTestsuites
,
"name"
,
"AllTests"
);
*
stream
<<
">
\n
"
;
for
(
int
i
=
0
;
i
<
unit_test
.
total_test_case_count
();
++
i
)
{
PrintXmlTestCase
(
stream
,
*
unit_test
.
GetTestCase
(
i
));
}
*
stream
<<
"</"
<<
kTestsuites
<<
">
\n
"
;
}
}
// Produces a string representing the test properties in a result as space
// Produces a string representing the test properties in a result as space
...
@@ -3452,7 +3574,7 @@ void TestEventListeners::SuppressEventForwarding() {
...
@@ -3452,7 +3574,7 @@ void TestEventListeners::SuppressEventForwarding() {
// We don't protect this under mutex_ as a user is not supposed to
// 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
// call this before main() starts, from which point on the return
// value will never change.
// value will never change.
UnitTest
*
UnitTest
::
GetInstance
()
{
UnitTest
*
UnitTest
::
GetInstance
()
{
// When compiled with MSVC 7.1 in optimized mode, destroying the
// When compiled with MSVC 7.1 in optimized mode, destroying the
// UnitTest object upon exiting the program messes up the exit code,
// UnitTest object upon exiting the program messes up the exit code,
// causing successful tests to appear failed. We have to use a
// causing successful tests to appear failed. We have to use a
...
@@ -3537,6 +3659,12 @@ const TestCase* UnitTest::GetTestCase(int i) const {
...
@@ -3537,6 +3659,12 @@ const TestCase* UnitTest::GetTestCase(int i) const {
return
impl
()
->
GetTestCase
(
i
);
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
// 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.
// total_test_case_count() - 1. If i is not in that range, returns NULL.
TestCase
*
UnitTest
::
GetMutableTestCase
(
int
i
)
{
TestCase
*
UnitTest
::
GetMutableTestCase
(
int
i
)
{
...
@@ -3635,12 +3763,14 @@ void UnitTest::AddTestPartResult(
...
@@ -3635,12 +3763,14 @@ void UnitTest::AddTestPartResult(
}
}
}
}
// Creates and adds a property to the current TestResult. If a property matching
// Adds a TestProperty to the current TestResult object when invoked from
// the supplied value already exists, updates its value instead.
// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
void
UnitTest
::
RecordPropertyForCurrentTest
(
const
char
*
key
,
// from SetUpTestCase or TearDownTestCase, or to the global property set
const
char
*
value
)
{
// when invoked elsewhere. If the result already contains a property with
const
TestProperty
test_property
(
key
,
value
);
// the same key, the value will be updated.
impl_
->
current_test_result
()
->
RecordProperty
(
test_property
);
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.
// Runs all tests in this UnitTest object and prints the result.
...
@@ -3813,6 +3943,28 @@ UnitTestImpl::~UnitTestImpl() {
...
@@ -3813,6 +3943,28 @@ UnitTestImpl::~UnitTestImpl() {
delete
os_stack_trace_getter_
;
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
#if GTEST_HAS_DEATH_TEST
// Disables event forwarding if the control is currently in a death test
// Disables event forwarding if the control is currently in a death test
// subprocess. Must not be called before InitGoogleTest.
// subprocess. Must not be called before InitGoogleTest.
...
...
test/gtest_unittest.cc
View file @
f5fa71f7
...
@@ -180,6 +180,18 @@ class TestEventListenersAccessor {
...
@@ -180,6 +180,18 @@ class TestEventListenersAccessor {
}
}
};
};
class
UnitTestRecordPropertyTestHelper
:
public
Test
{
protected
:
UnitTestRecordPropertyTestHelper
()
{}
// Forwards to UnitTest::RecordProperty() to bypass access controls.
void
UnitTestRecordProperty
(
const
char
*
key
,
const
std
::
string
&
value
)
{
unit_test_
.
RecordProperty
(
key
,
value
);
}
UnitTest
unit_test_
;
};
}
// namespace internal
}
// namespace internal
}
// namespace testing
}
// namespace testing
...
@@ -188,6 +200,7 @@ using testing::AssertionResult;
...
@@ -188,6 +200,7 @@ using testing::AssertionResult;
using
testing
::
AssertionSuccess
;
using
testing
::
AssertionSuccess
;
using
testing
::
DoubleLE
;
using
testing
::
DoubleLE
;
using
testing
::
EmptyTestEventListener
;
using
testing
::
EmptyTestEventListener
;
using
testing
::
Environment
;
using
testing
::
FloatLE
;
using
testing
::
FloatLE
;
using
testing
::
GTEST_FLAG
(
also_run_disabled_tests
);
using
testing
::
GTEST_FLAG
(
also_run_disabled_tests
);
using
testing
::
GTEST_FLAG
(
break_on_failure
);
using
testing
::
GTEST_FLAG
(
break_on_failure
);
...
@@ -213,6 +226,7 @@ using testing::StaticAssertTypeEq;
...
@@ -213,6 +226,7 @@ using testing::StaticAssertTypeEq;
using
testing
::
Test
;
using
testing
::
Test
;
using
testing
::
TestCase
;
using
testing
::
TestCase
;
using
testing
::
TestEventListeners
;
using
testing
::
TestEventListeners
;
using
testing
::
TestInfo
;
using
testing
::
TestPartResult
;
using
testing
::
TestPartResult
;
using
testing
::
TestPartResultArray
;
using
testing
::
TestPartResultArray
;
using
testing
::
TestProperty
;
using
testing
::
TestProperty
;
...
@@ -1447,7 +1461,7 @@ TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
...
@@ -1447,7 +1461,7 @@ TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
TEST
(
TestResultPropertyTest
,
OnePropertyFoundWhenAdded
)
{
TEST
(
TestResultPropertyTest
,
OnePropertyFoundWhenAdded
)
{
TestResult
test_result
;
TestResult
test_result
;
TestProperty
property
(
"key_1"
,
"1"
);
TestProperty
property
(
"key_1"
,
"1"
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property
);
ASSERT_EQ
(
1
,
test_result
.
test_property_count
());
ASSERT_EQ
(
1
,
test_result
.
test_property_count
());
const
TestProperty
&
actual_property
=
test_result
.
GetTestProperty
(
0
);
const
TestProperty
&
actual_property
=
test_result
.
GetTestProperty
(
0
);
EXPECT_STREQ
(
"key_1"
,
actual_property
.
key
());
EXPECT_STREQ
(
"key_1"
,
actual_property
.
key
());
...
@@ -1459,8 +1473,8 @@ TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
...
@@ -1459,8 +1473,8 @@ TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
TestResult
test_result
;
TestResult
test_result
;
TestProperty
property_1
(
"key_1"
,
"1"
);
TestProperty
property_1
(
"key_1"
,
"1"
);
TestProperty
property_2
(
"key_2"
,
"2"
);
TestProperty
property_2
(
"key_2"
,
"2"
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_2
);
ASSERT_EQ
(
2
,
test_result
.
test_property_count
());
ASSERT_EQ
(
2
,
test_result
.
test_property_count
());
const
TestProperty
&
actual_property_1
=
test_result
.
GetTestProperty
(
0
);
const
TestProperty
&
actual_property_1
=
test_result
.
GetTestProperty
(
0
);
EXPECT_STREQ
(
"key_1"
,
actual_property_1
.
key
());
EXPECT_STREQ
(
"key_1"
,
actual_property_1
.
key
());
...
@@ -1478,10 +1492,10 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
...
@@ -1478,10 +1492,10 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
TestProperty
property_2_1
(
"key_2"
,
"2"
);
TestProperty
property_2_1
(
"key_2"
,
"2"
);
TestProperty
property_1_2
(
"key_1"
,
"12"
);
TestProperty
property_1_2
(
"key_1"
,
"12"
);
TestProperty
property_2_2
(
"key_2"
,
"22"
);
TestProperty
property_2_2
(
"key_2"
,
"22"
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_1_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_1_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_2_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_2_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_1_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_1_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_2_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_2_2
);
ASSERT_EQ
(
2
,
test_result
.
test_property_count
());
ASSERT_EQ
(
2
,
test_result
.
test_property_count
());
const
TestProperty
&
actual_property_1
=
test_result
.
GetTestProperty
(
0
);
const
TestProperty
&
actual_property_1
=
test_result
.
GetTestProperty
(
0
);
...
@@ -1494,14 +1508,14 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
...
@@ -1494,14 +1508,14 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
}
}
// Tests TestResult::GetTestProperty().
// Tests TestResult::GetTestProperty().
TEST
(
TestResultProperty
Death
Test
,
GetTestProperty
)
{
TEST
(
TestResultPropertyTest
,
GetTestProperty
)
{
TestResult
test_result
;
TestResult
test_result
;
TestProperty
property_1
(
"key_1"
,
"1"
);
TestProperty
property_1
(
"key_1"
,
"1"
);
TestProperty
property_2
(
"key_2"
,
"2"
);
TestProperty
property_2
(
"key_2"
,
"2"
);
TestProperty
property_3
(
"key_3"
,
"3"
);
TestProperty
property_3
(
"key_3"
,
"3"
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_1
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_2
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property_3
);
TestResultAccessor
::
RecordProperty
(
&
test_result
,
"testcase"
,
property_3
);
const
TestProperty
&
fetched_property_1
=
test_result
.
GetTestProperty
(
0
);
const
TestProperty
&
fetched_property_1
=
test_result
.
GetTestProperty
(
0
);
const
TestProperty
&
fetched_property_2
=
test_result
.
GetTestProperty
(
1
);
const
TestProperty
&
fetched_property_2
=
test_result
.
GetTestProperty
(
1
);
...
@@ -1520,42 +1534,6 @@ TEST(TestResultPropertyDeathTest, GetTestProperty) {
...
@@ -1520,42 +1534,6 @@ TEST(TestResultPropertyDeathTest, GetTestProperty) {
EXPECT_DEATH_IF_SUPPORTED
(
test_result
.
GetTestProperty
(
-
1
),
""
);
EXPECT_DEATH_IF_SUPPORTED
(
test_result
.
GetTestProperty
(
-
1
),
""
);
}
}
// When a property using a reserved key is supplied to this function, it tests
// that a non-fatal failure is added, a fatal failure is not added, and that the
// property is not recorded.
void
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
const
char
*
key
)
{
TestResult
test_result
;
TestProperty
property
(
key
,
"1"
);
EXPECT_NONFATAL_FAILURE
(
TestResultAccessor
::
RecordProperty
(
&
test_result
,
property
),
"Reserved key"
);
ASSERT_EQ
(
0
,
test_result
.
test_property_count
())
<<
"Not recorded"
;
}
// Attempting to recording a property with the Reserved literal "name"
// should add a non-fatal failure and the property should not be recorded.
TEST
(
TestResultPropertyTest
,
AddFailureWhenUsingReservedKeyCalledName
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
"name"
);
}
// Attempting to recording a property with the Reserved literal "status"
// should add a non-fatal failure and the property should not be recorded.
TEST
(
TestResultPropertyTest
,
AddFailureWhenUsingReservedKeyCalledStatus
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
"status"
);
}
// Attempting to recording a property with the Reserved literal "time"
// should add a non-fatal failure and the property should not be recorded.
TEST
(
TestResultPropertyTest
,
AddFailureWhenUsingReservedKeyCalledTime
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
"time"
);
}
// Attempting to recording a property with the Reserved literal "classname"
// should add a non-fatal failure and the property should not be recorded.
TEST
(
TestResultPropertyTest
,
AddFailureWhenUsingReservedKeyCalledClassname
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
"classname"
);
}
// Tests that GTestFlagSaver works on Windows and Mac.
// Tests that GTestFlagSaver works on Windows and Mac.
class
GTestFlagSaverTest
:
public
Test
{
class
GTestFlagSaverTest
:
public
Test
{
...
@@ -1961,6 +1939,168 @@ TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
...
@@ -1961,6 +1939,168 @@ TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
EXPECT_LE
(
UnitTest
::
GetInstance
()
->
start_timestamp
(),
GetTimeInMillis
());
EXPECT_LE
(
UnitTest
::
GetInstance
()
->
start_timestamp
(),
GetTimeInMillis
());
}
}
// When a property using a reserved key is supplied to this function, it
// tests that a non-fatal failure is added, a fatal failure is not added,
// and that the property is not recorded.
void
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
const
TestResult
&
test_result
,
const
char
*
key
)
{
EXPECT_NONFATAL_FAILURE
(
Test
::
RecordProperty
(
key
,
"1"
),
"Reserved key"
);
ASSERT_EQ
(
0
,
test_result
.
test_property_count
())
<<
"Property for key '"
<<
key
<<
"' recorded unexpectedly."
;
}
void
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
const
char
*
key
)
{
const
TestInfo
*
test_info
=
UnitTest
::
GetInstance
()
->
current_test_info
();
ASSERT_TRUE
(
test_info
!=
NULL
);
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
*
test_info
->
result
(),
key
);
}
void
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
const
char
*
key
)
{
const
TestCase
*
test_case
=
UnitTest
::
GetInstance
()
->
current_test_case
();
ASSERT_TRUE
(
test_case
!=
NULL
);
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
test_case
->
ad_hoc_test_result
(),
key
);
}
void
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
const
char
*
key
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKey
(
UnitTest
::
GetInstance
()
->
ad_hoc_test_result
(),
key
);
}
// Tests that property recording functions in UnitTest outside of tests
// functions correcly. Creating a separate instance of UnitTest ensures it
// is in a state similar to the UnitTest's singleton's between tests.
class
UnitTestRecordPropertyTest
:
public
testing
::
internal
::
UnitTestRecordPropertyTestHelper
{
public
:
static
void
SetUpTestCase
()
{
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"disabled"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"errors"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"failures"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"name"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"tests"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase
(
"time"
);
Test
::
RecordProperty
(
"test_case_key_1"
,
"1"
);
const
TestCase
*
test_case
=
UnitTest
::
GetInstance
()
->
current_test_case
();
ASSERT_TRUE
(
test_case
!=
NULL
);
ASSERT_EQ
(
1
,
test_case
->
ad_hoc_test_result
().
test_property_count
());
EXPECT_STREQ
(
"test_case_key_1"
,
test_case
->
ad_hoc_test_result
().
GetTestProperty
(
0
).
key
());
EXPECT_STREQ
(
"1"
,
test_case
->
ad_hoc_test_result
().
GetTestProperty
(
0
).
value
());
}
};
// Tests TestResult has the expected property when added.
TEST_F
(
UnitTestRecordPropertyTest
,
OnePropertyFoundWhenAdded
)
{
UnitTestRecordProperty
(
"key_1"
,
"1"
);
ASSERT_EQ
(
1
,
unit_test_
.
ad_hoc_test_result
().
test_property_count
());
EXPECT_STREQ
(
"key_1"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
key
());
EXPECT_STREQ
(
"1"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
value
());
}
// Tests TestResult has multiple properties when added.
TEST_F
(
UnitTestRecordPropertyTest
,
MultiplePropertiesFoundWhenAdded
)
{
UnitTestRecordProperty
(
"key_1"
,
"1"
);
UnitTestRecordProperty
(
"key_2"
,
"2"
);
ASSERT_EQ
(
2
,
unit_test_
.
ad_hoc_test_result
().
test_property_count
());
EXPECT_STREQ
(
"key_1"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
key
());
EXPECT_STREQ
(
"1"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
value
());
EXPECT_STREQ
(
"key_2"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
1
).
key
());
EXPECT_STREQ
(
"2"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
1
).
value
());
}
// Tests TestResult::RecordProperty() overrides values for duplicate keys.
TEST_F
(
UnitTestRecordPropertyTest
,
OverridesValuesForDuplicateKeys
)
{
UnitTestRecordProperty
(
"key_1"
,
"1"
);
UnitTestRecordProperty
(
"key_2"
,
"2"
);
UnitTestRecordProperty
(
"key_1"
,
"12"
);
UnitTestRecordProperty
(
"key_2"
,
"22"
);
ASSERT_EQ
(
2
,
unit_test_
.
ad_hoc_test_result
().
test_property_count
());
EXPECT_STREQ
(
"key_1"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
key
());
EXPECT_STREQ
(
"12"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
0
).
value
());
EXPECT_STREQ
(
"key_2"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
1
).
key
());
EXPECT_STREQ
(
"22"
,
unit_test_
.
ad_hoc_test_result
().
GetTestProperty
(
1
).
value
());
}
TEST_F
(
UnitTestRecordPropertyTest
,
AddFailureInsideTestsWhenUsingTestCaseReservedKeys
)
{
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"name"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"value_param"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"type_param"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"status"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"time"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest
(
"classname"
);
}
TEST_F
(
UnitTestRecordPropertyTest
,
AddRecordWithReservedKeysGeneratesCorrectPropertyList
)
{
EXPECT_NONFATAL_FAILURE
(
Test
::
RecordProperty
(
"name"
,
"1"
),
"'classname', 'name', 'status', 'time', 'type_param', and 'value_param'"
" are reserved"
);
}
class
UnitTestRecordPropertyTestEnvironment
:
public
Environment
{
public
:
virtual
void
TearDown
()
{
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"tests"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"failures"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"disabled"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"errors"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"name"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"timestamp"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"time"
);
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase
(
"random_seed"
);
}
};
// This will test property recording outside of any test or test case.
static
Environment
*
record_property_env
=
AddGlobalTestEnvironment
(
new
UnitTestRecordPropertyTestEnvironment
);
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
// of various arities. They do not attempt to be exhaustive. Rather,
// of various arities. They do not attempt to be exhaustive. Rather,
// view them as smoke tests that can be easily reviewed and verified.
// view them as smoke tests that can be easily reviewed and verified.
...
...
test/gtest_xml_output_unittest.py
View file @
f5fa71f7
...
@@ -57,7 +57,7 @@ else:
...
@@ -57,7 +57,7 @@ else:
STACK_TRACE_TEMPLATE
=
''
STACK_TRACE_TEMPLATE
=
''
EXPECTED_NON_EMPTY_XML
=
"""<?xml version="1.0" encoding="UTF-8"?>
EXPECTED_NON_EMPTY_XML
=
"""<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="23" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests">
<testsuites tests="23" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests"
ad_hoc_property="42"
>
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
<testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
</testsuite>
</testsuite>
...
@@ -97,7 +97,7 @@ Invalid characters in brackets []%(stack)s]]></failure>
...
@@ -97,7 +97,7 @@ Invalid characters in brackets []%(stack)s]]></failure>
<testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
<testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
<testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
<testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
</testsuite>
</testsuite>
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*">
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*"
SetUpTestCase="yes" TearDownTestCase="aye"
>
<testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/>
<testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/>
<testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/>
<testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/>
<testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/>
<testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/>
...
...
test/gtest_xml_output_unittest_.cc
View file @
f5fa71f7
...
@@ -95,6 +95,9 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
...
@@ -95,6 +95,9 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
}
}
class
PropertyRecordingTest
:
public
Test
{
class
PropertyRecordingTest
:
public
Test
{
public
:
static
void
SetUpTestCase
()
{
RecordProperty
(
"SetUpTestCase"
,
"yes"
);
}
static
void
TearDownTestCase
()
{
RecordProperty
(
"TearDownTestCase"
,
"aye"
);
}
};
};
TEST_F
(
PropertyRecordingTest
,
OneProperty
)
{
TEST_F
(
PropertyRecordingTest
,
OneProperty
)
{
...
@@ -120,12 +123,12 @@ TEST(NoFixtureTest, RecordProperty) {
...
@@ -120,12 +123,12 @@ TEST(NoFixtureTest, RecordProperty) {
RecordProperty
(
"key"
,
"1"
);
RecordProperty
(
"key"
,
"1"
);
}
}
void
ExternalUtilityThatCallsRecordProperty
(
const
char
*
key
,
int
value
)
{
void
ExternalUtilityThatCallsRecordProperty
(
const
std
::
string
&
key
,
int
value
)
{
testing
::
Test
::
RecordProperty
(
key
,
value
);
testing
::
Test
::
RecordProperty
(
key
,
value
);
}
}
void
ExternalUtilityThatCallsRecordProperty
(
const
char
*
key
,
void
ExternalUtilityThatCallsRecordProperty
(
const
std
::
string
&
key
,
const
char
*
value
)
{
const
std
::
string
&
value
)
{
testing
::
Test
::
RecordProperty
(
key
,
value
);
testing
::
Test
::
RecordProperty
(
key
,
value
);
}
}
...
@@ -173,5 +176,6 @@ int main(int argc, char** argv) {
...
@@ -173,5 +176,6 @@ int main(int argc, char** argv) {
TestEventListeners
&
listeners
=
UnitTest
::
GetInstance
()
->
listeners
();
TestEventListeners
&
listeners
=
UnitTest
::
GetInstance
()
->
listeners
();
delete
listeners
.
Release
(
listeners
.
default_xml_generator
());
delete
listeners
.
Release
(
listeners
.
default_xml_generator
());
}
}
testing
::
Test
::
RecordProperty
(
"ad_hoc_property"
,
"42"
);
return
RUN_ALL_TESTS
();
return
RUN_ALL_TESTS
();
}
}
test/gtest_xml_test_utils.py
View file @
f5fa71f7
...
@@ -80,7 +80,9 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
...
@@ -80,7 +80,9 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
actual_attributes
=
actual_node
.
attributes
actual_attributes
=
actual_node
.
attributes
self
.
assertEquals
(
self
.
assertEquals
(
expected_attributes
.
length
,
actual_attributes
.
length
,
expected_attributes
.
length
,
actual_attributes
.
length
,
'attribute numbers differ in element '
+
actual_node
.
tagName
)
'attribute numbers differ in element
%
s:
\n
Expected:
%
r
\n
Actual:
%
r'
%
(
actual_node
.
tagName
,
expected_attributes
.
keys
(),
actual_attributes
.
keys
()))
for
i
in
range
(
expected_attributes
.
length
):
for
i
in
range
(
expected_attributes
.
length
):
expected_attr
=
expected_attributes
.
item
(
i
)
expected_attr
=
expected_attributes
.
item
(
i
)
actual_attr
=
actual_attributes
.
get
(
expected_attr
.
name
)
actual_attr
=
actual_attributes
.
get
(
expected_attr
.
name
)
...
...
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