Lots of changes:
* changes the XML report format to match JUnit/Ant's. * improves file path handling. * allows the user to disable RTTI using the GTEST_HAS_RTTI macro. * makes the code compile with -Wswitch-enum.
This commit is contained in:
@@ -123,8 +123,6 @@ TEST(IsEmptyTest, ReturnsFalseForNonEmptyPath) {
|
||||
EXPECT_FALSE(FilePath("a\\b\\").IsEmpty());
|
||||
}
|
||||
|
||||
// FilePath's functions used by UnitTestOptions::GetOutputFile.
|
||||
|
||||
// RemoveDirectoryName "" -> ""
|
||||
TEST(RemoveDirectoryNameTest, WhenEmptyName) {
|
||||
EXPECT_STREQ("", FilePath("").RemoveDirectoryName().c_str());
|
||||
@@ -257,6 +255,110 @@ TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
|
||||
FilePath("foo" PATH_SEP "bar").RemoveTrailingPathSeparator().c_str());
|
||||
}
|
||||
|
||||
TEST(DirectoryTest, RootDirectoryExists) {
|
||||
#ifdef GTEST_OS_WINDOWS // We are on Windows.
|
||||
char current_drive[_MAX_PATH];
|
||||
current_drive[0] = _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
|
||||
}
|
||||
|
||||
#ifdef 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];
|
||||
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
|
||||
|
||||
TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
|
||||
EXPECT_FALSE(FilePath("").DirectoryExists());
|
||||
}
|
||||
|
||||
TEST(DirectoryTest, CurrentDirectoryExists) {
|
||||
#ifdef 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
|
||||
}
|
||||
|
||||
TEST(NormalizeTest, NullStringsEqualEmptyDirectory) {
|
||||
EXPECT_STREQ("", FilePath(NULL).c_str());
|
||||
EXPECT_STREQ("", FilePath(String(NULL)).c_str());
|
||||
}
|
||||
|
||||
// "foo/bar" == foo//bar" == "foo///bar"
|
||||
TEST(NormalizeTest, MultipleConsecutiveSepaparatorsInMidstring) {
|
||||
EXPECT_STREQ("foo" PATH_SEP "bar",
|
||||
FilePath("foo" PATH_SEP "bar").c_str());
|
||||
EXPECT_STREQ("foo" PATH_SEP "bar",
|
||||
FilePath("foo" PATH_SEP PATH_SEP "bar").c_str());
|
||||
EXPECT_STREQ("foo" PATH_SEP "bar",
|
||||
FilePath("foo" PATH_SEP PATH_SEP PATH_SEP "bar").c_str());
|
||||
}
|
||||
|
||||
// "/bar" == //bar" == "///bar"
|
||||
TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringStart) {
|
||||
EXPECT_STREQ(PATH_SEP "bar",
|
||||
FilePath(PATH_SEP "bar").c_str());
|
||||
EXPECT_STREQ(PATH_SEP "bar",
|
||||
FilePath(PATH_SEP PATH_SEP "bar").c_str());
|
||||
EXPECT_STREQ(PATH_SEP "bar",
|
||||
FilePath(PATH_SEP PATH_SEP PATH_SEP "bar").c_str());
|
||||
}
|
||||
|
||||
// "foo/" == foo//" == "foo///"
|
||||
TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
|
||||
EXPECT_STREQ("foo" PATH_SEP,
|
||||
FilePath("foo" PATH_SEP).c_str());
|
||||
EXPECT_STREQ("foo" PATH_SEP,
|
||||
FilePath("foo" PATH_SEP PATH_SEP).c_str());
|
||||
EXPECT_STREQ("foo" PATH_SEP,
|
||||
FilePath("foo" PATH_SEP PATH_SEP PATH_SEP).c_str());
|
||||
}
|
||||
|
||||
TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
|
||||
FilePath default_path;
|
||||
FilePath non_default_path("path");
|
||||
non_default_path = default_path;
|
||||
EXPECT_STREQ("", non_default_path.c_str());
|
||||
EXPECT_STREQ("", default_path.c_str()); // RHS var is unchanged.
|
||||
}
|
||||
|
||||
TEST(AssignmentOperatorTest, NonDefaultAssignedToDefault) {
|
||||
FilePath non_default_path("path");
|
||||
FilePath default_path;
|
||||
default_path = non_default_path;
|
||||
EXPECT_STREQ("path", default_path.c_str());
|
||||
EXPECT_STREQ("path", non_default_path.c_str()); // 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_STREQ("const_path", non_default_path.c_str());
|
||||
}
|
||||
|
||||
class DirectoryCreationTest : public Test {
|
||||
protected:
|
||||
|
||||
@@ -58,10 +58,12 @@
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
|
||||
bool ParseInt32Flag(const char* str, const char* flag, Int32* value);
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
using testing::internal::FormatTimeInMillisAsSeconds;
|
||||
using testing::internal::ParseInt32Flag;
|
||||
|
||||
namespace testing {
|
||||
@@ -118,6 +120,28 @@ using testing::internal::WideStringToUtf8;
|
||||
// This line tests that we can define tests in an unnamed namespace.
|
||||
namespace {
|
||||
|
||||
// Tests FormatTimeInMillisAsSeconds().
|
||||
|
||||
TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) {
|
||||
EXPECT_STREQ("0", FormatTimeInMillisAsSeconds(0));
|
||||
}
|
||||
|
||||
TEST(FormatTimeInMillisAsSecondsTest, FormatsPositiveNumber) {
|
||||
EXPECT_STREQ("0.003", FormatTimeInMillisAsSeconds(3));
|
||||
EXPECT_STREQ("0.01", FormatTimeInMillisAsSeconds(10));
|
||||
EXPECT_STREQ("0.2", FormatTimeInMillisAsSeconds(200));
|
||||
EXPECT_STREQ("1.2", FormatTimeInMillisAsSeconds(1200));
|
||||
EXPECT_STREQ("3", FormatTimeInMillisAsSeconds(3000));
|
||||
}
|
||||
|
||||
TEST(FormatTimeInMillisAsSecondsTest, FormatsNegativeNumber) {
|
||||
EXPECT_STREQ("-0.003", FormatTimeInMillisAsSeconds(-3));
|
||||
EXPECT_STREQ("-0.01", FormatTimeInMillisAsSeconds(-10));
|
||||
EXPECT_STREQ("-0.2", FormatTimeInMillisAsSeconds(-200));
|
||||
EXPECT_STREQ("-1.2", FormatTimeInMillisAsSeconds(-1200));
|
||||
EXPECT_STREQ("-3", FormatTimeInMillisAsSeconds(-3000));
|
||||
}
|
||||
|
||||
#ifndef __SYMBIAN32__
|
||||
// NULL testing does not work with Symbian compilers.
|
||||
|
||||
|
||||
@@ -122,9 +122,9 @@ class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
|
||||
actual = minidom.parse(output_file1)
|
||||
else:
|
||||
actual = minidom.parse(output_file2)
|
||||
self._NormalizeXml(actual.documentElement)
|
||||
self._AssertEquivalentElements(expected.documentElement,
|
||||
actual.documentElement)
|
||||
self.NormalizeXml(actual.documentElement)
|
||||
self.AssertEquivalentNodes(expected.documentElement,
|
||||
actual.documentElement)
|
||||
expected.unlink()
|
||||
actual.unlink()
|
||||
|
||||
|
||||
@@ -54,14 +54,20 @@ EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
</testsuite>
|
||||
<testsuite name="FailedTest" tests="1" failures="1" disabled="0" errors="0" time="*">
|
||||
<testcase name="Fails" status="run" time="*" classname="FailedTest">
|
||||
<failure message="gtest_xml_output_unittest_.cc:*
Value of: 2
Expected: 1" type=""/>
|
||||
<failure message="Value of: 2
Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||
Value of: 2
|
||||
Expected: 1]]></failure>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" errors="0" time="*">
|
||||
<testcase name="Succeeds" status="run" time="*" classname="MixedResultTest"/>
|
||||
<testcase name="Fails" status="run" time="*" classname="MixedResultTest">
|
||||
<failure message="gtest_xml_output_unittest_.cc:*
Value of: 2
Expected: 1" type=""/>
|
||||
<failure message="gtest_xml_output_unittest_.cc:*
Value of: 3
Expected: 2" type=""/>
|
||||
<failure message="Value of: 2
Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||
Value of: 2
|
||||
Expected: 1]]></failure>
|
||||
<failure message="Value of: 3
Expected: 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||
Value of: 3
|
||||
Expected: 2]]></failure>
|
||||
</testcase>
|
||||
<testcase name="DISABLED_test" status="notrun" time="*" classname="MixedResultTest"/>
|
||||
</testsuite>
|
||||
@@ -160,14 +166,14 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
|
||||
|
||||
expected = minidom.parseString(expected_xml)
|
||||
actual = minidom.parse(xml_path)
|
||||
self._NormalizeXml(actual.documentElement)
|
||||
self._AssertEquivalentElements(expected.documentElement,
|
||||
actual.documentElement)
|
||||
self.NormalizeXml(actual.documentElement)
|
||||
self.AssertEquivalentNodes(expected.documentElement,
|
||||
actual.documentElement)
|
||||
expected.unlink()
|
||||
actual .unlink()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.environ['GTEST_STACK_TRACE_DEPTH'] = '0'
|
||||
os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
|
||||
gtest_test_utils.Main()
|
||||
|
||||
@@ -47,27 +47,35 @@ class GTestXMLTestCase(unittest.TestCase):
|
||||
"""
|
||||
|
||||
|
||||
def _AssertEquivalentElements(self, expected_element, actual_element):
|
||||
def AssertEquivalentNodes(self, expected_node, actual_node):
|
||||
"""
|
||||
Asserts that actual_element (a DOM element object) is equivalent to
|
||||
expected_element (another DOM element object), in that it meets all
|
||||
of the following conditions:
|
||||
* It has the same tag name as expected_element.
|
||||
* It has the same set of attributes as expected_element, each with
|
||||
the same value as the corresponding attribute of expected_element.
|
||||
An exception is any attribute named "time", which need only be
|
||||
convertible to a long integer.
|
||||
* Each child element is equivalent to a child element of
|
||||
expected_element. Child elements are matched according to an
|
||||
attribute that varies depending on the element; "name" for
|
||||
<testsuite> and <testcase> elements, "message" for <failure>
|
||||
elements. This matching is necessary because child elements are
|
||||
not guaranteed to be ordered in any particular way.
|
||||
"""
|
||||
self.assertEquals(expected_element.tagName, actual_element.tagName)
|
||||
Asserts that actual_node (a DOM node object) is equivalent to
|
||||
expected_node (another DOM node object), in that either both of
|
||||
them are CDATA nodes and have the same value, or both are DOM
|
||||
elements and actual_node meets all of the following conditions:
|
||||
|
||||
expected_attributes = expected_element.attributes
|
||||
actual_attributes = actual_element .attributes
|
||||
* It has the same tag name as expected_node.
|
||||
* It has the same set of attributes as expected_node, each with
|
||||
the same value as the corresponding attribute of expected_node.
|
||||
An exception is any attribute named "time", which needs only be
|
||||
convertible to a floating-point number.
|
||||
* It has an equivalent set of child nodes (including elements and
|
||||
CDATA sections) as expected_node. Note that we ignore the
|
||||
order of the children as they are not guaranteed to be in any
|
||||
particular order.
|
||||
"""
|
||||
|
||||
if expected_node.nodeType == Node.CDATA_SECTION_NODE:
|
||||
self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType)
|
||||
self.assertEquals(expected_node.nodeValue, actual_node.nodeValue)
|
||||
return
|
||||
|
||||
self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType)
|
||||
self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType)
|
||||
self.assertEquals(expected_node.tagName, actual_node.tagName)
|
||||
|
||||
expected_attributes = expected_node.attributes
|
||||
actual_attributes = actual_node .attributes
|
||||
self.assertEquals(expected_attributes.length, actual_attributes.length)
|
||||
for i in range(expected_attributes.length):
|
||||
expected_attr = expected_attributes.item(i)
|
||||
@@ -75,13 +83,13 @@ class GTestXMLTestCase(unittest.TestCase):
|
||||
self.assert_(actual_attr is not None)
|
||||
self.assertEquals(expected_attr.value, actual_attr.value)
|
||||
|
||||
expected_child = self._GetChildElements(expected_element)
|
||||
actual_child = self._GetChildElements(actual_element)
|
||||
self.assertEquals(len(expected_child), len(actual_child))
|
||||
for child_id, element in expected_child.iteritems():
|
||||
self.assert_(child_id in actual_child,
|
||||
'<%s> is not in <%s>' % (child_id, actual_child))
|
||||
self._AssertEquivalentElements(element, actual_child[child_id])
|
||||
expected_children = self._GetChildren(expected_node)
|
||||
actual_children = self._GetChildren(actual_node)
|
||||
self.assertEquals(len(expected_children), len(actual_children))
|
||||
for child_id, child in expected_children.iteritems():
|
||||
self.assert_(child_id in actual_children,
|
||||
'<%s> is not in <%s>' % (child_id, actual_children))
|
||||
self.AssertEquivalentNodes(child, actual_children[child_id])
|
||||
|
||||
identifying_attribute = {
|
||||
"testsuite": "name",
|
||||
@@ -89,18 +97,20 @@ class GTestXMLTestCase(unittest.TestCase):
|
||||
"failure": "message",
|
||||
}
|
||||
|
||||
def _GetChildElements(self, element):
|
||||
def _GetChildren(self, element):
|
||||
"""
|
||||
Fetches all of the Element type child nodes of element, a DOM
|
||||
Element object. Returns them as the values of a dictionary keyed by
|
||||
the value of one of the node's attributes. For <testsuite> and
|
||||
<testcase> elements, the identifying attribute is "name"; for
|
||||
<failure> elements, it is "message". An exception is raised if
|
||||
any element other than the above three is encountered, if two
|
||||
child elements with the same identifying attributes are encountered,
|
||||
or if any other type of node is encountered, other than Text nodes
|
||||
containing only whitespace.
|
||||
Fetches all of the child nodes of element, a DOM Element object.
|
||||
Returns them as the values of a dictionary keyed by the IDs of the
|
||||
children. For <testsuite> and <testcase> elements, the ID is the
|
||||
value of their "name" attribute; for <failure> elements, it is the
|
||||
value of the "message" attribute; for CDATA section node, it is
|
||||
"detail". An exception is raised if any element other than the
|
||||
above four is encountered, if two child elements with the same
|
||||
identifying attributes are encountered, or if any other type of
|
||||
node is encountered, other than Text nodes containing only
|
||||
whitespace.
|
||||
"""
|
||||
|
||||
children = {}
|
||||
for child in element.childNodes:
|
||||
if child.nodeType == Node.ELEMENT_NODE:
|
||||
@@ -111,11 +121,14 @@ class GTestXMLTestCase(unittest.TestCase):
|
||||
children[childID] = child
|
||||
elif child.nodeType == Node.TEXT_NODE:
|
||||
self.assert_(child.nodeValue.isspace())
|
||||
elif child.nodeType == Node.CDATA_SECTION_NODE:
|
||||
self.assert_("detail" not in children)
|
||||
children["detail"] = child
|
||||
else:
|
||||
self.fail("Encountered unexpected node type %d" % child.nodeType)
|
||||
return children
|
||||
|
||||
def _NormalizeXml(self, element):
|
||||
def NormalizeXml(self, element):
|
||||
"""
|
||||
Normalizes Google Test's XML output to eliminate references to transient
|
||||
information that may change from run to run.
|
||||
@@ -126,13 +139,20 @@ class GTestXMLTestCase(unittest.TestCase):
|
||||
* The line number reported in the first line of the "message"
|
||||
attribute of <failure> elements is replaced with a single asterisk.
|
||||
* The directory names in file paths are removed.
|
||||
* The stack traces are removed.
|
||||
"""
|
||||
|
||||
if element.tagName in ("testsuite", "testcase"):
|
||||
time = element.getAttributeNode("time")
|
||||
time.value = re.sub(r"^\d+$", "*", time.value)
|
||||
time.value = re.sub(r"^\d+(\.\d+)?$", "*", time.value)
|
||||
elif element.tagName == "failure":
|
||||
message = element.getAttributeNode("message")
|
||||
message.value = re.sub(r"^.*/(.*:)\d+\n", "\\1*\n", message.value)
|
||||
for child in element.childNodes:
|
||||
if child.nodeType == Node.CDATA_SECTION_NODE:
|
||||
# Removes the source line number.
|
||||
cdata = re.sub(r"^.*/(.*:)\d+\n", "\\1*\n", child.nodeValue)
|
||||
# Removes the actual stack trace.
|
||||
child.nodeValue = re.sub(r"\nStack trace:\n(.|\n)*",
|
||||
"", cdata)
|
||||
for child in element.childNodes:
|
||||
if child.nodeType == Node.ELEMENT_NODE:
|
||||
self._NormalizeXml(child)
|
||||
self.NormalizeXml(child)
|
||||
|
||||
Reference in New Issue
Block a user