deps: update googletest to 8eff9e336692fc95961e096564f1044c600b881d

PR-URL: https://github.com/nodejs/node/pull/66009
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Node.js GitHub Bot authored and Antoine du Hamel committed 2026-09-16 21:12:17 +02:00
1 parent 3a69cc1bf4
commit e8edeffe2d
5 files changed
+42 -306

No files matched your search

+4 -48
View File
@@ -105,54 +105,10 @@ GTEST_API_ bool InDeathTestChild();
//
// On the regular expressions used in death tests:
//
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
// which uses the POSIX extended regex syntax.
//
// On other platforms (e.g. Windows or Mac), we only support a simple regex
// syntax implemented as part of Google Test. This limited
// implementation should be enough most of the time when writing
// death tests; though it lacks many features you can find in PCRE
// or POSIX extended regex syntax. For example, we don't support
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
// repetition count ("x{5,7}"), among others.
//
// Below is the syntax that we do support. We chose it to be a
// subset of both PCRE and POSIX extended regex, so it's easy to
// learn wherever you come from. In the following: 'A' denotes a
// literal character, period (.), or a single \\ escape sequence;
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
// natural numbers.
//
// c matches any literal character c
// \\d matches any decimal digit
// \\D matches any character that's not a decimal digit
// \\f matches \f
// \\n matches \n
// \\r matches \r
// \\s matches any ASCII whitespace, including \n
// \\S matches any character that's not a whitespace
// \\t matches \t
// \\v matches \v
// \\w matches any letter, _, or decimal digit
// \\W matches any character that \\w doesn't match
// \\c matches any literal character c, which must be a punctuation
// . matches any single character except \n
// A? matches 0 or 1 occurrences of A
// A* matches 0 or many occurrences of A
// A+ matches 1 or many occurrences of A
// ^ matches the beginning of a string (not that of each line)
// $ matches the end of a string (not that of each line)
// xy matches x followed by y
//
// If you accidentally use PCRE or POSIX extended regex features
// not implemented by us, you will get a run-time failure. In that
// case, please try to rewrite your regular expression within the
// above syntax.
//
// This implementation is *not* meant to be as highly tuned or robust
// as a compiled regex library, but should perform well enough for a
// death test, which already incurs significant overhead by launching
// a child process.
// Depending on the platform, this may use RE2, the POSIX <regex.h> library,
// the C++11 standard library's <regex> engine with ECMAScript syntax, or
// another similar engine. Regular expressions should be simple and portable
// enough to work across the engines of interest.
//
// Known caveats:
//
+17 -15
View File
@@ -176,7 +176,7 @@
// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
// GTEST_HAS_POSIX_RE (see above) which users can
// define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
// GTEST_USES_STD_RE - std::regex from the C++ standard library is used;
// the above RE\b(s) are mutually exclusive.
// GTEST_HAS_ABSL - Google Test is compiled with Abseil.
@@ -438,8 +438,9 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#include <regex.h> // NOLINT
#define GTEST_USES_POSIX_RE 1
#else
// Use our own simple regex implementation.
#define GTEST_USES_SIMPLE_RE 1
// Use std::regex from the C++ standard library.
#include <regex> // NOLINT
#define GTEST_USES_STD_RE 1
#endif
#ifndef GTEST_HAS_EXCEPTIONS
@@ -992,12 +993,11 @@ class GTEST_API_ [[nodiscard]] RE {
RE2 regex_;
};
#elif defined(GTEST_USES_POSIX_RE) || defined(GTEST_USES_SIMPLE_RE)
#elif defined(GTEST_USES_POSIX_RE) || defined(GTEST_USES_STD_RE)
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
// Regular Expression syntax.
// A simple C++ wrapper for <regex.h> or <regex>.
class GTEST_API_ [[nodiscard]] RE {
public:
// A copy constructor is required by the Standard to initialize object
@@ -1037,9 +1037,9 @@ class GTEST_API_ [[nodiscard]] RE {
regex_t full_regex_; // For FullMatch().
regex_t partial_regex_; // For PartialMatch().
#else // GTEST_USES_SIMPLE_RE
#else // GTEST_USES_STD_RE
std::string full_pattern_; // For FullMatch();
std::regex regex_;
#endif
};
@@ -1755,14 +1755,16 @@ class [[nodiscard]] MutexBase {
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::MutexBase mutex
#if defined(PTHREAD_NULL)
#define GTEST_INTERNAL_PTHREAD_NULL PTHREAD_NULL
#else
#define GTEST_INTERNAL_PTHREAD_NULL (pthread_t{})
#endif
// Defines and statically (i.e. at link time) initializes a static mutex.
// The initialization list here does not explicitly initialize each field,
// instead relying on default initialization for the unspecified fields. In
// particular, the owner_ field (a pthread_t) is not explicitly initialized.
// This allows initialization to work whether pthread_t is a scalar or struct.
// The flag -Wmissing-field-initializers must not be specified for this to work.
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0}
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, \
GTEST_INTERNAL_PTHREAD_NULL}
// The Mutex class can only be used for mutexes created at runtime. It
// shares its API with MutexBase otherwise.
-19
View File
@@ -980,26 +980,7 @@ inline UnitTestImpl* GetUnitTestImpl() {
return UnitTest::GetInstance()->impl();
}
#ifdef 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.
+20 -223
View File
@@ -766,249 +766,46 @@ void RE::Init(const char* regex) {
delete[] full_pattern;
}
#elif defined(GTEST_USES_SIMPLE_RE)
// Returns true if and only if ch appears anywhere in str (excluding the
// terminating '\0' character).
bool IsInSet(char ch, const char* str) {
return ch != '\0' && strchr(str, ch) != nullptr;
}
// Returns true if and only if 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 if and only if "\\c" is a supported escape sequence.
bool IsValidEscape(char c) {
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
}
// Returns true if and only if 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.
static 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 == nullptr) {
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
return false;
}
bool is_valid = true;
// True if and only if ?, *, 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 if and only if 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 if and only if 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 == nullptr || str == nullptr) 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.
#elif defined(GTEST_USES_STD_RE)
RE::~RE() = default;
// Returns true if and only if regular expression re matches the entire str.
bool RE::FullMatch(const char* str, const RE& re) {
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_.c_str(), str);
if (!re.is_valid_ || str == nullptr) return false;
return std::regex_match(str, re.regex_);
}
// Returns true if and only if 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_.c_str(), str);
if (!re.is_valid_ || str == nullptr) return false;
return std::regex_search(str, re.regex_);
}
// Initializes an RE from its string representation.
void RE::Init(const char* regex) {
full_pattern_.clear();
pattern_.clear();
pattern_ = regex == nullptr ? "" : regex;
is_valid_ = false;
if (regex != nullptr) {
pattern_ = regex;
}
is_valid_ = ValidateRegex(regex);
if (!is_valid_) {
// No need to calculate the full pattern when the regex is invalid.
if (regex == nullptr) {
ADD_FAILURE() << "NULL is not a valid regular expression.";
return;
}
// Reserves enough bytes to hold the regular expression used for a
// full match: we need space to prepend a '^' and append a '$'.
full_pattern_.reserve(pattern_.size() + 2);
if (pattern_.empty() || pattern_.front() != '^') {
full_pattern_.push_back('^'); // Makes sure full_pattern_ starts with '^'.
#if GTEST_HAS_EXCEPTIONS
try {
regex_ = std::regex(regex, std::regex_constants::ECMAScript);
} catch (const std::regex_error& e) {
ADD_FAILURE() << "Regular expression \"" << regex
<< "\" is not a valid regular expression: " << e.what();
return;
}
#else
regex_ = std::regex(regex, std::regex_constants::ECMAScript);
#endif
full_pattern_.append(pattern_);
if (pattern_.empty() || pattern_.back() != '$') {
full_pattern_.push_back('$'); // Makes sure full_pattern_ ends with '$'.
}
is_valid_ = true;
}
#endif // GTEST_USES_POSIX_RE
+1 -1
View File
@@ -4648,7 +4648,7 @@ std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) {
m << "\\r";
break;
default:
if (ch < ' ') {
if (static_cast<unsigned char>(ch) < ' ' || ch == '\x7F') {
m << "\\u00" << String::FormatByte(static_cast<unsigned char>(ch));
} else {
m << ch;