SERVER-102107 Fix and reenable mongo polyfill check (#34879)

GitOrigin-RevId: 721448be067332e2106b165a7b410809e1a263d9
This commit is contained in:
Alex Li 2025-05-22 10:10:06 -04:00 committed by MongoDB Bot
parent c53f216dce
commit 6d35264914
21 changed files with 207 additions and 111 deletions

View File

@ -75,6 +75,7 @@ Checks: '-*,
mongo-invariant-status-is-ok-check,
mongo-macro-definition-leaks-check,
mongo-mutex-check,
mongo-polyfill-check,
mongo-rand-check,
mongo-std-atomic-check,
mongo-std-optional-check,

View File

@ -37,7 +37,6 @@
#include <s2regioncoverer.h>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
@ -50,6 +49,7 @@
#include "mongo/db/query/interval.h"
#include "mongo/logv2/log.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/util/assert_util.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
@ -200,7 +200,7 @@ void ExpressionMapping::S2CellIdsToIntervalsWithParents(const std::vector<S2Cell
const S2IndexingParams& indexParams,
OrderedIntervalList* oilOut) {
// There may be duplicates when going up parent cells if two cells share a parent
std::unordered_set<S2CellId> exactSet; // NOLINT
stdx::unordered_set<S2CellId> exactSet;
for (const S2CellId& interval : intervalSet) {
S2CellId coveredCell = interval;
// Look at the cells that cover us. We want to look at every cell that contains the

View File

@ -50,6 +50,7 @@
#include "mongo/db/pipeline/expression_context.h"
#include "mongo/db/query/fle/encrypted_predicate_test_fixtures.h"
#include "mongo/db/query/fle/text_search_predicate.h"
#include "mongo/stdx/unordered_map.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"
@ -168,7 +169,7 @@ private:
};
// Key the tags for agg expressions based on values only, since we don't have access to the
// field name. The Value in the map must contain BSONBinData type used for payloads.
std::unordered_map<Value, std::vector<PrfBlock>, KeyHash, KeyEqual> _exprTags;
stdx::unordered_map<Value, std::vector<PrfBlock>, KeyHash, KeyEqual> _exprTags;
};
class TextSearchPredicateRewriteTestWithFFP : public EncryptedPredicateRewriteTest {

View File

@ -132,7 +132,7 @@ void IntentRegistry::deregisterIntent(IntentRegistry::IntentToken token) {
stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOperations(
IntentRegistry::InterruptionType interrupt, boost::optional<uint32_t> timeout_sec) {
LOGV2(9945003, "Intent Registry killConflictingOperations", "interrupt"_attr = interrupt);
auto timeOutSec = std::chrono::seconds(
auto timeOutSec = stdx::chrono::seconds(
timeout_sec ? *timeout_sec : repl::fassertOnLockTimeoutForStepUpDown.load());
{
stdx::unique_lock<stdx::mutex> lock(_stateMutex);
@ -172,14 +172,14 @@ stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOpe
break;
}
_waitForDrain(Intent::PreparedTransaction, std::chrono::milliseconds(0));
_waitForDrain(Intent::PreparedTransaction, stdx::chrono::milliseconds(0));
if (intents) {
for (auto intent : *intents) {
_killOperationsByIntent(intent);
}
Timer timer;
auto timeout = std::chrono::duration_cast<std::chrono::milliseconds>(timeOutSec);
auto timeout = stdx::chrono::duration_cast<stdx::chrono::milliseconds>(timeOutSec);
for (auto intent : *intents) {
_waitForDrain(intent, timeout);
// Negative duration to cv::wait_for can cause undefined behavior
@ -187,7 +187,7 @@ stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOpe
// non-zero timeout to ever drop to 0 by setting it to at least to 1ms
if (timeout.count()) {
timeout -= std::min(
std::chrono::milliseconds(durationCount<Milliseconds>(timer.elapsed())),
stdx::chrono::milliseconds(durationCount<Milliseconds>(timer.elapsed())),
timeout - 1ms);
}
}
@ -262,7 +262,7 @@ void IntentRegistry::_killOperationsByIntent(IntentRegistry::Intent intent) {
}
void IntentRegistry::_waitForDrain(IntentRegistry::Intent intent,
std::chrono::milliseconds timeout) {
stdx::chrono::milliseconds timeout) {
auto& tokenMap = _tokenMaps[(size_t)intent];
stdx::unique_lock<stdx::mutex> lock(tokenMap.lock);
if (timeout.count() &&

View File

@ -36,6 +36,7 @@
#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/service_context.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/chrono.h"
#include "mongo/stdx/future.h"
#include "mongo/stdx/mutex.h"
#include "mongo/stdx/unordered_map.h"
@ -184,7 +185,7 @@ private:
};
bool _validIntent(Intent intent) const;
void _killOperationsByIntent(Intent intent);
void _waitForDrain(Intent intent, std::chrono::milliseconds timeout);
void _waitForDrain(Intent intent, stdx::chrono::milliseconds timeout);
static std::string _intentToString(Intent intent);
bool _enabled = true;

View File

@ -29,6 +29,8 @@
#include "mongo/db/repl/intent_guard.h"
#include "mongo/db/repl/intent_registry_test_fixture.h"
#include "mongo/stdx/chrono.h"
#include "mongo/stdx/thread.h"
namespace mongo {
@ -143,7 +145,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsStepUp) {
guard->reset();
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
{
auto clientWritePrepared = serviceContext->getService()->makeClient("testClientWrite");
auto opCtx = clientWritePrepared->makeOperationContext();
@ -499,7 +501,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsShutdown) {
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
// Any attempt to register an intent during a Shutdown interruption should throw an
// exception.
@ -593,7 +595,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsRollback) {
guard->reset();
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
// Any attempt to register an intent during a Rollback interruption should throw an
// exception.
@ -686,7 +688,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsStepDown) {
guard->reset();
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
{
auto clientWritePrepared =
serviceContext->getService()->makeClient("testClientWritePrepared");

View File

@ -37,6 +37,7 @@
#include "mongo/db/storage/wiredtiger/spill_record_store.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@ -364,7 +365,7 @@ TEST_F(SpillRecordStoreTest, TableCreation) {
}
auto allIdents = _kvEngine->getAllIdents(wtRu);
std::unordered_set<std::string> allIdentsSet(allIdents.begin(), allIdents.end());
stdx::unordered_set<std::string> allIdentsSet(allIdents.begin(), allIdents.end());
ASSERT_EQ(allIdentsSet.size(), 4);
ASSERT_TRUE(allIdentsSet.contains("a.b"));
for (int i = 0; i < 3; ++i) {

View File

@ -55,6 +55,7 @@
#include "mongo/db/timeseries/timeseries_test_fixture.h"
#include "mongo/db/timeseries/write_ops/timeseries_write_ops_utils_internal.h"
#include "mongo/stdx/thread.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"
@ -5583,7 +5584,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexNoMeta) {
BSON(_timeField << Date_t::fromMillisSinceEpoch(6)),
};
std::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
stdx::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
size_t startIndex = 2;
size_t numDocsToStage = 5;
@ -5607,8 +5608,8 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexNoMeta) {
auto writeBatch = writeBatches.front();
ASSERT_EQ(writeBatch->measurements.size(), numDocsToStage);
ASSERT_EQ(std::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
writeBatch->userBatchIndices.end()),
ASSERT_EQ(stdx::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
writeBatch->userBatchIndices.end()),
expectedIndices);
}
@ -5628,7 +5629,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexWithMeta) {
BSON(_metaField << _metaValue << _timeField << Date_t::fromMillisSinceEpoch(6)),
};
std::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
stdx::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
size_t startIndex = 2;
size_t numDocsToStage = 5;
@ -5650,7 +5651,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexWithMeta) {
auto writeBatches = swWriteBatches.getValue();
ASSERT_EQ(writeBatches.size(), 3);
std::unordered_set<size_t> actualIndices;
stdx::unordered_set<size_t> actualIndices;
for (auto& batch : writeBatches) {
for (auto index : batch->userBatchIndices) {
actualIndices.insert(index);
@ -5703,9 +5704,9 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryNoMeta) {
auto writeBatch = writeBatches.front();
ASSERT_EQ(writeBatch->measurements.size(), docsToRetry.size());
ASSERT_EQ(std::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
writeBatch->userBatchIndices.end()),
std::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
ASSERT_EQ(stdx::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
writeBatch->userBatchIndices.end()),
stdx::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
}
TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryWithMeta) {
@ -5749,14 +5750,14 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryWithMeta) {
auto writeBatches = swWriteBatches.getValue();
ASSERT_EQ(writeBatches.size(), 3);
std::unordered_set<size_t> actualIndices;
stdx::unordered_set<size_t> actualIndices;
for (auto& batch : writeBatches) {
for (auto index : batch->userBatchIndices) {
actualIndices.insert(index);
}
}
ASSERT_EQ(actualIndices, std::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
ASSERT_EQ(actualIndices, stdx::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
}
TEST_F(BucketCatalogTest, CreateOrderedPotentialBucketsVectorWithoutAnyBuckets) {

View File

@ -41,6 +41,7 @@
#include "mongo/db/timeseries/write_ops/timeseries_write_ops.h"
#include "mongo/db/transaction/session_catalog_mongod_transaction_interface_impl.h"
#include "mongo/db/transaction/transaction_participant.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"

View File

@ -66,6 +66,7 @@
#include "mongo/executor/remote_command_response.h"
#include "mongo/logv2/log.h"
#include "mongo/logv2/log_severity_suppressor.h"
#include "mongo/stdx/unordered_map.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/duration.h"
#include "mongo/util/fail_point.h"
@ -129,7 +130,7 @@ void TLTypeFactory::shutdown() {
stdx::lock_guard<stdx::mutex> lk(_mutex);
std::unordered_map<std::string, int> counts;
stdx::unordered_map<std::string, int> counts;
for (const Type* collar : _collars) {
++counts[demangleName(typeid(collar))];
}

View File

@ -133,7 +133,7 @@ void MockNetwork::runUntilIdle() {
} while (_net->hasReadyNetworkOperations());
}
void MockNetwork::runUntilExpectationsSatisfied(std::chrono::seconds timeoutSeconds) {
void MockNetwork::runUntilExpectationsSatisfied(stdx::chrono::seconds timeoutSeconds) {
Timer timer;
// If there exist extra threads beside the executor and the mock/test thread, when the
// network is idle, the extra threads may be running and will schedule new requests. As a

View File

@ -43,6 +43,7 @@
#include "mongo/executor/network_interface_mock.h"
#include "mongo/executor/remote_command_response.h"
#include "mongo/logv2/log.h"
#include "mongo/stdx/chrono.h"
#include "mongo/stdx/thread.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/duration.h"
@ -375,7 +376,7 @@ public:
// Run until both the executor and the network are idle and all expectations are satisfied.
// Otherwise, it fatal logs after timeoutSeconds.
void runUntilExpectationsSatisfied(
std::chrono::seconds timeoutSeconds = std::chrono::seconds(120));
stdx::chrono::seconds timeoutSeconds = stdx::chrono::seconds(120));
private:
bool _allExpectationsSatisfied() const;

View File

@ -39,6 +39,7 @@
#include "mongo/executor/thread_pool_task_executor.h"
#include "mongo/executor/thread_pool_task_executor_test_fixture.h"
#include "mongo/rpc/op_msg_rpc_impls.h"
#include "mongo/stdx/chrono.h"
#include "mongo/transport/mock_session.h"
#include "mongo/transport/test_fixtures.h"
#include "mongo/transport/transport_layer.h"
@ -133,7 +134,7 @@ public:
return true;
}
return _readyRequestCV.wait_for(lk, std::chrono::seconds(10), [&] {
return _readyRequestCV.wait_for(lk, stdx::chrono::seconds(10), [&] {
return _hasWaitingSinkMessage || _hasWaitingSourceMessage;
});
}

View File

@ -29,97 +29,157 @@
#include "MongoPolyFillCheck.h"
#include <vector>
#include <array>
#include <clang/Lex/Lexer.h>
namespace mongo::tidy {
using namespace clang;
using namespace clang::ast_matchers;
namespace {
// List of base polyfill type names from the std and boost namespaces to be checked
constexpr std::initializer_list<llvm::StringRef> basePolyfillTypeNames = {
"condition_variable",
"condition_variable_any",
"cv_status",
"future",
"future_status",
"launch",
"packaged_task",
"promise",
"recursive_mutex",
"shared_mutex",
"shared_timed_mutex",
"thread",
"timed_mutex",
"unordered_map",
"unordered_multimap",
"unordered_multiset",
"unordered_set",
};
// List of base polyfill enum names from the std and boost namespaces to be checked
constexpr std::initializer_list<llvm::StringRef> basePolyfillEnumNames = {
"cv_status",
"future_status",
"launch",
};
// List of base polyfill function names from the std and boost namespaces to be checked
constexpr std::initializer_list<llvm::StringRef> basePolyfillFuncNames = {
"async",
"get_terminate",
"notify_all_at_thread_exit",
"set_terminate",
};
// List of base polyfill namespace names from the std and boost namespaces to be checked
constexpr std::initializer_list<llvm::StringRef> basePolyfillNamespaces = {
"this_thread",
"chrono",
};
} // namespace
// Generate a list of fully qualified polyfill names by prefixing each name
// in the input list with 'std::' and 'boost::'
std::vector<std::string> generateQualifiedPolyfillNames(
const std::vector<std::string>& bannedNames) {
const std::vector<llvm::StringRef>& bannedNames) {
std::vector<std::string> fullyBannedNames;
for (const auto& name : bannedNames) {
fullyBannedNames.push_back("std::" + name);
fullyBannedNames.push_back("boost::" + name);
for (auto&& name : bannedNames) {
fullyBannedNames.push_back("std::" + name.str());
fullyBannedNames.push_back("boost::" + name.str());
}
return fullyBannedNames;
}
// List of base polyfill names from the std and boost namespaces to be checked
std::vector<std::string> MongoPolyFillCheck::basePolyfillNames = {"adopt_lock",
"async",
"chrono",
"condition_variable",
"condition_variable_any",
"cv_status",
"defer_lock",
"future",
"future_status",
"get_terminate",
"launch",
"lock_guard",
"mutex",
"notify_all_at_thread_exit",
"packaged_task",
"promise",
"recursive_mutex",
"set_terminate",
"shared_lock",
"shared_mutex",
"shared_timed_mutex",
"this_thread",
"thread",
"timed_mutex",
"try_to_lock",
"unique_lock",
"unordered_map",
"unordered_multimap",
"unordered_multiset",
"unordered_set"};
MongoPolyFillCheck::MongoPolyFillCheck(StringRef Name, clang::tidy::ClangTidyContext* Context)
: ClangTidyCheck(Name, Context) {
std::vector<llvm::StringRef> basePolyfillNames;
basePolyfillNames.insert(
basePolyfillNames.end(), basePolyfillTypeNames.begin(), basePolyfillTypeNames.end());
basePolyfillNames.insert(
basePolyfillNames.end(), basePolyfillEnumNames.begin(), basePolyfillEnumNames.end());
basePolyfillNames.insert(
basePolyfillNames.end(), basePolyfillFuncNames.begin(), basePolyfillFuncNames.end());
basePolyfillNames.insert(
basePolyfillNames.end(), basePolyfillNamespaces.begin(), basePolyfillNamespaces.end());
// Generate a list of fully polyfill names
fullyQualifiedPolyfillNames = generateQualifiedPolyfillNames(basePolyfillNames);
}
void MongoPolyFillCheck::registerMatchers(ast_matchers::MatchFinder* Finder) {
// Create an ArrayRef from the vector of banned names. This provides a
// lightweight, non-owning reference to the array of names.
std::vector<llvm::StringRef> basePolyfillNamesRefVector(basePolyfillNames.begin(),
basePolyfillNames.end());
llvm::ArrayRef<llvm::StringRef> basePolyfillNamesRefArray(basePolyfillNamesRefVector);
// Register an AST Matcher to find type declarations that use any of the banned names
Finder->addMatcher(loc(hasUnqualifiedDesugaredType(recordType(
hasDeclaration(namedDecl(hasAnyName(basePolyfillNamesRefArray))))))
.bind("bannedNames"),
// Register AST Matchers to find any use of the banned names.
Finder->addMatcher(declRefExpr(hasDeclaration(enumConstantDecl(
hasParent(enumDecl(hasAnyName(basePolyfillEnumNames))))))
.bind("bannedEnumConstants"),
this);
Finder->addMatcher(declaratorDecl(hasType(namedDecl(hasAnyName(basePolyfillTypeNames))))
.bind("bannedTypeNames"),
this);
Finder->addMatcher(callExpr(callee(expr(hasDescendant(declRefExpr(hasDeclaration(
functionDecl(hasAnyName(basePolyfillFuncNames))))))))
.bind("bannedFunctionNames"),
this);
Finder->addMatcher(declRefExpr(hasDeclaration(namedDecl(hasParent(
namespaceDecl(hasAnyName(basePolyfillNamespaces))))))
.bind("bannedNamespaceFromRef"),
this);
Finder->addMatcher(expr(hasType(qualType(hasDeclaration(namedDecl(
hasParent(namespaceDecl(hasAnyName(basePolyfillNamespaces))))))))
.bind("bannedNamespaceFromType"),
this);
Finder->addMatcher(declaratorDecl(hasParent(namespaceDecl(hasAnyName(basePolyfillNamespaces))))
.bind("bannedNamespaceFromDecl"),
this);
}
void MongoPolyFillCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
const auto* MatchedTypeLoc = Result.Nodes.getNodeAs<TypeLoc>("bannedNames");
if (MatchedTypeLoc) {
auto typeStr = MatchedTypeLoc->getType().getAsString();
// we catch this_thread but not this_thread::at_thread_exit
if (typeStr.find("this_thread::at_thread_exit") != std::string::npos)
return;
void MongoPolyFillCheck::checkBannedName(const SourceLocation loc, const llvm::StringRef name) {
// we catch this_thread but not this_thread::at_thread_exit
if (name.find("this_thread::at_thread_exit") != std::string::npos)
return;
// Check if the type string starts with 'std' or 'boost' and contains a banned name.
for (const auto& name : fullyQualifiedPolyfillNames) {
if ((typeStr.find("std") == 0 || typeStr.find("boost") == 0) &&
typeStr.find(name) != std::string::npos) {
auto location = MatchedTypeLoc->getBeginLoc();
if (location.isValid())
diag(MatchedTypeLoc->getBeginLoc(),
"Illegal use of banned name from std::/boost:: for %0, use mongo::stdx:: "
"variant instead")
<< name;
}
// Check if the type string starts with 'std' or 'boost' and contains a banned name.
for (auto&& polyfillName : fullyQualifiedPolyfillNames) {
if ((name.starts_with("std::") || name.starts_with("boost::")) &&
name.find(polyfillName) != std::string::npos) {
if (loc.isValid())
diag(loc,
"Illegal use of banned name from std::/boost:: for %0. Consider using "
"alternatives such as the polyfills from the mongo::stdx:: namespace.")
<< name;
}
}
}
// Get full name as written in source from a clang node to ensure any alias makes it into the
// returned string.
template <typename Node>
llvm::StringRef getFullName(const Node* node, const clang::ASTContext& Context) {
const clang::SourceManager& SM = Context.getSourceManager();
clang::SourceRange Range = node->getSourceRange();
return Lexer::getSourceText(CharSourceRange::getTokenRange(Range), SM, Context.getLangOpts());
}
void MongoPolyFillCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
for (auto&& matcher : {"bannedFunctionNames",
"bannedEnumConstants",
"bannedNamespaceFromRef",
"bannedNamespaceFromType"}) {
if (const auto* matched = Result.Nodes.getNodeAs<Expr>(matcher)) {
auto name = getFullName(matched, *Result.Context);
checkBannedName(matched->getBeginLoc(), std::move(name));
}
}
// DeclaratorDecl inherits from Decl instead of Expr, so it's extracted separately.
for (auto&& matcher : {"bannedTypeNames", "bannedNamespaceFromDecl"}) {
if (const auto* matched = Result.Nodes.getNodeAs<DeclaratorDecl>(matcher)) {
auto name = getFullName(matched, *Result.Context);
checkBannedName(matched->getBeginLoc(), std::move(name));
}
}
}

View File

@ -43,12 +43,11 @@ namespace mongo::tidy {
* flags the matched occurrences.
*/
class MongoPolyFillCheck : public clang::tidy::ClangTidyCheck {
public:
MongoPolyFillCheck(clang::StringRef Name, clang::tidy::ClangTidyContext* Context);
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
static std::vector<std::string> basePolyfillNames;
void checkBannedName(clang::SourceLocation loc, llvm::StringRef name);
private:
std::vector<std::string> fullyQualifiedPolyfillNames;

View File

@ -406,12 +406,27 @@ class MongoTidyTests(unittest.TestCase):
""")
)
test_names = [
"std::mutex myMutex",
"std::lock_guard lock{myMutex, std::adopt_lock}",
"std::adopt_lock",
"std::cv_status wait_result{std::cv_status::timeout}",
"std::cv_status::timeout",
"std::cv_status::timeout",
"std::this_thread::get_id",
"std::get_terminate()",
"std::chrono::seconds(1)",
"std::future<int> myFuture",
"std::condition_variable cv",
"std::unordered_map<int, int> myMap",
"boost::unordered_map<int, int> boostMap",
]
self.expected_output = [
"error: Illegal use of banned name from std::/boost:: for std::mutex, use mongo::stdx:: variant instead",
"error: Illegal use of banned name from std::/boost:: for std::future, use mongo::stdx:: variant instead",
"error: Illegal use of banned name from std::/boost:: for std::condition_variable, use mongo::stdx:: variant instead",
"error: Illegal use of banned name from std::/boost:: for std::unordered_map, use mongo::stdx:: variant instead",
"error: Illegal use of banned name from std::/boost:: for boost::unordered_map, use mongo::stdx:: variant instead",
"error: Illegal use of banned name from std::/boost:: for "
+ name
+ ". Consider using alternatives such as the polyfills from the mongo::stdx:: namespace."
for name in test_names
]
self.run_clang_tidy()

View File

@ -2,11 +2,18 @@
#include <condition_variable>
#include <future>
#include <mutex>
#include <thread>
#include <unordered_map>
namespace mongo {
void mongoPolyFillCheckTest() {
std::mutex myMutex;
std::cv_status wait_result{std::cv_status::timeout};
if (wait_result == std::cv_status::timeout) {
}
std::this_thread::get_id();
std::get_terminate();
std::chrono::seconds(1);
std::chrono::seconds seconds(1);
std::future<int> myFuture;
std::condition_variable cv;
std::unordered_map<int, int> myMap;

View File

@ -34,6 +34,8 @@
#include <opentelemetry/sdk/trace/exporter.h>
#include <opentelemetry/sdk/trace/recordable.h>
#include "mongo/stdx/unordered_map.h"
namespace mongo {
namespace tracing {
@ -76,7 +78,7 @@ public:
opentelemetry::trace::SpanId parentId;
opentelemetry::trace::StatusCode status = opentelemetry::trace::StatusCode::kUnset;
std::string name;
std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes;
stdx::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes;
};
class MockExporter : public opentelemetry::sdk::trace::SpanExporter {

View File

@ -42,6 +42,7 @@
#include <opentelemetry/trace/provider.h>
#include "mongo/logv2/log.h"
#include "mongo/stdx/chrono.h"
#include "mongo/tracing/trace_settings_gen.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
@ -130,7 +131,7 @@ Status initialize(std::string name) {
void shutdown() {
if (!gOpenTelemetryHttpEndpoint.empty() || !gOpenTelemetryTraceDirectory.empty()) {
auto tracer = opentelemetry::trace::Provider::GetTracerProvider()->GetTracer("mongodb");
tracer->Close(std::chrono::seconds{1});
tracer->Close(stdx::chrono::seconds{1});
trace_api::Provider::SetTracerProvider({});
}

View File

@ -36,6 +36,7 @@
#include "mongo/base/string_data.h"
#include "mongo/logv2/log.h"
#include "mongo/platform/atomic.h"
#include "mongo/stdx/thread.h"
#include "mongo/stdx/type_traits.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@ -268,7 +269,7 @@ DEATH_TEST_F(MallocFreeOStreamGuardTest, WithBlockedSignal, "[survived][sig<0>][
auto h0 = handlerCount.load();
blockSignal(sig<0>, false);
while (handlerCount.load() == h0)
std::this_thread::yield();
stdx::this_thread::yield();
}
class BlockInsideSignalHandlerTest : public MallocFreeOStreamGuardTest {

View File

@ -27,12 +27,12 @@
* it in the license file.
*/
#include <chrono>
#include <cstdlib>
#include <functional>
#include <future>
#include <link.h>
#include "mongo/stdx/chrono.h"
#include "mongo/stdx/future.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/join_thread.h"
#include "mongo/unittest/unittest.h"
@ -52,13 +52,13 @@ public:
return _f.wait();
}
bool waitFor(std::chrono::milliseconds dur) const {
return _f.wait_for(dur) == std::future_status::ready;
bool waitFor(stdx::chrono::milliseconds dur) const {
return _f.wait_for(dur) == stdx::future_status::ready;
}
private:
std::promise<void> _p; // NOLINT
std::future<void> _f{_p.get_future()}; // NOLINT
stdx::promise<void> _p;
stdx::future<void> _f{_p.get_future()};
};
using OnPhdrFunc = std::function<int(dl_phdr_info*, size_t)>;
@ -92,7 +92,7 @@ public:
void wait() {
return _paused.wait();
}
bool waitFor(std::chrono::milliseconds dur) const {
bool waitFor(stdx::chrono::milliseconds dur) const {
return _paused.waitFor(dur);
}