Alien-cares
view release on metacpan or search on metacpan
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
// The list of event listeners that can be used to track events inside
// Google Test.
TestEventListeners listeners_;
// The OS stack trace getter. Will be deleted when the UnitTest
// object is destructed. By default, an OsStackTraceGetter is used,
// but the user can set this field to use a custom getter if that is
// desired.
OsStackTraceGetterInterface* os_stack_trace_getter_;
// True iff PostFlagParsingInit() has been called.
bool post_flag_parse_init_performed_;
// The random number seed used at the beginning of the test run.
int random_seed_;
// 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_;
#if GTEST_HAS_DEATH_TEST
// The decomposed components of the gtest_internal_run_death_test flag,
// parsed when RUN_ALL_TESTS is called.
internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
#endif // GTEST_HAS_DEATH_TEST
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
// The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
// starts.
bool catch_exceptions_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
}; // class UnitTestImpl
// Convenience function for accessing the global UnitTest
// implementation object.
inline UnitTestImpl* GetUnitTestImpl() {
return UnitTest::GetInstance()->impl();
}
#if GTEST_USES_SIMPLE_RE
// Internal helper functions for implementing the simple regular
// expression matcher.
GTEST_API_ bool IsInSet(char ch, const char* str);
GTEST_API_ bool IsAsciiDigit(char ch);
GTEST_API_ bool IsAsciiPunct(char ch);
GTEST_API_ bool IsRepeat(char ch);
GTEST_API_ bool IsAsciiWhiteSpace(char ch);
GTEST_API_ bool IsAsciiWordChar(char ch);
GTEST_API_ bool IsValidEscape(char ch);
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
GTEST_API_ bool ValidateRegex(const char* regex);
GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
GTEST_API_ bool MatchRepetitionAndRegexAtHead(
bool escaped, char ch, char repeat, const char* regex, const char* str);
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
#endif // GTEST_USES_SIMPLE_RE
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test.
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
#if GTEST_HAS_DEATH_TEST
// Returns the message describing the last system error, regardless of the
// platform.
GTEST_API_ std::string GetLastErrnoDescription();
// Attempts to parse a string into a positive integer pointed to by the
// number parameter. Returns true if that is possible.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
// it here.
template <typename Integer>
bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
// Fail fast if the given string does not begin with a digit;
// this bypasses strtoXXX's "optional leading whitespace and plus
// or minus sign" semantics, which are undesirable here.
if (str.empty() || !IsDigit(str[0])) {
return false;
}
errno = 0;
char* end;
// BiggestConvertible is the largest integer type that system-provided
// string-to-number conversion routines can return.
# if GTEST_OS_WINDOWS && !defined(__GNUC__)
// MSVC and C++ Builder define __int64 instead of the standard long long.
typedef unsigned __int64 BiggestConvertible;
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
# else
typedef unsigned long long BiggestConvertible; // NOLINT
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
const bool parse_success = *end == '\0' && errno == 0;
// TODO(vladl@google.com): Convert this to compile time assertion when it is
// available.
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
const Integer result = static_cast<Integer>(parsed);
if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
*number = result;
return true;
}
return false;
}
#endif // GTEST_HAS_DEATH_TEST
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
while (edit_i < edits.size()) {
// Find first edit.
while (edit_i < edits.size() && edits[edit_i] == kMatch) {
++l_i;
++r_i;
++edit_i;
}
// Find the first line to include in the hunk.
const size_t prefix_context = std::min(l_i, context);
Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
for (size_t i = prefix_context; i > 0; --i) {
hunk.PushLine(' ', left[l_i - i].c_str());
}
// Iterate the edits until we found enough suffix for the hunk or the input
// is over.
size_t n_suffix = 0;
for (; edit_i < edits.size(); ++edit_i) {
if (n_suffix >= context) {
// Continue only if the next hunk is very close.
std::vector<EditType>::const_iterator it = edits.begin() + edit_i;
while (it != edits.end() && *it == kMatch) ++it;
if (it == edits.end() || (it - edits.begin()) - edit_i >= context) {
// There is no next edit or it is too far away.
break;
}
}
EditType edit = edits[edit_i];
// Reset count when a non match is found.
n_suffix = edit == kMatch ? n_suffix + 1 : 0;
if (edit == kMatch || edit == kRemove || edit == kReplace) {
hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
}
if (edit == kAdd || edit == kReplace) {
hunk.PushLine('+', right[r_i].c_str());
}
// Advance indices, depending on edit type.
l_i += edit != kAdd;
r_i += edit != kRemove;
}
if (!hunk.has_edits()) {
// We are done. We don't want this hunk.
break;
}
hunk.PrintTo(&ss);
}
return ss.str();
}
} // namespace edit_distance
namespace {
// The string representation of the values received in EqFailure() are already
// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
// characters the same.
std::vector<std::string> SplitEscapedString(const std::string& str) {
std::vector<std::string> lines;
size_t start = 0, end = str.size();
if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
++start;
--end;
}
bool escaped = false;
for (size_t i = start; i + 1 < end; ++i) {
if (escaped) {
escaped = false;
if (str[i] == 'n') {
lines.push_back(str.substr(start, i - start - 1));
start = i + 1;
}
} else {
escaped = str[i] == '\\';
}
}
lines.push_back(str.substr(start, end - start));
return lines;
}
} // namespace
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
// The first four parameters are the expressions used in the assertion
// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
// where foo is 5 and bar is 6, we have:
//
// lhs_expression: "foo"
// rhs_expression: "bar"
// lhs_value: "5"
// rhs_value: "6"
//
// The ignoring_case parameter is true iff the assertion is a
// *_STRCASEEQ*. When it's true, the string "Ignoring case" will
// be inserted into the message.
AssertionResult EqFailure(const char* lhs_expression,
const char* rhs_expression,
const std::string& lhs_value,
const std::string& rhs_value,
bool ignoring_case) {
Message msg;
msg << " Expected: " << lhs_expression;
if (lhs_value != lhs_expression) {
msg << "\n Which is: " << lhs_value;
}
msg << "\nTo be equal to: " << rhs_expression;
if (rhs_value != rhs_expression) {
msg << "\n Which is: " << rhs_value;
}
if (ignoring_case) {
msg << "\nIgnoring case";
}
if (!lhs_value.empty() && !rhs_value.empty()) {
const std::vector<std::string> lhs_lines =
SplitEscapedString(lhs_value);
const std::vector<std::string> rhs_lines =
SplitEscapedString(rhs_value);
if (lhs_lines.size() > 1 || rhs_lines.size() > 1) {
msg << "\nWith diff:\n"
<< edit_distance::CreateUnifiedDiff(lhs_lines, rhs_lines);
}
}
return AssertionFailure() << msg;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
std::string GetBoolAssertionFailureMessage(
const AssertionResult& assertion_result,
const char* expression_text,
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
listeners_[i]->Name(parameter); \
} \
} \
}
GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
#undef GTEST_REPEATER_METHOD_
#undef GTEST_REVERSE_REPEATER_METHOD_
void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
int iteration) {
if (forwarding_enabled_) {
for (size_t i = 0; i < listeners_.size(); i++) {
listeners_[i]->OnTestIterationStart(unit_test, iteration);
}
}
}
void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
int iteration) {
if (forwarding_enabled_) {
for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
listeners_[i]->OnTestIterationEnd(unit_test, iteration);
}
}
}
// End TestEventRepeater
// This class generates an XML output file.
class XmlUnitTestResultPrinter : public EmptyTestEventListener {
public:
explicit XmlUnitTestResultPrinter(const char* output_file);
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
private:
// Is c a whitespace character that is normalized to a space character
// when it appears in an XML attribute value?
static bool IsNormalizableWhitespace(char c) {
return c == 0x9 || c == 0xA || c == 0xD;
}
// May c appear in a well-formed XML document?
static bool IsValidXmlCharacter(char c) {
return IsNormalizableWhitespace(c) || c >= 0x20;
}
// Returns an XML-escaped copy of the input string str. If
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// with character references.
static std::string EscapeXml(const std::string& str, bool is_attribute);
// Returns the given string with all characters invalid in XML removed.
static std::string RemoveInvalidXmlCharacters(const std::string& str);
// Convenience wrapper around EscapeXml when str is an attribute value.
static std::string EscapeXmlAttribute(const std::string& str) {
return EscapeXml(str, true);
}
// Convenience wrapper around EscapeXml when str is not an attribute value.
static std::string EscapeXmlText(const char* str) {
return EscapeXml(str, false);
}
// Verifies that the given attribute belongs to the given element and
// streams the attribute as XML.
static void OutputXmlAttribute(std::ostream* stream,
const std::string& element_name,
const std::string& name,
const std::string& value);
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
// Streams an XML representation of a TestInfo object.
static void OutputXmlTestInfo(::std::ostream* stream,
const char* test_case_name,
const TestInfo& test_info);
// Prints an XML representation of a TestCase object
static void PrintXmlTestCase(::std::ostream* stream,
const TestCase& test_case);
// Prints an XML summary of unit_test to output stream out.
static void PrintXmlUnitTest(::std::ostream* stream,
const UnitTest& unit_test);
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
// When the std::string is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
// The output file.
const std::string output_file_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
};
// Creates a new XmlUnitTestResultPrinter.
XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
: output_file_(output_file) {
if (output_file_.c_str() == NULL || output_file_.empty()) {
fprintf(stderr, "XML output file may not be null\n");
fflush(stderr);
exit(EXIT_FAILURE);
}
}
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) {
FILE* xmlout = NULL;
FilePath output_file(output_file_);
FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
xmlout = posix::FOpen(output_file_.c_str(), "w");
}
if (xmlout == NULL) {
// TODO(wan): report the reason of the failure.
//
// We don't do it for now as:
//
// 1. There is no urgent need for it.
// 2. It's a bit involved to make the errno variable thread-safe on
// all three operating systems (Linux, Windows, and Mac OS).
// 3. To interpret the meaning of errno in a thread-safe way,
// we need the strerror_r() function, which is not available on
// Windows.
fprintf(stderr,
"Unable to open file \"%s\"\n",
output_file_.c_str());
fflush(stderr);
exit(EXIT_FAILURE);
}
std::stringstream stream;
PrintXmlUnitTest(&stream, unit_test);
fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
fclose(xmlout);
}
// Returns an XML-escaped copy of the input string str. If is_attribute
// is true, the text is meant to appear as an attribute value, and
// normalizable whitespace is preserved by replacing it with character
// references.
//
// Invalid XML characters in str, if any, are stripped from the output.
// It is expected that most, if not all, of the text processed by this
// module will consist of ordinary English text.
// If this module is ever modified to produce version 1.1 XML output,
// most invalid characters can be retained using character references.
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
std::string XmlUnitTestResultPrinter::EscapeXml(
const std::string& str, bool is_attribute) {
Message m;
for (size_t i = 0; i < str.size(); ++i) {
const char ch = str[i];
switch (ch) {
case '<':
m << "<";
break;
case '>':
m << ">";
break;
case '&':
m << "&";
break;
case '\'':
if (is_attribute)
m << "'";
else
m << '\'';
break;
case '"':
if (is_attribute)
m << """;
else
m << '"';
break;
default:
if (IsValidXmlCharacter(ch)) {
if (is_attribute && IsNormalizableWhitespace(ch))
m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
<< ";";
else
m << ch;
}
break;
}
}
return m.GetString();
}
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
const std::string& str) {
std::string output;
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, true);
// Aborts if the parsing failed.
if (value_str == NULL) return false;
// Converts the string value to a bool.
*value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
return true;
}
// 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
// true. On failure, returns false without changing *value.
bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false);
// Aborts if the parsing failed.
if (value_str == NULL) return false;
// Sets *value to the value of the flag.
return ParseInt32(Message() << "The value of flag --" << flag,
value_str, value);
}
// Parses a string for a string flag, in the form of
// "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false);
// Aborts if the parsing failed.
if (value_str == NULL) return false;
// Sets *value to the value of the flag.
*value = value_str;
return true;
}
// Determines whether a string has a prefix that Google Test uses for its
// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
// If Google Test detects that a command line flag has its prefix but is not
// recognized, it will print its help message. Flags starting with
// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
// internal flags and do not trigger the help message.
static bool HasGoogleTestFlagPrefix(const char* str) {
return (SkipPrefix("--", &str) ||
SkipPrefix("-", &str) ||
SkipPrefix("/", &str)) &&
!SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
(SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
}
// Prints a string containing code-encoded text. The following escape
// sequences can be used in the string to control the text color:
//
// @@ prints a single '@' character.
// @R changes the color to red.
// @G changes the color to green.
// @Y changes the color to yellow.
// @D changes to the default terminal text color.
//
// TODO(wan@google.com): Write tests for this once we add stdout
// capturing to Google Test.
static void PrintColorEncoded(const char* str) {
GTestColor color = COLOR_DEFAULT; // The current color.
// Conceptually, we split the string into segments divided by escape
// sequences. Then we print one segment at a time. At the end of
// each iteration, the str pointer advances to the beginning of the
// next segment.
for (;;) {
const char* p = strchr(str, '@');
if (p == NULL) {
ColoredPrintf(color, "%s", str);
return;
}
ColoredPrintf(color, "%s", std::string(str, p).c_str());
const char ch = p[1];
str = p + 2;
if (ch == '@') {
ColoredPrintf(color, "@");
} else if (ch == 'D') {
color = COLOR_DEFAULT;
} else if (ch == 'R') {
color = COLOR_RED;
} else if (ch == 'G') {
color = COLOR_GREEN;
} else if (ch == 'Y') {
color = COLOR_YELLOW;
} else {
--str;
}
}
}
static const char kColorEncodedHelpMessage[] =
"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
"following command line flags to control its behavior:\n"
"\n"
"Test Selection:\n"
" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
" List the names of all tests instead of running them. The name of\n"
" TEST(Foo, Bar) is \"Foo.Bar\".\n"
" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
"[@G-@YNEGATIVE_PATTERNS]@D\n"
" Run only the tests whose name matches one of the positive patterns but\n"
" none of the negative patterns. '?' matches any single character; '*'\n"
" matches any substring; ':' separates two patterns.\n"
" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
" Run all disabled tests too.\n"
"\n"
"Test Execution:\n"
" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
" Run the tests repeatedly; use a negative count to repeat forever.\n"
" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
" Randomize tests' orders on every iteration.\n"
" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
" Random number seed to use for shuffling test orders (between 1 and\n"
" 99999, or 0 to use a seed based on the current time).\n"
"\n"
"Test Output:\n"
" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
" Enable/disable colored output. The default is @Gauto@D.\n"
" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
" Don't print the elapsed time of each test.\n"
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
// (including str itself).
bool RE::PartialMatch(const char* str, const RE& re) {
if (!re.is_valid_) return false;
regmatch_t match;
return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
}
// Initializes an RE from its string representation.
void RE::Init(const char* regex) {
pattern_ = posix::StrDup(regex);
// Reserves enough bytes to hold the regular expression used for a
// full match.
const size_t full_regex_len = strlen(regex) + 10;
char* const full_pattern = new char[full_regex_len];
snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
// We want to call regcomp(&partial_regex_, ...) even if the
// previous expression returns false. Otherwise partial_regex_ may
// not be properly initialized can may cause trouble when it's
// freed.
//
// Some implementation of POSIX regex (e.g. on at least some
// versions of Cygwin) doesn't accept the empty string as a valid
// regex. We change it to an equivalent form "()" to be safe.
if (is_valid_) {
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
}
EXPECT_TRUE(is_valid_)
<< "Regular expression \"" << regex
<< "\" is not a valid POSIX Extended regular expression.";
delete[] full_pattern;
}
#elif GTEST_USES_SIMPLE_RE
// Returns true iff ch appears anywhere in str (excluding the
// terminating '\0' character).
bool IsInSet(char ch, const char* str) {
return ch != '\0' && strchr(str, ch) != NULL;
}
// Returns true iff ch belongs to the given classification. Unlike
// similar functions in <ctype.h>, these aren't affected by the
// current locale.
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
bool IsAsciiPunct(char ch) {
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
}
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
bool IsAsciiWordChar(char ch) {
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') || ch == '_';
}
// Returns true iff "\\c" is a supported escape sequence.
bool IsValidEscape(char c) {
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
}
// Returns true iff the given atom (specified by escaped and pattern)
// matches ch. The result is undefined if the atom is invalid.
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
if (escaped) { // "\\p" where p is pattern_char.
switch (pattern_char) {
case 'd': return IsAsciiDigit(ch);
case 'D': return !IsAsciiDigit(ch);
case 'f': return ch == '\f';
case 'n': return ch == '\n';
case 'r': return ch == '\r';
case 's': return IsAsciiWhiteSpace(ch);
case 'S': return !IsAsciiWhiteSpace(ch);
case 't': return ch == '\t';
case 'v': return ch == '\v';
case 'w': return IsAsciiWordChar(ch);
case 'W': return !IsAsciiWordChar(ch);
}
return IsAsciiPunct(pattern_char) && pattern_char == ch;
}
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
}
// Helper function used by ValidateRegex() to format error messages.
std::string FormatRegexSyntaxError(const char* regex, int index) {
return (Message() << "Syntax error at index " << index
<< " in simple regular expression \"" << regex << "\": ").GetString();
}
// Generates non-fatal failures and returns false if regex is invalid;
// otherwise returns true.
bool ValidateRegex(const char* regex) {
if (regex == NULL) {
// TODO(wan@google.com): fix the source file location in the
// assertion failures to match where the regex is used in user
// code.
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
return false;
}
bool is_valid = true;
// True iff ?, *, or + can follow the previous atom.
bool prev_repeatable = false;
for (int i = 0; regex[i]; i++) {
if (regex[i] == '\\') { // An escape sequence
i++;
if (regex[i] == '\0') {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
<< "'\\' cannot appear at the end.";
return false;
}
if (!IsValidEscape(regex[i])) {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
<< "invalid escape sequence \"\\" << regex[i] << "\".";
is_valid = false;
}
prev_repeatable = true;
} else { // Not an escape sequence.
const char ch = regex[i];
if (ch == '^' && i > 0) {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
<< "'^' can only appear at the beginning.";
is_valid = false;
} else if (ch == '$' && regex[i + 1] != '\0') {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
<< "'$' can only appear at the end.";
is_valid = false;
} else if (IsInSet(ch, "()[]{}|")) {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
<< "'" << ch << "' is unsupported.";
is_valid = false;
} else if (IsRepeat(ch) && !prev_repeatable) {
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
<< "'" << ch << "' can only follow a repeatable token.";
is_valid = false;
}
prev_repeatable = !IsInSet(ch, "^$?*+");
}
}
return is_valid;
}
// Matches a repeated regex atom followed by a valid simple regular
// expression. The regex atom is defined as c if escaped is false,
// or \c otherwise. repeat is the repetition meta character (?, *,
// or +). The behavior is undefined if str contains too many
// characters to be indexable by size_t, in which case the test will
// probably time out anyway. We are fine with this limitation as
// std::string has it too.
bool MatchRepetitionAndRegexAtHead(
bool escaped, char c, char repeat, const char* regex,
const char* str) {
const size_t min_count = (repeat == '+') ? 1 : 0;
const size_t max_count = (repeat == '?') ? 1 :
static_cast<size_t>(-1) - 1;
// We cannot call numeric_limits::max() as it conflicts with the
// max() macro on Windows.
for (size_t i = 0; i <= max_count; ++i) {
// We know that the atom matches each of the first i characters in str.
if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
// We have enough matches at the head, and the tail matches too.
// Since we only care about *whether* the pattern matches str
// (as opposed to *how* it matches), there is no need to find a
// greedy match.
return true;
}
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
return false;
}
return false;
}
// Returns true iff regex matches a prefix of str. regex must be a
// valid simple regular expression and not start with "^", or the
// result is undefined.
bool MatchRegexAtHead(const char* regex, const char* str) {
if (*regex == '\0') // An empty regex matches a prefix of anything.
return true;
// "$" only matches the end of a string. Note that regex being
// valid guarantees that there's nothing after "$" in it.
if (*regex == '$')
return *str == '\0';
// Is the first thing in regex an escape sequence?
const bool escaped = *regex == '\\';
if (escaped)
++regex;
if (IsRepeat(regex[1])) {
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
// here's an indirect recursion. It terminates as the regex gets
// shorter in each recursion.
return MatchRepetitionAndRegexAtHead(
escaped, regex[0], regex[1], regex + 2, str);
} else {
// regex isn't empty, isn't "$", and doesn't start with a
// repetition. We match the first atom of regex with the first
// character of str and recurse.
return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
MatchRegexAtHead(regex + 1, str + 1);
}
}
// Returns true iff regex matches any substring of str. regex must be
// a valid simple regular expression, or the result is undefined.
//
// The algorithm is recursive, but the recursion depth doesn't exceed
// the regex length, so we won't need to worry about running out of
// stack space normally. In rare cases the time complexity can be
// exponential with respect to the regex length + the string length,
// but usually it's must faster (often close to linear).
bool MatchRegexAnywhere(const char* regex, const char* str) {
if (regex == NULL || str == NULL)
return false;
if (*regex == '^')
return MatchRegexAtHead(regex + 1, str);
// A successful match can be anywhere in str.
do {
if (MatchRegexAtHead(regex, str))
return true;
} while (*str++ != '\0');
return false;
}
// Implements the RE class.
RE::~RE() {
free(const_cast<char*>(pattern_));
free(const_cast<char*>(full_pattern_));
}
// Returns true iff regular expression re matches the entire str.
bool RE::FullMatch(const char* str, const RE& re) {
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
}
// Returns true iff regular expression re matches a substring of str
// (including str itself).
bool RE::PartialMatch(const char* str, const RE& re) {
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
}
// Initializes an RE from its string representation.
void RE::Init(const char* regex) {
pattern_ = full_pattern_ = NULL;
if (regex != NULL) {
pattern_ = posix::StrDup(regex);
}
is_valid_ = ValidateRegex(regex);
if (!is_valid_) {
// No need to calculate the full pattern when the regex is invalid.
return;
}
const size_t len = strlen(regex);
// Reserves enough bytes to hold the regular expression used for a
libcares/test/gmock-1.8.0/gmock-gtest-all.cc view on Meta::CPAN
for (size_t i = 0; i != count; i++) {
const size_t j = start + i;
if (i != 0) {
// Organizes the bytes into groups of 2 for easy parsing by
// human.
if ((j % 2) == 0)
*os << ' ';
else
*os << '-';
}
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
*os << text;
}
}
// Prints the bytes in the given value to the given ostream.
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
ostream* os) {
// Tells the user how big the object is.
*os << count << "-byte object <";
const size_t kThreshold = 132;
const size_t kChunkSize = 64;
// If the object size is bigger than kThreshold, we'll have to omit
// some details by printing only the first and the last kChunkSize
// bytes.
// TODO(wan): let the user control the threshold using a flag.
if (count < kThreshold) {
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
} else {
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
*os << " ... ";
// Rounds up to 2-byte boundary.
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
}
*os << ">";
}
} // namespace
namespace internal2 {
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
// given object. The delegation simplifies the implementation, which
// uses the << operator and thus is easier done outside of the
// ::testing::internal namespace, which contains a << operator that
// sometimes conflicts with the one in STL.
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
ostream* os) {
PrintBytesInObjectToImpl(obj_bytes, count, os);
}
} // namespace internal2
namespace internal {
// Depending on the value of a char (or wchar_t), we print it in one
// of three formats:
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
// - as a hexidecimal escape sequence (e.g. '\x7F'), or
// - as a special escape sequence (e.g. '\r', '\n').
enum CharFormat {
kAsIs,
kHexEscape,
kSpecialEscape
};
// Returns true if c is a printable ASCII character. We test the
// value of c directly instead of calling isprint(), which is buggy on
// Windows Mobile.
inline bool IsPrintableAscii(wchar_t c) {
return 0x20 <= c && c <= 0x7E;
}
// Prints a wide or narrow char c as a character literal without the
// quotes, escaping it when necessary; returns how c was formatted.
// The template argument UnsignedChar is the unsigned version of Char,
// which is the type of c.
template <typename UnsignedChar, typename Char>
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
switch (static_cast<wchar_t>(c)) {
case L'\0':
*os << "\\0";
break;
case L'\'':
*os << "\\'";
break;
case L'\\':
*os << "\\\\";
break;
case L'\a':
*os << "\\a";
break;
case L'\b':
*os << "\\b";
break;
case L'\f':
*os << "\\f";
break;
case L'\n':
*os << "\\n";
break;
case L'\r':
*os << "\\r";
break;
case L'\t':
*os << "\\t";
break;
case L'\v':
*os << "\\v";
break;
default:
if (IsPrintableAscii(c)) {
*os << static_cast<char>(c);
return kAsIs;
} else {
*os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
return kHexEscape;
}
}
return kSpecialEscape;
}
// Prints a wchar_t c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
return kAsIs;
case L'"':
*os << "\\\"";
return kSpecialEscape;
default:
return PrintAsCharLiteralTo<wchar_t>(c, os);
}
}
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
return PrintAsStringLiteralTo(
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
}
// Prints a wide or narrow character c and its code. '\0' is printed
// as "'\\0'", other unprintable characters are also properly escaped
// using the standard C++ escape sequence. The template argument
// UnsignedChar is the unsigned version of Char, which is the type of c.
template <typename UnsignedChar, typename Char>
void PrintCharAndCodeTo(Char c, ostream* os) {
// First, print c as a literal in the most readable form we can find.
*os << ((sizeof(c) > 1) ? "L'" : "'");
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
*os << "'";
// To aid user debugging, we also print c's code in decimal, unless
// it's 0 (in which case c was printed as '\\0', making the code
// obvious).
if (c == 0)
return;
*os << " (" << static_cast<int>(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
// [1, 9].
if (format == kHexEscape || (1 <= c && c <= 9)) {
// Do nothing.
} else {
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
}
*os << ")";
}
void PrintTo(unsigned char c, ::std::ostream* os) {
PrintCharAndCodeTo<unsigned char>(c, os);
}
void PrintTo(signed char c, ::std::ostream* os) {
PrintCharAndCodeTo<unsigned char>(c, os);
}
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
void PrintTo(wchar_t wc, ostream* os) {
PrintCharAndCodeTo<wchar_t>(wc, os);
}
// Prints the given array of characters to the ostream. CharType must be either
// char or wchar_t.
// The array starts at begin, the length is len, it may include '\0' characters
// and may not be NUL-terminated.
template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
*os << kQuoteBegin;
bool is_previous_hex = false;
for (size_t index = 0; index < len; ++index) {
const CharType cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) {
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
*os << "\" " << kQuoteBegin;
}
( run in 1.595 second using v1.01-cache-2.11-cpan-6fb7bf0f510 )