summaryrefslogtreecommitdiffstats
path: root/src/gtest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtest.cc')
-rw-r--r--src/gtest.cc173
1 files changed, 74 insertions, 99 deletions
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<char>(code_point); // 0xxxxxxx
@@ -1405,22 +1408,12 @@ char* CodePointToUtf8(UInt32 code_point, char* str) {
str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
str[0] = static_cast<char>(0xE0 | code_point); // 1110xxxx
- } else if (code_point <= kMaxCodePoint4) {
+ } else { // code_point <= kMaxCodePoint4
str[4] = '\0';
str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
str[0] = static_cast<char>(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<UInt32>(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, "<formatting error or buffer exceeded>" 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 "<formatting error or buffer exceeded>";
- } 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<unsigned int>(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<unsigned char>(*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<unsigned char>(ch)));
+ result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
break;
default:
result.push_back(ch);