mirror of https://github.com/mongodb/mongo
SERVER-113951 Introduce LiteParseRegistration struct with ability to register primary and fallback parsers (#44070)
GitOrigin-RevId: 90c7d3fef67b034fe33bda10b9880b81cc93d3b9
This commit is contained in:
parent
b4beaca4b2
commit
6f0f9a8652
|
|
@ -1177,6 +1177,7 @@ mongo_cc_unit_test(
|
||||||
"field_path_test.cpp",
|
"field_path_test.cpp",
|
||||||
"granularity_rounder_powers_of_two_test.cpp",
|
"granularity_rounder_powers_of_two_test.cpp",
|
||||||
"granularity_rounder_preferred_numbers_test.cpp",
|
"granularity_rounder_preferred_numbers_test.cpp",
|
||||||
|
"lite_parsed_document_source_test.cpp",
|
||||||
"lookup_set_cache_test.cpp",
|
"lookup_set_cache_test.cpp",
|
||||||
"monotonic_expression_test.cpp",
|
"monotonic_expression_test.cpp",
|
||||||
"partition_key_comparator_test.cpp",
|
"partition_key_comparator_test.cpp",
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,41 @@ namespace {
|
||||||
// Empty vector used by LiteParsedDocumentSources which do not have a sub pipeline.
|
// Empty vector used by LiteParsedDocumentSources which do not have a sub pipeline.
|
||||||
inline static std::vector<LiteParsedPipeline> kNoSubPipeline = {};
|
inline static std::vector<LiteParsedPipeline> kNoSubPipeline = {};
|
||||||
|
|
||||||
StringMap<LiteParsedDocumentSource::LiteParserInfo> parserMap;
|
StringMap<LiteParsedDocumentSource::LiteParserRegistration> parserMap;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
const LiteParsedDocumentSource::LiteParserInfo&
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration::getParser() const {
|
||||||
|
// If there's no feature flag toggle, or the feature flag toggle exists and the feature is
|
||||||
|
// enabled in this context, use the primary parser. Otherwise, use the fallback parser.
|
||||||
|
if (_primaryParserFeatureFlag == nullptr || _primaryParserFeatureFlag->checkEnabled()) {
|
||||||
|
return _primaryParser;
|
||||||
|
} else {
|
||||||
|
return _fallbackParser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteParsedDocumentSource::LiteParserRegistration::setPrimaryParser(LiteParserInfo&& lpi) {
|
||||||
|
_primaryParser = std::move(lpi);
|
||||||
|
_primaryIsSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteParsedDocumentSource::LiteParserRegistration::setFallbackParser(
|
||||||
|
LiteParserInfo&& lpi, IncrementalRolloutFeatureFlag* ff) {
|
||||||
|
_fallbackParser = std::move(lpi);
|
||||||
|
_primaryParserFeatureFlag = ff;
|
||||||
|
_fallbackIsSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LiteParsedDocumentSource::LiteParserRegistration::isPrimarySet() const {
|
||||||
|
return _primaryIsSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LiteParsedDocumentSource::LiteParserRegistration::isFallbackSet() const {
|
||||||
|
return _fallbackIsSet;
|
||||||
|
}
|
||||||
|
|
||||||
void LiteParsedDocumentSource::registerParser(const std::string& name,
|
void LiteParsedDocumentSource::registerParser(const std::string& name,
|
||||||
Parser parser,
|
Parser parser,
|
||||||
AllowedWithApiStrict allowedWithApiStrict,
|
AllowedWithApiStrict allowedWithApiStrict,
|
||||||
|
|
@ -62,7 +93,46 @@ void LiteParsedDocumentSource::registerParser(const std::string& name,
|
||||||
aggStageCounters.addMetric(name);
|
aggStageCounters.addMetric(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
parserMap[name] = {parser, allowedWithApiStrict, allowedWithClientType};
|
// Retrieve an existing or create a new registration.
|
||||||
|
auto& registration = parserMap[name];
|
||||||
|
registration.setPrimaryParser({parser, allowedWithApiStrict, allowedWithClientType});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteParsedDocumentSource::registerFallbackParser(const std::string& name,
|
||||||
|
Parser parser,
|
||||||
|
FeatureFlag* parserFeatureFlag,
|
||||||
|
AllowedWithApiStrict allowedWithApiStrict,
|
||||||
|
AllowedWithClientType allowedWithClientType) {
|
||||||
|
if (parserMap.contains(name)) {
|
||||||
|
const auto& registration = parserMap.at(name);
|
||||||
|
|
||||||
|
// We require that the fallback parser is always registered prior to the primary parser.
|
||||||
|
// At extension load time, it’s then explicit which stages are permitted to be overridden
|
||||||
|
// and which cannot.
|
||||||
|
tassert(11395100,
|
||||||
|
"A stage's fallback parser must be registered before the primary parser",
|
||||||
|
registration.isFallbackSet() || !registration.isPrimarySet());
|
||||||
|
|
||||||
|
// Silently skip registration if a fallback parser has already been registered. The first
|
||||||
|
// fallback parser registration gets priority.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize a counter for this document source to track how many times it is used.
|
||||||
|
aggStageCounters.addMetric(name);
|
||||||
|
|
||||||
|
// Create a new registration and save the parser as the fallback parser.
|
||||||
|
auto& registration = parserMap[name];
|
||||||
|
|
||||||
|
// TODO SERVER-114028 Remove the following dynamic cast and tassert when fallback parsing
|
||||||
|
// supports all feature flags.
|
||||||
|
auto* ifrFeatureFlag = dynamic_cast<IncrementalRolloutFeatureFlag*>(parserFeatureFlag);
|
||||||
|
tassert(11395101,
|
||||||
|
"Fallback parsing only supports IncrementalRolloutFeatureFlags.",
|
||||||
|
ifrFeatureFlag != nullptr);
|
||||||
|
|
||||||
|
registration.setFallbackParser({parser, allowedWithApiStrict, allowedWithClientType},
|
||||||
|
ifrFeatureFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiteParsedDocumentSource::unregisterParser_forTest(const std::string& name) {
|
void LiteParsedDocumentSource::unregisterParser_forTest(const std::string& name) {
|
||||||
|
|
@ -77,23 +147,23 @@ std::unique_ptr<LiteParsedDocumentSource> LiteParsedDocumentSource::parse(
|
||||||
BSONElement specElem = spec.firstElement();
|
BSONElement specElem = spec.firstElement();
|
||||||
|
|
||||||
auto stageName = specElem.fieldNameStringData();
|
auto stageName = specElem.fieldNameStringData();
|
||||||
auto it = parserMap.find(stageName);
|
const auto it = parserMap.find(stageName);
|
||||||
|
|
||||||
uassert(40324,
|
uassert(40324,
|
||||||
str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'",
|
str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'",
|
||||||
it != parserMap.end());
|
it != parserMap.end());
|
||||||
|
|
||||||
return it->second.parser(nss, specElem, options);
|
return it->second.getParser().parser(nss, specElem, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LiteParsedDocumentSource::LiteParserInfo& LiteParsedDocumentSource::getInfo(
|
const LiteParsedDocumentSource::LiteParserInfo& LiteParsedDocumentSource::getInfo(
|
||||||
const std::string& stageName) {
|
const std::string& stageName) {
|
||||||
auto it = parserMap.find(stageName);
|
const auto it = parserMap.find(stageName);
|
||||||
uassert(5407200,
|
uassert(5407200,
|
||||||
str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'",
|
str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'",
|
||||||
it != parserMap.end());
|
it != parserMap.end());
|
||||||
|
|
||||||
return it->second;
|
return it->second.getParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<LiteParsedPipeline>& LiteParsedDocumentSource::getSubPipelines() const {
|
const std::vector<LiteParsedPipeline>& LiteParsedDocumentSource::getSubPipelines() const {
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,44 @@ public:
|
||||||
AllowedWithClientType allowedWithClientType;
|
AllowedWithClientType allowedWithClientType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A LiteParserRegistration encapsulates the set of all parsers that can be used to parse a
|
||||||
|
* stage into a LiteParsedDocumentSource, controlled by the value of a feature flag.
|
||||||
|
*/
|
||||||
|
class LiteParserRegistration {
|
||||||
|
public:
|
||||||
|
const LiteParserInfo& getParser() const;
|
||||||
|
|
||||||
|
void setPrimaryParser(LiteParserInfo&& lpi);
|
||||||
|
|
||||||
|
// TODO SERVER-114028 Update when fallback parsing supports all feature flags.
|
||||||
|
void setFallbackParser(LiteParserInfo&& lpi, IncrementalRolloutFeatureFlag* ff);
|
||||||
|
|
||||||
|
bool isPrimarySet() const;
|
||||||
|
|
||||||
|
bool isFallbackSet() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The preferred method of parsing this LiteParsedDocumentSource. If the feature flag is
|
||||||
|
// enabled, the primary parser will be used to parse the stage.
|
||||||
|
LiteParserInfo _primaryParser;
|
||||||
|
|
||||||
|
// The fallback method of parsing this LiteParsedDocumentSource. If the feature flag is
|
||||||
|
// disabled, the fallback parser will be used to parse the stage.
|
||||||
|
LiteParserInfo _fallbackParser;
|
||||||
|
|
||||||
|
// When enabled, signals to use the primary parser; when disabled, signals to use the
|
||||||
|
// fallback parser.
|
||||||
|
// TODO SERVER-114028 Generalize this to be FeatureFlag*.
|
||||||
|
IncrementalRolloutFeatureFlag* _primaryParserFeatureFlag = nullptr;
|
||||||
|
|
||||||
|
// Whether or not the primary parser has been registered or not.
|
||||||
|
bool _primaryIsSet = false;
|
||||||
|
|
||||||
|
// Whether or not the fallback parser has been registered or not.
|
||||||
|
bool _fallbackIsSet = false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a LiteParsedDocumentSource from the user-supplied BSON.
|
* Constructs a LiteParsedDocumentSource from the user-supplied BSON.
|
||||||
*
|
*
|
||||||
|
|
@ -120,6 +158,12 @@ public:
|
||||||
AllowedWithApiStrict allowedWithApiStrict,
|
AllowedWithApiStrict allowedWithApiStrict,
|
||||||
AllowedWithClientType allowedWithClientType);
|
AllowedWithClientType allowedWithClientType);
|
||||||
|
|
||||||
|
static void registerFallbackParser(const std::string& name,
|
||||||
|
Parser parser,
|
||||||
|
FeatureFlag* parserFeatureFlag,
|
||||||
|
AllowedWithApiStrict allowedWithApiStrict,
|
||||||
|
AllowedWithClientType allowedWithClientType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that will be used as an alternate parser for a document source that has been
|
* Function that will be used as an alternate parser for a document source that has been
|
||||||
* disabled.
|
* disabled.
|
||||||
|
|
@ -347,6 +391,8 @@ private:
|
||||||
* only meant to be used in the context of unit tests. This is because the parserMap is not
|
* only meant to be used in the context of unit tests. This is because the parserMap is not
|
||||||
* thread safe, so modifying it at runtime is unsafe.
|
* thread safe, so modifying it at runtime is unsafe.
|
||||||
*/
|
*/
|
||||||
|
friend class LiteParserRegistrationTest;
|
||||||
|
friend class LiteParsedDocumentSourceParseTest;
|
||||||
static void unregisterParser_forTest(const std::string& name);
|
static void unregisterParser_forTest(const std::string& name);
|
||||||
|
|
||||||
std::string _parseTimeName;
|
std::string _parseTimeName;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2018-present MongoDB, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the Server Side Public License, version 1,
|
||||||
|
* as published by MongoDB, Inc.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* Server Side Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Server Side Public License
|
||||||
|
* along with this program. If not, see
|
||||||
|
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||||
|
*
|
||||||
|
* As a special exception, the copyright holders give permission to link the
|
||||||
|
* code of portions of this program with the OpenSSL library under certain
|
||||||
|
* conditions as described in each individual source file and distribute
|
||||||
|
* linked combinations including the program with the OpenSSL library. You
|
||||||
|
* must comply with the Server Side Public License in all respects for
|
||||||
|
* all of the code used other than as permitted herein. If you modify file(s)
|
||||||
|
* with this exception, you may extend this exception to your version of the
|
||||||
|
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||||
|
* delete this exception statement from your version. If you delete this
|
||||||
|
* exception statement from all source files in the program, then also delete
|
||||||
|
* it in the license file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mongo/db/pipeline/lite_parsed_document_source.h"
|
||||||
|
|
||||||
|
#include "mongo/base/error_codes.h"
|
||||||
|
#include "mongo/bson/bsonmisc.h"
|
||||||
|
#include "mongo/bson/bsonobj.h"
|
||||||
|
#include "mongo/db/feature_flag.h"
|
||||||
|
#include "mongo/db/namespace_string.h"
|
||||||
|
#include "mongo/db/query/allowed_contexts.h"
|
||||||
|
#include "mongo/unittest/assert.h"
|
||||||
|
#include "mongo/unittest/death_test.h"
|
||||||
|
#include "mongo/unittest/framework.h"
|
||||||
|
#include "mongo/util/assert_util.h"
|
||||||
|
|
||||||
|
namespace mongo {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const NamespaceString kTestNss =
|
||||||
|
NamespaceString::createNamespaceString_forTest("test.liteParsedDocSource"_sd);
|
||||||
|
|
||||||
|
// Mock parser functions for testing
|
||||||
|
std::unique_ptr<LiteParsedDocumentSource> createMockParser(const NamespaceString& nss,
|
||||||
|
const BSONElement& spec,
|
||||||
|
const LiteParserOptions& options) {
|
||||||
|
return std::make_unique<LiteParsedDocumentSourceDefault>(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class LiteParserRegistrationTest : public unittest::Test {
|
||||||
|
protected:
|
||||||
|
void setUp() override {
|
||||||
|
primaryParser = {
|
||||||
|
createMockParser, AllowedWithApiStrict::kAlways, AllowedWithClientType::kAny};
|
||||||
|
fallbackParser = {createMockParser,
|
||||||
|
AllowedWithApiStrict::kNeverInVersion1,
|
||||||
|
AllowedWithClientType::kInternal};
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertParserIsPrimary(const LiteParsedDocumentSource::LiteParserInfo& parserInfo) {
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithApiStrict, AllowedWithApiStrict::kAlways);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithClientType, AllowedWithClientType::kAny);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertParserIsFallback(const LiteParsedDocumentSource::LiteParserInfo& parserInfo) {
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithApiStrict, AllowedWithApiStrict::kNeverInVersion1);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithClientType, AllowedWithClientType::kInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteParsedDocumentSource::LiteParserInfo primaryParser;
|
||||||
|
LiteParsedDocumentSource::LiteParserInfo fallbackParser;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, SetPrimaryParser) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
ASSERT_FALSE(registration.isPrimarySet());
|
||||||
|
registration.setPrimaryParser(std::move(primaryParser));
|
||||||
|
ASSERT_TRUE(registration.isPrimarySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, SetFallbackParser) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
|
||||||
|
// Create a mock IncrementalRolloutFeatureFlag.
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registration.setFallbackParser(std::move(fallbackParser), &mockFlag);
|
||||||
|
|
||||||
|
// Verify primary is still not set.
|
||||||
|
ASSERT_FALSE(registration.isPrimarySet());
|
||||||
|
ASSERT_TRUE(registration.isFallbackSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, GetParserWithoutFeatureFlag) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
|
||||||
|
registration.setPrimaryParser(std::move(primaryParser));
|
||||||
|
|
||||||
|
// When there's no feature flag, should return primary parser.
|
||||||
|
const auto& parserInfo = registration.getParser();
|
||||||
|
assertParserIsPrimary(parserInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, GetParserWithFeatureFlagEnabled) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, true);
|
||||||
|
registration.setFallbackParser(std::move(fallbackParser), &mockFlag);
|
||||||
|
registration.setPrimaryParser(std::move(primaryParser));
|
||||||
|
|
||||||
|
// When feature flag is enabled, should return primary parser.
|
||||||
|
const auto& parserInfo = registration.getParser();
|
||||||
|
assertParserIsPrimary(parserInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, GetParserWithFeatureFlagDisabled) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registration.setFallbackParser(std::move(fallbackParser), &mockFlag);
|
||||||
|
registration.setPrimaryParser(std::move(primaryParser));
|
||||||
|
|
||||||
|
// When feature flag is disabled, should return fallback parser.
|
||||||
|
const auto& parserInfo = registration.getParser();
|
||||||
|
assertParserIsFallback(parserInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParserRegistrationTest, GetParserWithChangingFeatureFlag) {
|
||||||
|
LiteParsedDocumentSource::LiteParserRegistration registration;
|
||||||
|
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registration.setFallbackParser(std::move(fallbackParser), &mockFlag);
|
||||||
|
registration.setPrimaryParser(std::move(primaryParser));
|
||||||
|
|
||||||
|
// When feature flag is disabled, should return fallback parser.
|
||||||
|
assertParserIsFallback(registration.getParser());
|
||||||
|
|
||||||
|
// Enable the feature flag and check that the primary parser is chosen.
|
||||||
|
mockFlag.setForServerParameter(true);
|
||||||
|
assertParserIsPrimary(registration.getParser());
|
||||||
|
|
||||||
|
// Disable it and check that the fallback parser is chosen.
|
||||||
|
mockFlag.setForServerParameter(false);
|
||||||
|
assertParserIsFallback(registration.getParser());
|
||||||
|
}
|
||||||
|
|
||||||
|
class LiteParsedDocumentSourceParseTest : public unittest::Test {
|
||||||
|
protected:
|
||||||
|
void registerPrimaryParser() {
|
||||||
|
LiteParsedDocumentSource::registerParser(_stageName,
|
||||||
|
createMockParser,
|
||||||
|
AllowedWithApiStrict::kAlways,
|
||||||
|
AllowedWithClientType::kAny);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerFallbackParser(FeatureFlag* ff) {
|
||||||
|
LiteParsedDocumentSource::registerFallbackParser(_stageName,
|
||||||
|
createMockParser,
|
||||||
|
ff,
|
||||||
|
AllowedWithApiStrict::kNeverInVersion1,
|
||||||
|
AllowedWithClientType::kInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown() override {
|
||||||
|
LiteParsedDocumentSource::unregisterParser_forTest(_stageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that _stageName should be unique between every test and set at the beginning. This is
|
||||||
|
// because we have no way of clearing out the global variable aggStageCounters.
|
||||||
|
std::string _stageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(LiteParsedDocumentSourceParseTest, CanRegisterBothPrimaryAndFallback) {
|
||||||
|
_stageName = "$canRegisterBothPrimaryAndFallback";
|
||||||
|
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registerFallbackParser(&mockFlag);
|
||||||
|
registerPrimaryParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, MustRegisterPrimaryAfterFallback, "11395100") {
|
||||||
|
_stageName = "$mustRegisterPrimaryAfterFallback";
|
||||||
|
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registerPrimaryParser();
|
||||||
|
registerFallbackParser(&mockFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParsedDocumentSourceParseTest, FirstFallbackParserTakesPrecedence) {
|
||||||
|
_stageName = "$firstFallbackParserTakesPrecedence";
|
||||||
|
|
||||||
|
// Disable the feature flag such that the parser returns the fallback parser.
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registerFallbackParser(&mockFlag);
|
||||||
|
registerPrimaryParser();
|
||||||
|
|
||||||
|
// Try creating another fallback parser.
|
||||||
|
LiteParsedDocumentSource::registerFallbackParser(_stageName,
|
||||||
|
createMockParser,
|
||||||
|
&mockFlag,
|
||||||
|
AllowedWithApiStrict::kNeverInVersion1,
|
||||||
|
AllowedWithClientType::kAny);
|
||||||
|
|
||||||
|
// Ensure that the parser info is the original fallback parser.
|
||||||
|
auto parserInfo = LiteParsedDocumentSource::getInfo(_stageName);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithApiStrict, AllowedWithApiStrict::kNeverInVersion1);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithClientType, AllowedWithClientType::kInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiteParsedDocumentSourceParseTest, FirstFallbackParserTakesPrecedenceWithNoPrimary) {
|
||||||
|
_stageName = "$firstFallbackParserTakesPrecedenceWithNoPrimary";
|
||||||
|
|
||||||
|
// Disable the feature flag such that the parser returns the fallback parser.
|
||||||
|
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||||
|
registerFallbackParser(&mockFlag);
|
||||||
|
|
||||||
|
// Try creating another fallback parser.
|
||||||
|
LiteParsedDocumentSource::registerFallbackParser(_stageName,
|
||||||
|
createMockParser,
|
||||||
|
&mockFlag,
|
||||||
|
AllowedWithApiStrict::kNeverInVersion1,
|
||||||
|
AllowedWithClientType::kAny);
|
||||||
|
|
||||||
|
// Ensure that the parser info is the original fallback parser.
|
||||||
|
auto parserInfo = LiteParsedDocumentSource::getInfo(_stageName);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithApiStrict, AllowedWithApiStrict::kNeverInVersion1);
|
||||||
|
ASSERT_EQ(parserInfo.allowedWithClientType, AllowedWithClientType::kInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO SERVER-114028 Remove the following test when fallback parsing supports all feature flags.
|
||||||
|
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, IFRFlagIsRequired, "11395101") {
|
||||||
|
_stageName = "$IFRFlagIsRequired";
|
||||||
|
|
||||||
|
BinaryCompatibleFeatureFlag mockFlag(false);
|
||||||
|
registerFallbackParser(&mockFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mongo
|
||||||
|
|
||||||
Loading…
Reference in New Issue