From 3b8388d9490a64a47ed8cbdab2021935b1b2c76c Mon Sep 17 00:00:00 2001 From: "kosak@google.com" Date: Fri, 22 Feb 2013 20:10:40 +0000 Subject: Removes testing::internal::String::Format(), which causes problems as it truncates the result at 4096 chars. Also update an obsolete link in comment. git-svn-id: http://googletest.googlecode.com/svn/trunk@636 861a406c-534a-0410-8894-cb66d6ee9925 --- src/gtest-death-test.cc | 85 ++++++++++++----------- src/gtest-filepath.cc | 2 +- src/gtest-internal-inl.h | 8 +-- src/gtest-port.cc | 12 ++-- src/gtest-printers.cc | 7 +- src/gtest.cc | 173 ++++++++++++++++++++--------------------------- 6 files changed, 131 insertions(+), 156 deletions(-) (limited to 'src') diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc index 8b52431..a6023fc 100644 --- a/src/gtest-death-test.cc +++ b/src/gtest-death-test.cc @@ -272,9 +272,10 @@ void DeathTestAbort(const std::string& message) { # define GTEST_DEATH_TEST_CHECK_(expression) \ do { \ if (!::testing::internal::IsTrue(expression)) { \ - DeathTestAbort(::testing::internal::String::Format( \ - "CHECK failed: File %s, line %d: %s", \ - __FILE__, __LINE__, #expression)); \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ } \ } while (::testing::internal::AlwaysFalse()) @@ -292,9 +293,10 @@ void DeathTestAbort(const std::string& message) { gtest_retval = (expression); \ } while (gtest_retval == -1 && errno == EINTR); \ if (gtest_retval == -1) { \ - DeathTestAbort(::testing::internal::String::Format( \ - "CHECK failed: File %s, line %d: %s != -1", \ - __FILE__, __LINE__, #expression)); \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ } \ } while (::testing::internal::AlwaysFalse()) @@ -716,14 +718,14 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { info->test_case_name() + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + - "=" + file_ + "|" + String::Format("%d|%d|%u|%Iu|%Iu", line_, - death_test_index, - static_cast(::GetCurrentProcessId()), - // size_t has the same with as pointers on both 32-bit and 64-bit + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit // Windows platforms. // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. - reinterpret_cast(write_handle), - reinterpret_cast(event_handle_.Get())); + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); char executable_path[_MAX_PATH + 1]; // NOLINT GTEST_DEATH_TEST_CHECK_( @@ -1114,13 +1116,13 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); const std::string filter_flag = - String::Format("--%s%s=%s.%s", - GTEST_FLAG_PREFIX_, kFilterFlag, - info->test_case_name(), info->name()); + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); const std::string internal_flag = - String::Format("--%s%s=%s|%d|%d|%d", - GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag, - file_, line_, death_test_index, pipe_fd[1]); + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); Arguments args; args.AddArguments(GetArgvsForDeathTestChildProcess()); args.AddArgument(filter_flag.c_str()); @@ -1159,9 +1161,10 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, if (flag != NULL) { if (death_test_index > flag->index()) { - DeathTest::set_last_death_test_message(String::Format( - "Death test count (%d) somehow exceeded expected maximum (%d)", - death_test_index, flag->index())); + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); return false; } @@ -1190,9 +1193,9 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, # endif // GTEST_OS_WINDOWS else { // NOLINT - this is more readable than unbalanced brackets inside #if. - DeathTest::set_last_death_test_message(String::Format( - "Unknown death test style \"%s\" encountered", - GTEST_FLAG(death_test_style).c_str())); + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); return false; } @@ -1230,8 +1233,8 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, FALSE, // Non-inheritable. parent_process_id)); if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { - DeathTestAbort(String::Format("Unable to open parent process %u", - parent_process_id)); + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); } // TODO(vladl@google.com): Replace the following check with a @@ -1251,9 +1254,10 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, // DUPLICATE_SAME_ACCESS is used. FALSE, // Request non-inheritable handler. DUPLICATE_SAME_ACCESS)) { - DeathTestAbort(String::Format( - "Unable to duplicate the pipe handle %Iu from the parent process %u", - write_handle_as_size_t, parent_process_id)); + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); } const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); @@ -1264,17 +1268,18 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, 0x0, FALSE, DUPLICATE_SAME_ACCESS)) { - DeathTestAbort(String::Format( - "Unable to duplicate the event handle %Iu from the parent process %u", - event_handle_as_size_t, parent_process_id)); + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); } const int write_fd = ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); if (write_fd == -1) { - DeathTestAbort(String::Format( - "Unable to convert pipe handle %Iu to a file descriptor", - write_handle_as_size_t)); + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); } // Signals the parent that the write end of the pipe has been acquired @@ -1311,9 +1316,8 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { || !ParseNaturalNumber(fields[3], &parent_process_id) || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { - DeathTestAbort(String::Format( - "Bad --gtest_internal_run_death_test flag: %s", - GTEST_FLAG(internal_run_death_test).c_str())); + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); } write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t, @@ -1324,9 +1328,8 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { || !ParseNaturalNumber(fields[1], &line) || !ParseNaturalNumber(fields[2], &index) || !ParseNaturalNumber(fields[3], &write_fd)) { - DeathTestAbort(String::Format( - "Bad --gtest_internal_run_death_test flag: %s", - GTEST_FLAG(internal_run_death_test).c_str())); + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); } # endif // GTEST_OS_WINDOWS diff --git a/src/gtest-filepath.cc b/src/gtest-filepath.cc index 4d40cb9..708389d 100644 --- a/src/gtest-filepath.cc +++ b/src/gtest-filepath.cc @@ -182,7 +182,7 @@ FilePath FilePath::MakeFileName(const FilePath& directory, if (number == 0) { file = base_name.string() + "." + extension; } else { - file = base_name.string() + "_" + String::Format("%d", number).c_str() + file = base_name.string() + "_" + StreamableToString(number) + "." + extension; } return ConcatPaths(directory, FilePath(file)); diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h index 54717c9..2491eee 100644 --- a/src/gtest-internal-inl.h +++ b/src/gtest-internal-inl.h @@ -222,12 +222,10 @@ class GTestFlagSaver { // Converts a Unicode code point to a narrow string in UTF-8 encoding. // code_point parameter is of type UInt32 because wchar_t may not be // wide enough to contain a code point. -// The output buffer str must containt at least 32 characters. -// The function returns the address of the output buffer. // If the code_point is not a valid Unicode code point -// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output -// as '(Invalid Unicode 0xXXXXXXXX)'. -GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str); +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: diff --git a/src/gtest-port.cc b/src/gtest-port.cc index fa8f29c..0c4df5f 100644 --- a/src/gtest-port.cc +++ b/src/gtest-port.cc @@ -454,15 +454,15 @@ const char kUnknownFile[] = "unknown file"; // Formats a source file path and a line number as they would appear // in an error message from the compiler used to compile this code. GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { - const char* const file_name = file == NULL ? kUnknownFile : file; + const std::string file_name(file == NULL ? kUnknownFile : file); if (line < 0) { - return String::Format("%s:", file_name).c_str(); + return file_name + ":"; } #ifdef _MSC_VER - return String::Format("%s(%d):", file_name, line).c_str(); + return file_name + "(" + StreamableToString(line) + "):"; #else - return String::Format("%s:%d:", file_name, line).c_str(); + return file_name + ":" + StreamableToString(line) + ":"; #endif // _MSC_VER } @@ -473,12 +473,12 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { // to the file location it produces, unlike FormatFileLocation(). GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( const char* file, int line) { - const char* const file_name = file == NULL ? kUnknownFile : file; + const std::string file_name(file == NULL ? kUnknownFile : file); if (line < 0) return file_name; else - return String::Format("%s:%d", file_name, line).c_str(); + return file_name + ":" + StreamableToString(line); } diff --git a/src/gtest-printers.cc b/src/gtest-printers.cc index 898d61d..75fa408 100644 --- a/src/gtest-printers.cc +++ b/src/gtest-printers.cc @@ -176,7 +176,7 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { *os << static_cast(c); return kAsIs; } else { - *os << String::Format("\\x%X", static_cast(c)); + *os << "\\x" + String::FormatHexInt(static_cast(c)); return kHexEscape; } } @@ -221,7 +221,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) { // obvious). if (c == 0) return; - *os << " (" << String::Format("%d", c).c_str(); + *os << " (" << static_cast(c); // For more convenience, we print c's code again in hexidecimal, // unless c was already printed in the form '\x##' or the code is in @@ -229,8 +229,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) { if (format == kHexEscape || (1 <= c && c <= 9)) { // Do nothing. } else { - *os << String::Format(", 0x%X", - static_cast(c)).c_str(); + *os << ", 0x" << String::FormatHexInt(static_cast(c)); } *os << ")"; } diff --git a/src/gtest.cc b/src/gtest.cc index 0567e83..8bf4b80 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -1309,7 +1309,7 @@ AssertionResult HRESULTFailureHelper(const char* expr, // want inserts expanded. const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; - const DWORD kBufSize = 4096; // String::Format can't exceed this length. + const DWORD kBufSize = 4096; // Gets the system's human readable message string for this HRESULT. char error_text[kBufSize] = { '\0' }; DWORD message_length = ::FormatMessageA(kFlags, @@ -1319,7 +1319,7 @@ AssertionResult HRESULTFailureHelper(const char* expr, error_text, // output buffer kBufSize, // buf size NULL); // no arguments for inserts - // Trims tailing white space (FormatMessage leaves a trailing cr-lf) + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) for (; message_length && IsSpace(error_text[message_length - 1]); --message_length) { error_text[message_length - 1] = '\0'; @@ -1327,10 +1327,10 @@ AssertionResult HRESULTFailureHelper(const char* expr, # endif // GTEST_OS_WINDOWS_MOBILE - const std::string error_hex(String::Format("0x%08X ", hr)); + const std::string error_hex("0x" + String::FormatHexInt(hr)); return ::testing::AssertionFailure() << "Expected: " << expr << " " << expected << ".\n" - << " Actual: " << error_hex << error_text << "\n"; + << " Actual: " << error_hex << " " << error_text << "\n"; } } // namespace @@ -1387,12 +1387,15 @@ inline UInt32 ChopLowBits(UInt32* bits, int n) { // Converts a Unicode code point to a narrow string in UTF-8 encoding. // code_point parameter is of type UInt32 because wchar_t may not be // wide enough to contain a code point. -// The output buffer str must containt at least 32 characters. -// The function returns the address of the output buffer. // If the code_point is not a valid Unicode code point -// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output -// as '(Invalid Unicode 0xXXXXXXXX)'. -char* CodePointToUtf8(UInt32 code_point, char* str) { +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. if (code_point <= kMaxCodePoint1) { str[1] = '\0'; str[0] = static_cast(code_point); // 0xxxxxxx @@ -1405,22 +1408,12 @@ char* CodePointToUtf8(UInt32 code_point, char* str) { str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[0] = static_cast(0xE0 | code_point); // 1110xxxx - } else if (code_point <= kMaxCodePoint4) { + } else { // code_point <= kMaxCodePoint4 str[4] = '\0'; str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[0] = static_cast(0xF0 | code_point); // 11110xxx - } else { - // The longest string String::Format can produce when invoked - // with these parameters is 28 character long (not including - // the terminating nul character). We are asking for 32 character - // buffer just in case. This is also enough for strncpy to - // null-terminate the destination string. - posix::StrNCpy( - str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32); - str[31] = '\0'; // Makes sure no change in the format to strncpy leaves - // the result unterminated. } return str; } @@ -1479,8 +1472,7 @@ std::string WideStringToUtf8(const wchar_t* str, int num_chars) { unicode_code_point = static_cast(str[i]); } - char buffer[32]; // CodePointToUtf8 requires a buffer this big. - stream << CodePointToUtf8(unicode_code_point, buffer); + stream << CodePointToUtf8(unicode_code_point); } return StringStreamToString(&stream); } @@ -1597,47 +1589,26 @@ bool String::EndsWithCaseInsensitive( suffix.c_str()); } -// Formats a list of arguments to an std::string, using the same format -// spec string as for printf. -// -// We do not use the StringPrintf class as it is not universally -// available. -// -// The result is limited to 4096 characters (including the tailing 0). -// If 4096 characters are not enough to format the input, or if -// there's an error, "" is -// returned. -std::string String::Format(const char * format, ...) { - va_list args; - va_start(args, format); - - char buffer[4096]; - const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]); - - // MSVC 8 deprecates vsnprintf(), so we want to suppress warning - // 4996 (deprecated function) there. -#ifdef _MSC_VER // We are using MSVC. -# pragma warning(push) // Saves the current warning state. -# pragma warning(disable:4996) // Temporarily disables warning 4996. - - const int size = vsnprintf(buffer, kBufferSize, format, args); +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} -# pragma warning(pop) // Restores the warning state. -#else // We are not using MSVC. - const int size = vsnprintf(buffer, kBufferSize, format, args); -#endif // _MSC_VER - va_end(args); +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} - // vsnprintf()'s behavior is not portable. When the buffer is not - // big enough, it returns a negative value in MSVC, and returns the - // needed buffer size on Linux. When there is an output error, it - // always returns a negative value. For simplicity, we lump the two - // error cases together. - if (size < 0 || size >= kBufferSize) { - return ""; - } else { - return std::string(buffer, size); - } +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); } // Converts the buffer in a stringstream to an std::string, converting NUL @@ -2091,10 +2062,8 @@ bool Test::HasNonfatalFailure() { // Constructs a TestInfo object. It assumes ownership of the test factory // object. -// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s -// to signify they cannot be NULLs. -TestInfo::TestInfo(const char* a_test_case_name, - const char* a_name, +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, const char* a_type_param, const char* a_value_param, internal::TypeId fixture_class_id, @@ -2133,7 +2102,8 @@ namespace internal { // The newly created TestInfo instance will assume // ownership of the factory object. TestInfo* MakeAndRegisterTestInfo( - const char* test_case_name, const char* name, + const char* test_case_name, + const char* name, const char* type_param, const char* value_param, TypeId fixture_class_id, @@ -2385,8 +2355,8 @@ void TestCase::UnshuffleTests() { static std::string FormatCountableNoun(int count, const char * singular_form, const char * plural_form) { - return internal::String::Format("%d %s", count, - count == 1 ? singular_form : plural_form); + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); } // Formats the count of tests. @@ -3056,7 +3026,8 @@ std::string XmlUnitTestResultPrinter::EscapeXml( default: if (IsValidXmlCharacter(*src)) { if (is_attribute && IsNormalizableWhitespace(*src)) - m << String::Format("&#x%02X;", unsigned(*src)); + m << "&#x" << String::FormatByte(static_cast(*src)) + << ";"; else m << *src; } @@ -3121,13 +3092,13 @@ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { 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); + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); } // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. @@ -3268,7 +3239,7 @@ class StreamingListener : public EmptyTestEventListener { StreamingListener(const string& host, const string& port) : sockfd_(-1), host_name_(host), port_num_(port) { MakeConnection(); - Send("gtest_streaming_protocol_version=1.0\n"); + SendLn("gtest_streaming_protocol_version=1.0"); } virtual ~StreamingListener() { @@ -3277,59 +3248,58 @@ class StreamingListener : public EmptyTestEventListener { } void OnTestProgramStart(const UnitTest& /* unit_test */) { - Send("event=TestProgramStart\n"); + SendLn("event=TestProgramStart"); } void OnTestProgramEnd(const UnitTest& unit_test) { // Note that Google Test current only report elapsed time for each // test iteration, not for the entire test program. - Send(String::Format("event=TestProgramEnd&passed=%d\n", - unit_test.Passed())); + SendLn("event=TestProgramEnd&passed=" + + StreamableToString(unit_test.Passed())); // Notify the streaming server to stop. CloseConnection(); } void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { - Send(String::Format("event=TestIterationStart&iteration=%d\n", - iteration)); + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); } void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { - Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n", - unit_test.Passed(), - StreamableToString(unit_test.elapsed_time()).c_str())); + SendLn("event=TestIterationEnd&passed=" + + StreamableToString(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); } void OnTestCaseStart(const TestCase& test_case) { - Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name())); + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); } void OnTestCaseEnd(const TestCase& test_case) { - Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n", - test_case.Passed(), - StreamableToString(test_case.elapsed_time()).c_str())); + SendLn("event=TestCaseEnd&passed=" + StreamableToString(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); } void OnTestStart(const TestInfo& test_info) { - Send(String::Format("event=TestStart&name=%s\n", test_info.name())); + SendLn(std::string("event=TestStart&name=") + test_info.name()); } void OnTestEnd(const TestInfo& test_info) { - Send(String::Format( - "event=TestEnd&passed=%d&elapsed_time=%sms\n", - (test_info.result())->Passed(), - StreamableToString((test_info.result())->elapsed_time()).c_str())); + SendLn("event=TestEnd&passed=" + + StreamableToString((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); } void OnTestPartResult(const TestPartResult& test_part_result) { const char* file_name = test_part_result.file_name(); if (file_name == NULL) file_name = ""; - Send(String::Format("event=TestPartResult&file=%s&line=%d&message=", - UrlEncode(file_name).c_str(), - test_part_result.line_number())); - Send(UrlEncode(test_part_result.message()) + "\n"); + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); } private: @@ -3358,6 +3328,11 @@ class StreamingListener : public EmptyTestEventListener { } } + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + int sockfd_; // socket file descriptor const string host_name_; const string port_num_; @@ -3379,7 +3354,7 @@ string StreamingListener::UrlEncode(const char* str) { case '=': case '&': case '\n': - result.append(String::Format("%%%02x", static_cast(ch))); + result.append("%" + String::FormatByte(static_cast(ch))); break; default: result.push_back(ch); -- cgit v1.2.3