summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvladlosev <vladlosev@861a406c-534a-0410-8894-cb66d6ee9925>2011-10-05 05:52:34 +0000
committervladlosev <vladlosev@861a406c-534a-0410-8894-cb66d6ee9925>2011-10-05 05:52:34 +0000
commit8883b42f2a78976dde09f31ca72806072e33bd5f (patch)
treedd74052e6e0f73cf9d68b55dab4f438b33c57820 /src
parente35019652516ad3b4e9bd8c49dbcfca9d443d7e4 (diff)
downloadgtest-8883b42f2a78976dde09f31ca72806072e33bd5f.tar.gz
gtest-8883b42f2a78976dde09f31ca72806072e33bd5f.tar.bz2
gtest-8883b42f2a78976dde09f31ca72806072e33bd5f.tar.xz
Implements the timestamp attribute for the testsuites element in the output XML (external contribution by Dirk Meister).
git-svn-id: http://googletest.googlecode.com/svn/trunk@600 861a406c-534a-0410-8894-cb66d6ee9925
Diffstat (limited to 'src')
-rw-r--r--src/gtest-internal-inl.h14
-rw-r--r--src/gtest.cc38
2 files changed, 51 insertions, 1 deletions
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index 65a2101..8a85724 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -112,6 +112,12 @@ GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
// Formats the given time in milliseconds as seconds.
GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information. N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe. Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
// Parses a string for an Int32 flag, in the form of "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
@@ -548,6 +554,10 @@ class GTEST_API_ UnitTestImpl {
// Gets the number of tests that should run.
int test_to_run_count() const;
+ // Gets the time of the test program start, in ms from the start of the
+ // UNIX epoch.
+ TimeInMillis start_timestamp() const { return start_timestamp_; }
+
// Gets the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; }
@@ -880,6 +890,10 @@ class GTEST_API_ UnitTestImpl {
// Our random number generator.
internal::Random random_;
+ // The time of the test program start, in ms from the start of the
+ // UNIX epoch.
+ TimeInMillis start_timestamp_;
+
// How long the test took to run, in milliseconds.
TimeInMillis elapsed_time_;
diff --git a/src/gtest.cc b/src/gtest.cc
index 6f7216f..7bdd28a 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -39,6 +39,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <wchar.h>
#include <wctype.h>
@@ -3195,6 +3196,32 @@ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
return ss.str();
}
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+ // Using non-reentrant version as localtime_r is not portable.
+ time_t seconds = static_cast<time_t>(ms / 1000);
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996
+ // (function or variable may be unsafe).
+ const struct tm* const time_struct = localtime(&seconds); // NOLINT
+# pragma warning(pop) // Restores the warning state again.
+#else
+ const struct tm* const time_struct = localtime(&seconds); // NOLINT
+#endif
+ if (time_struct == NULL)
+ return ""; // Invalid ms value
+
+ return String::Format("%d-%02d-%02dT%02d:%02d:%02d", // YYYY-MM-DDThh:mm:ss
+ time_struct->tm_year + 1900,
+ time_struct->tm_mon + 1,
+ time_struct->tm_mday,
+ time_struct->tm_hour,
+ time_struct->tm_min,
+ time_struct->tm_sec);
+}
+
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
const char* data) {
@@ -3291,10 +3318,11 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fprintf(out,
"<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
- "errors=\"0\" time=\"%s\" ",
+ "errors=\"0\" timestamp=\"%s\" time=\"%s\" ",
unit_test.total_test_count(),
unit_test.failed_test_count(),
unit_test.disabled_test_count(),
+ FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()).c_str(),
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
if (GTEST_FLAG(shuffle)) {
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
@@ -3687,6 +3715,12 @@ int UnitTest::total_test_count() const { return impl()->total_test_count(); }
// Gets the number of tests that should run.
int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+ return impl()->start_timestamp();
+}
+
// Gets the elapsed time, in milliseconds.
internal::TimeInMillis UnitTest::elapsed_time() const {
return impl()->elapsed_time();
@@ -3961,6 +3995,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
post_flag_parse_init_performed_(false),
random_seed_(0), // Will be overridden by the flag before first use.
random_(0), // Will be reseeded before first use.
+ start_timestamp_(0),
elapsed_time_(0),
#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_(NULL),
@@ -4192,6 +4227,7 @@ bool UnitTestImpl::RunAllTests() {
TestEventListener* repeater = listeners()->repeater();
+ start_timestamp_ = GetTimeInMillis();
repeater->OnTestProgramStart(*parent_);
// How many times to repeat the tests? We don't want to repeat them