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:
shiqian
2008-09-26 16:08:30 +00:00
parent e79c3ccb73
commit 64cdcb69b2
13 changed files with 397 additions and 77 deletions

View File

@@ -416,6 +416,7 @@ bool ForkingDeathTest::Passed(bool status_ok) {
<< " " << ExitSummary(status_) << "\n";
}
break;
case IN_PROGRESS:
default:
GTEST_LOG(FATAL,
"DeathTest::Passed somehow called before conclusion of test");

View File

@@ -161,10 +161,13 @@ bool FilePath::FileOrDirectoryExists() const {
// that exists.
bool FilePath::DirectoryExists() const {
bool result = false;
#ifdef _WIN32
FilePath removed_sep(this->RemoveTrailingPathSeparator());
#ifdef GTEST_OS_WINDOWS
// Don't strip off trailing separator if path is a root directory on
// Windows (like "C:\\").
const FilePath& path(IsRootDirectory() ? *this :
RemoveTrailingPathSeparator());
#ifdef _WIN32_WCE
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
const DWORD attributes = GetFileAttributes(unicode);
delete [] unicode;
if ((attributes != kInvalidFileAttributes) &&
@@ -173,17 +176,32 @@ bool FilePath::DirectoryExists() const {
}
#else
struct _stat file_stat = {};
result = _stat(removed_sep.c_str(), &file_stat) == 0 &&
result = _stat(path.c_str(), &file_stat) == 0 &&
(_S_IFDIR & file_stat.st_mode) != 0;
#endif // _WIN32_WCE
#else
struct stat file_stat = {};
result = stat(pathname_.c_str(), &file_stat) == 0 &&
S_ISDIR(file_stat.st_mode);
#endif // _WIN32
#endif // GTEST_OS_WINDOWS
return result;
}
// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool FilePath::IsRootDirectory() const {
#ifdef GTEST_OS_WINDOWS
const char* const name = pathname_.c_str();
return pathname_.GetLength() == 3 &&
((name[0] >= 'a' && name[0] <= 'z') ||
(name[0] >= 'A' && name[0] <= 'Z')) &&
name[1] == ':' &&
name[2] == kPathSeparator;
#else
return pathname_ == kPathSeparatorString;
#endif
}
// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
@@ -258,5 +276,31 @@ FilePath FilePath::RemoveTrailingPathSeparator() const {
: *this;
}
// Normalize removes any redundant separators that might be in the pathname.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
void FilePath::Normalize() {
if (pathname_.c_str() == NULL) {
pathname_ = "";
return;
}
const char* src = pathname_.c_str();
char* const dest = new char[pathname_.GetLength() + 1];
char* dest_ptr = dest;
memset(dest_ptr, 0, pathname_.GetLength() + 1);
while (*src != '\0') {
*dest_ptr++ = *src;
if (*src != kPathSeparator)
src++;
else
while (*src == kPathSeparator)
src++;
}
*dest_ptr = '\0';
pathname_ = dest;
delete[] dest;
}
} // namespace internal
} // namespace testing

View File

@@ -134,6 +134,10 @@ static const char kUniversalFilter[] = "*";
// The default output file for XML output.
static const char kDefaultOutputFile[] = "test_detail.xml";
// The text used in failure messages to indicate the start of the
// stack trace.
static const char kStackTraceMarker[] = "\nStack trace:\n";
GTEST_DEFINE_bool(
break_on_failure,
internal::BoolFromGTestEnv("break_on_failure", false),
@@ -200,6 +204,14 @@ GTEST_DEFINE_bool(
"True iff " GTEST_NAME " should include internal stack frames when "
"printing test failure stack traces.");
// Gets the summary of the failure message by omitting the stack trace
// in it.
internal::String TestPartResult::ExtractSummary(const char* message) {
const char* const stack_trace = strstr(message, kStackTraceMarker);
return stack_trace == NULL ? internal::String(message) :
internal::String(message, stack_trace - message);
}
namespace internal {
// GTestIsInitialized() returns true iff the user has initialized
@@ -2923,13 +2935,28 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
// <testsuite 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 message="..." /> <-- individual assertion failures
// <failure message="..." />
// <failure message="...">...</failure>
// <failure message="...">...</failure>
// <failure message="...">...</failure>
// <-- individual assertion failures
// </testcase>
// </testsuite>
// </testsuite>
namespace internal {
// Formats the given time in milliseconds as seconds. The returned
// C-string is owned by this function and cannot be released by the
// caller. Calling the function again invalidates the previous
// result.
const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
static String str;
str = (Message() << (ms/1000.0)).GetString();
return str.c_str();
}
} // namespace internal
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
@@ -2942,7 +2969,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
"classname=\"%s\"%s",
EscapeXmlAttribute(test_info->name()).c_str(),
test_info->should_run() ? "run" : "notrun",
internal::StreamableToString(result->elapsed_time()).c_str(),
internal::FormatTimeInMillisAsSeconds(result->elapsed_time()),
EscapeXmlAttribute(test_case_name).c_str(),
TestPropertiesAsXmlAttributes(result).c_str());
@@ -2958,8 +2985,9 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
if (++failures == 1)
fprintf(out, ">\n");
fprintf(out,
" <failure message=\"%s\" type=\"\"/>\n",
EscapeXmlAttribute(message.c_str()).c_str());
" <failure message=\"%s\" type=\"\"><![CDATA[%s]]>"
"</failure>\n",
EscapeXmlAttribute(part.summary()).c_str(), message.c_str());
}
}
@@ -2981,7 +3009,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
test_case->disabled_test_count());
fprintf(out,
"errors=\"0\" time=\"%s\">\n",
internal::StreamableToString(test_case->elapsed_time()).c_str());
internal::FormatTimeInMillisAsSeconds(test_case->elapsed_time()));
for (const internal::ListNode<TestInfo*>* info_node =
test_case->test_info_list().Head();
info_node != NULL;
@@ -3002,7 +3030,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
impl->total_test_count(),
impl->failed_test_count(),
impl->disabled_test_count(),
internal::StreamableToString(impl->elapsed_time()).c_str());
internal::FormatTimeInMillisAsSeconds(impl->elapsed_time()));
fprintf(out, "name=\"AllTests\">\n");
for (const internal::ListNode<TestCase*>* case_node =
impl->test_cases()->Head();
@@ -3153,7 +3181,7 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type,
}
if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
msg << "\nStack trace:\n" << os_stack_trace;
msg << kStackTraceMarker << os_stack_trace;
}
const TestPartResult result =