Refactors for the event listener API (by Vlad Losev): hides some methods in UnitTest; implements the result printers using the public API.

This commit is contained in:
zhanyong.wan 2009-06-25 20:49:23 +00:00
parent e6095deec8
commit aaebfcdc40
5 changed files with 139 additions and 138 deletions

View File

@ -141,8 +141,12 @@ const int kMaxStackTraceDepth = 100;
namespace internal {
class AssertHelper;
class GTestFlagSaver;
class TestCase; // A collection of related tests.
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResultType result_type,
const String& message);
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@ -759,33 +763,6 @@ class UnitTest {
// Consecutive calls will return the same object.
static UnitTest* GetInstance();
// 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.
//
// This method can only be called from the main thread.
Environment* AddEnvironment(Environment* 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.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
void AddTestPartResult(TestPartResultType result_type,
const char* file_name,
int line_number,
const internal::String& message,
const internal::String& os_stack_trace);
// Adds a TestProperty to the current TestResult object. If the result already
// contains a property with the same key, the value will be updated.
void RecordPropertyForCurrentTest(const char* key, const char* value);
// Runs all tests in this UnitTest object and prints the result.
// Returns 0 if successful, or 1 otherwise.
//
@ -809,14 +786,41 @@ class UnitTest {
#if GTEST_HAS_PARAM_TEST
// Returns the ParameterizedTestCaseRegistry object used to keep track of
// value-parameterized tests and instantiate and register them.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
internal::ParameterizedTestCaseRegistry& parameterized_test_registry();
#endif // GTEST_HAS_PARAM_TEST
private:
// 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.
//
// This method can only be called from the main thread.
Environment* AddEnvironment(Environment* 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 AddTestPartResult(TestPartResultType result_type,
const char* file_name,
int line_number,
const internal::String& message,
const internal::String& os_stack_trace);
// Adds a TestProperty to the current TestResult object. If the result already
// contains a property with the same key, the value will be updated.
void RecordPropertyForCurrentTest(const char* key, const char* value);
// Accessors for the implementation object.
internal::UnitTestImpl* impl() { return impl_; }
const internal::UnitTestImpl* impl() const { return impl_; }
private:
// Gets the number of successful test cases.
int successful_test_case_count() const;
@ -861,7 +865,20 @@ class UnitTest {
// ScopedTrace is a friend as it needs to modify the per-thread
// trace stack, which is a private member of UnitTest.
// TODO(vladl@google.com): Order all declarations according to the style
// guide after publishing of the above methods is done.
friend class internal::ScopedTrace;
friend Environment* AddGlobalTestEnvironment(Environment* env);
friend internal::UnitTestImpl* internal::GetUnitTestImpl();
friend class internal::AssertHelper;
friend class Test;
friend void internal::ReportFailureInUnknownLocation(
TestPartResultType result_type,
const internal::String& message);
// TODO(vladl@google.com): Remove these when publishing the new accessors.
friend class PrettyUnitTestResultPrinter;
friend class XmlUnitTestResultPrinter;
// Creates an empty UnitTest.
UnitTest();

View File

@ -44,6 +44,8 @@
namespace testing {
using internal::GetUnitTestImpl;
// Gets the summary of the failure message by omitting the stack trace
// in it.
internal::String TestPartResult::ExtractSummary(const char* message) {
@ -101,14 +103,13 @@ namespace internal {
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
: has_new_fatal_failure_(false),
original_reporter_(UnitTest::GetInstance()->impl()->
original_reporter_(GetUnitTestImpl()->
GetTestPartResultReporterForCurrentThread()) {
UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread(
this);
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
}
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread(
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
original_reporter_);
}

View File

@ -565,7 +565,7 @@ ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
}
void ScopedFakeTestPartResultReporter::Init() {
internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl();
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
old_reporter_ = impl->GetGlobalTestPartResultReporter();
impl->SetGlobalTestPartResultReporter(this);
@ -578,7 +578,7 @@ void ScopedFakeTestPartResultReporter::Init() {
// The d'tor restores the test part result reporter used by Google Test
// before.
ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl();
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
impl->SetGlobalTestPartResultReporter(old_reporter_);
} else {
@ -1985,6 +1985,22 @@ void Test::RecordProperty(const char* key, int value) {
RecordProperty(key, value_message.GetString().c_str());
}
namespace internal {
void ReportFailureInUnknownLocation(TestPartResultType result_type,
const 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,
String()); // No stack trace, either.
}
} // namespace internal
#if GTEST_OS_WINDOWS
// We are on Windows.
@ -1995,15 +2011,8 @@ static void AddExceptionThrownFailure(DWORD exception_code,
message << "Exception thrown with code 0x" << std::setbase(16) <<
exception_code << std::setbase(10) << " in " << location << ".";
UnitTest* const unit_test = UnitTest::GetInstance();
unit_test->AddTestPartResult(
TPRT_FATAL_FAILURE,
static_cast<const char *>(NULL),
// We have no info about the source file where the exception
// occurred.
-1, // We have no info on which line caused the exception.
message.GetString(),
internal::String(""));
internal::ReportFailureInUnknownLocation(TPRT_FATAL_FAILURE,
message.GetString());
}
#endif // GTEST_OS_WINDOWS
@ -2699,6 +2708,8 @@ class PrettyUnitTestResultPrinter : public UnitTestEventListenerInterface {
virtual void OnUnitTestEnd(const UnitTest& unit_test);
private:
static void PrintFailedTests(const UnitTest& unit_test);
internal::String test_case_name_;
};
@ -2720,11 +2731,10 @@ void PrettyUnitTestResultPrinter::OnUnitTestStart(const UnitTest& unit_test) {
internal::posix::GetEnv(kTestTotalShards));
}
const internal::UnitTestImpl* const impl = unit_test.impl();
ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("Running %s from %s.\n",
FormatTestCount(impl->test_to_run_count()).c_str(),
FormatTestCaseCount(impl->test_case_to_run_count()).c_str());
FormatTestCount(unit_test.test_to_run_count()).c_str(),
FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
fflush(stdout);
}
@ -2808,71 +2818,62 @@ void PrettyUnitTestResultPrinter::OnGlobalTearDownStart(
fflush(stdout);
}
namespace internal {
// Internal helper for printing the list of failed tests.
static void PrintFailedTestsPretty(const UnitTestImpl* impl) {
const int failed_test_count = impl->failed_test_count();
void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
const int failed_test_count = unit_test.failed_test_count();
if (failed_test_count == 0) {
return;
}
for (const internal::ListNode<TestCase*>* node = impl->test_cases()->Head();
node != NULL; node = node->next()) {
const TestCase* const tc = node->element();
if (!tc->should_run() || (tc->failed_test_count() == 0)) {
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 (const internal::ListNode<TestInfo*>* tinode =
tc->test_info_list().Head();
tinode != NULL; tinode = tinode->next()) {
const TestInfo* const ti = tinode->element();
if (!tc->ShouldRunTest(ti) || tc->TestPassed(ti)) {
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", ti->test_case_name(), ti->name());
if (ti->test_case_comment()[0] != '\0' ||
ti->comment()[0] != '\0') {
printf(", where %s", ti->test_case_comment());
if (ti->test_case_comment()[0] != '\0' &&
ti->comment()[0] != '\0') {
printf("%s.%s", test_case.name(), test_info.name());
if (test_case.comment()[0] != '\0' ||
test_info.comment()[0] != '\0') {
printf(", where %s", test_case.comment());
if (test_case.comment()[0] != '\0' &&
test_info.comment()[0] != '\0') {
printf(" and ");
}
}
printf("%s\n", ti->comment());
printf("%s\n", test_info.comment());
}
}
}
} // namespace internal
void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
const internal::UnitTestImpl* const impl = unit_test.impl();
ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("%s from %s ran.",
FormatTestCount(impl->test_to_run_count()).c_str(),
FormatTestCaseCount(impl->test_case_to_run_count()).c_str());
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(impl->elapsed_time()).c_str());
internal::StreamableToString(unit_test.elapsed_time()).c_str());
}
printf("\n");
ColoredPrintf(COLOR_GREEN, "[ PASSED ] ");
printf("%s.\n", FormatTestCount(impl->successful_test_count()).c_str());
printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
int num_failures = impl->failed_test_count();
if (!impl->Passed()) {
const int failed_test_count = impl->failed_test_count();
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());
internal::PrintFailedTestsPretty(impl);
PrintFailedTests(unit_test);
printf("\n%2d FAILED %s\n", num_failures,
num_failures == 1 ? "TEST" : "TESTS");
}
int num_disabled = impl->disabled_test_count();
int num_disabled = unit_test.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.
@ -2996,10 +2997,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// Prints an XML representation of a TestInfo object.
static void PrintXmlTestInfo(FILE* out,
const char* test_case_name,
const TestInfo* test_info);
const TestInfo& test_info);
// Prints an XML representation of a TestCase object
static void PrintXmlTestCase(FILE* out, const TestCase* test_case);
static void PrintXmlTestCase(FILE* out, const TestCase& test_case);
// Prints an XML summary of unit_test to output stream out.
static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test);
@ -3009,7 +3010,7 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// When the String is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static internal::String TestPropertiesAsXmlAttributes(
const internal::TestResult* result);
const internal::TestResult& result);
// The output file.
const internal::String output_file_;
@ -3147,23 +3148,20 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
// TODO(wan): There is also value in printing properties with the plain printer.
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
const char* test_case_name,
const TestInfo* test_info) {
const internal::TestResult * const result = test_info->result();
const internal::List<TestPartResult> &results = result->test_part_results();
const TestInfo& test_info) {
const internal::TestResult& result = *test_info.result();
fprintf(out,
" <testcase name=\"%s\" status=\"%s\" time=\"%s\" "
"classname=\"%s\"%s",
EscapeXmlAttribute(test_info->name()).c_str(),
test_info->should_run() ? "run" : "notrun",
internal::FormatTimeInMillisAsSeconds(result->elapsed_time()),
EscapeXmlAttribute(test_info.name()).c_str(),
test_info.should_run() ? "run" : "notrun",
internal::FormatTimeInMillisAsSeconds(result.elapsed_time()),
EscapeXmlAttribute(test_case_name).c_str(),
TestPropertiesAsXmlAttributes(result).c_str());
int failures = 0;
for (const internal::ListNode<TestPartResult>* part_node = results.Head();
part_node != NULL;
part_node = part_node->next()) {
const TestPartResult& part = part_node->element();
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = *result.GetTestPartResult(i);
if (part.failed()) {
const internal::String message =
internal::String::Format("%s:%d\n%s", part.file_name(),
@ -3185,60 +3183,47 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
// Prints an XML representation of a TestCase object
void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
const TestCase* test_case) {
const TestCase& test_case) {
fprintf(out,
" <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" "
"disabled=\"%d\" ",
EscapeXmlAttribute(test_case->name()).c_str(),
test_case->total_test_count(),
test_case->failed_test_count(),
test_case->disabled_test_count());
EscapeXmlAttribute(test_case.name()).c_str(),
test_case.total_test_count(),
test_case.failed_test_count(),
test_case.disabled_test_count());
fprintf(out,
"errors=\"0\" time=\"%s\">\n",
internal::FormatTimeInMillisAsSeconds(test_case->elapsed_time()));
for (const internal::ListNode<TestInfo*>* info_node =
test_case->test_info_list().Head();
info_node != NULL;
info_node = info_node->next()) {
PrintXmlTestInfo(out, test_case->name(), info_node->element());
}
internal::FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
for (int i = 0; i < test_case.total_test_count(); ++i)
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
fprintf(out, " </testsuite>\n");
}
// Prints an XML summary of unit_test to output stream out.
void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
const UnitTest& unit_test) {
const internal::UnitTestImpl* const impl = unit_test.impl();
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fprintf(out,
"<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
"errors=\"0\" time=\"%s\" ",
impl->total_test_count(),
impl->failed_test_count(),
impl->disabled_test_count(),
internal::FormatTimeInMillisAsSeconds(impl->elapsed_time()));
unit_test.total_test_count(),
unit_test.failed_test_count(),
unit_test.disabled_test_count(),
internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
fprintf(out, "name=\"AllTests\">\n");
for (const internal::ListNode<TestCase*>* case_node =
impl->test_cases()->Head();
case_node != NULL;
case_node = case_node->next()) {
PrintXmlTestCase(out, case_node->element());
}
for (int i = 0; i < unit_test.total_test_case_count(); ++i)
PrintXmlTestCase(out, *unit_test.GetTestCase(i));
fprintf(out, "</testsuites>\n");
}
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const internal::TestResult* result) {
const internal::TestResult& result) {
using internal::TestProperty;
Message attributes;
const internal::List<TestProperty>& properties = result->test_properties();
for (const internal::ListNode<TestProperty>* property_node =
properties.Head();
property_node != NULL;
property_node = property_node->next()) {
const TestProperty& property = property_node->element();
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = *result.GetTestProperty(i);
attributes << " " << property.key() << "="
<< "\"" << EscapeXmlAttribute(property.value()) << "\"";
}
@ -4136,7 +4121,7 @@ TestInfoImpl::~TestInfoImpl() {
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 unit_test->impl()->CurrentOsStackTraceExceptTop(skip_count + 1);
return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
}
// Returns the number of failed test parts in the given test result object.

View File

@ -67,6 +67,7 @@ using testing::internal::DeathTest;
using testing::internal::DeathTestFactory;
using testing::internal::FilePath;
using testing::internal::GetLastErrnoDescription;
using testing::internal::GetUnitTestImpl;
using testing::internal::ParseNaturalNumber;
using testing::internal::String;
@ -77,22 +78,22 @@ namespace internal {
// single UnitTest object during their lifetimes.
class ReplaceDeathTestFactory {
public:
ReplaceDeathTestFactory(UnitTest* parent, DeathTestFactory* new_factory)
: parent_impl_(parent->impl()) {
old_factory_ = parent_impl_->death_test_factory_.release();
parent_impl_->death_test_factory_.reset(new_factory);
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() {
parent_impl_->death_test_factory_.release();
parent_impl_->death_test_factory_.reset(old_factory_);
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* parent_impl_;
UnitTestImpl* unit_test_impl_;
DeathTestFactory* old_factory_;
};
@ -846,8 +847,7 @@ class MacroLogicDeathTest : public testing::Test {
static void SetUpTestCase() {
factory_ = new MockDeathTestFactory;
replacer_ = new testing::internal::ReplaceDeathTestFactory(
testing::UnitTest::GetInstance(), factory_);
replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_);
}
static void TearDownTestCase() {
@ -959,8 +959,7 @@ TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
// Returns the number of successful parts in the current test.
static size_t GetSuccessfulTestPartCount() {
return testing::UnitTest::GetInstance()->impl()->current_test_result()->
successful_part_count();
return GetUnitTestImpl()->current_test_result()->successful_part_count();
}
// Tests that a successful death test does not register a successful

View File

@ -136,6 +136,7 @@ using testing::internal::GetCurrentOsStackTraceExceptTop;
using testing::internal::GetFailedPartCount;
using testing::internal::GetTestTypeId;
using testing::internal::GetTypeId;
using testing::internal::GetUnitTestImpl;
using testing::internal::GTestFlagSaver;
using testing::internal::Int32;
using testing::internal::Int32FromEnvOrDie;
@ -3600,8 +3601,7 @@ TEST(AssertionSyntaxTest, WorksWithConst) {
// Returns the number of successful parts in the current test.
static size_t GetSuccessfulPartCount() {
return UnitTest::GetInstance()->impl()->current_test_result()->
successful_part_count();
return GetUnitTestImpl()->current_test_result()->successful_part_count();
}
namespace testing {
@ -4416,8 +4416,7 @@ namespace testing {
class TestInfoTest : public Test {
protected:
static TestInfo * GetTestInfo(const char* test_name) {
return UnitTest::GetInstance()->impl()->
GetTestCase("TestInfoTest", "", NULL, NULL)->
return GetUnitTestImpl()->GetTestCase("TestInfoTest", "", NULL, NULL)->
GetTestInfo(test_name);
}