SERVER-115106 Port to GoogleTest (#45689)

Co-authored-by: James Bronsted <james.bronsted@mongodb.com>
Co-authored-by: Billy Donahue <billy.donahue@mongodb.com>
Co-authored-by: James Bronsted <32047428+jpbronsted@users.noreply.github.com>
Co-authored-by: Sean Lyons <sean.lyons@mongodb.com>
Co-authored-by: Billy Donahue <BillyDonahue@users.noreply.github.com>
Co-authored-by: Ronald Steinke <167128994+rsteinkeX@users.noreply.github.com>
GitOrigin-RevId: 44975de45e91c0666e545b65519822f7b6a4ad15
This commit is contained in:
Alex Li 2025-12-29 17:16:30 -05:00 committed by MongoDB Bot
parent d9d753f9c8
commit 88deba90af
245 changed files with 4258 additions and 4692 deletions

3
.github/CODEOWNERS vendored
View File

@ -364,6 +364,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/docs/owners/** @10gen/devprod-correctness @svc-auto-approve-bot
/docs/**/poetry_execution.md @10gen/devprod-correctness @svc-auto-approve-bot
/docs/**/server_parameters.md @10gen/server-programmability @svc-auto-approve-bot
/docs/**/unit_test.md @10gen/server-programmability @svc-auto-approve-bot
# The following patterns are parsed from ./docs/antithesis/OWNERS.yml
/docs/antithesis/ @10gen/devprod-correctness @svc-auto-approve-bot
@ -3322,7 +3323,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/src/third_party/**/croaring @10gen/query-execution @svc-auto-approve-bot
/src/third_party/**/fmt @10gen/server-programmability @svc-auto-approve-bot
/src/third_party/**/folly @10gen/server-workload-resilience @svc-auto-approve-bot
/src/third_party/**/googletest_restricted_for_disagg_only @10gen/server-disagg-storage @svc-auto-approve-bot
/src/third_party/**/googletest @10gen/server-programmability @svc-auto-approve-bot
/src/third_party/**/gperftools @10gen/server-workload-resilience @svc-auto-approve-bot
/src/third_party/**/grpc @10gen/server-networking-and-observability @svc-auto-approve-bot
/src/third_party/**/icu4c* @10gen/query-execution @svc-auto-approve-bot

View File

@ -20,6 +20,12 @@
"*.idl": "yaml",
},
"files.insertFinalNewline": true,
"files.watcherInclude": [
"bazel-bin"
],
"files.watcherExclude": {
"bazel-bin/**/*.runfiles/**": true
},
"js/ts.implicitProjectConfig.target": "ES2020",
"python.autoComplete.extraPaths": [
"/opt/mongodbtoolchain/v5/share/gcc-14.2.0/python"
@ -65,6 +71,34 @@
],
},
"C_Cpp.intelliSenseEngine": "disabled",
"typescript.inlayHints.enumMemberValues.enabled": true,
"testMate.cpp.test.advancedExecutables": [
{
"pattern": "bazel-bin/src/mongo/**/*test*_with_debug",
"exclude": "files.watcherExclude",
// "parallelizationLimit": 1, // Needed for unittest_test :(
"cwd": "${workspaceFolder}",
"runTask": {
"before": [ "_buildForTestMate" ],
},
"gtest": {
"prependTestRunningArgs": [
// TODO(gtest): Enable fancy output when we add support for it,
// if it's not on by default.
],
"testGrouping": {
"groupByLabel": { // Binary name w/o "_with_debug"
"label": "${filename`(.*)_with_debug`$1`}",
"groupBySource": {
"groupByTags": { // Suite
"groupByTestName": true
}
}
}
}
}
},
],
},
"extensions": {
"recommendations": [
@ -82,7 +116,8 @@
"bazelbuild.vscode-bazel",
"rioj7.command-variable",
"augustocdias.tasks-shell-input",
"ms-vscode.cpptools"
"ms-vscode.cpptools",
"matepek.vscode-catch2-test-adapter",
]
},
"tasks": {
@ -122,6 +157,31 @@
"isDefault": true
}
},
{
"label": "Build current file's test (config=dbg)",
"type": "bazel",
"command": "build",
"targets": [
"+${fileBasenameNoExtension}"
],
"options": [
"--config=dbg"
],
"group": "build",
},
{
"label": "_buildForTestMate",
"type": "shell",
"command": "bazel build --config=dbg $(echo ${absPathConcatWithSpace} | sed -Ee 's;[^ ]*(src/mongo/[^ ]*)_with_debug;\\1;g')",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
}
},
]
},
"launch": {

View File

@ -926,6 +926,7 @@ def mongo_cc_test(
# We can remove this once we are on bazel 9 because it has removed the
# logic that looks for this var always behaves as if it is set.
"EXPERIMENTAL_SPLIT_XML_GENERATION": "1",
"GTEST_OUTPUT": "",
} | select({
"//bazel/config:dev_stacktrace_enabled": {
# Forcing bazel's test environment setup script to run from the
@ -957,12 +958,12 @@ def mongo_cc_unit_test(
additional_linker_inputs = [],
features = [],
exec_properties = {},
has_custom_mainline = False,
provides_main = False,
**kwargs):
mongo_cc_test(
name = name,
srcs = srcs,
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:unittest_main"]),
deps = deps + ([] if provides_main else ["//src/mongo/unittest:unittest_main"]),
private_hdrs = private_hdrs,
visibility = visibility,
data = data,
@ -1342,12 +1343,12 @@ def mongo_cc_benchmark(
additional_linker_inputs = [],
features = [],
exec_properties = {},
has_custom_mainline = False,
provides_main = False,
**kwargs):
mongo_cc_test(
name = name,
srcs = srcs,
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:benchmark_main"]),
deps = deps + ([] if provides_main else ["//src/mongo/unittest:benchmark_main"]),
private_hdrs = private_hdrs,
visibility = visibility,
data = data,
@ -1383,12 +1384,12 @@ def mongo_cc_integration_test(
additional_linker_inputs = [],
features = [],
exec_properties = {},
has_custom_mainline = False,
provides_main = False,
**kwargs):
mongo_cc_test(
name = name,
srcs = srcs,
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:integration_test_main"]),
deps = deps + ([] if provides_main else ["//src/mongo/unittest:integration_test_main"]),
private_hdrs = private_hdrs,
visibility = visibility,
data = data,
@ -1424,7 +1425,7 @@ def mongo_cc_fuzzer_test(
additional_linker_inputs = [],
features = [],
exec_properties = {},
has_custom_mainline = False,
provides_main = False,
**kwargs):
mongo_cc_test(
name = name,

View File

@ -1,6 +1,7 @@
import json
import time
from glob import glob
from pathlib import Path
from typing import List
import typer
@ -48,7 +49,7 @@ def main(testlog_dir: str):
else:
status = "pass"
log_raw = testsuite.find("system-out").text
log_raw = Path(test_xml).with_suffix(".log").read_text()
# Bazel gives just a duration, while Evergreen expects a start and end
# time to calculate the duration. Evergreen itself does something similar

View File

@ -3360,12 +3360,17 @@ return std::move({varname});"""
with self._condition(opt.condition):
with self._block(section, ";"):
self._writer.write_line(f"""\
.addOptionChaining({_encaps(opt.name)}, {_encaps(opt.short_name)}, moe::{opt.arg_vartype},
{_get_expression(opt.description)}, {_encaps_list(opt.deprecated_name)},
{_encaps_list(opt.deprecated_short_name)}, {usage})
.setSources(moe::{opt.source})
""")
self._writer.write_line(
""
+ f".addOptionChaining({_encaps(opt.name)},"
+ f" {_encaps(opt.short_name)},"
+ f" moe::{opt.arg_vartype},"
+ f" {_get_expression(opt.description)},"
+ f" {_encaps_list(opt.deprecated_name)},"
+ f" {_encaps_list(opt.deprecated_short_name)},"
+ f" {usage})"
)
self._writer.write_line(f".setSources(moe::{opt.source})")
if opt.hidden:
self._writer.write_line(".hidden()")
if opt.redact:

View File

@ -1023,6 +1023,7 @@ def _parse_config_option(ctxt, spec, name, node):
"requires": _RuleDesc("scalar_or_sequence"),
"hidden": _RuleDesc("bool_scalar"),
"redact": _RuleDesc("bool_scalar"),
"ignoreIfDuplicate": _RuleDesc("bool_scalar"),
"default": _RuleDesc("scalar_or_mapping", mapping_parser_func=_parse_expression),
"implicit": _RuleDesc("scalar_or_mapping", mapping_parser_func=_parse_expression),
"source": _RuleDesc("scalar_or_sequence"),

View File

@ -932,6 +932,7 @@ class ConfigOption(common.SourceLocation):
self.requires = [] # type: List[str]
self.hidden = False # type: bool
self.redact = False # type: bool
self.ignoreIfDuplicate = False # type: bool
self.default = None # type: Expression
self.implicit = None # type: Expression
self.source = [] # type: List[str]

View File

@ -42,5 +42,7 @@ class CPPIntegrationTestCase(interface.ProcessTestCase):
def _make_process(self):
return core.programs.generic_program(
self.logger, [self.program_executable], **self.program_options
self.logger,
[self.program_executable, "--enhancedReporter=false"],
**self.program_options,
)

View File

@ -29,5 +29,7 @@ class CPPUnitTestCase(interface.ProcessTestCase):
def _make_process(self):
return core.programs.make_process(
self.logger, [self.program_executable], **self.program_options
self.logger,
[self.program_executable, "--enhancedReporter=false"],
**self.program_options,
)

View File

@ -39,3 +39,6 @@ filters:
- "server_parameters.md":
approvers:
- 10gen/server-programmability
- "unit_test.md":
approvers:
- 10gen/server-programmability

98
docs/unit_test.md Normal file
View File

@ -0,0 +1,98 @@
Note: this doc is being continuously updated while changes are being made to the unit test framework.
# Overview
# Features
The MongoDB unit test framework is a thin layer built atop GoogleTest, so most GoogleTest features
(see [Google Test documentation](google_test_docs)) are available for use aside from anything
listed out in [Banned Features](#banned-features). The unit testing framework also includes
enhanced reporting of test output (see
[Enhanced Reporting of Test Output](#enhanced-reporting-of-test-output)).
## GoogleTest Features
### Parameterized tests
Parameterized tests are a GoogleTest feature that allows the same test logic to be run with
different values or types (see GoogleTest docs on
[Value-Parameterized Tests](value_parameterized_tests) and [Typed Tests](typed_tests)).
```cpp
class TestFixture :
public testing::TestWithParam<mongo::repl::ReadConcernLevel> {
};
INSTANTIATE_TEST_SUITE_P(TestSuite,
TestFixture,
testing::Values(ReadConcernLevel::kLocalReadConcern,
ReadConcernLevel::kMajorityReadConcern));
TEST_P(TestFixture, MongoTest) {
...
sendRead(GetParam()); // Uses either ReadConcernLevel::kLocalReadConcern or
// ReadConcernLevel::kMajorityReadConcern
}
```
## Banned Features
- `ASSERT_DEATH` - should not be used. Use `DEATH_TEST` instead (see [Death Tests](#death-tests)).
- GoogleMock - not yet available for use. Support for GoogleMock is coming soon.
## Upcoming Features
- IDE Integration
- GoogleMock
- Color output (Evergreen support, filter out color when terminal not detected)
- Output filtering/formatting
- New APIs to help with unit testing developer experience
## Throwing Assertions
Unlike GoogleTest's fatal test assertions, which implements fatal assertions with `return;`, we
throw an exception when our fatal assertions are triggered. This is to avoid limitations of
GoogleTest fatal assertions, such as no fatal assertions allowed in non-void helper functions.
## Enhanced Reporting of Test Output
The Enhanced Reporter improves test reporting by colorizing and formatting output, maintaining
a progress indicator, printing enhanced failure information, and suppressing log output on
passing tests.
These command line flags may be used to configure the Enhanced Reporter:
- `--showEachTest` - turns off any suppresion of log output.
- `--enhancedReporter=<true/false>` - enable all of the Enhanced Reporter behavior described above.
## Death Tests
The MongoDB unit testing framework uses `DEATH_TEST` (with `DEATH_TEST_F`, `DEATH_TEST_REGEX`,
and `DEATH_TEST_REGEX_F` variants) to test code that is expected to cause the process to
terminate. This should replace all uses of the `ASSERT_DEATH` macro from GoogleTest (see
[unittest/death_test.h](death_test_h) for more details).
Similar to GoogleTest, `DEATH_TEST` test suite names should be suffixed with `DeathTest`. For
instance, for a death test intending to be associated with `SuiteName` should use
`SuiteNameDeathTest` (see GoogleTest's [Death Test naming](death_test_naming)).
```cpp
TEST(SuiteName, TestName) {
...
}
DEATH_TEST(SuiteNameDeathTest, TestName) {
...
}
using FixtureNameDeathTest = FixtureName;
DEATH_TEST_F(FixtureNameDeathTest, TestName) {
...
}
```
[death_test_naming]: https://github.com/google/googletest/blob/main/docs/advanced.md#death-test-naming
[death_test_h]: ../src/mongo/unittest/death_test.h
[google_test_docs]: https://github.com/google/googletest/blob/main/docs/primer.md
[value_parameterized_tests]: https://github.com/google/googletest/blob/main/docs/advanced.md#value-parameterized-tests
[typed_tests]: https://github.com/google/googletest/blob/main/docs/advanced.md#typed-tests

View File

@ -1216,6 +1216,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest,-final_target,-intermediate_debug,-incompatible_with_bazel_remote_test
--build_tag_filters=mongo_unittest,-incompatible_with_bazel_remote_test
--keep_going
--test_arg=--showEachTest
- name: unit_tests_remote_exec_incompatible
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1243,6 +1245,8 @@ tasks:
--separate_debug=False
--test_tag_filters=incompatible_with_bazel_remote_test,-intermediate_debug,-final_target
--build_tag_filters=incompatible_with_bazel_remote_test
--keep_going
--test_arg=--showEachTest
- name: unit_test_group1
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1270,6 +1274,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_first_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_first_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group2
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1297,6 +1303,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_second_group,-intermediate_debug,-tracing_test,-final_target
--build_tag_filters=mongo_unittest_second_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group3
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1324,6 +1332,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_third_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_third_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group4
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1351,6 +1361,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_fourth_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_fourth_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group5
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1378,6 +1390,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_fifth_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_fifth_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group6
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1405,6 +1419,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_sixth_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_sixth_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group7
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1432,6 +1448,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_seventh_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_seventh_group
--keep_going
--test_arg=--showEachTest
- name: unit_test_group8
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
@ -1459,6 +1477,8 @@ tasks:
--separate_debug=False
--test_tag_filters=mongo_unittest_eighth_group,-intermediate_debug,-final_target
--build_tag_filters=mongo_unittest_eighth_group
--keep_going
--test_arg=--showEachTest
- name: monitor_build_status
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]

View File

@ -1173,59 +1173,6 @@
},
"scope": "excluded"
},
{
"type": "library",
"bom-ref": "pkg:github/google/googletest@v1.17.0",
"supplier": {
"name": "Google LLC",
"url": [
"https://opensource.google/"
]
},
"author": "The Google Test and Google Mock Communities",
"group": "google.opensource",
"name": "googletest",
"version": "1.17.0",
"description": "GoogleTest - Google Testing and Mocking Framework",
"licenses": [
{
"license": {
"id": "BSD-3-Clause"
}
}
],
"copyright": "Copyright 2008, Google Inc. All rights reserved.",
"cpe": "cpe:2.3:a:google:google_test:1.17.0:*:*:*:*:*:*:*",
"purl": "pkg:github/google/googletest@v1.17.0",
"externalReferences": [
{
"url": "https://github.com/google/googletest.git",
"type": "distribution"
}
],
"properties": [
{
"name": "internal:team_responsible",
"value": "Disaggregated Storage"
},
{
"name": "emits_persisted_data",
"value": "false"
},
{
"name": "import_script_path",
"value": "src/third_party/googletest_restricted_for_disagg_only/scripts/import.sh"
}
],
"evidence": {
"occurrences": [
{
"location": "src/third_party/googletest_restricted_for_disagg_only"
}
]
},
"scope": "excluded"
},
{
"type": "library",
"bom-ref": "pkg:github/google/re2@2025-08-05",
@ -1380,6 +1327,49 @@
},
"scope": "required"
},
{
"supplier": {
"name": "Organization: github"
},
"name": "googletest",
"version": "1.17.0",
"licenses": [
{
"license": {
"id": "BSD-3-Clause"
}
}
],
"purl": "pkg:github/googletest/googletest@v1.17.0",
"properties": [
{
"name": "internal:team_responsible",
"value": "Server Programmability"
},
{
"name": "emits_persisted_data",
"value": "false"
},
{
"name": "info_link",
"value": "https://github.com/google/googletest"
},
{
"name": "import_script_path",
"value": "src/third_party/googletest/scripts/import.sh"
}
],
"type": "library",
"bom-ref": "e57f94bd-b0b1-4e47-912e-c690a01e4f95",
"evidence": {
"occurrences": [
{
"location": "src/third_party/googletest"
}
]
},
"scope": "excluded"
},
{
"type": "library",
"bom-ref": "pkg:github/google/tcmalloc@f3b20f9a07e175c5d897df7b49d9830d4efa6110",

View File

@ -1271,6 +1271,17 @@ mongo_cc_library(
],
)
mongo_cc_library(
name = "server_parameter",
srcs = [
"server_parameter.cpp",
],
deps = [
"//src/mongo:base",
"//src/mongo/db:logical_time",
],
)
# The 'server_base' library must only contain basic, stateless, value types which are used throughout
# all the server binaries. It must not depend on anything other than utilities that are outside of
# the server codebase.
@ -1287,7 +1298,6 @@ mongo_cc_library(
"mirror_maestro_feature_flags_gen",
"read_write_concern_provenance.cpp",
"server_options.cpp",
"server_parameter.cpp",
"shutdown_in_progress_quiesce_info.cpp",
"tenant_id.cpp",
"version_context.cpp",
@ -1335,19 +1345,20 @@ mongo_cc_library(
"//src/mongo/idl:generic_argument_gen",
"//src/mongo/rpc/metadata:audit_metadata_gen",
"//src/mongo/util:database_name_util.cpp",
"//src/mongo/util:fail_point.cpp",
"//src/mongo/util:fail_point_server_parameter_gen",
"//src/mongo/util:namespace_string_util.cpp",
],
deps = [
":cluster_role",
":logical_time",
":server_parameter",
"//src/mongo:base",
"//src/mongo/bson/util:bson_extract",
"//src/mongo/db/repl:optime",
"//src/mongo/idl:basic_types_serialization",
"//src/mongo/idl:idl_parser",
"//src/mongo/rpc:get_status_from_command_result",
"//src/mongo/util:fail_point",
"//src/mongo/util:pcre_wrapper",
"//src/mongo/util/net:hostandport_impl",
],

View File

@ -450,6 +450,7 @@ mongo_cc_library(
"//src/mongo/db:query_matcher",
"//src/mongo/db:service_context",
"//src/mongo/db/update:update_driver",
"//src/mongo/unittest",
],
)

View File

@ -150,6 +150,13 @@ public:
<< "test")));
}
void assertCounts(uint64_t whole, uint64_t name, uint64_t tenant) {
auto counts = mockRouter->counts();
ASSERT_EQ(counts.wholeCache, whole);
ASSERT_EQ(counts.byName, name);
ASSERT_EQ(counts.byTenant, tenant);
}
void doInsert(const NamespaceString& nss,
const std::vector<BSONObj> insertDocs,
bool shouldInvalidateCache) {
@ -172,14 +179,14 @@ public:
/*recordIds*/ {},
/*fromMigrate=*/std::vector<bool>(stmts.size(), false),
/*defaultFromMigrate=*/false);
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
wuow.commit();
// The cache should only invalidate after the WUOW commits if shouldInvalidateCache is true.
if (shouldInvalidateCache) {
mockRouter->assertCounts(0, 1, 0);
assertCounts(0, 1, 0);
} else {
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
}
}
@ -203,13 +210,13 @@ public:
OplogUpdateEntryArgs entryArgs(&updateArgs, *autoColl);
opObserver.onUpdate(opCtx.get(), entryArgs);
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
wuow.commit();
if (shouldInvalidateCache) {
mockRouter->assertCounts(0, 1, 0);
assertCounts(0, 1, 0);
} else {
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
}
}
@ -225,13 +232,13 @@ public:
const auto& deleteDocumentKey = getDocumentKey(*coll, deleteDoc);
opObserver.onDelete(opCtx.get(), *coll, {}, deleteDoc, deleteDocumentKey, args);
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
wuow.commit();
if (shouldInvalidateCache) {
mockRouter->assertCounts(0, 1, 0);
assertCounts(0, 1, 0);
} else {
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
}
}
@ -242,13 +249,13 @@ public:
WriteUnitOfWork wuow(opCtx.get());
opObserver.onDropDatabase(opCtx.get(), dbname, false /*fromMigrate*/);
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
wuow.commit();
if (shouldInvalidateCache) {
mockRouter->assertCounts(1, 0, 0);
assertCounts(1, 0, 0);
} else {
mockRouter->assertCounts(0, 0, 0);
assertCounts(0, 0, 0);
}
}

View File

@ -39,6 +39,10 @@ namespace mongo {
// functions have been called.
class AuthorizationRouterImplForTest : public AuthorizationRouterImpl {
public:
struct Counts {
uint64_t byName, byTenant, wholeCache;
};
using AuthorizationRouterImpl::AuthorizationRouterImpl;
void invalidateUserByName(const UserName& user) override {
@ -62,10 +66,8 @@ public:
_wholeCacheCount.store(0);
}
void assertCounts(uint64_t whole, uint64_t name, uint64_t tenant) {
ASSERT_EQ(whole, _wholeCacheCount.load());
ASSERT_EQ(name, _byNameCount.load());
ASSERT_EQ(tenant, _byTenantCount.load());
Counts counts() const {
return {_byNameCount.load(), _byTenantCount.load(), _wholeCacheCount.load()};
}
private:

View File

@ -197,7 +197,7 @@ struct SCRAMStepsResult {
}
};
class SCRAMFixture : public mongo::unittest::Test {
class SCRAMFixture : public mongo::unittest::Test, public testing::WithParamInterface<bool> {
protected:
const SCRAMStepsResult goalState =
SCRAMStepsResult(SaslTestState(SaslTestState::kClient, 4), Status::OK());
@ -211,7 +211,7 @@ protected:
std::unique_ptr<ServerMechanismBase> saslServerSession;
std::unique_ptr<NativeSaslClientSession> saslClientSession;
void setUp() final {
void SetUp() override {
auto serviceContextHolder = ServiceContext::make();
serviceContext = serviceContextHolder.get();
setGlobalServiceContext(std::move(serviceContextHolder));
@ -238,6 +238,14 @@ protected:
authzBackend = reinterpret_cast<auth::AuthorizationBackendMock*>(
auth::AuthorizationBackendInterface::get(serviceContext->getService()));
if (_digestPassword()) {
LOGV2(20252, "SCRAM-SHA-1 variant");
saslServerSession = std::make_unique<SaslSCRAMSHA1ServerMechanism>("test");
} else {
LOGV2(20253, "SCRAM-SHA-256 variant");
saslServerSession = std::make_unique<SaslSCRAMSHA256ServerMechanism>("test");
}
saslClientSession = std::make_unique<NativeSaslClientSession>();
saslClientSession->setParameter(NativeSaslClientSession::parameterMechanism,
saslServerSession->mechanismName());
@ -248,7 +256,7 @@ protected:
"MockServer.test:27017");
}
void tearDown() final {
void TearDown() override {
opCtx.reset();
client.reset();
setGlobalServiceContext(nullptr);
@ -259,7 +267,7 @@ protected:
}
std::string createPasswordDigest(StringData username, StringData password) {
if (_digestPassword) {
if (_digestPassword()) {
return mongo::createPasswordDigest(username, password);
} else {
return std::string{password};
@ -301,24 +309,14 @@ protected:
return result;
}
bool _digestPassword;
public:
void run() {
LOGV2(20252, "SCRAM-SHA-1 variant");
saslServerSession = std::make_unique<SaslSCRAMSHA1ServerMechanism>("test");
_digestPassword = true;
Test::run();
LOGV2(20253, "SCRAM-SHA-256 variant");
saslServerSession = std::make_unique<SaslSCRAMSHA256ServerMechanism>("test");
_digestPassword = false;
Test::run();
bool _digestPassword() const {
return GetParam();
}
};
TEST_F(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
INSTANTIATE_TEST_SUITE_P(, SCRAMFixture, testing::Values(false, true));
TEST_P(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -340,7 +338,7 @@ TEST_F(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
TEST_P(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -362,7 +360,7 @@ TEST_F(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testClientStep2GivesBadProof) {
TEST_P(SCRAMFixture, testClientStep2GivesBadProof) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -387,7 +385,7 @@ TEST_F(SCRAMFixture, testClientStep2GivesBadProof) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testServerStep2GivesBadVerifier) {
TEST_P(SCRAMFixture, testServerStep2GivesBadVerifier) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -420,7 +418,7 @@ TEST_F(SCRAMFixture, testServerStep2GivesBadVerifier) {
}
TEST_F(SCRAMFixture, testSCRAM) {
TEST_P(SCRAMFixture, testSCRAM) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -433,7 +431,7 @@ TEST_F(SCRAMFixture, testSCRAM) {
ASSERT_EQ(goalState, runSteps());
}
TEST_F(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
TEST_P(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -451,7 +449,7 @@ TEST_F(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
ASSERT_EQ(goalState, runSteps(mutator));
}
TEST_F(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
TEST_P(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -472,7 +470,7 @@ TEST_F(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
TEST_P(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -493,7 +491,7 @@ TEST_F(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testNULLInPassword) {
TEST_P(SCRAMFixture, testNULLInPassword) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "saj\0ack"), BSONObj()));
@ -507,7 +505,7 @@ TEST_F(SCRAMFixture, testNULLInPassword) {
}
TEST_F(SCRAMFixture, testCommasInUsernameAndPassword) {
TEST_P(SCRAMFixture, testCommasInUsernameAndPassword) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("s,a,jack", "s,a,jack"), BSONObj()));
@ -520,7 +518,7 @@ TEST_F(SCRAMFixture, testCommasInUsernameAndPassword) {
ASSERT_EQ(goalState, runSteps());
}
TEST_F(SCRAMFixture, testIncorrectUser) {
TEST_P(SCRAMFixture, testIncorrectUser) {
saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack");
saslClientSession->setParameter(NativeSaslClientSession::parameterPassword,
createPasswordDigest("sajack", "sajack"));
@ -533,7 +531,7 @@ TEST_F(SCRAMFixture, testIncorrectUser) {
runSteps());
}
TEST_F(SCRAMFixture, testIncorrectPassword) {
TEST_P(SCRAMFixture, testIncorrectPassword) {
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -549,7 +547,7 @@ TEST_F(SCRAMFixture, testIncorrectPassword) {
runSteps());
}
TEST_F(SCRAMFixture, testOptionalClientExtensions) {
TEST_P(SCRAMFixture, testOptionalClientExtensions) {
// Verify server ignores unknown/optional extensions sent by client.
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -573,7 +571,7 @@ TEST_F(SCRAMFixture, testOptionalClientExtensions) {
runSteps(mutator));
}
TEST_F(SCRAMFixture, testOptionalServerExtensions) {
TEST_P(SCRAMFixture, testOptionalServerExtensions) {
// Verify client errors on unknown/optional extensions sent by server.
ASSERT_OK(authzBackend->insertUserDocument(
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
@ -660,11 +658,11 @@ void runTestClientConversationUsesCacheTest(SaslClientSession* saslClientSession
assertCacheStats(cache, 5, 4, 2);
}
TEST_F(SCRAMFixture, testClientConversationUsesCacheSHA1) {
TEST_P(SCRAMFixture, testClientConversationUsesCacheSHA1) {
runTestClientConversationUsesCacheTest<SHA1Block>(saslClientSession.get());
}
TEST_F(SCRAMFixture, testClientConversationUsesCacheSHA256) {
TEST_P(SCRAMFixture, testClientConversationUsesCacheSHA256) {
runTestClientConversationUsesCacheTest<SHA256Block>(saslClientSession.get());
}

View File

@ -106,7 +106,7 @@ void setX509PeerInfo(const std::shared_ptr<transport::Session>& session, SSLPeer
class SASLX509Test : public mongo::unittest::Test {
protected:
void setUp() final try {
void SetUp() override try {
auto serviceContextHolder = ServiceContext::make();
serviceContext = serviceContextHolder.get();
setGlobalServiceContext(std::move(serviceContextHolder));
@ -158,6 +158,7 @@ protected:
"MockServer.test");
saslClientSession->setParameter(NativeSaslClientSession::parameterServiceHostAndPort,
"MockServer.test:27017");
LOGV2(82092, "X509 variant");
} catch (const DBException& e) {
::mongo::StringBuilder sb;
sb << "SASLX509Test Fixture Setup Failed: " << e.what();
@ -189,12 +190,6 @@ protected:
saslServerSession.reset();
}
public:
void run() {
LOGV2(82092, "X509 variant");
Test::run();
}
protected:
ServiceContext* serviceContext;
Client* client;

View File

@ -63,7 +63,8 @@ protected:
}
};
DEATH_TEST_F(FeatureCompatibilityVersionTestFixture, NotInitialized, "invariant") {
using FeatureCompatibilityVersionTestFixtureDeathTest = FeatureCompatibilityVersionTestFixture;
DEATH_TEST_F(FeatureCompatibilityVersionTestFixtureDeathTest, NotInitialized, "invariant") {
FeatureCompatibilityVersion::fassertInitializedAfterStartup(operationContext());
}

View File

@ -142,7 +142,7 @@ enum ShardFilteringStrategy { NoShardFilter, ShardFilter };
class ShardFilteringDistinctScanPerfTestFixture : public QueryShardServerTestFixture {
public:
void _doTest() final { /* Unused. */ }
void TestBody() override {}
struct DistinctScanParamsForTest {
// Collection & sharding set-up.

View File

@ -48,7 +48,10 @@ namespace unittest {
std::ostringstream os; \
os << "Expected [ " << aExpression << " " #OPERATOR " " << bExpression \
<< " ] but found [ " << aValue << " " #OPERATOR " " << bValue << "]"; \
TestAssertionFailure(theFile, theLine, os.str()).stream(); \
GTEST_MESSAGE_AT_(theFile.c_str(), \
theLine, \
os.str().c_str(), \
::testing::TestPartResult::kFatalFailure); \
} \
}

View File

@ -66,37 +66,20 @@ BSONObj wrapInLiteral(const T& arg) {
return BSON("$literal" << arg);
}
/**
* This test fixture run the test twice, one when the fast-path projection mode is allowed, another
* one when it's not.
*
* The 'AllowFallBackToDefault' parameter should be set to 'true', if the executor is allowed to
* fall back to the default inclusion projection implementation if the fast-path projection cannot
* be used for a specific test. If set to 'false', a tassert will be triggered if fast-path
* projection was expected to be chosen, but the default one has been picked instead.
*/
template <bool AllowFallBackToDefault>
class BaseInclusionProjectionExecutionTest : public mongo::unittest::Test {
enum AllowFallBackToDefault : bool {};
enum AllowFastPath : bool {};
class BaseInclusionProjectionExecutionTest : public mongo::unittest::Test,
public testing::WithParamInterface<AllowFastPath> {
public:
void run() {
auto base = static_cast<mongo::unittest::Test*>(this);
try {
if (_runFastPath) {
_allowFastPath = true;
base->run();
}
if (_runDefault) {
_allowFastPath = false;
base->run();
}
} catch (...) {
LOGV2(20587,
"Exception while testing",
"allowFastPath"_attr = _allowFastPath,
"allowFallBackToDefault"_attr = AllowFallBackToDefault);
throw;
}
}
/**
* The 'allowFallBackToDefault' parameter should be set to 'true', if the executor is allowed to
* fall back to the default inclusion projection implementation if the fast-path projection
* cannot be used for a specific test. If set to 'false', a tassert will be triggered if
* fast-path projection was expected to be chosen, but the default one has been picked instead.
*/
explicit BaseInclusionProjectionExecutionTest(AllowFallBackToDefault allowFallBackToDefault)
: _allowFallBackToDefault{allowFallBackToDefault}, _allowFastPath{GetParam()} {}
protected:
auto createProjectionExecutor(const BSONObj& projSpec,
@ -130,7 +113,7 @@ protected:
if (_allowFastPath) {
uassert(51752,
"Fast-path projection mode or fall back to default expected",
fastPathRootNode || AllowFallBackToDefault);
fastPathRootNode || _allowFallBackToDefault);
} else {
uassert(51753, "Default projection mode expected", !fastPathRootNode);
}
@ -173,21 +156,34 @@ protected:
projSpec, matchSpec, ProjectionPolicies::findProjectionPolicies());
}
AllowFallBackToDefault _allowFallBackToDefault;
// True, if the projection executor is allowed to use the fast-path inclusion projection
// implementation.
bool _allowFastPath{true};
// Run the test using fast-path projection mode.
bool _runFastPath{true};
// Run the test using default projection mode.
bool _runDefault{true};
AllowFastPath _allowFastPath;
};
using InclusionProjectionExecutionTestWithFallBackToDefault =
BaseInclusionProjectionExecutionTest<true>;
using InclusionProjectionExecutionTestWithoutFallBackToDefault =
BaseInclusionProjectionExecutionTest<false>;
class InclusionProjectionExecutionTestWithFallBackToDefault
: public BaseInclusionProjectionExecutionTest {
public:
InclusionProjectionExecutionTestWithFallBackToDefault()
: BaseInclusionProjectionExecutionTest{AllowFallBackToDefault{true}} {}
};
INSTANTIATE_TEST_SUITE_P(,
InclusionProjectionExecutionTestWithFallBackToDefault,
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
class InclusionProjectionExecutionTestWithoutFallBackToDefault
: public BaseInclusionProjectionExecutionTest {
public:
InclusionProjectionExecutionTestWithoutFallBackToDefault()
: BaseInclusionProjectionExecutionTest{AllowFallBackToDefault{false}} {}
};
INSTANTIATE_TEST_SUITE_P(,
InclusionProjectionExecutionTestWithoutFallBackToDefault,
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldAddIncludedFieldsToDependencies) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("_id" << false << "a" << true << "x.y" << true));
@ -201,7 +197,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_EQ(deps.fields.count("x.y"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldAddIdToDependenciesIfNotSpecified) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
@ -213,7 +209,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_EQ(deps.fields.count("a"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddDependenciesOfComputedFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$a"
<< "x"
@ -228,7 +224,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_EQ(deps.fields.count("z"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddPathToDependenciesForNestedComputedFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a.b.c" << BSON("$add" << BSON_ARRAY(1 << 2))));
@ -242,7 +238,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_EQ(deps.fields.count("a.b"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldNotAddTopLevelDependencyWithExpressionOnTopLevelPath) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a" << BSON("$add" << BSON_ARRAY(1 << 2))));
@ -254,7 +250,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_EQ(deps.fields.count("_id"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddPathToDependenciesForNestedComputedFieldsUsingVariableReferences) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("x.y" << "$z"));
@ -270,7 +266,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_EQ(deps.fields.count("x"), 1UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldSerializeToEquivalentProjection) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
fromjson("{a: {$add: ['$a', 2]}, b: {d: 3}, 'x.y': {$literal: 4}}"));
@ -293,7 +289,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldSerializeExplicitExclusionOfId) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << false << "a" << true));
@ -314,7 +310,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerializeWithTopLevelID) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerializeWithTopLevelID) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << 1 << "b" << 1));
auto serialization = inclusion->serializeTransformation();
ASSERT_VALUE_EQ(serialization["a"], Value(true));
@ -351,7 +347,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerialize
ASSERT_VALUE_EQ(serialization["_id"], Value(true));
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopLevelExpressions) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopLevelExpressions) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a" << BSON("$add" << BSON_ARRAY(1 << 2))));
@ -372,7 +368,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopL
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNestedExpressions) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNestedExpressions) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a.b" << BSON("$add" << BSON_ARRAY(1 << 2))));
@ -394,7 +390,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNest
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldReportThatAllExceptIncludedFieldsAreModified) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << wrapInLiteral("computedVal") << "b.c" << wrapInLiteral("computedVal") << "d"
@ -412,7 +408,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_EQ(modifiedPaths.paths.size(), 3UL);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldReportThatAllExceptIncludedFieldsAreModifiedWithIdExclusion) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("_id" << false << "a" << wrapInLiteral("computedVal") << "b.c"
@ -436,7 +432,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
// Top-level only.
//
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTopLevelField) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTopLevelField) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
// More than one field in document.
@ -460,7 +456,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTo
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedTopLevelField) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedTopLevelField) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("newField" << wrapInLiteral("computedVal")));
auto result = inclusion->applyTransformation(Document{});
@ -473,7 +469,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedT
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldApplyBothInclusionsAndComputedFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << true << "newField" << wrapInLiteral("computedVal")));
@ -482,7 +478,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldIncludeFieldsInOrderOfInputDoc) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("first" << true << "second" << true << "third" << true));
@ -491,7 +487,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, inputDoc);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldApplyComputedFieldsInOrderSpecified) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON(
"firstComputed" << wrapInLiteral("FIRST") << "secondComputed" << wrapInLiteral("SECOND")));
@ -501,7 +497,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldImplicitlyIncludeId) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldImplicitlyIncludeId) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
auto result = inclusion->applyTransformation(Document{{"_id", "ID"_sd}, {"a", 1}, {"b", 2}});
auto expectedResult = Document{{"_id", "ID"_sd}, {"a", 1}};
@ -513,7 +509,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldImplicitl
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldImplicitlyIncludeIdWithComputedFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("newField" << wrapInLiteral("computedVal")));
@ -522,7 +518,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldIncludeIdIfExplicitlyIncluded) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << true << "_id" << true << "b" << true));
@ -532,7 +528,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldExcludeIdIfExplicitlyExcluded) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a" << true << "_id" << false));
@ -541,7 +537,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWithComputedId) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWithComputedId) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << wrapInLiteral("newId")));
auto result = inclusion->applyTransformation(Document{{"a", 1}, {"b", 2}, {"_id", "ID"_sd}});
@ -553,7 +549,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWit
// Projections with nested fields.
//
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldIncludeSimpleDottedFieldFromSubDoc) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
@ -578,7 +574,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldNotCreateSubDocIfDottedIncludedFieldDoesNotExist) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("sub.target" << true));
@ -593,7 +589,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldApplyDottedInclusionToEachElementInArray) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
@ -611,7 +607,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddComputedDottedFieldToSubDocument) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("sub.target" << wrapInLiteral("computedVal")));
@ -633,7 +629,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldCreateSubDocIfDottedComputedFieldDoesntExist) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("sub.target" << wrapInLiteral("computedVal")));
@ -648,7 +644,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldCreateNestedSubDocumentsAllTheWayToComputedField) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a.b.c.d" << wrapInLiteral("computedVal")));
@ -664,7 +660,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddComputedDottedFieldToEachElementInArray) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << wrapInLiteral("COMPUTED")));
@ -687,7 +683,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldApplyInclusionsAndAdditionsToEachElementInArray) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a.inc" << true << "a.comp" << wrapInLiteral("COMPUTED")));
@ -715,7 +711,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrIncludeSubFieldsOfId) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrIncludeSubFieldsOfId) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("_id.X" << true << "_id.Z" << wrapInLiteral("NEW")));
auto result = inclusion->applyTransformation(Document{{"_id", Document{{"X", 1}, {"Y", 2}}}});
@ -723,7 +719,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrInclude
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAllowMixedNestedAndDottedFields) {
// Include all of "a.b", "a.c", "a.d", and "a.e".
// Add new computed fields "a.W", "a.X", "a.Y", and "a.Z".
@ -747,7 +743,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldApplyNestedComputedFieldsInOrderSpecified) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << wrapInLiteral("FIRST") << "b.c" << wrapInLiteral("SECOND")));
@ -756,7 +752,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldApplyComputedFieldsAfterAllInclusions) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("b.c" << wrapInLiteral("NEW") << "a" << true));
@ -776,7 +772,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ComputedFieldReplacingExistingShouldAppearAfterInclusions) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("b" << wrapInLiteral("NEW") << "a" << true));
@ -792,7 +788,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
// Metadata inclusion.
//
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldAlwaysKeepMetadataFromOriginalDoc) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
@ -808,7 +804,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedDoc.freeze());
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
MetaDependenciesFalseWhenNotIncluded) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1}"));
@ -832,7 +828,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_FALSE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddSingleMetaExpressionDependency) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$meta: 'geoNearPoint'}}"));
@ -859,7 +855,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_FALSE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ShouldAddMetaExpressionsToDependencies) {
// Used to set 'score' metadata.
RAIIServerParameterControllerForTest featureFlagController("featureFlagRankFusionFull", true);
@ -899,7 +895,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMetaExpressions) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMetaExpressions) {
// Used to set 'score' metadata.
RAIIServerParameterControllerForTest featureFlagController("featureFlagRankFusionFull", true);
auto inclusion =
@ -946,7 +942,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMeta
// _id inclusion policy.
//
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdByDefault) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdByDefault) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
@ -955,7 +951,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeId
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdWithIncludePolicy) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdWithIncludePolicy) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
@ -964,7 +960,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeId
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeIdWithExcludePolicy) {
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeIdWithExcludePolicy) {
auto inclusion = makeInclusionProjectionWithDefaultIdExclusion(BSON("a" << true));
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
@ -973,7 +969,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeId
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldOverrideIncludePolicyWithExplicitExcludeIdSpec) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << false << "a" << true));
@ -984,7 +980,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldOverrideExcludePolicyWithExplicitIncludeIdSpec) {
auto inclusion =
makeInclusionProjectionWithDefaultIdExclusion(BSON("_id" << true << "a" << true));
@ -995,7 +991,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldAllowInclusionOfIdSubfieldWithDefaultIncludePolicy) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("_id.id1" << true << "a" << true));
@ -1007,7 +1003,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldAllowInclusionOfIdSubfieldWithDefaultExcludePolicy) {
auto inclusion =
makeInclusionProjectionWithDefaultIdExclusion(BSON("_id.id1" << true << "a" << true));
@ -1023,7 +1019,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
// Nested array recursion.
//
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldRecurseNestedArraysByDefault) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
@ -1037,7 +1033,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldNotRecurseNestedArraysForNoRecursePolicy) {
auto inclusion = makeInclusionProjectionWithNoArrayRecursion(BSON("a.b" << true));
@ -1051,7 +1047,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ShouldRetainNestedArraysIfNoRecursionNeeded) {
auto inclusion = makeInclusionProjectionWithNoArrayRecursion(BSON("a" << true));
@ -1066,7 +1062,7 @@ TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ComputedFieldIsAddedToNestedArrayElementsForRecursePolicy) {
auto inclusion =
makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << wrapInLiteral("COMPUTED")));
@ -1089,7 +1085,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ComputedFieldShouldReplaceNestedArrayForNoRecursePolicy) {
auto inclusion =
makeInclusionProjectionWithNoArrayRecursion(BSON("a.b" << wrapInLiteral("COMPUTED")));
@ -1116,7 +1112,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedProjections) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedProjections) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("computedMeta1" << BSON("$toUpper" << "$myMeta.x") << "computed2"
<< BSON("$add" << BSON_ARRAY(1 << "$c")) << "computedMeta3"
@ -1140,7 +1136,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedPro
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ExtractComputedProjectionInProjectShouldNotHideDependentFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
<< "b"
@ -1158,7 +1154,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ExtractComputedProjectionInProjectShouldNotIncludeId) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << BSON("$sum" << BSON_ARRAY("$myMeta" << "$_id"))));
@ -1175,7 +1171,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ExtractComputedProjectionInProjectShouldNotHideDependentSubFields) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
<< "b"
@ -1193,7 +1189,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
ExtractComputedProjectionInProjectShouldNotHideDependentSubFieldsWithDottedSibling) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
<< "c.b"
@ -1211,7 +1207,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAfterSplit) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAfterSplit) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << true << "computedMeta1" << BSON("$toUpper" << "$myMeta.x") << "computed2"
<< BSON("$add" << BSON_ARRAY(1 << "$c")) << "c" << true << "computedMeta3"
@ -1231,7 +1227,7 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAft
ASSERT_DOCUMENT_EQ(result, expectedResult);
}
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReservedNames) {
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReservedNames) {
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
BSON("a" << true << "data" << BSON("$toUpper" << "$myMeta.x") << "newMeta"
<< "$myMeta"));
@ -1250,71 +1246,67 @@ TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReserv
"{_id: true, a: true, data: {\"$toUpper\" : [\"$myMeta.x\"]}, newMeta: \"$newMeta\"}"));
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
}
} // namespace
// The tests in this block are for the fast-path projection only, as the default projection mode
// would always succeed, so we'll set the _runDefault flag to false to skip applying the projection
// in default mode.
namespace fast_path_projection_only_tests {
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
class InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly
: public InclusionProjectionExecutionTestWithoutFallBackToDefault {};
INSTANTIATE_TEST_SUITE_P(,
InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
testing::Values(AllowFastPath{true}));
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithFindPositional) {
_runDefault = false;
ASSERT_THROWS_CODE(
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, 'b.$': 1}"), fromjson("{b: 1}")),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, CannotUseFastPathWithFindSlice) {
_runDefault = false;
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithFindSlice) {
ASSERT_THROWS_CODE(
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, b: {$slice: 2}}"), {}),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithFindElemMatch) {
_runDefault = false;
ASSERT_THROWS_CODE(
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, b: {$elemMatch: {c: 1}}}"), {}),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithRegularExpression) {
_runDefault = false;
ASSERT_THROWS_CODE(
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$add: ['$c', 1]}}")),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithMetadataExpression) {
_runDefault = false;
ASSERT_THROWS_CODE(
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$meta: 'randVal'}}")),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, CannotUseFastPathWithLiteral) {
_runDefault = false;
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithLiteral) {
ASSERT_THROWS_CODE(
makeInclusionProjectionWithDefaultPolicies(BSON("a" << 1 << "b" << wrapInLiteral("abc"))),
AssertionException,
51752);
}
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
CannotUseFastPathWithFieldPathExpression) {
_runDefault = false;
ASSERT_THROWS_CODE(makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: '$c'}")),
AssertionException,
51752);
}
} // namespace fast_path_projection_only_tests
} // namespace
} // namespace mongo::projection_executor

View File

@ -60,35 +60,23 @@
namespace mongo::projection_executor {
namespace {
/**
* This test fixture run the test twice, one when the fast-path projection mode is allowed, another
* one when it's not.
*
* The 'AllowFallBackToDefault' parameter should be set to 'true', if the executor is allowed to
* fall back to the default inclusion projection implementation if the fast-path projection cannot
* be used for a specific test. If set to 'false', a tassert will be triggered if fast-path
* projection was expected to be chosen, but the default one has been picked instead.
*/
template <bool AllowFallBackToDefault>
class BaseProjectionExecutorTest : public AggregationContextFixture {
public:
void run() {
auto base = static_cast<mongo::unittest::Test*>(this);
try {
_allowFastPath = true;
base->run();
_allowFastPath = false;
base->run();
} catch (...) {
LOGV2(20597,
"Exception while testing",
"allowFastPath"_attr = _allowFastPath,
"allowFallBackToDefault"_attr = AllowFallBackToDefault);
throw;
}
}
enum AllowFastPath : bool {};
enum AllowFallBackToDefault : bool {};
class BaseProjectionExecutorTest : public AggregationContextFixture,
public testing::WithParamInterface<AllowFastPath> {
public:
protected:
/**
* The 'allowFallBackToDefault' parameter should be set to 'true', if the executor is allowed to
* fall back to the default inclusion projection implementation if the fast-path projection
* cannot be used for a specific test. If set to 'false', a tassert will be triggered if
* fast-path projection was expected to be chosen, but the default one has been picked instead.
*/
explicit BaseProjectionExecutorTest(AllowFallBackToDefault allowFallBackToDefault)
: _allowFallBackToDefault{allowFallBackToDefault}, _allowFastPath{GetParam()} {}
projection_ast::Projection parseWithDefaultPolicies(
const BSONObj& projectionBson, boost::optional<BSONObj> matchExprBson = boost::none) {
return parseWithPolicies(projectionBson, matchExprBson, ProjectionPolicies{});
@ -142,21 +130,39 @@ protected:
auto executorImpl = static_cast<ExecutorImpl*>(executor);
auto fastPathRootNode = exact_pointer_cast<FastPathNode*>(executorImpl->getRoot());
if (_allowFastPath) {
ASSERT_TRUE(fastPathRootNode || AllowFallBackToDefault);
ASSERT_TRUE(fastPathRootNode || _allowFallBackToDefault);
} else {
ASSERT_FALSE(fastPathRootNode);
}
}
AllowFallBackToDefault _allowFallBackToDefault;
// True, if the projection executor is allowed to use the fast-path inclusion projection
// implementation.
bool _allowFastPath{true};
AllowFastPath _allowFastPath;
};
using ProjectionExecutorTestWithFallBackToDefault = BaseProjectionExecutorTest<true>;
using ProjectionExecutorTestWithoutFallBackToDefault = BaseProjectionExecutorTest<false>;
class ProjectionExecutorTestWithFallBackToDefault : public BaseProjectionExecutorTest {
public:
ProjectionExecutorTestWithFallBackToDefault()
: BaseProjectionExecutorTest{AllowFallBackToDefault{true}} {}
};
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionWithIdPath) {
class ProjectionExecutorTestWithoutFallBackToDefault : public BaseProjectionExecutorTest {
public:
ProjectionExecutorTestWithoutFallBackToDefault()
: BaseProjectionExecutorTest{AllowFallBackToDefault{false}} {}
};
INSTANTIATE_TEST_SUITE_P(,
ProjectionExecutorTestWithoutFallBackToDefault,
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
INSTANTIATE_TEST_SUITE_P(,
ProjectionExecutorTestWithFallBackToDefault,
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionWithIdPath) {
auto projWithId = parseWithDefaultPolicies(fromjson("{a: 1, _id: 1}"));
auto executor = createProjectionExecutor(projWithId);
ASSERT_DOCUMENT_EQ(Document{fromjson("{_id: 123, a: 'abc'}")},
@ -170,7 +176,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionWithId
Document{fromjson("{_id: 123, a: 'abc', b: 'def', c: 'ghi'}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndottedPath) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndottedPath) {
auto proj = parseWithDefaultPolicies(fromjson("{a: 1, b: 1}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -178,7 +184,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndott
executor->applyTransformation(Document{fromjson("{a: 'abc', b: 'def', c: 'ghi'}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPath) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPath) {
auto proj = parseWithDefaultPolicies(fromjson("{'a.b': 1, 'a.d': 1}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -186,7 +192,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDotted
executor->applyTransformation(Document{fromjson("{a: {b: 'abc', c: 'def', d: 'ghi'}}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPathNestedArrays) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPathNestedArrays) {
auto proj = parseWithDefaultPolicies(fromjson("{'a.b': 1}"));
auto executor = createProjectionExecutor(proj);
Document input{fromjson("{a: [{b: 'abc', c: 'def'}, [{b: 'abc', c: 'def'}, 'd'], 'd']}")};
@ -198,14 +204,14 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDotted
ASSERT_BSONOBJ_EQ(expected, found);
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpression) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpression) {
auto proj = parseWithDefaultPolicies(fromjson("{c: {$add: ['$a', '$b']}}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(Document{fromjson("{c: 3}")},
executor->applyTransformation(Document{fromjson("{a: 1, b: 2}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpressionWithCommonParent) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpressionWithCommonParent) {
auto proj = parseWithDefaultPolicies(
fromjson("{'a.b.c': 1, 'b.c.d': 1, 'a.p.c' : {$add: ['$a.b.e', '$a.p']}, 'a.b.e': 1}"));
auto executor = createProjectionExecutor(proj);
@ -213,7 +219,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpressionWithComm
executor->applyTransformation(Document{fromjson("{a: {b: {e: 4}, p: 2}}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithIdPath) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithIdPath) {
auto projWithoutId = parseWithDefaultPolicies(fromjson("{a: 0, _id: 0}"));
auto executor = createProjectionExecutor(projWithoutId);
ASSERT_DOCUMENT_EQ(Document{fromjson("{b: 'def', c: 'ghi'}")},
@ -221,7 +227,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithId
Document{fromjson("{_id: 123, a: 'abc', b: 'def', c: 'ghi'}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndottedPath) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndottedPath) {
auto proj = parseWithDefaultPolicies(fromjson("{a: 0, b: 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -229,7 +235,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndott
executor->applyTransformation(Document{fromjson("{a: 'abc', b: 'def', c: 'ghi'}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPath) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPath) {
auto proj = parseWithDefaultPolicies(fromjson("{'a.b': 0, 'a.d': 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -237,7 +243,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDotted
executor->applyTransformation(Document{fromjson("{a: {b: 'abc', c: 'def', d: 'ghi'}}")}));
}
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPathNestedArrays) {
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPathNestedArrays) {
auto proj = parseWithDefaultPolicies(fromjson("{'a.c': 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(Document{fromjson("{a: [{b: 'abc'}, [{b: 'abc'}, 'd'], 'd']}")},
@ -245,7 +251,7 @@ TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDotted
"{a: [{b: 'abc', c: 'def'}, [{b: 'abc', c: 'def'}, 'd'], 'd']}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
auto proj =
parseWithFindFeaturesEnabled(fromjson("{'a.b.$': 1}"), fromjson("{'a.b': {$gte: 3}}"));
auto executor = createProjectionExecutor(proj);
@ -256,7 +262,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
executor->applyTransformation(Document{fromjson("{a: {b: [4, 3, 2]}}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithInclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithInclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{a: {$elemMatch: {b: {$gte: 3}}}, c: 1}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -264,7 +270,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithI
executor->applyTransformation(Document{fromjson("{a: [{b: 1}, {b: 2}, {b: 3}]}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatch) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatch) {
const BSONObj obj = fromjson("{a: [{b: 3, c: 1}, {b: 1, c: 2}, {b: 1, c: 3}]}");
{
auto proj = parseWithFindFeaturesEnabled(fromjson("{a: {$elemMatch: {b: 1}}}"));
@ -281,7 +287,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatch) {
}
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
auto collator =
std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString);
getExpCtx()->setCollator(std::move(collator));
@ -294,7 +300,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
executor->applyTransformation(Document{fromjson("{a: ['zaa', 'zbb', 'zdd', 'zee']}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithExclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithExclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{a: {$elemMatch: {b: {$gte: 3}}}, c: 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(Document{fromjson("{a: [{b: 3}], d: 'def'}")},
@ -302,7 +308,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithE
fromjson("{a: [{b: 1}, {b: 2}, {b: 3}], c: 'abc', d: 'def'}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 1}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -310,7 +316,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclu
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3]}, c: 'abc'}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithInclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithInclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 1}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -318,7 +324,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimit
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWithExclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWithExclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: 3}, c: 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -326,7 +332,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWith
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithExclusion) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithExclusion) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 0}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(
@ -334,7 +340,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimit
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositional) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositional) {
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, 'c.$': 1}"),
fromjson("{c: {$gte: 6}}"));
auto executor = createProjectionExecutor(proj);
@ -343,7 +349,7 @@ TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositi
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: [5,6,7]}")}));
}
TEST_F(ProjectionExecutorTestWithFallBackToDefault, ExecutorOptimizesExpression) {
TEST_P(ProjectionExecutorTestWithFallBackToDefault, ExecutorOptimizesExpression) {
auto proj = parseWithDefaultPolicies(fromjson("{a: 1, b: {$add: [1, 2]}}"));
auto executor = createProjectionExecutor(proj);
ASSERT_DOCUMENT_EQ(Document{fromjson("{_id: true, a: true, b: {$const: 3}}")},

View File

@ -31,6 +31,7 @@
#include "mongo/db/exec/sbe/sbe_hash_lookup_shared_test.h"
#include "mongo/db/exec/sbe/stages/hash_lookup.h"
#include "mongo/unittest/test_info.h"
#include "mongo/unittest/unittest.h"
#include <benchmark/benchmark.h>
@ -41,11 +42,19 @@ public:
void runVariation(const RunVariationParams& params) override {
return;
}
void _doTest() override {
void TestBody() override {
return;
}
};
class DummyBenchmarkTestFixture : public ::testing::Test {
public:
void TestBody() override {}
};
// Register a dummy test for GoldenTestContext initialization. This test is never run.
TEST_F(DummyBenchmarkTestFixture, DummyBenchmarkTest) {}
class HashLookupBenchmarkFixture : public benchmark::Fixture {
public:
void runVariation(benchmark::State& state,
@ -139,14 +148,15 @@ public:
sharedTest.tearDown();
} // runVariation
void _doTest() {
void TestBody() {
return;
}
unittest::GoldenTestContext getGoldenTestContext() {
TestInfo testInfo(
"HashLookupBenchmarkFixture", "runVariation", "sbe_hash_lookup_bm.cpp", __LINE__);
// GoldenTestContext not used in this benchmark, create a dummy GoldenTestContext.
static const ::testing::TestInfo* dummyTestInfo =
::testing::UnitTest::GetInstance()->GetTestSuite(0)->GetTestInfo(0);
return unittest::GoldenTestContext(
&goldenTestConfigSbe, &testInfo, false /* validateOnClose */);
&goldenTestConfigSbe, dummyTestInfo, false /* validateOnClose */);
}
};

View File

@ -93,7 +93,7 @@ public:
}
// virtual function needs to be defined
void _doTest() override {}
void TestBody() override {}
const NamespaceString _nss =
NamespaceString::createNamespaceString_forTest("testdb.sbe_scan_stage");

View File

@ -98,8 +98,8 @@ protected:
};
TEST_F(SBENumericTest, Compile) {
GoldenTestContext gctx(&goldenTestConfigSbe);
gctx.printTestHeader(GoldenTestContext::HeaderFormat::Text);
unittest::GoldenTestContext gctx(&goldenTestConfigSbe);
gctx.printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
auto& os = gctx.outStream();
auto expr = test_detail::makeEFromNumber(

View File

@ -87,7 +87,7 @@ public:
return colls;
}
void _doTest() override {}
void TestBody() override {}
const NamespaceString _nss =
NamespaceString::createNamespaceString_forTest("testdb.sbe_scan_stage");

View File

@ -491,8 +491,8 @@ TEST(SBEVM, CodeFragmentToStringSanity) {
}
TEST(SBEVM, CodeFragmentPrintStable) {
GoldenTestContext ctx(&goldenTestConfigSbe);
ctx.printTestHeader(GoldenTestContext::HeaderFormat::Text);
unittest::GoldenTestContext ctx(&goldenTestConfigSbe);
ctx.printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
auto& os = ctx.outStream();

View File

@ -40,27 +40,15 @@ namespace mongo::sbe {
unittest::GoldenTestConfig goldenTestConfigSbe{"src/mongo/db/test_output/exec/sbe"};
void GoldenSBETestFixture::run() {
GoldenTestContext ctx(&goldenTestConfigSbe);
ctx.validateOnClose(false);
auto guard = ScopeGuard([&] { gctx = nullptr; });
gctx = &ctx;
gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
void GoldenSBETestFixture::setUp() {
gctx = std::make_unique<unittest::GoldenTestContext>(&goldenTestConfigSbe);
gctx->validateOnClose(false);
gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
}
if (_debug) {
try {
Test::run();
} catch (::mongo::unittest::TestAssertionFailureException&) {
std::cout << "== Golden test failed before output comparison. ==" << std::endl;
std::cout << "Output so far:" << std::endl << ctx.getOutputString() << std::endl;
std::cout.flush();
throw;
}
} else {
Test::run();
}
ctx.verifyOutput();
void GoldenSBETestFixture::tearDown() {
gctx->verifyOutput();
gctx.reset();
}
void GoldenSBETestFixture::printVariation(const std::string& name) {

View File

@ -44,9 +44,6 @@
namespace mongo::sbe {
using namespace mongo::unittest;
using namespace mongo::unittest::match;
typedef std::pair<value::TypeTags, value::Value> TypedValue;
typedef std::vector<TypedValue> TypedValues;
@ -69,11 +66,14 @@ class GoldenSBETestFixture : public virtual SBETestFixture {
public:
GoldenSBETestFixture(bool debug = false) : _debug(debug), _variationCount(0) {}
void run();
void setUp() override;
void tearDown() override;
void printVariation(const std::string& name = "");
protected:
GoldenTestContext* gctx;
std::unique_ptr<unittest::GoldenTestContext> gctx;
private:
bool _debug;
@ -81,66 +81,60 @@ private:
};
/** SBE Value Equal to. */
class ValueEq : public mongo::unittest::match::Matcher {
class ValueEqMatcher {
public:
explicit ValueEq(TypedValue v) : _v{v} {}
explicit ValueEq(value::TagValueView v) : _v{v.tag, v.value} {}
explicit ValueEqMatcher(TypedValue v) : _v{v} {}
explicit ValueEqMatcher(value::TagValueView v) : _v{v.tag, v.value} {}
std::string describe() const {
std::stringstream ss;
ss << "ValueEq(" << _v << ")";
return ss.str();
void DescribeTo(std::ostream* os) const {
*os << "ValueEq(" << _v << ")";
}
MatchResult match(const TypedValue x) const {
void DescribeNegationTo(std::ostream* os) const {
*os << "not ValueEq(" << _v << ")";
}
bool MatchAndExplain(const TypedValue& x, ::testing::MatchResultListener* listener) const {
auto [tag, val] = sbe::value::compareValue(_v.first, _v.second, x.first, x.second);
return MatchResult{tag == sbe::value::TypeTags::NumberInt32 &&
sbe::value::bitcastTo<int>(val) == 0};
return tag == sbe::value::TypeTags::NumberInt32 && sbe::value::bitcastTo<int>(val) == 0;
}
MatchResult match(const value::TagValueView x) const {
return match(std::make_pair(x.tag, x.value));
bool MatchAndExplain(const value::TagValueView& x,
::testing::MatchResultListener* listener) const {
return MatchAndExplain(std::make_pair(x.tag, x.value), listener);
}
private:
TypedValue _v;
};
inline auto ValueEq(TypedValue v) {
return ::testing::MakePolymorphicMatcher(ValueEqMatcher(v));
}
inline auto ValueEq(value::TagValueView v) {
return ::testing::MakePolymorphicMatcher(ValueEqMatcher(v));
}
/* Similar to ValueEq, but also value difference within certain limit for double and decimal */
class ValueRoughEq : public mongo::unittest::match::Matcher {
public:
explicit ValueRoughEq(TypedValue v, double limit) : _v{v}, _limit{limit} {}
std::string describe() const {
std::stringstream ss;
ss << "ValueEq(" << _v << ")";
return ss.str();
}
MatchResult match(const TypedValue& x) const {
auto [tag, val] = sbe::value::compareValue(_v.first, _v.second, x.first, x.second);
bool equal =
tag == sbe::value::TypeTags::NumberInt32 && sbe::value::bitcastTo<int>(val) == 0;
if (!equal) {
if (_v.first == sbe::value::TypeTags::NumberDouble &&
x.first == sbe::value::TypeTags::NumberDouble) {
auto diff = sbe::value::bitcastTo<double>(_v.second) -
sbe::value::bitcastTo<double>(x.second);
equal = std::abs(diff) <= _limit;
} else if (_v.first == sbe::value::TypeTags::NumberDecimal &&
x.first == sbe::value::TypeTags::NumberDecimal) {
auto diff = sbe::value::bitcastTo<Decimal128>(_v.second).subtract(
sbe::value::bitcastTo<Decimal128>(x.second));
equal = diff.toAbs().toDouble() <= _limit;
}
MATCHER_P2(ValueRoughEq, v, limit, "") {
auto [tag, val] = sbe::value::compareValue(v.first, v.second, arg.first, arg.second);
bool equal = tag == sbe::value::TypeTags::NumberInt32 && sbe::value::bitcastTo<int>(val) == 0;
if (!equal) {
if (v.first == sbe::value::TypeTags::NumberDouble &&
arg.first == sbe::value::TypeTags::NumberDouble) {
auto diff =
sbe::value::bitcastTo<double>(v.second) - sbe::value::bitcastTo<double>(arg.second);
equal = std::abs(diff) <= limit;
} else if (v.first == sbe::value::TypeTags::NumberDecimal &&
arg.first == sbe::value::TypeTags::NumberDecimal) {
auto diff = sbe::value::bitcastTo<Decimal128>(v.second).subtract(
sbe::value::bitcastTo<Decimal128>(arg.second));
equal = diff.toAbs().toDouble() <= limit;
}
return MatchResult{equal};
}
private:
TypedValue _v;
double _limit;
};
return equal;
}
class ValueVectorGuard {
ValueVectorGuard() = delete;

View File

@ -127,13 +127,6 @@ std::string posInfoToString(const std::vector<int32_t>& posInfo) {
class BsonBlockDecodingTest : public mongo::unittest::Test {
public:
void run() {
auto base = static_cast<mongo::unittest::Test*>(this);
// Run the tests using the block-based BSON implementation for extracting paths.
base->run();
}
// Given an object that matches what we might see in the data field of a bucket, produce the
// corresonding vector of objects.
std::vector<BSONObj> columnsToObjs(BSONObj bsonColumns) {

View File

@ -186,6 +186,8 @@ class BSONObjValueAccessorTest : public SlotTestBase<value::BSONObjValueAccessor
public mongo::unittest::Test {
public:
void testGetOwnedBSONObj() {
using testing::Eq;
using testing::Ne;
BSONObjBuilder bob;
bob.append("a", 1);
BSONObj obj = bob.obj();

View File

@ -61,7 +61,7 @@
namespace mongo::extension::sdk {
namespace {
class AggStageDeathTest : public unittest::Test {
class AggStageErrorFixture : public unittest::Test {
public:
void setUp() override {
// Initialize HostServices so that aggregation stages will be able to access member
@ -151,7 +151,8 @@ public:
}
};
DEATH_TEST_F(AggStageDeathTest, EmptyDesugarExpansionFails, "11113803") {
using AggStageErrorFixtureDeathTest = AggStageErrorFixture;
DEATH_TEST_F(AggStageErrorFixtureDeathTest, EmptyDesugarExpansionFails, "11113803") {
auto emptyDesugarParseNode =
new ExtensionAggStageParseNode(shared_test_stages::DesugarToEmptyParseNode::make());
auto handle = extension::AggStageParseNodeHandle{emptyDesugarParseNode};
@ -159,7 +160,7 @@ DEATH_TEST_F(AggStageDeathTest, EmptyDesugarExpansionFails, "11113803") {
[[maybe_unused]] auto expanded = handle->expand();
}
TEST_F(AggStageDeathTest, GetExpandedSizeLessThanActualExpansionSizeFails) {
TEST_F(AggStageErrorFixture, GetExpandedSizeLessThanActualExpansionSizeFails) {
auto getExpandedSizeLessThanActualExpansionSizeParseNode = new ExtensionAggStageParseNode(
shared_test_stages::GetExpandedSizeLessThanActualExpansionSizeParseNode::make());
auto handle =
@ -173,7 +174,7 @@ TEST_F(AggStageDeathTest, GetExpandedSizeLessThanActualExpansionSizeFails) {
11113802);
}
TEST_F(AggStageDeathTest, GetExpandedSizeGreaterThanActualExpansionSizeFails) {
TEST_F(AggStageErrorFixture, GetExpandedSizeGreaterThanActualExpansionSizeFails) {
auto getExpandedSizeGreaterThanActualExpansionSizeParseNode = new ExtensionAggStageParseNode(
shared_test_stages::GetExpandedSizeGreaterThanActualExpansionSizeParseNode::make());
auto handle =
@ -187,7 +188,7 @@ TEST_F(AggStageDeathTest, GetExpandedSizeGreaterThanActualExpansionSizeFails) {
11113802);
}
DEATH_TEST_F(AggStageDeathTest, DescriptorAndParseNodeNameMismatchFails, "11217602") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, DescriptorAndParseNodeNameMismatchFails, "11217602") {
auto descriptor = std::make_unique<ExtensionAggStageDescriptor>(
shared_test_stages::NameMismatchStageDescriptor::make());
auto handle = extension::AggStageDescriptorHandle{descriptor.get()};
@ -318,7 +319,7 @@ DEATH_TEST(ExecAggStageVTableDeathTest, InvalidExecAggStageVTableFailsClose, "11
};
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultAdvanced, "10956801") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultAdvanced, "10956801") {
auto invalidExtensionExecAggStageAdvancedState = new extension::sdk::ExtensionExecAggStage(
InvalidExtensionExecAggStageAdvancedState::make());
@ -326,7 +327,9 @@ DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultAdvanced, "10956801
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultPauseExecution, "10956802") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
InvalidExtensionGetNextResultPauseExecution,
"10956802") {
auto invalidExtensionExecAggStagePauseExecutionState =
new extension::sdk::ExtensionExecAggStage(
InvalidExtensionExecAggStagePauseExecutionState::make());
@ -335,7 +338,7 @@ DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultPauseExecution, "10
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultEOF, "10956805") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultEOF, "10956805") {
auto invalidExtensionExecAggStageEofState =
new extension::sdk::ExtensionExecAggStage(InvalidExtensionExecAggStageEofState::make());
@ -343,14 +346,14 @@ DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultEOF, "10956805") {
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest, InvalidMongoExtensionGetNextResultCode, "10956803") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidMongoExtensionGetNextResultCode, "10956803") {
::MongoExtensionGetNextResult result = {.code =
static_cast<::MongoExtensionGetNextResultCode>(10),
.resultDocument = createEmptyByteContainer()};
[[maybe_unused]] auto converted = extension::ExtensionGetNextResult::makeFromApiResult(result);
};
DEATH_TEST_F(AggStageDeathTest, InvalidGetNextCode, "10956804") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidGetNextCode, "10956804") {
auto invalidExtensionExecAggStageGetNextCode =
new extension::sdk::ExtensionExecAggStage(InvalidExtensionExecAggStageGetNextCode::make());
@ -402,7 +405,7 @@ public:
}
};
DEATH_TEST_F(AggStageDeathTest,
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
InvalidExtensionGetNextResultAdvancedFromCompiledExecAggStage,
"10956801") {
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
@ -414,7 +417,7 @@ DEATH_TEST_F(AggStageDeathTest,
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest,
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
InvalidExtensionGetNextResultPauseExecutionFromCompiledExecAggStage,
"10956802") {
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
@ -426,7 +429,7 @@ DEATH_TEST_F(AggStageDeathTest,
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest,
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
InvalidExtensionGetNextResultEOFFromCompiledExecAggStage,
"10956805") {
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
@ -438,7 +441,7 @@ DEATH_TEST_F(AggStageDeathTest,
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
};
DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsSize, "11368301") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidDPLArrayContainerVTableFailsSize, "11368301") {
auto handle = DPLArrayContainerHandle{new sdk::ExtensionDPLArrayContainerAdapter(
sdk::DPLArrayContainer(std::vector<VariantDPLHandle>{}))};
@ -447,7 +450,9 @@ DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsSize, "113683
DPLArrayContainerAPI::assertVTableConstraints(vtable);
};
DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsTransfer, "11368302") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
InvalidDPLArrayContainerVTableFailsTransfer,
"11368302") {
auto handle = DPLArrayContainerHandle{new sdk::ExtensionDPLArrayContainerAdapter(
sdk::DPLArrayContainer(std::vector<VariantDPLHandle>{}))};
@ -456,7 +461,9 @@ DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsTransfer, "11
DPLArrayContainerAPI::assertVTableConstraints(vtable);
};
DEATH_TEST_F(AggStageDeathTest, DPLArrayContainerExtensionToHostWrongSizeFails, "11368303") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
DPLArrayContainerExtensionToHostWrongSizeFails,
"11368303") {
auto logicalStage =
new sdk::ExtensionLogicalAggStage(shared_test_stages::CountingLogicalStage::make());
auto parseNode = new sdk::ExtensionAggStageParseNode(shared_test_stages::CountingParse::make());
@ -520,7 +527,9 @@ DEATH_TEST(DistributedPlanLogicVTableDeathTest, InvalidDPLVTableFailsGetSortPatt
DistributedPlanLogicAPI::assertVTableConstraints(vtable);
};
DEATH_TEST_F(AggStageDeathTest, SourceStageForTransformExtensionStageBecomesInvalid, "10957209") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
SourceStageForTransformExtensionStageBecomesInvalid,
"10957209") {
// This test verifies that if the source stage becomes invalid or is deleted,
// the extension stage will safely fail when trying to access it.
QueryTestServiceContext testCtx;
@ -563,7 +572,7 @@ DEATH_TEST_F(AggStageDeathTest, SourceStageForTransformExtensionStageBecomesInva
result = extensionStage->getNext();
};
DEATH_TEST_F(AggStageDeathTest, NoSourceStageForTransformStage, "10957209") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, NoSourceStageForTransformStage, "10957209") {
auto transformStage = shared_test_stages::AddFruitsToDocumentsExecStage::make();
QueryTestServiceContext testCtx;
@ -580,11 +589,11 @@ DEATH_TEST_F(AggStageDeathTest, NoSourceStageForTransformStage, "10957209") {
[[maybe_unused]] auto result = transformStage->getNext(&ctxAdapter, nullptr);
}
DEATH_TEST_F(AggStageDeathTest, HostExecAggStageAdapterNullStageAsserts, "10957207") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, HostExecAggStageAdapterNullStageAsserts, "10957207") {
[[maybe_unused]] auto adapter = host_connector::HostExecAggStageAdapter{nullptr};
}
DEATH_TEST_F(AggStageDeathTest, SetSourceOnSourceStageFails, "10957210") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, SetSourceOnSourceStageFails, "10957210") {
// Setting the source of a source stage should fail irrespective of the type of the stage being
// set as the source.
auto sourceHandle = extension::ExecAggStageHandle{new extension::sdk::ExtensionExecAggStage(
@ -597,14 +606,14 @@ DEATH_TEST_F(AggStageDeathTest, SetSourceOnSourceStageFails, "10957210") {
handle->setSource(sourceHandle);
}
DEATH_TEST_F(AggStageDeathTest, GetSourceOnSourceStageFails, "10957208") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, GetSourceOnSourceStageFails, "10957208") {
shared_test_stages::FruitsAsDocumentsExecStage sourceStage{};
// Calling getSource on a source stage should fail.
[[maybe_unused]] auto source = sourceStage._getSource();
}
DEATH_TEST_F(AggStageDeathTest, GetNameOnMovedHandleFails, "10596403") {
DEATH_TEST_F(AggStageErrorFixtureDeathTest, GetNameOnMovedHandleFails, "10596403") {
auto sourceHandle = extension::ExecAggStageHandle{new extension::sdk::ExtensionExecAggStage(
shared_test_stages::AddFruitsToDocumentsExecStage::make())};

View File

@ -176,42 +176,42 @@ TEST(ExtensionStatusTest, extensionStatusInvokeCAndConvertStatusToException_Exte
kErrorString);
}
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsGetCode, "10930105") {
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsGetCode, "10930105") {
StatusHandle status(new ExtensionGenericStatus());
auto vtable = status->vtable();
vtable.get_code = nullptr;
StatusAPI::assertVTableConstraints(vtable);
}
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsGetReason, "10930106") {
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsGetReason, "10930106") {
StatusHandle status(new ExtensionGenericStatus());
auto vtable = status->vtable();
vtable.get_reason = nullptr;
StatusAPI::assertVTableConstraints(vtable);
}
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsSetCode, "11186306") {
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsSetCode, "11186306") {
StatusHandle status(new ExtensionGenericStatus());
auto vtable = status->vtable();
vtable.set_code = nullptr;
StatusAPI::assertVTableConstraints(vtable);
}
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsSetReason, "11186309") {
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsSetReason, "11186309") {
StatusHandle status(new ExtensionGenericStatus());
auto vtable = status->vtable();
vtable.set_reason = nullptr;
StatusAPI::assertVTableConstraints(vtable);
}
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsClone, "11186310") {
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsClone, "11186310") {
StatusHandle status(new ExtensionGenericStatus());
auto vtable = status->vtable();
vtable.clone = nullptr;
StatusAPI::assertVTableConstraints(vtable);
}
DEATH_TEST(ExtensionStatusTest, ExtensionStatusOKSetReasonFails, "11186303") {
DEATH_TEST(ExtensionStatusTestDeathTest, ExtensionStatusOKSetReasonFails, "11186303") {
StatusHandle status(&ExtensionStatusOK::getInstance());
status->setReason("");
}
@ -222,7 +222,7 @@ TEST(ExtensionStatusTest, ExtensionStatusOKSetCodeNoOp) {
ASSERT_EQ(status->getCode(), 0);
}
DEATH_TEST(ExtensionStatusTest, ExtensionStatusExceptionSetReasonFails, "11186304") {
DEATH_TEST(ExtensionStatusTestDeathTest, ExtensionStatusExceptionSetReasonFails, "11186304") {
StatusHandle status(wrapCXXAndConvertExceptionToStatus(
[&]() { uasserted(11186311, "Failed with uassert in $noOpExtension parse."); }));
status->setReason("");

View File

@ -36,7 +36,6 @@
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_test_fixture.h"
#include "mongo/db/topology/cluster_role.h"
#include "mongo/unittest/assert_that.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/concurrency/notification.h"
#include "mongo/util/duration.h"

View File

@ -37,7 +37,6 @@
namespace mongo {
const Date_t kDate = Date_t::now();
const std::vector<BSONObj> kField1Elements = {
BSON("logLevel" << 2),

View File

@ -75,8 +75,6 @@ namespace mongo {
namespace {
// Reusing the ConfigServerTestFixture for benchmarking.
// _doTest has empty implementation to honor the abstract class, but it is not used in the benchmark
// framework.
class BenchmarkConfigServerTestFixture : public ConfigServerTestFixture {
public:
BenchmarkConfigServerTestFixture() : ConfigServerTestFixture() {
@ -176,7 +174,7 @@ public:
}
private:
void _doTest() override {};
void TestBody() override {}
std::vector<BSONObj> _generateConfigShardSampleData(int nShards) const {
std::vector<BSONObj> configShardData;

View File

@ -284,7 +284,7 @@ TEST(ChunkType, ParseFromNetworkRequest) {
<< onCurrentShardSince << ChunkHistoryBase::kShardFieldName
<< "shard0001")))));
ASSERT_EQ("shard0001", chunk.getShard());
ASSERT_EQ("shard0001"_sd, chunk.getShard());
ASSERT_EQ(chunkVersion, chunk.getVersion());
}

View File

@ -1116,7 +1116,7 @@ private:
class ParseErrorBase : public Base {
public:
~ParseErrorBase() override {}
void _doTest() final {
void TestBody() final {
ASSERT_THROWS(createGroup(spec()), AssertionException);
}
@ -1127,7 +1127,7 @@ protected:
class ExpressionBase : public Base {
public:
~ExpressionBase() override {}
void _doTest() final {
void TestBody() final {
createGroup(spec());
auto mockStage = exec::agg::MockStage::createForTest(Document(doc()), ctx());
groupStage()->setSource(mockStage.get());
@ -1157,7 +1157,7 @@ class IdConstantBase : public ExpressionBase {
/** $group spec is not an object. */
class NonObject : public Base {
public:
void _doTest() final {
void TestBody() final {
BSONObj spec = BSON(getStageName() << "foo");
BSONElement specElement = spec.firstElement();
ASSERT_THROWS(createFromBson(specElement, ctx()), AssertionException);
@ -1373,7 +1373,7 @@ public:
CheckResultsBase(GroupStageType groupStageType = GroupStageType::Default)
: Base(groupStageType) {}
~CheckResultsBase() override {}
void _doTest() override {
void TestBody() override {
runSharded(false);
runSharded(true);
}
@ -1582,7 +1582,7 @@ class UndefinedAccumulatorValue : public CheckResultsBase {
/** Simulate merging sharded results in the router. */
class RouterMerger : public CheckResultsBase {
public:
void _doTest() final {
void TestBody() final {
auto mockStage = exec::agg::MockStage::createForTest({"{_id:0,list:[1,2]}",
"{_id:1,list:[3,4]}",
"{_id:0,list:[10,20]}",
@ -1609,7 +1609,7 @@ private:
/** Dependant field paths. */
class Dependencies : public Base {
public:
void _doTest() final {
void TestBody() final {
createGroup(fromjson("{_id:'$x',a:{$sum:'$y.z'},b:{$avg:{$add:['$u','$v']}}}"));
DepsTracker dependencies;
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_ALL, group()->getDependencies(&dependencies));
@ -1644,11 +1644,11 @@ class StringConstantIdAndAccumulatorExpressions : public CheckResultsBase {
/** An array constant passed to an accumulator. */
class ArrayConstantAccumulatorExpression : public CheckResultsBase {
public:
void _doTest() final {
void TestBody() final {
// A parse exception is thrown when a raw array is provided to an accumulator.
ASSERT_THROWS(createGroup(fromjson("{_id:1,a:{$push:[4,5,6]}}")), AssertionException);
// Run standard base tests.
CheckResultsBase::_doTest();
CheckResultsBase::TestBody();
}
std::deque<DocumentSource::GetNextResult> inputData() override {
return {Document()};
@ -1691,7 +1691,7 @@ public:
CheckResultsAndSpills(GroupStageType groupStageType, uint64_t expectedSpills)
: CheckResultsBase(groupStageType), _expectedSpills(expectedSpills) {}
void _doTest() final {
void TestBody() final {
for (int sharded = 0; sharded < 2; ++sharded) {
runSharded(sharded);
const auto* groupStats =

View File

@ -191,7 +191,9 @@ TEST_F(LiteParsedDocumentSourceParseTest, CanRegisterBothPrimaryAndFallback) {
registerPrimaryParser();
}
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, MustRegisterPrimaryAfterFallback, "11395100") {
using LiteParsedDocumentSourceParseDeathTest = LiteParsedDocumentSourceParseTest;
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, MustRegisterPrimaryAfterFallback, "11395100") {
_stageName = "$mustRegisterPrimaryAfterFallback";
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
@ -199,7 +201,7 @@ DEATH_TEST_F(LiteParsedDocumentSourceParseTest, MustRegisterPrimaryAfterFallback
registerFallbackParser(&mockFlag);
}
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, CannotOverridePrimaryParser, "11534800") {
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, CannotOverridePrimaryParser, "11534800") {
_stageName = "$cannotOverridePrimaryParser";
// Register the primary parser first.
@ -251,7 +253,7 @@ TEST_F(LiteParsedDocumentSourceParseTest, FirstFallbackParserTakesPrecedenceWith
}
// TODO SERVER-114028 Remove the following test when fallback parsing supports all feature flags.
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, IFRFlagIsRequired, "11395101") {
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, IFRFlagIsRequired, "11395101") {
_stageName = "$IFRFlagIsRequired";
BinaryCompatibleFeatureFlag mockFlag(false);
@ -371,4 +373,3 @@ TEST(ViewPolicy, CanSpecifyDisallowViewPolicyCustomValues) {
}
} // namespace mongo

View File

@ -42,7 +42,10 @@ namespace {
using MakePipelineBSONElementTest = AggregationContextFixture;
DEATH_TEST_F(MakePipelineBSONElementTest, TassertFailsWhenBSONElementIsNotArray, "11524600") {
using MakePipelineBSONElementTestDeathTest = MakePipelineBSONElementTest;
DEATH_TEST_F(MakePipelineBSONElementTestDeathTest,
TassertFailsWhenBSONElementIsNotArray,
"11524600") {
auto expCtx = getExpCtx();
BSONObj cmdObj = BSON("pipeline" << 123); // Not an array
BSONElement pipelineElem = cmdObj["pipeline"];

View File

@ -77,7 +77,7 @@ public:
* Test that buildDocumentSource tasserts for stages that are not registered
* in the StageParams to DocumentSource registry.
*/
DEATH_TEST(StageParamsToDocumentSourceRegistryTest, UnregisteredStageReturnsNone, "11434300") {
DEATH_TEST(StageParamsToDocumentSourceRegistryDeathTest, UnregisteredStageReturnsNone, "11434300") {
BSONObj spec = BSON("$unregisteredTestStage" << BSONObj());
auto liteParsed = UnregisteredTestLiteParsed(spec.firstElement());
auto expCtx = make_intrusive<ExpressionContextForTest>();
@ -132,7 +132,7 @@ REGISTER_STAGE_PARAMS_TO_DOCUMENT_SOURCE_MAPPING(duplicateRegistrationTest,
* This ensures that each stage can only have one registered mapping function,
* preventing accidental overwrites or conflicting implementations.
*/
DEATH_TEST(StageParamsToDocumentSourceRegistryTest, DuplicateRegistrationFails, "11458700") {
DEATH_TEST(StageParamsToDocumentSourceRegistryDeathTest, DuplicateRegistrationFails, "11458700") {
// Attempt to register a second mapping function for the same StageParams::Id.
// This should trigger a tassert.
registerStageParamsToDocumentSourceFn(DuplicateRegistrationTestStageParams::id, dummyMappingFn);
@ -140,4 +140,3 @@ DEATH_TEST(StageParamsToDocumentSourceRegistryTest, DuplicateRegistrationFails,
} // namespace
} // namespace mongo

View File

@ -279,7 +279,7 @@ TEST_F(CanonicalDistinctTest, CopyMaintainsDistinctProperties) {
originalDistinct->setSortRequirement(SortPattern(BSON("x" << 1), expCtx));
const auto& copyDistinct = CanonicalDistinct(*originalDistinct);
ASSERT_NE(&originalDistinct, &copyDistinct);
ASSERT_NE(originalDistinct, &copyDistinct);
ASSERT_EQ(originalDistinct->getKey(), copyDistinct.getKey());
ASSERT_EQ(originalDistinct->isMirrored(), copyDistinct.isMirrored());

View File

@ -172,7 +172,7 @@ public:
return CardinalityEstimate(CardinalityType{estimate}, source);
}
void _doTest() override {}
void TestBody() override {}
OperationContext* getOperationContext() const {
return operationContext();

View File

@ -232,14 +232,14 @@ TEST(PlannerWildcardHelpersTest, Expand_CompoundWildcardIndex_NumericComponents)
ASSERT_EQ(expectedMks, expandedIndexes.front().multikeyPaths);
}
DEATH_TEST(PlannerWildcardHelpersTest, InvalidIndexExpansion, "11390001") {
DEATH_TEST(PlannerWildcardHelpersTestDeathTest, InvalidIndexExpansion, "11390001") {
WildcardIndexEntryMock wildcardIndex{BSON("a" << 1 << "$**" << 1), BSON("_id" << 0), {}};
std::set<std::string> fields{"a"};
std::vector<IndexEntry> expandedIndexes{};
expandWildcardIndexEntry(*wildcardIndex.indexEntry, fields, &expandedIndexes);
}
DEATH_TEST(PlannerWildcardHelpersTest, AnotherInvalidIndexExpansion, "11390001") {
DEATH_TEST(PlannerWildcardHelpersTestDeathTest, AnotherInvalidIndexExpansion, "11390001") {
WildcardIndexEntryMock wildcardIndex{BSON("$**" << 1 << "a" << 1), BSON("_id" << 0), {}};
std::set<std::string> fields{"a"};
std::vector<IndexEntry> expandedIndexes{};

View File

@ -78,7 +78,7 @@ public:
}
private:
void _doTest() override {}
void TestBody() override {}
void setUp() final {
CatalogTestFixture::setUp();

View File

@ -94,7 +94,7 @@ public:
ASSERT_EQ(resultSlots.size(), 1);
// Print the stage explain output and verify.
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
sbe::DebugPrintInfo debugPrintInfo{};
_gctx->outStream() << sbe::DebugPrinter().print(*stage.get(), debugPrintInfo);
_gctx->outStream() << std::endl;

View File

@ -649,7 +649,7 @@ public:
void setUp() override {
GoldenSbeStageBuilderTest::setUp();
_gctx->validateOnClose(true);
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
}
void tearDown() override {

View File

@ -180,7 +180,7 @@ void GoldenSbeStageBuilderTestFixture::runTest(std::unique_ptr<QuerySolutionNode
ASSERT_EQ(resultAccessors.size(), 1u);
// Print the stage explain output and verify.
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
sbe::DebugPrintInfo debugPrintInfo{};
auto explain = sbe::DebugPrinter().print(*stage.get(), debugPrintInfo);
_gctx->outStream() << (localColl ? replaceUuid(explain, localColl->getCollection().uuid())
@ -245,7 +245,7 @@ void GoldenSbeExprBuilderTestFixture::runTest(stage_builder::SbExpr sbExpr,
StringData test) {
auto sbeEExpr = sbExpr.lower(*_state);
// Print the stage explain output and verify.
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
_gctx->outStream() << test << std::endl;
_gctx->outStream() << sbe::DebugPrinter().print(sbeEExpr->debugPrint());
_gctx->outStream() << std::endl;

View File

@ -54,9 +54,6 @@
namespace mongo {
using namespace mongo::unittest;
using namespace mongo::unittest::match;
/**
* SbeStageBuilderTestFixture is a unittest fixture that can be used to facilitate testing the
* translation of a QuerySolution tree to an sbe PlanStage tree.
@ -143,7 +140,7 @@ extern unittest::GoldenTestConfig goldenTestConfigSbe;
class GoldenSbeStageBuilderTestFixture : public SbeStageBuilderTestFixture {
public:
GoldenSbeStageBuilderTestFixture()
: _gctx(std::make_unique<GoldenTestContext>(&goldenTestConfigSbe)) {
: _gctx(std::make_unique<unittest::GoldenTestContext>(&goldenTestConfigSbe)) {
_gctx->validateOnClose(false);
}
@ -157,7 +154,7 @@ protected:
const mongo::BSONArray& expectedValue,
BuildPlanStageParam param = {});
std::unique_ptr<GoldenTestContext> _gctx;
std::unique_ptr<unittest::GoldenTestContext> _gctx;
bool _collInitialized = false;
};

View File

@ -623,8 +623,7 @@ DEATH_TEST_F(ApplyOpsDeathTest, ApplyOpsRidOnNonRridCollection, "11454700") {
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
BSONObjBuilder resultBuilder;
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
}
DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateNoRidOnRridCollection, "11454701") {
@ -643,8 +642,7 @@ DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateNoRidOnRridCollection, "11454701") {
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
BSONObjBuilder resultBuilder;
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
}
DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateRidOnNonRridCollection, "11454701") {
@ -661,8 +659,7 @@ DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateRidOnNonRridCollection, "11454701") {
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
BSONObjBuilder resultBuilder;
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
}
} // namespace

View File

@ -1249,8 +1249,8 @@ DEATH_TEST_F(OplogApplierImplTestDeathTest, ApplyOpsRidOnNonRridCollectionGroupe
std::vector<ApplierOperation> ops = {ApplierOperation{&op1}, ApplierOperation{&op2}};
OplogEntryOrGroupedInserts groupedInserts(ops.begin(), ops.end());
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kApplyOpsCmd));
(void)_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kApplyOpsCmd);
}
DEATH_TEST_F(OplogApplierImplTestDeathTest, SteadyStateRidOnNonRridCollectionGrouped, "11454703") {
@ -1273,8 +1273,8 @@ DEATH_TEST_F(OplogApplierImplTestDeathTest, SteadyStateRidOnNonRridCollectionGro
std::vector<ApplierOperation> ops = {ApplierOperation{&op1}, ApplierOperation{&op2}};
OplogEntryOrGroupedInserts groupedInserts(ops.begin(), ops.end());
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary));
(void)_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary);
}
DEATH_TEST_F(OplogApplierImplTestDeathTest, SteadyStateNoRidOnRridCollectionGrouped, "11454703") {
@ -1299,8 +1299,8 @@ DEATH_TEST_F(OplogApplierImplTestDeathTest, SteadyStateNoRidOnRridCollectionGrou
std::vector<ApplierOperation> ops = {ApplierOperation{&op1}, ApplierOperation{&op2}};
OplogEntryOrGroupedInserts groupedInserts(ops.begin(), ops.end());
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary));
(void)_applyOplogEntryOrGroupedInsertsWrapper(
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary);
}
bool _testOplogEntryIsForCappedCollection(OperationContext* opCtx,

View File

@ -560,8 +560,7 @@ TEST_F(OplogEntryTest, OpTimeBaseNonStrictParsing) {
// OpTimeBase should be successfully created from an OplogEntry, even though it has
// extraneous fields.
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
OpTimeBase::parse(oplogEntryExtraField, IDLParserContext("OpTimeBase")));
(void)OpTimeBase::parse(oplogEntryExtraField, IDLParserContext("OpTimeBase"));
// OplogEntryBase should still use strict parsing and throw an error when it has extraneous
// fields.

View File

@ -77,7 +77,7 @@ void FailingOplogWriter::waitForScheduledWrites(OperationContext* opCtx) {};
* Tests for the parent class behavior for OplogWriter.
* Uses a default ThreadPoolExecutor.
*/
class OplogWriterTest : public ServiceContextMongoDTest {};
class OplogWriterTest : public executor::ThreadPoolExecutorTest {};
/**
@ -95,11 +95,7 @@ using OplogWriterTestDeathTest = OplogWriterTest;
DEATH_TEST_F(OplogWriterTestDeathTest,
ThrowingInRunLoopLogsUsefulError,
"OplogWriter threw a DBException") {
executor::ThreadPoolMock::Options threadPoolMockOptions;
executor::ThreadPoolExecutorTest executorFixture{threadPoolMockOptions};
executorFixture.setUp();
auto& executor = executorFixture.getExecutor();
auto& executor = getExecutor();
executor.startup();
OplogWriter::Options options(false /* skipWritesToOplogColl */);

View File

@ -115,7 +115,7 @@ public:
}
private:
void _doTest() override {};
void TestBody() override {}
void setUp() override {
ServiceContextMongoDTest::setUp();

View File

@ -221,7 +221,7 @@ public:
assertStartSuccess(configObj, HostAndPort("node1", 12345));
}
void _doTest() final {}
void TestBody() override {}
};
namespace {

View File

@ -1806,7 +1806,7 @@ TEST_F(StorageTimestampTest, SetMinValidAppliedThrough) {
*/
class KVDropDatabase : public StorageTimestampTest {
private:
void _doTest() override {
void TestBody() override {
// Not actually called.
}
@ -1928,12 +1928,7 @@ TEST(SimpleStorageTimestampTest, KVDropDatabasePrimary) {
* entry is processed. Secondaries will look at the logical clock when completing the index
* build. This is safe so long as completion is not racing with secondary oplog application.
*/
class TimestampIndexBuilds : public StorageTimestampTest {
private:
void _doTest() override {
// Not actually called.
}
class TimestampIndexBuilds : public StorageTimestampTest, public testing::WithParamInterface<bool> {
public:
void run(bool simulatePrimary) {
const bool simulateSecondary = !simulatePrimary;
@ -2071,17 +2066,10 @@ public:
}
}
};
INSTANTIATE_TEST_SUITE_P(, TimestampIndexBuilds, testing::Values(false, true));
TEST(SimpleStorageTimestampTest, TimestampIndexBuilds) {
{
TimestampIndexBuilds test;
test.run(false);
}
// Reconstruct the datafiles from scratch across tests.
{
TimestampIndexBuilds test;
test.run(true);
}
TEST_P(TimestampIndexBuilds, Build) {
run(GetParam());
}
TEST_F(StorageTimestampTest, TimestampMultiIndexBuilds) {

View File

@ -102,7 +102,8 @@ TEST(RangeDeletionRecoveryTracker, AddJobForCompletedTermDoesNothing) {
ASSERT_EQ(tracker.getTrackedTermsCount(), 0);
}
DEATH_TEST(RangeDeletionRecoveryTracker,
using RangeDeletionRecoveryTrackerDeathTest = RangeDeletionRecoveryTracker;
DEATH_TEST(RangeDeletionRecoveryTrackerDeathTest,
NotifyMoreJobsThanRegisteredAsserts,
"Tripwire assertion") {
RangeDeletionRecoveryTracker tracker;
@ -137,7 +138,7 @@ TEST(RangeDeletionRecoveryTracker, EndTermAfterAllJobsComplete) {
ASSERT_EQ(future.get(), RangeDeletionRecoveryTracker::Outcome::kComplete);
}
DEATH_TEST(RangeDeletionRecoveryTracker,
DEATH_TEST(RangeDeletionRecoveryTrackerDeathTest,
RegisterJobAfterRecoveryCompleteAsserts,
"Tripwire assertion") {
const auto term = 0;

View File

@ -1594,7 +1594,8 @@ TEST_F(TransactionCoordinatorTest,
executor::NetworkInterfaceMock::InNetworkGuard(network())->runReadyNetworkOperations();
}
DEATH_TEST_REGEX_F(TransactionCoordinatorTest,
using TransactionCoordinatorTestDeathTest = TransactionCoordinatorTest;
DEATH_TEST_REGEX_F(TransactionCoordinatorTestDeathTest,
CoordinatorTerminatedWithUnexpectedErrorAfterDurablyWritingDecision,
"Fatal assertion.*11353000") {
// Create the coordinator.

View File

@ -136,7 +136,7 @@ private:
/** A `unittest::Test` fixture being overloaded as a benchmark harness. */
class Test : public ServiceContextMongoDTest {
public:
void _doTest() override {}
void TestBody() override {}
void setUp() override {
ServiceContextMongoDTest::setUp();

View File

@ -106,17 +106,10 @@ public:
}
};
} // namespace
class AllCatalogTests : public unittest::OldStyleSuiteSpecification {
public:
AllCatalogTests() : unittest::OldStyleSuiteSpecification("CatalogTests") {}
template <typename T>
void add() {
addNameCallback(nameForTestClass<T>(), [] { T().run(); });
}
void setupTests() override {
add<ConcurrentCreateCollectionTest>();
}
@ -124,4 +117,5 @@ public:
unittest::OldStyleSuiteInitializer<AllCatalogTests> allCatalogTests;
} // namespace
} // namespace mongo

View File

@ -537,7 +537,8 @@ TEST_F(CollectionShardingRuntimeTest, ShardVersionCheckDetectsClusterTimeConflic
}
}
DEATH_TEST_REGEX_F(CollectionShardingRuntimeTest,
using CollectionShardingRuntimeTestDeathTest = CollectionShardingRuntimeTest;
DEATH_TEST_REGEX_F(CollectionShardingRuntimeTestDeathTest,
TestsShouldTassertIfPlacementConflictTimeIsNotPresentInTxns,
"Tripwire assertion.*10206300") {
CollectionShardingRuntime csr(getServiceContext(), kTestNss);

View File

@ -432,7 +432,9 @@ TEST_F(DatabaseShardingRuntimeTestWithMockedLoader,
}
}
DEATH_TEST_REGEX_F(DatabaseShardingRuntimeTestWithMockedLoader,
using DatabaseShardingRuntimeTestWithMockedLoaderDeathTest =
DatabaseShardingRuntimeTestWithMockedLoader;
DEATH_TEST_REGEX_F(DatabaseShardingRuntimeTestWithMockedLoaderDeathTest,
TestsShouldTassertIfPlacementConflictTimeIsNotPresentInTxns,
"Tripwire assertion.*9758701") {
const auto installedDbVersion = DatabaseVersion(UUID::gen(), Timestamp(10, 0));

View File

@ -404,7 +404,8 @@ TEST_F(ShardRemoteTest, TargeterMarksHostAsDownWhenConfigShuttingDown) {
ASSERT_EQ(1UL, configTargeter()->getAndClearMarkedDownHosts().size());
}
TEST_F(ShardRemoteTest, FindOnConfigRespectsDefaultConfigCommandTimeout) {
TEST_F(ShardRemoteTest, FindOnConfigFromShardRespectsDefaultConfigCommandTimeout) {
serverGlobalParams.clusterRole = ClusterRole::ShardServer;
// Set the timeout for config commands to 1 second.
auto timeoutMs = 1000;
RAIIServerParameterControllerForTest configCommandTimeout{"defaultConfigCommandTimeoutMS",

View File

@ -36,7 +36,7 @@
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
namespace mongo::key_string_test {
TEST_F(KeyStringBuilderTest, CommonIntPerf) {
TEST_P(KeyStringBuilderTest, CommonIntPerf) {
// Exponential distribution, so skewed towards smaller integers.
std::mt19937 gen(newSeed());
std::exponential_distribution<double> expReal(1e-3);
@ -48,7 +48,7 @@ TEST_F(KeyStringBuilderTest, CommonIntPerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, UniformInt64Perf) {
TEST_P(KeyStringBuilderTest, UniformInt64Perf) {
std::vector<BSONObj> numbers;
std::mt19937 gen(newSeed());
std::uniform_int_distribution<long long> uniformInt64(std::numeric_limits<long long>::min(),
@ -60,7 +60,7 @@ TEST_F(KeyStringBuilderTest, UniformInt64Perf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, CommonDoublePerf) {
TEST_P(KeyStringBuilderTest, CommonDoublePerf) {
std::mt19937 gen(newSeed());
std::exponential_distribution<double> expReal(1e-3);
@ -71,7 +71,7 @@ TEST_F(KeyStringBuilderTest, CommonDoublePerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, UniformDoublePerf) {
TEST_P(KeyStringBuilderTest, UniformDoublePerf) {
std::vector<BSONObj> numbers;
std::mt19937 gen(newSeed());
std::uniform_int_distribution<long long> uniformInt64(std::numeric_limits<long long>::min(),
@ -87,7 +87,7 @@ TEST_F(KeyStringBuilderTest, UniformDoublePerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, CommonDecimalPerf) {
TEST_P(KeyStringBuilderTest, CommonDecimalPerf) {
std::mt19937 gen(newSeed());
std::exponential_distribution<double> expReal(1e-3);
@ -104,7 +104,7 @@ TEST_F(KeyStringBuilderTest, CommonDecimalPerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, UniformDecimalPerf) {
TEST_P(KeyStringBuilderTest, UniformDecimalPerf) {
std::mt19937 gen(newSeed());
std::uniform_int_distribution<long long> uniformInt64(std::numeric_limits<long long>::min(),
std::numeric_limits<long long>::max());
@ -123,7 +123,7 @@ TEST_F(KeyStringBuilderTest, UniformDecimalPerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, DecimalFromUniformDoublePerf) {
TEST_P(KeyStringBuilderTest, DecimalFromUniformDoublePerf) {
std::vector<BSONObj> numbers;
std::mt19937 gen(newSeed());
std::uniform_int_distribution<long long> uniformInt64(std::numeric_limits<long long>::min(),
@ -150,7 +150,7 @@ TEST_F(KeyStringBuilderTest, DecimalFromUniformDoublePerf) {
perfTest(version, numbers);
}
TEST_F(KeyStringBuilderTest, AllPermCompare) {
TEST_P(KeyStringBuilderTest, AllPermCompare) {
std::vector<BSONObj> elements = getInterestingElements(version);
for (size_t i = 0; i < elements.size(); i++) {
@ -165,7 +165,7 @@ TEST_F(KeyStringBuilderTest, AllPermCompare) {
testPermutation(version, elements, orderings, false);
}
TEST_F(KeyStringBuilderTest, AllPerm2Compare) {
TEST_P(KeyStringBuilderTest, AllPerm2Compare) {
std::vector<BSONObj> baseElements = getInterestingElements(version);
auto seed = newSeed();
@ -207,7 +207,7 @@ TEST_F(KeyStringBuilderTest, AllPerm2Compare) {
testPermutation(version, elements, orderings, false);
}
TEST_F(KeyStringBuilderTest, LotsOfNumbers3) {
TEST_P(KeyStringBuilderTest, LotsOfNumbers3) {
std::vector<stdx::future<void>> futures;
for (double k = 0; k < 8; k++) {
@ -251,7 +251,7 @@ TEST_F(KeyStringBuilderTest, LotsOfNumbers3) {
}
}
TEST_F(KeyStringBuilderTest, NumberOrderLots) {
TEST_P(KeyStringBuilderTest, NumberOrderLots) {
std::vector<BSONObj> numbers;
{
numbers.push_back(BSON("" << 0));
@ -330,4 +330,8 @@ TEST_F(KeyStringBuilderTest, NumberOrderLots) {
}
}
}
INSTANTIATE_TEST_SUITE_P(KeyStringBuilderLongRunningTest,
KeyStringBuilderTest,
testing::Values(key_string::Version::V0, key_string::Version::V1));
} // namespace mongo::key_string_test

View File

@ -183,7 +183,7 @@ TEST(TypeBitsTest, AppendLotsOfZeroTypeBits) {
ASSERT(!typeBits.isLongEncoding());
}
TEST_F(KeyStringBuilderTest, TooManyElementsInCompoundKey) {
TEST_P(KeyStringBuilderTest, TooManyElementsInCompoundKey) {
// Construct a KeyString with more than the limit of 32 elements in a compound index key. Encode
// 33 kBoolTrue ('o') values.
// Note that this KeyString encoding is legal, but it may not be legally stored in an index.
@ -199,7 +199,7 @@ TEST_F(KeyStringBuilderTest, TooManyElementsInCompoundKey) {
ASSERT_EQ(size, key_string::getKeySize(ks.getView(), ALL_ASCENDING, ks.version));
}
TEST_F(KeyStringBuilderTest, MaxElementsInCompoundKey) {
TEST_P(KeyStringBuilderTest, MaxElementsInCompoundKey) {
// Construct a KeyString with 32 elements in a compound index key followed by an end byte.
// Encode 32 kBoolTrue ('o') values and an end byte, 0x4.
const char* data = "oooooooooooooooooooooooooooooooo\x4";
@ -214,7 +214,7 @@ TEST_F(KeyStringBuilderTest, MaxElementsInCompoundKey) {
ASSERT_EQ(size, key_string::getKeySize(ks.getView(), ALL_ASCENDING, ks.version));
}
TEST_F(KeyStringBuilderTest, SizeOfIncompleteKey) {
TEST_P(KeyStringBuilderTest, SizeOfIncompleteKey) {
// The key portion of a keystring is terminated with kEnd, so missing that means the key size is
// zero
const char* data = "oooo\x4";
@ -223,13 +223,13 @@ TEST_F(KeyStringBuilderTest, SizeOfIncompleteKey) {
ASSERT_EQ(0, key_string::getKeySize({data, size - 1}, ALL_ASCENDING, key_string::Version::V1));
}
TEST_F(KeyStringBuilderTest, SizeWithTrailingDataInBuffer) {
TEST_P(KeyStringBuilderTest, SizeWithTrailingDataInBuffer) {
// Verify that we actually stop counting key bytes when we reach kEnd
const char data[] = {'o', 'o', 4, 'a', 'b', 'c'};
ASSERT_EQ(3, key_string::getKeySize(data, ALL_ASCENDING, key_string::Version::V1));
}
TEST_F(KeyStringBuilderTest, EmbeddedkEnd) {
TEST_P(KeyStringBuilderTest, EmbeddedkEnd) {
// Construct a KeyString which contains kEnd inside a string key and verify that getKeySize()
// does not report that the size ends at that spot
key_string::Builder ks(version, ALL_ASCENDING);
@ -240,7 +240,7 @@ TEST_F(KeyStringBuilderTest, EmbeddedkEnd) {
ASSERT_EQ(key_string::getKeySize(buffer, ALL_ASCENDING, version), buffer.size());
}
TEST_F(KeyStringBuilderTest, EmbeddedNullString) {
TEST_P(KeyStringBuilderTest, EmbeddedNullString) {
// Construct a KeyString where \x3c defines the type kStringLike then embedded with null
// characters and followed by \x00.
const char data[4] = {0x3c, 0, char(0xFF), 0};
@ -251,7 +251,7 @@ TEST_F(KeyStringBuilderTest, EmbeddedNullString) {
BSON("" << StringData("\x00", 1)));
};
TEST_F(KeyStringBuilderTest, ExceededBSONDepth) {
TEST_P(KeyStringBuilderTest, ExceededBSONDepth) {
// Construct an illegal KeyString encoding with excessively nested BSON arrays '80' (P).
const auto nestedArr = std::string(BSONDepth::getMaxAllowableDepth() + 1, 'P');
ASSERT_THROWS_CODE(
@ -277,7 +277,7 @@ TEST_F(KeyStringBuilderTest, ExceededBSONDepth) {
ErrorCodes::Overflow);
}
TEST_F(KeyStringBuilderTest, Simple1) {
TEST_P(KeyStringBuilderTest, Simple1) {
BSONObj a = BSON("" << 5);
BSONObj b = BSON("" << 6);
@ -287,11 +287,11 @@ TEST_F(KeyStringBuilderTest, Simple1) {
key_string::Builder(version, b, ALL_ASCENDING, RecordId(1)));
}
TEST_F(KeyStringBuilderTest, DeprecatedBinData) {
TEST_P(KeyStringBuilderTest, DeprecatedBinData) {
ROUNDTRIP(version, BSON("" << BSONBinData(nullptr, 0, ByteArrayDeprecated)));
}
TEST_F(KeyStringBuilderTest, ValidColumn) {
TEST_P(KeyStringBuilderTest, ValidColumn) {
BSONColumnBuilder cb;
cb.append(BSON("a" << "deadbeef").getField("a"));
cb.append(BSON("a" << 1).getField("a"));
@ -303,7 +303,7 @@ TEST_F(KeyStringBuilderTest, ValidColumn) {
ROUNDTRIP(version, objData);
}
TEST_F(KeyStringBuilderTest, InvalidColumn) {
TEST_P(KeyStringBuilderTest, InvalidColumn) {
const BSONObj objData = BSON("" << BSONBinData("foobar", 6, Column));
const key_string::Builder builder(version, objData, ALL_ASCENDING);
@ -313,7 +313,7 @@ TEST_F(KeyStringBuilderTest, InvalidColumn) {
50833);
}
TEST_F(KeyStringBuilderTest, ActualBytesDouble) {
TEST_P(KeyStringBuilderTest, ActualBytesDouble) {
// just one test like this for utter sanity
BSONObj a = BSON("" << 5.5);
@ -355,7 +355,7 @@ TEST_F(KeyStringBuilderTest, ActualBytesDouble) {
ASSERT_EQUALS(hexFlipped, ks.toString());
}
TEST_F(KeyStringBuilderTest, AllTypesSimple) {
TEST_P(KeyStringBuilderTest, AllTypesSimple) {
ROUNDTRIP(version, BSON("" << 5.5));
ROUNDTRIP(version, BSON("" << "abc"));
ROUNDTRIP(version, BSON("" << BSON("a" << 5)));
@ -375,7 +375,7 @@ TEST_F(KeyStringBuilderTest, AllTypesSimple) {
ROUNDTRIP(version, BSON("" << 1235123123123LL));
}
TEST_F(KeyStringBuilderTest, Array1) {
TEST_P(KeyStringBuilderTest, Array1) {
BSONObj emptyArray = BSON("" << BSONArray());
ASSERT_EQUALS(BSONType::array, emptyArray.firstElement().type());
@ -399,7 +399,7 @@ TEST_F(KeyStringBuilderTest, Array1) {
}
}
TEST_F(KeyStringBuilderTest, SubDoc1) {
TEST_P(KeyStringBuilderTest, SubDoc1) {
ROUNDTRIP(version, BSON("" << BSON("foo" << 2)));
ROUNDTRIP(version,
BSON("" << BSON("foo" << 2 << "bar"
@ -407,7 +407,7 @@ TEST_F(KeyStringBuilderTest, SubDoc1) {
ROUNDTRIP(version, BSON("" << BSON("foo" << BSON_ARRAY(2 << 4))));
}
TEST_F(KeyStringBuilderTest, SubDoc2) {
TEST_P(KeyStringBuilderTest, SubDoc2) {
BSONObj a = BSON("" << BSON("a" << "foo"));
BSONObj b = BSON("" << BSON("b" << 5.5));
BSONObj c = BSON("" << BSON("c" << BSON("x" << 5)));
@ -421,23 +421,23 @@ TEST_F(KeyStringBuilderTest, SubDoc2) {
}
TEST_F(KeyStringBuilderTest, Compound1) {
TEST_P(KeyStringBuilderTest, Compound1) {
ROUNDTRIP(version, BSON("" << BSON("a" << 5) << "" << 1));
ROUNDTRIP(version, BSON("" << BSON("" << 5) << "" << 1));
}
TEST_F(KeyStringBuilderTest, Undef1) {
TEST_P(KeyStringBuilderTest, Undef1) {
ROUNDTRIP(version, BSON("" << BSONUndefined));
}
TEST_F(KeyStringBuilderTest, NumberLong0) {
TEST_P(KeyStringBuilderTest, NumberLong0) {
double d = (1ll << 52) - 1;
long long ll = static_cast<long long>(d);
double d2 = static_cast<double>(ll);
ASSERT_EQUALS(d, d2);
}
TEST_F(KeyStringBuilderTest, NumbersNearInt32Max) {
TEST_P(KeyStringBuilderTest, NumbersNearInt32Max) {
int64_t start = std::numeric_limits<int32_t>::max();
for (int64_t i = -1000; i < 1000; i++) {
long long toTest = start + i;
@ -447,7 +447,7 @@ TEST_F(KeyStringBuilderTest, NumbersNearInt32Max) {
}
}
TEST_F(KeyStringBuilderTest, DecimalNumbers) {
TEST_P(KeyStringBuilderTest, DecimalNumbers) {
if (version == key_string::Version::V0) {
LOGV2(22228, "not testing DecimalNumbers for KeyStringBuilder V0");
return;
@ -519,7 +519,7 @@ TEST_F(KeyStringBuilderTest, DecimalNumbers) {
ROUNDTRIP(V1, BSON("" << BSONNULL << "" << BSON("a" << Decimal128::kPositiveInfinity)));
}
TEST_F(KeyStringBuilderTest, KeyStringValue) {
TEST_P(KeyStringBuilderTest, KeyStringValue) {
// Test that KeyStringBuilder is releasable into a Value type that is comparable. Once
// released, it is reusable once reset.
key_string::HeapBuilder ks1(key_string::Version::V1, BSON("" << 1), ALL_ASCENDING);
@ -541,7 +541,7 @@ TEST_F(KeyStringBuilderTest, KeyStringValue) {
ASSERT_EQ(data2.compare(dataCopy), 0);
}
TEST_F(KeyStringBuilderTest, KeyStringValueReleaseReusableTest) {
TEST_P(KeyStringBuilderTest, KeyStringValueReleaseReusableTest) {
// Test that KeyStringBuilder is reusable once reset.
BSONObj doc1 = BSON("fieldA" << 1 << "fieldB" << 2);
BSONObj doc2 = BSON("fieldA" << 2 << "fieldB" << 3);
@ -560,7 +560,7 @@ TEST_F(KeyStringBuilderTest, KeyStringValueReleaseReusableTest) {
COMPARE_KS_BSON(data2, bson2, ALL_ASCENDING);
}
TEST_F(KeyStringBuilderTest, KeyStringGetValueCopyTest) {
TEST_P(KeyStringBuilderTest, KeyStringGetValueCopyTest) {
// Test that KeyStringGetValueCopyTest creates a copy.
BSONObj doc = BSON("fieldA" << 1);
key_string::HeapBuilder ks(key_string::Version::V1, ALL_ASCENDING);
@ -575,7 +575,7 @@ TEST_F(KeyStringBuilderTest, KeyStringGetValueCopyTest) {
COMPARE_KS_BSON(data2, BSON("" << 1), ALL_ASCENDING);
}
TEST_F(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
TEST_P(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
// Test that appendBsonElement works.
{
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
@ -611,7 +611,7 @@ TEST_F(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
}
}
TEST_F(KeyStringBuilderTest, KeyStringBuilderOrdering) {
TEST_P(KeyStringBuilderTest, KeyStringBuilderOrdering) {
// Test that ordering works.
BSONObj doc = BSON("fieldA" << 1);
key_string::HeapBuilder ks1(key_string::Version::V1, ALL_ASCENDING);
@ -627,7 +627,7 @@ TEST_F(KeyStringBuilderTest, KeyStringBuilderOrdering) {
ASSERT_FALSE(std::ranges::equal(data1.getView(), data2.getView()));
}
TEST_F(KeyStringBuilderTest, KeyStringBuilderExclusiveBeforeDiscriminator) {
TEST_P(KeyStringBuilderTest, KeyStringBuilderExclusiveBeforeDiscriminator) {
// test that when passed in a Discriminator it gets added.
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
key_string::HeapBuilder ks(
@ -639,7 +639,7 @@ TEST_F(KeyStringBuilderTest, KeyStringBuilderExclusiveBeforeDiscriminator) {
ASSERT_EQ(1, appendedDiscriminator);
}
TEST_F(KeyStringBuilderTest, KeyStringBuilderExclusiveAfterDiscriminator) {
TEST_P(KeyStringBuilderTest, KeyStringBuilderExclusiveAfterDiscriminator) {
// test that when passed in a Discriminator it gets added.
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
key_string::HeapBuilder ks(
@ -651,7 +651,7 @@ TEST_F(KeyStringBuilderTest, KeyStringBuilderExclusiveAfterDiscriminator) {
ASSERT_EQ(254, appendedDiscriminator);
}
TEST_F(KeyStringBuilderTest, KeyStringBuilderInclusiveDiscriminator) {
TEST_P(KeyStringBuilderTest, KeyStringBuilderInclusiveDiscriminator) {
// test that when passed in a Discriminator it gets added.
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
key_string::HeapBuilder ks(
@ -663,7 +663,7 @@ TEST_F(KeyStringBuilderTest, KeyStringBuilderInclusiveDiscriminator) {
ASSERT_EQ(4, appendedDiscriminator);
}
TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
key_string::HeapBuilder ks1(
@ -681,7 +681,7 @@ TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
ASSERT_EQ(data1.compareWithoutDiscriminator(data2), 0);
}
TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
key_string::HeapBuilder ks1(
@ -699,7 +699,7 @@ TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
ASSERT(data1.compareWithoutDiscriminator(data2) > 0);
}
TEST_F(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
TEST_P(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
// Test that an illegally encoded double throws an error.
const char data[8] = {
// kNumericPositive7ByteInt
@ -724,7 +724,7 @@ TEST_F(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
31209);
}
TEST_F(KeyStringBuilderTest, InvalidInfinityDecimalV0) {
TEST_P(KeyStringBuilderTest, InvalidInfinityDecimalV0) {
// Encode a Decimal positive infinity in a V1 keystring.
mongo::key_string::Builder ks(
mongo::key_string::Version::V1, BSON("" << Decimal128::kPositiveInfinity), ALL_ASCENDING);
@ -739,7 +739,7 @@ TEST_F(KeyStringBuilderTest, InvalidInfinityDecimalV0) {
mongo::key_string::toBsonSafe(ks.getView(), ALL_ASCENDING, tb), AssertionException, 31231);
}
TEST_F(KeyStringBuilderTest, CannotEncodeDecimalInV0) {
TEST_P(KeyStringBuilderTest, CannotEncodeDecimalInV0) {
// Try encode a Decimal by passing it as a part of BSON
ASSERT_THROWS_CODE(mongo::key_string::Builder(mongo::key_string::Version::V0,
BSON("d" << Decimal128::kPi),
@ -754,7 +754,7 @@ TEST_F(KeyStringBuilderTest, CannotEncodeDecimalInV0) {
ErrorCodes::UnsupportedFormat);
}
TEST_F(KeyStringBuilderTest, ReasonableSize) {
TEST_P(KeyStringBuilderTest, ReasonableSize) {
// Tests that key_string::Builders do not use an excessive amount of memory for small key
// generation. These upper bounds were the calculated sizes of each type at the time this
// test was written.
@ -798,7 +798,7 @@ TEST_F(KeyStringBuilderTest, ReasonableSize) {
ASSERT_LTE(fragmentBuilder.memUsage(), 64);
}
TEST_F(KeyStringBuilderTest, DiscardIfNotReleased) {
TEST_P(KeyStringBuilderTest, DiscardIfNotReleased) {
SharedBufferFragmentBuilder fragmentBuilder(1024);
{
// Intentially not released, but the data should be discarded correctly.
@ -812,7 +812,7 @@ TEST_F(KeyStringBuilderTest, DiscardIfNotReleased) {
}
}
TEST_F(KeyStringBuilderTest, LotsOfNumbers1) {
TEST_P(KeyStringBuilderTest, LotsOfNumbers1) {
for (int i = 0; i < 64; i++) {
int64_t x = 1LL << i;
ROUNDTRIP(version, BSON("" << static_cast<long long>(x)));
@ -842,7 +842,7 @@ TEST_F(KeyStringBuilderTest, LotsOfNumbers1) {
}
}
TEST_F(KeyStringBuilderTest, LotsOfNumbers2) {
TEST_P(KeyStringBuilderTest, LotsOfNumbers2) {
for (double i = -1100; i < 1100; i++) {
double x = pow(2, i);
ROUNDTRIP(version, BSON("" << x));
@ -853,7 +853,7 @@ TEST_F(KeyStringBuilderTest, LotsOfNumbers2) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdOrder1) {
TEST_P(KeyStringBuilderTest, RecordIdOrder1) {
Ordering ordering = Ordering::make(BSON("a" << 1));
key_string::Builder a(version, BSON("" << 5), ordering, RecordId::minLong());
@ -868,7 +868,7 @@ TEST_F(KeyStringBuilderTest, RecordIdOrder1) {
ASSERT_LESS_THAN(e, d);
}
TEST_F(KeyStringBuilderTest, RecordIdOrder2) {
TEST_P(KeyStringBuilderTest, RecordIdOrder2) {
Ordering ordering = Ordering::make(BSON("a" << -1 << "b" << -1));
key_string::Builder a(version, BSON("" << 5 << "" << 6), ordering, RecordId::minLong());
@ -884,7 +884,7 @@ TEST_F(KeyStringBuilderTest, RecordIdOrder2) {
ASSERT_LESS_THAN(b, d);
}
TEST_F(KeyStringBuilderTest, RecordIdOrder2Double) {
TEST_P(KeyStringBuilderTest, RecordIdOrder2Double) {
Ordering ordering = Ordering::make(BSON("a" << -1 << "b" << -1));
key_string::Builder a(version, BSON("" << 5.0 << "" << 6.0), ordering, RecordId::minLong());
@ -896,7 +896,7 @@ TEST_F(KeyStringBuilderTest, RecordIdOrder2Double) {
ASSERT_LESS_THAN(a, c);
}
TEST_F(KeyStringBuilderTest, Timestamp) {
TEST_P(KeyStringBuilderTest, Timestamp) {
BSONObj a = BSON("" << Timestamp(0, 0));
BSONObj b = BSON("" << Timestamp(1234, 1));
BSONObj c = BSON("" << Timestamp(1234, 2));
@ -946,7 +946,7 @@ TEST_F(KeyStringBuilderTest, Timestamp) {
}
}
TEST_F(KeyStringBuilderTest, AllTypesRoundtrip) {
TEST_P(KeyStringBuilderTest, AllTypesRoundtrip) {
for (int i = 1; i <= stdx::to_underlying(BSONType::jsTypeMax); i++) {
{
BSONObjBuilder b;
@ -963,7 +963,7 @@ TEST_F(KeyStringBuilderTest, AllTypesRoundtrip) {
}
}
TEST_F(KeyStringBuilderTest, SerializeDeserialize) {
TEST_P(KeyStringBuilderTest, SerializeDeserialize) {
BSONObj doc = BSON("a" << 1 << "b" << 2.0);
// Round trip through serialize and deserialize
{
@ -1001,7 +1001,7 @@ TEST_F(KeyStringBuilderTest, SerializeDeserialize) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStr) {
TEST_P(KeyStringBuilderTest, RecordIdStr) {
const int kSize = 12;
for (int i = 0; i < kSize; i++) {
unsigned char buf[kSize];
@ -1056,7 +1056,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStr) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
TEST_P(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
{
const int size = 90;
@ -1079,7 +1079,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStrBig2SizeSegments) {
TEST_P(KeyStringBuilderTest, RecordIdStrBig2SizeSegments) {
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
{
// Min 2-byte encoded string size is 128B: 1B CType + ridStr + string terminator
@ -1112,7 +1112,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStrBig2SizeSegments) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStrBig3SizeSegments) {
TEST_P(KeyStringBuilderTest, RecordIdStrBig3SizeSegments) {
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
{
// Min 3-byte encoded string size is 16384B: 1B CType + ridStr + string terminator
@ -1136,7 +1136,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStrBig3SizeSegments) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStrBig4SizeSegments) {
TEST_P(KeyStringBuilderTest, RecordIdStrBig4SizeSegments) {
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
{
// Min 4-byte encoded string size is 2097152B: 1B CType + ridStr + string terminator
@ -1160,7 +1160,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStrBig4SizeSegments) {
}
}
TEST_F(KeyStringBuilderTest, RecordIdStrBigSizeWithoutRecordIdStr) {
TEST_P(KeyStringBuilderTest, RecordIdStrBigSizeWithoutRecordIdStr) {
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
const char str[] = "keyval";
const int padStr = 3; // kStringLike CType + string terminator + discriminator
@ -1190,7 +1190,7 @@ TEST_F(KeyStringBuilderTest, RecordIdStrBigSizeWithoutRecordIdStr) {
}
TEST_F(KeyStringBuilderTest, NaNs) {
TEST_P(KeyStringBuilderTest, NaNs) {
// TODO use hex floats to force distinct NaNs
const double nan1 = std::numeric_limits<double>::quiet_NaN();
const double nan2 = std::numeric_limits<double>::signaling_NaN();
@ -1234,7 +1234,7 @@ TEST_F(KeyStringBuilderTest, NaNs) {
ASSERT(toBson(ks4d, ONE_DESCENDING)[""].Decimal().isNaN());
}
TEST_F(KeyStringBuilderTest, RecordIds) {
TEST_P(KeyStringBuilderTest, RecordIds) {
for (int i = 0; i < 63; i++) {
const RecordId rid = RecordId(1ll << i);
@ -1303,7 +1303,7 @@ TEST_F(KeyStringBuilderTest, RecordIds) {
}
}
TEST_F(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
TEST_P(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
BSONObj obj;
{
BSONObjBuilder builder;
@ -1320,7 +1320,7 @@ TEST_F(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
ROUNDTRIP(version, obj);
}
TEST_F(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
TEST_P(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
checkKeyWithNByteOfTypeBits(version, 0, false);
checkKeyWithNByteOfTypeBits(version, 1, false);
checkKeyWithNByteOfTypeBits(version, 1, true);
@ -1332,12 +1332,12 @@ TEST_F(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
checkKeyWithNByteOfTypeBits(version, 129, true);
}
TEST_F(KeyStringBuilderTest, VeryLargeString) {
TEST_P(KeyStringBuilderTest, VeryLargeString) {
BSONObj obj = BSON("" << std::string(123456, 'x'));
ROUNDTRIP(version, obj);
}
TEST_F(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
TEST_P(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
key_string::TypeBits typeBits(key_string::Version::V1);
const char invalidString[] = {
@ -1363,7 +1363,7 @@ TEST_F(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
key_string::toBsonSafe(invalidNumber, ALL_ASCENDING, typeBits), AssertionException, 50810);
}
TEST_F(KeyStringBuilderTest, InvalidDecimalExponent) {
TEST_P(KeyStringBuilderTest, InvalidDecimalExponent) {
const Decimal128 dec("1125899906842624.1");
const key_string::Builder ks(key_string::Version::V1, BSON("" << dec), ALL_ASCENDING);
@ -1377,7 +1377,7 @@ TEST_F(KeyStringBuilderTest, InvalidDecimalExponent) {
50814);
}
TEST_F(KeyStringBuilderTest, InvalidDecimalZero) {
TEST_P(KeyStringBuilderTest, InvalidDecimalZero) {
const key_string::Builder ks(
key_string::Version::V1, BSON("" << Decimal128("-0")), ALL_ASCENDING);
@ -1389,7 +1389,7 @@ TEST_F(KeyStringBuilderTest, InvalidDecimalZero) {
50846);
}
TEST_F(KeyStringBuilderTest, InvalidDecimalContinuation) {
TEST_P(KeyStringBuilderTest, InvalidDecimalContinuation) {
auto elem = Decimal128("1.797693134862315708145274237317043E308");
const key_string::Builder ks(key_string::Version::V1, BSON("" << elem), ALL_ASCENDING);
@ -1408,7 +1408,7 @@ TEST_F(KeyStringBuilderTest, InvalidDecimalContinuation) {
50850);
}
TEST_F(KeyStringBuilderTest, RandomizedInputsForToBsonSafe) {
TEST_P(KeyStringBuilderTest, RandomizedInputsForToBsonSafe) {
std::mt19937 gen(newSeed());
std::uniform_int_distribution<unsigned int> randomNum(std::numeric_limits<unsigned int>::min(),
std::numeric_limits<unsigned int>::max());
@ -1458,6 +1458,10 @@ TEST_F(KeyStringBuilderTest, RandomizedInputsForToBsonSafe) {
}
}
INSTANTIATE_TEST_SUITE_P(KeyStringBuilderTest,
KeyStringBuilderTest,
testing::Values(key_string::Version::V0, key_string::Version::V1));
DEATH_TEST(KeyStringBuilderDeathTest,
ToBsonPromotesAssertionsToTerminate,
"KeyString format error: Failed to find null terminator in string.") {

View File

@ -53,22 +53,6 @@ unsigned newSeed() {
return seed;
}
void KeyStringBuilderTest::run() {
try {
version = key_string::Version::V0;
unittest::Test::run();
version = key_string::Version::V1;
unittest::Test::run();
} catch (...) {
LOGV2(22226,
"exception while testing KeyStringBuilder version "
"{mongo_KeyString_keyStringVersionToString_version}",
"mongo_KeyString_keyStringVersionToString_version"_attr =
key_string::keyStringVersionToString(version));
throw;
}
}
BSONObj toBson(const key_string::Builder& ks, Ordering ord) {
return key_string::toBson(ks.getView(), ord, ks.getTypeBits());
}

View File

@ -35,9 +35,11 @@
namespace MONGO_MOD_PRIVATE mongo {
namespace key_string_test {
class KeyStringBuilderTest : public unittest::Test {
class KeyStringBuilderTest : public testing::TestWithParam<key_string::Version> {
public:
void run();
void SetUp() override {
version = GetParam();
}
protected:
key_string::Version version;

View File

@ -276,6 +276,7 @@ DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, AbortMustBeInUnitOfWork, "invaria
DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, CannotHaveUnfinishedUnitOfWorkOnExit, "invariant") {
ru->beginUnitOfWork(opCtx->readOnly());
opCtx.reset();
}
DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, PrepareMustBeInUnitOfWork, "invariant") {

View File

@ -167,7 +167,16 @@ private:
class WiredTigerKVEngineTest : public ServiceContextTest {
public:
WiredTigerKVEngineTest(bool repair = false, bool preciseCheckpoints = false)
: _helper(getServiceContext(), repair, preciseCheckpoints) {}
: _repair(repair), _preciseCheckpoints(preciseCheckpoints) {}
void setUp() override {
_helper = std::make_unique<WiredTigerKVHarnessHelper>(
getServiceContext(), _repair, _preciseCheckpoints);
}
void tearDown() override {
_helper.reset();
}
protected:
using ClientAndCtx =
@ -176,7 +185,7 @@ protected:
ServiceContext::UniqueOperationContext _makeOperationContext() {
auto opCtx = makeOperationContext();
shard_role_details::setRecoveryUnit(opCtx.get(),
_helper.getEngine()->newRecoveryUnit(),
_helper->getEngine()->newRecoveryUnit(),
WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
return opCtx;
}
@ -185,14 +194,16 @@ protected:
auto* sc = getServiceContext();
auto client = sc->getService()->makeClient(clientName);
auto opCtx = client->makeOperationContext();
_helper.getEngine()->newRecoveryUnit();
_helper->getEngine()->newRecoveryUnit();
shard_role_details::setRecoveryUnit(opCtx.get(),
_helper.getEngine()->newRecoveryUnit(),
_helper->getEngine()->newRecoveryUnit(),
WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
return std::make_pair(std::move(client), std::move(opCtx));
}
WiredTigerKVHarnessHelper _helper;
bool _repair;
bool _preciseCheckpoints;
std::unique_ptr<WiredTigerKVHarnessHelper> _helper;
};
class WiredTigerKVEngineRepairTest : public WiredTigerKVEngineTest {
@ -209,8 +220,8 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
auto& provider = rss::ReplicatedStorageService::get(opCtxPtr.get()).getPersistenceProvider();
auto& ru = *shard_role_details::getRecoveryUnit(opCtxPtr.get());
ASSERT_OK(
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
auto rs = _helper.getWiredTigerKVEngine()->getRecordStore(
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
auto rs = _helper->getWiredTigerKVEngine()->getRecordStore(
opCtxPtr.get(), nss, ident, options, UUID::gen());
ASSERT(rs);
@ -230,7 +241,7 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
}
const boost::optional<boost::filesystem::path> dataFilePath =
_helper.getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
_helper->getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
ASSERT(dataFilePath);
ASSERT(boost::filesystem::exists(*dataFilePath));
@ -240,12 +251,12 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
#ifdef _WIN32
auto status =
_helper.getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
ASSERT_EQ(ErrorCodes::CommandNotSupported, status.code());
#else
// Dropping a collection might fail if we haven't checkpointed the data.
_helper.getWiredTigerKVEngine()->checkpoint();
_helper->getWiredTigerKVEngine()->checkpoint();
// Move the data file out of the way so the ident can be dropped. This not permitted on Windows
// because the file cannot be moved while it is open. The implementation for orphan recovery is
@ -254,7 +265,7 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
boost::filesystem::rename(*dataFilePath, tmpFile, err);
ASSERT(!err) << err.message();
ASSERT_OK(_helper.getWiredTigerKVEngine()->dropIdent(
ASSERT_OK(_helper->getWiredTigerKVEngine()->dropIdent(
*shard_role_details::getRecoveryUnit(opCtxPtr.get()), ident, /*identHasSizeInfo=*/true));
// The data file is moved back in place so that it becomes an "orphan" of the storage
@ -263,7 +274,7 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
ASSERT(!err) << err.message();
auto status =
_helper.getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
ASSERT_EQ(ErrorCodes::DataModifiedByRepair, status.code());
#endif
}
@ -277,11 +288,11 @@ TEST_F(WiredTigerKVEngineRepairTest, UnrecoverableOrphanedDataFilesAreRebuilt) {
auto& provider = rss::ReplicatedStorageService::get(opCtxPtr.get()).getPersistenceProvider();
auto& ru = *shard_role_details::getRecoveryUnit(opCtxPtr.get());
ASSERT_OK(
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
UUID uuid = UUID::gen();
auto rs =
_helper.getWiredTigerKVEngine()->getRecordStore(opCtxPtr.get(), nss, ident, options, uuid);
_helper->getWiredTigerKVEngine()->getRecordStore(opCtxPtr.get(), nss, ident, options, uuid);
ASSERT(rs);
RecordId loc;
@ -300,20 +311,20 @@ TEST_F(WiredTigerKVEngineRepairTest, UnrecoverableOrphanedDataFilesAreRebuilt) {
}
const boost::optional<boost::filesystem::path> dataFilePath =
_helper.getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
_helper->getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
ASSERT(dataFilePath);
ASSERT(boost::filesystem::exists(*dataFilePath));
// Dropping a collection might fail if we haven't checkpointed the data
_helper.getWiredTigerKVEngine()->checkpoint();
_helper->getWiredTigerKVEngine()->checkpoint();
ASSERT_OK(_helper.getWiredTigerKVEngine()->dropIdent(
ASSERT_OK(_helper->getWiredTigerKVEngine()->dropIdent(
*shard_role_details::getRecoveryUnit(opCtxPtr.get()), ident, /*identHasSizeInfo=*/true));
#ifdef _WIN32
auto status =
_helper.getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
ASSERT_EQ(ErrorCodes::CommandNotSupported, status.code());
#else
// The ident may not get immediately dropped, so ensure it is completely gone.
@ -332,13 +343,14 @@ TEST_F(WiredTigerKVEngineRepairTest, UnrecoverableOrphanedDataFilesAreRebuilt) {
// This should recreate an empty data file successfully and move the old one to a name that ends
// in ".corrupt".
auto status =
_helper.getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->recoverOrphanedIdent(provider, ru, nss, ident, options);
ASSERT_EQ(ErrorCodes::DataModifiedByRepair, status.code()) << status.reason();
boost::filesystem::path corruptFile = (dataFilePath->string() + ".corrupt");
ASSERT(boost::filesystem::exists(corruptFile));
rs = _helper.getWiredTigerKVEngine()->getRecordStore(opCtxPtr.get(), nss, ident, options, uuid);
rs =
_helper->getWiredTigerKVEngine()->getRecordStore(opCtxPtr.get(), nss, ident, options, uuid);
RecordData data;
ASSERT_FALSE(rs->findRecord(
opCtxPtr.get(), *shard_role_details::getRecoveryUnit(opCtxPtr.get()), loc, &data));
@ -366,7 +378,7 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
// The initial data timestamp has to be set to take stable checkpoints. The first stable
// timestamp greater than this will also trigger a checkpoint. The following loop of the
// CheckpointThread will observe the new `syncdelay` value.
_helper.getWiredTigerKVEngine()->setInitialDataTimestamp(Timestamp(1, 1));
_helper->getWiredTigerKVEngine()->setInitialDataTimestamp(Timestamp(1, 1));
// Simulate the callback that queries config.transactions for the oldest active transaction.
boost::optional<Timestamp> oldestActiveTxnTimestamp;
@ -380,7 +392,7 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
return ResultType(oldestActiveTxnTimestamp);
};
_helper.getWiredTigerKVEngine()->setOldestActiveTransactionTimestampCallback(callback);
_helper->getWiredTigerKVEngine()->setOldestActiveTransactionTimestampCallback(callback);
// A method that will poll the WiredTigerKVEngine until it sees the amount of oplog necessary
// for crash recovery exceeds the input.
@ -388,7 +400,7 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
// If the current oplog needed for rollback does not exceed the requested pinned out, we
// cannot expect the CheckpointThread to eventually publish a sufficient crash recovery
// value.
auto needed = _helper.getWiredTigerKVEngine()->getOplogNeededForRollback();
auto needed = _helper->getWiredTigerKVEngine()->getOplogNeededForRollback();
if (needed.isOK()) {
ASSERT_TRUE(needed.getValue() >= newPinned);
}
@ -396,9 +408,9 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
// Do 100 iterations that sleep for 100 milliseconds between polls. This will wait for up
// to 10 seconds to observe an asynchronous update that iterates once per second.
for (auto iterations = 0; iterations < 100; ++iterations) {
if (_helper.getWiredTigerKVEngine()->getPinnedOplog() >= newPinned) {
if (_helper->getWiredTigerKVEngine()->getPinnedOplog() >= newPinned) {
ASSERT_TRUE(
_helper.getWiredTigerKVEngine()->getOplogNeededForCrashRecovery().value() >=
_helper->getWiredTigerKVEngine()->getOplogNeededForCrashRecovery().value() >=
newPinned);
return;
}
@ -410,34 +422,34 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
"Expected the pinned oplog to advance.",
"expectedValue"_attr = newPinned,
"publishedValue"_attr =
_helper.getWiredTigerKVEngine()->getOplogNeededForCrashRecovery());
_helper->getWiredTigerKVEngine()->getOplogNeededForCrashRecovery());
FAIL("");
};
oldestActiveTxnTimestamp = boost::none;
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(10, 1), false);
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(10, 1), false);
assertPinnedMovesSoon(Timestamp(10, 1));
oldestActiveTxnTimestamp = Timestamp(15, 1);
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(20, 1), false);
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(20, 1), false);
assertPinnedMovesSoon(Timestamp(15, 1));
oldestActiveTxnTimestamp = Timestamp(19, 1);
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
assertPinnedMovesSoon(Timestamp(19, 1));
oldestActiveTxnTimestamp = boost::none;
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
assertPinnedMovesSoon(Timestamp(30, 1));
callbackShouldFail.store(true);
ASSERT_NOT_OK(_helper.getWiredTigerKVEngine()->getOplogNeededForRollback());
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(40, 1), false);
ASSERT_NOT_OK(_helper->getWiredTigerKVEngine()->getOplogNeededForRollback());
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(40, 1), false);
// Await a new checkpoint. Oplog needed for rollback does not advance.
sleepmillis(1100);
ASSERT_EQ(_helper.getWiredTigerKVEngine()->getOplogNeededForCrashRecovery().value(),
ASSERT_EQ(_helper->getWiredTigerKVEngine()->getOplogNeededForCrashRecovery().value(),
Timestamp(30, 1));
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(30, 1), false);
callbackShouldFail.store(false);
assertPinnedMovesSoon(Timestamp(40, 1));
}
@ -451,7 +463,7 @@ TEST_F(WiredTigerKVEngineTest, CreateRecordStoreFailsWithExistingIdent) {
auto& provider = rss::ReplicatedStorageService::get(opCtxPtr.get()).getPersistenceProvider();
auto& ru = *shard_role_details::getRecoveryUnit(opCtxPtr.get());
ASSERT_OK(
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
// A new record store must always have its own storage table uniquely identified by the ident.
// Otherwise, multiple record stores could point to the same storage resource and lead to data
@ -461,7 +473,7 @@ TEST_F(WiredTigerKVEngineTest, CreateRecordStoreFailsWithExistingIdent) {
// use.
const auto status =
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options);
ASSERT_NOT_OK(status);
ASSERT_EQ(status.code(), ErrorCodes::ObjectAlreadyExists);
}
@ -481,27 +493,27 @@ TEST_F(WiredTigerKVEngineTest, IdentDrop) {
auto& provider = rss::ReplicatedStorageService::get(opCtxPtr.get()).getPersistenceProvider();
auto& ru = *shard_role_details::getRecoveryUnit(opCtxPtr.get());
ASSERT_OK(
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
const boost::optional<boost::filesystem::path> dataFilePath =
_helper.getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
_helper->getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
ASSERT(dataFilePath);
ASSERT(boost::filesystem::exists(*dataFilePath));
_helper.getWiredTigerKVEngine()->dropIdentForImport(
_helper->getWiredTigerKVEngine()->dropIdentForImport(
*opCtxPtr.get(), *shard_role_details::getRecoveryUnit(opCtxPtr.get()), ident);
ASSERT(boost::filesystem::exists(*dataFilePath));
// Because the underlying file was not removed, it will be renamed out of the way by WiredTiger
// when creating a new table with the same ident.
ASSERT_OK(
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options));
const boost::filesystem::path renamedFilePath = dataFilePath->generic_string() + ".1";
ASSERT(boost::filesystem::exists(*dataFilePath));
ASSERT(boost::filesystem::exists(renamedFilePath));
ASSERT_OK(_helper.getWiredTigerKVEngine()->dropIdent(
ASSERT_OK(_helper->getWiredTigerKVEngine()->dropIdent(
*shard_role_details::getRecoveryUnit(opCtxPtr.get()), ident, /*identHasSizeInfo=*/true));
// WiredTiger drops files asynchronously.
@ -520,36 +532,36 @@ TEST_F(WiredTigerKVEngineTest, TestBasicPinOldestTimestamp) {
const Timestamp initTs = Timestamp(1, 0);
// Initialize the oldest timestamp.
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Assert that advancing the oldest timestamp still succeeds.
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 1, false);
ASSERT_EQ(initTs + 1, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 1, false);
ASSERT_EQ(initTs + 1, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Error if there's a request to pin the oldest timestamp earlier than what it is already set
// as. This error case is not exercised in this test.
const bool roundUpIfTooOld = false;
// Pin the oldest timestamp to "3".
auto pinnedTs = unittest::assertGet(_helper.getWiredTigerKVEngine()->pinOldestTimestamp(
auto pinnedTs = unittest::assertGet(_helper->getWiredTigerKVEngine()->pinOldestTimestamp(
*shard_role_details::getRecoveryUnit(opCtxRaii.get()), "A", initTs + 3, roundUpIfTooOld));
// Assert that the pinning method returns the same timestamp as was requested.
ASSERT_EQ(initTs + 3, pinnedTs);
// Assert that pinning the oldest timestamp does not advance it.
ASSERT_EQ(initTs + 1, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs + 1, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Attempt to advance the oldest timestamp to "5".
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
// Observe the oldest timestamp was pinned at the requested "3".
ASSERT_EQ(initTs + 3, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs + 3, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Unpin the oldest timestamp. Assert that unpinning does not advance the oldest timestamp.
_helper.getWiredTigerKVEngine()->unpinOldestTimestamp("A");
ASSERT_EQ(initTs + 3, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->unpinOldestTimestamp("A");
ASSERT_EQ(initTs + 3, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Now advancing the oldest timestamp to "5" succeeds.
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 5, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 5, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
}
/**
@ -560,37 +572,37 @@ TEST_F(WiredTigerKVEngineTest, TestMultiPinOldestTimestamp) {
auto opCtxRaii = _makeOperationContext();
const Timestamp initTs = Timestamp(1, 0);
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Error if there's a request to pin the oldest timestamp earlier than what it is already set
// as. This error case is not exercised in this test.
const bool roundUpIfTooOld = false;
// Have "A" pin the timestamp to "1".
auto pinnedTs = unittest::assertGet(_helper.getWiredTigerKVEngine()->pinOldestTimestamp(
auto pinnedTs = unittest::assertGet(_helper->getWiredTigerKVEngine()->pinOldestTimestamp(
*shard_role_details::getRecoveryUnit(opCtxRaii.get()), "A", initTs + 1, roundUpIfTooOld));
ASSERT_EQ(initTs + 1, pinnedTs);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Have "B" pin the timestamp to "2".
pinnedTs = unittest::assertGet(_helper.getWiredTigerKVEngine()->pinOldestTimestamp(
pinnedTs = unittest::assertGet(_helper->getWiredTigerKVEngine()->pinOldestTimestamp(
*shard_role_details::getRecoveryUnit(opCtxRaii.get()), "B", initTs + 2, roundUpIfTooOld));
ASSERT_EQ(initTs + 2, pinnedTs);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Advancing the oldest timestamp to "5" will only succeed in advancing it to "1".
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 1, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 1, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// After unpinning "A" at "1", advancing the oldest timestamp will be pinned to "2".
_helper.getWiredTigerKVEngine()->unpinOldestTimestamp("A");
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 2, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->unpinOldestTimestamp("A");
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 2, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Unpinning "B" at "2" allows the oldest timestamp to advance freely.
_helper.getWiredTigerKVEngine()->unpinOldestTimestamp("B");
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 5, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->unpinOldestTimestamp("B");
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs + 5, false);
ASSERT_EQ(initTs + 5, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
}
/**
@ -601,8 +613,8 @@ TEST_F(WiredTigerKVEngineTest, TestPinOldestTimestampErrors) {
auto opCtxRaii = _makeOperationContext();
const Timestamp initTs = Timestamp(10, 0);
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs, false);
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
const bool roundUpIfTooOld = true;
// The false value means using this variable will cause the method to fail on error.
@ -610,15 +622,15 @@ TEST_F(WiredTigerKVEngineTest, TestPinOldestTimestampErrors) {
// When rounding on error, the pin will succeed, but the return value will be the current oldest
// timestamp instead of the requested value.
auto pinnedTs = unittest::assertGet(_helper.getWiredTigerKVEngine()->pinOldestTimestamp(
auto pinnedTs = unittest::assertGet(_helper->getWiredTigerKVEngine()->pinOldestTimestamp(
*shard_role_details::getRecoveryUnit(opCtxRaii.get()), "A", initTs - 1, roundUpIfTooOld));
ASSERT_EQ(initTs, pinnedTs);
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
// Using "fail on error" will result in a not-OK return value.
ASSERT_NOT_OK(_helper.getWiredTigerKVEngine()->pinOldestTimestamp(
ASSERT_NOT_OK(_helper->getWiredTigerKVEngine()->pinOldestTimestamp(
*shard_role_details::getRecoveryUnit(opCtxRaii.get()), "B", initTs - 1, failOnError));
ASSERT_EQ(initTs, _helper.getWiredTigerKVEngine()->getOldestTimestamp());
ASSERT_EQ(initTs, _helper->getWiredTigerKVEngine()->getOldestTimestamp());
}
/**
@ -630,26 +642,26 @@ TEST_F(WiredTigerKVEngineTest, TestOldestStableTimestampEndOfStartupRecovery) {
auto& ru = *shard_role_details::getRecoveryUnit(opCtxRaii.get());
// oldest and stable are both null.
ASSERT_DOES_NOT_THROW(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
ASSERT_DOES_NOT_THROW(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
// oldest is null, stable is not null.
const Timestamp initTs = Timestamp(10, 0);
_helper.getWiredTigerKVEngine()->setStableTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
_helper->getWiredTigerKVEngine()->setStableTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
// oldest and stable equal.
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
// stable > oldest.
Timestamp laterTs = Timestamp(15, 0);
_helper.getWiredTigerKVEngine()->setStableTimestamp(laterTs, true);
ASSERT_DOES_NOT_THROW(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
_helper->getWiredTigerKVEngine()->setStableTimestamp(laterTs, true);
ASSERT_DOES_NOT_THROW(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru));
// oldest > stable.
laterTs = Timestamp(20, 0);
_helper.getWiredTigerKVEngine()->setOldestTimestamp(laterTs, true);
ASSERT_THROWS_CODE(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru),
_helper->getWiredTigerKVEngine()->setOldestTimestamp(laterTs, true);
ASSERT_THROWS_CODE(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(ru),
AssertionException,
8470600);
}
@ -663,8 +675,8 @@ TEST_F(WiredTigerKVEngineTest, TestOldestStableTimestampEndOfStartupRecoveryStab
// oldest is not null, stable is null.
const Timestamp initTs = Timestamp(10, 0);
_helper.getWiredTigerKVEngine()->setOldestTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper.getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(
_helper->getWiredTigerKVEngine()->setOldestTimestamp(initTs, true);
ASSERT_DOES_NOT_THROW(_helper->getWiredTigerKVEngine()->notifyReplStartupRecoveryComplete(
*shard_role_details::getRecoveryUnit(opCtxRaii.get())));
}
@ -777,11 +789,11 @@ TEST_F(WiredTigerKVEngineTest, TestReconfigureLog) {
logv2::LogComponent::kWiredTigerCheckpoint, logv2::LogSeverity::Log()};
ASSERT_EQ(logv2::LogSeverity::Log(),
unittest::getMinimumLogSeverity(logv2::LogComponent::kWiredTigerCheckpoint));
ASSERT_OK(_helper.getWiredTigerKVEngine()->reconfigureLogging());
ASSERT_OK(_helper->getWiredTigerKVEngine()->reconfigureLogging());
// Perform a checkpoint. The goal here is create some activity in WiredTiger in order
// to generate verbose messages (we don't really care about the checkpoint itself).
unittest::LogCaptureGuard logs;
_helper.getWiredTigerKVEngine()->checkpoint();
_helper->getWiredTigerKVEngine()->checkpoint();
logs.stop();
// In this initial case, we don't expect to capture any debug checkpoint messages. The
// base severity for the checkpoint component should be at Log().
@ -800,13 +812,13 @@ TEST_F(WiredTigerKVEngineTest, TestReconfigureLog) {
// Set the WiredTiger Checkpoint LOGV2 component severity to the Debug(2) level.
auto severityGuard = unittest::MinimumLoggedSeverityGuard{
logv2::LogComponent::kWiredTigerCheckpoint, logv2::LogSeverity::Debug(2)};
ASSERT_OK(_helper.getWiredTigerKVEngine()->reconfigureLogging());
ASSERT_OK(_helper->getWiredTigerKVEngine()->reconfigureLogging());
ASSERT_EQ(logv2::LogSeverity::Debug(2),
unittest::getMinimumLogSeverity(logv2::LogComponent::kWiredTigerCheckpoint));
// Perform another checkpoint.
unittest::LogCaptureGuard logs;
_helper.getWiredTigerKVEngine()->checkpoint();
_helper->getWiredTigerKVEngine()->checkpoint();
logs.stop();
// This time we expect to detect WiredTiger checkpoint Debug() messages.
@ -824,8 +836,8 @@ TEST_F(WiredTigerKVEngineTest, TestReconfigureLog) {
TEST_F(WiredTigerKVEngineTest, RollbackToStableEBUSY) {
auto opCtxPtr = _makeOperationContext();
_helper.getWiredTigerKVEngine()->setInitialDataTimestamp(Timestamp(1, 1));
_helper.getWiredTigerKVEngine()->setStableTimestamp(Timestamp(1, 1), false);
_helper->getWiredTigerKVEngine()->setInitialDataTimestamp(Timestamp(1, 1));
_helper->getWiredTigerKVEngine()->setStableTimestamp(Timestamp(1, 1), false);
// Get a session. This will open a transaction.
WiredTigerSession* session =
@ -836,7 +848,7 @@ TEST_F(WiredTigerKVEngineTest, RollbackToStableEBUSY) {
// WT will return EBUSY due to the open transaction.
FailPointEnableBlock failPoint("WTRollbackToStableReturnOnEBUSY");
ASSERT_EQ(ErrorCodes::ObjectIsBusy,
_helper.getWiredTigerKVEngine()
_helper->getWiredTigerKVEngine()
->recoverToStableTimestamp(*opCtxPtr.get())
.getStatus()
.code());
@ -846,7 +858,7 @@ TEST_F(WiredTigerKVEngineTest, RollbackToStableEBUSY) {
->abandonSnapshot();
// WT will no longer return EBUSY.
ASSERT_OK(_helper.getWiredTigerKVEngine()->recoverToStableTimestamp(*opCtxPtr.get()));
ASSERT_OK(_helper->getWiredTigerKVEngine()->recoverToStableTimestamp(*opCtxPtr.get()));
}
std::unique_ptr<KVHarnessHelper> makeHelper(ServiceContext* svcCtx) {
@ -858,14 +870,14 @@ MONGO_INITIALIZER(RegisterKVHarnessFactory)(InitializerContext*) {
}
TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdown) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
engine->cleanShutdown(kMemLeakAllowed);
ASSERT(!engine->isWtConnReadyForStatsCollection_UNSAFE());
}
TEST_F(WiredTigerKVEngineTest, TestHandlerSingleActivityBeforeShutdownRAII) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
{
auto permit = engine->tryGetStatsCollectionPermit();
@ -880,7 +892,7 @@ TEST_F(WiredTigerKVEngineTest, TestHandlerSingleActivityBeforeShutdownRAII) {
}
TEST_F(WiredTigerKVEngineTest, TestHandlerMultipleActivitiesBeforeShutdownRAII) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
{
auto permit1 = engine->tryGetStatsCollectionPermit();
@ -902,7 +914,7 @@ TEST_F(WiredTigerKVEngineTest, TestHandlerMultipleActivitiesBeforeShutdownRAII)
}
TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdownBeforeActivity) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
engine->cleanShutdown(kMemLeakAllowed);
ASSERT(!engine->tryGetStatsCollectionPermit());
@ -911,7 +923,7 @@ TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdownBeforeActivity) {
}
TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdownBeforeActivityReleaseRAII) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
{
auto permit = engine->tryGetStatsCollectionPermit();
@ -932,7 +944,7 @@ TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdownBeforeActivityReleaseRAII
}
TEST_F(WiredTigerKVEngineTest, TestRestartUsesNewConn) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
{
@ -941,8 +953,8 @@ TEST_F(WiredTigerKVEngineTest, TestRestartUsesNewConn) {
ASSERT_EQ(engine->getConn(), permit->conn());
}
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto permit = engine->tryGetStatsCollectionPermit();
ASSERT(permit);
@ -950,7 +962,7 @@ TEST_F(WiredTigerKVEngineTest, TestRestartUsesNewConn) {
}
TEST_F(WiredTigerKVEngineTest, TestGetBackupCheckpointTimestampWithoutOpenBackupCursor) {
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
ASSERT_EQ(Timestamp::min(), engine->getBackupCheckpointTimestamp());
}
@ -977,18 +989,18 @@ protected:
rss::ReplicatedStorageService::get(getGlobalServiceContext()).getPersistenceProvider();
auto& ru = *shard_role_details::getRecoveryUnit(_opCtx.get());
Status stat =
_helper.getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options);
_helper->getWiredTigerKVEngine()->createRecordStore(provider, ru, nss, ident, options);
if (!stat.isOK()) {
return stat;
}
boost::optional<boost::filesystem::path> path =
_helper.getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
_helper->getWiredTigerKVEngine()->getDataFilePathForIdent(ident);
ASSERT_TRUE(path.has_value());
return *path;
}
Status removeIdent(StringData ident) {
return _helper.getWiredTigerKVEngine()->dropIdent(
return _helper->getWiredTigerKVEngine()->dropIdent(
*shard_role_details::getRecoveryUnit(_opCtx.get()), ident, /*identHasSizeInfo=*/true);
}
@ -1061,9 +1073,9 @@ TEST_F(WiredTigerKVEngineTest, CheckSessionCacheMax) {
RAIIServerParameterControllerForTest sessionCacheMax{"wiredTigerSessionCacheMaxPercentage", 20};
RAIIServerParameterControllerForTest sessionMax{"wiredTigerSessionMax", 150};
_helper.restartEngine();
_helper->restartEngine();
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
auto& connection = engine->getConnection();
// Check that the configured session cache max is derived correctly.
@ -1116,7 +1128,7 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
ASSERT_EQ(ru.getPreparedId().value(), preparedId);
// Create a checkpoint that includes the prepared transaction.
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
engine->setInitialDataTimestamp(Timestamp(1, 0));
engine->setStableTimestamp(prepareTimestamp, /*force=*/false);
engine->checkpoint();
@ -1130,8 +1142,8 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
opCtxPtr.reset();
// Simulate startup recovery by restarting the storage engine.
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto opCtxPtr2 = _makeOperationContext();
// Verify that we see the prepared transaction on startup recovery and reclaim it.
@ -1181,7 +1193,7 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
ASSERT_EQ(ru2.getPreparedId().value(), preparedId2);
// Create a checkpoint that includes both prepared transactions.
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
engine->setInitialDataTimestamp(Timestamp(1, 0));
engine->setStableTimestamp(prepareTimestamp2, /*force=*/false);
engine->checkpoint();
@ -1199,8 +1211,8 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
clientAndCtx2.first.reset();
// Simulate startup recovery by restarting the storage engine.
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto opCtxPtr = _makeOperationContext();
// Verify that we see both prepared transactions on startup recovery.
@ -1248,7 +1260,7 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
ru.abortUnitOfWork();
// Create a checkpoint that includes the aborted transaction.
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
engine->setInitialDataTimestamp(Timestamp(1, 0));
engine->setStableTimestamp(Timestamp(5, 0), /*force=*/false);
engine->checkpoint();
@ -1257,8 +1269,8 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
opCtxPtr.reset();
// Simulate startup recovery by restarting the storage engine.
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto opCtxPtr2 = _makeOperationContext();
// Verify that we do not see any prepared transactions on startup recovery.
@ -1284,7 +1296,7 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
ru.abortUnitOfWork();
// Create a checkpoint that includes the prepared transaction but not the abort.
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
engine->setInitialDataTimestamp(Timestamp(1, 0));
engine->setStableTimestamp(Timestamp(5, 0), /*force=*/false);
engine->checkpoint();
@ -1293,8 +1305,8 @@ TEST_F(WiredTigerKVEngineTestWithPreciseCheckpoints,
opCtxPtr.reset();
// Simulate startup recovery by restarting the storage engine.
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto opCtxPtr2 = _makeOperationContext();
auto& ru2 = *checked_cast<WiredTigerRecoveryUnit*>(
shard_role_details::getRecoveryUnit(opCtxPtr2.get()));
@ -1332,7 +1344,7 @@ DEATH_TEST_F(WiredTigerKVEngineTestWithPreciseCheckpointsDeathTest,
ASSERT_EQ(ru.getPreparedId().value(), preparedId);
// Create a checkpoint that includes the prepared transaction.
auto* engine = _helper.getWiredTigerKVEngine();
auto* engine = _helper->getWiredTigerKVEngine();
engine->setInitialDataTimestamp(Timestamp(1, 0));
engine->setStableTimestamp(prepareTimestamp, /*force=*/false);
engine->checkpoint();
@ -1347,8 +1359,8 @@ DEATH_TEST_F(WiredTigerKVEngineTestWithPreciseCheckpointsDeathTest,
opCtxPtr.reset();
// Simulate startup recovery by restarting the storage engine.
_helper.restartEngine();
engine = _helper.getWiredTigerKVEngine();
_helper->restartEngine();
engine = _helper->getWiredTigerKVEngine();
auto opCtxPtr2 = _makeOperationContext();
// Verify that we see the prepared transaction on startup recovery.

View File

@ -66,6 +66,10 @@ requires std::is_integral_v<Int>
class IntegerIntervalSet {
public:
class iterator;
using value_type = std::pair<Int, Int>;
using reference = value_type&;
using const_reference = const value_type&;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
IntegerIntervalSet() = default;
@ -290,8 +294,12 @@ public:
*/
class iterator {
public:
using value_type = std::pair<Int, Int>;
using difference_type = std::ptrdiff_t;
using difference_type = IntegerIntervalSet::difference_type;
using value_type = IntegerIntervalSet::value_type;
using reference = const value_type&;
using pointer = const value_type*;
using iterator_category = std::bidirectional_iterator_tag;
iterator() = default;
const std::pair<Int, Int>& operator*() const {
@ -320,7 +328,7 @@ public:
return *this;
}
// This is the postfix operator-- (i.e. "--iter")
// This is the postfix operator-- (i.e. "iter--")
iterator operator--(int) {
auto oldIter = _iter;
--(*this);

View File

@ -36,6 +36,7 @@ mongo_cc_library(
"//src/mongo/db/storage:storage_options",
"//src/mongo/scripting:scripting_common",
"//src/mongo/unittest",
"//src/mongo/unittest:unittest_main_core",
"//src/mongo/util:periodic_runner_factory",
"//src/mongo/util/options_parser:options_parser_init",
],

View File

@ -152,11 +152,12 @@ CollectionAcquisition WriteContextForTests::getCollection(LockMode mode) const {
}
int dbtestsMain(int argc, char** argv) {
auto progress = initializeDbTests(std::vector<std::string>(argv, argv + argc));
::mongo::setTestCommandsEnabled(true);
::mongo::TestingProctor::instance().setEnabled(true);
::mongo::setupSynchronousSignalHandlers();
mongo::runGlobalInitializersOrDie(std::vector<std::string>(argv, argv + argc));
runGlobalInitializersOrDie(progress.args());
// (Generic FCV reference): This FCV reference should exist across LTS binary versions.
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
repl::ReplSettings replSettings;
@ -204,7 +205,7 @@ int dbtestsMain(int argc, char** argv) {
query_settings::QuerySettingsService::initializeForTest(service);
return mongo::dbtests::runDbTests(argc, argv);
return runDbTests(progress);
}
} // namespace dbtests

View File

@ -62,9 +62,15 @@ namespace DirectClientTests {
const NamespaceString nss = NamespaceString::createNamespaceString_forTest("a.b");
class InsertMany {
class Base {
public:
virtual void run() {
virtual ~Base() = default;
virtual void run() = 0;
};
class InsertMany : public Base {
public:
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -88,9 +94,9 @@ public:
}
};
class BadNSCmd {
class BadNSCmd : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -104,9 +110,9 @@ public:
}
};
class BadNSQuery {
class BadNSQuery : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -119,9 +125,9 @@ public:
}
};
class BadNSGetMore {
class BadNSGetMore : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -133,9 +139,9 @@ public:
}
};
class BadNSInsert {
class BadNSInsert : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -146,9 +152,9 @@ public:
}
};
class BadNSUpdate {
class BadNSUpdate : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);
@ -161,9 +167,9 @@ public:
}
};
class BadNSRemove {
class BadNSRemove : public Base {
public:
virtual void run() {
void run() override {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
DBDirectClient client(&opCtx);

View File

@ -54,6 +54,7 @@
#include "mongo/scripting/dbdirectclient_factory.h"
#include "mongo/scripting/engine.h"
#include "mongo/unittest/unittest.h"
#include "mongo/unittest/unittest_main_core.h"
#include "mongo/util/exit.h"
#include "mongo/util/exit_code.h"
#include "mongo/util/periodic_runner.h"
@ -71,12 +72,21 @@
namespace mongo {
namespace dbtests {
int runDbTests(int argc, char** argv) {
if (frameworkGlobalParams.suites.empty()) {
LOGV2_ERROR(5733802, "The [suite] argument is required for dbtest and not specified here.");
return static_cast<int>(ExitCode::fail);
}
unittest::MainProgress initializeDbTests(std::vector<std::string> argVec) {
unittest::MainProgress progress(
{
.suppressGlobalInitializers = true,
.testSuites = frameworkGlobalParams.suites,
.runsPerTest = frameworkGlobalParams.runsPerTest,
},
std::move(argVec));
progress.initialize();
if (auto ec = progress.parseAndAcceptOptions())
std::quick_exit(static_cast<int>(*ec));
return progress;
}
int runDbTests(unittest::MainProgress& progress) {
frameworkGlobalParams.perfHist = 1;
frameworkGlobalParams.seed = time(nullptr);
frameworkGlobalParams.runsPerTest = 1;
@ -124,10 +134,7 @@ int runDbTests(int argc, char** argv) {
DatabaseShardingStateFactory::set(serviceContext,
std::make_unique<DatabaseShardingStateFactoryShard>());
int ret = unittest::Suite::run(frameworkGlobalParams.suites,
frameworkGlobalParams.filter,
"",
frameworkGlobalParams.runsPerTest);
int ret = progress.test();
// So everything shuts down cleanly
CollectionShardingStateFactory::clear(serviceContext);

View File

@ -29,15 +29,9 @@
#pragma once
/*
#include "mongo/unittest/unittest_main_core.h"
simple portable regression system
*/
#include <string>
namespace mongo {
namespace dbtests {
int runDbTests(int argc, char** argv);
} // namespace dbtests
} // namespace mongo
namespace mongo::dbtests {
unittest::MainProgress initializeDbTests(std::vector<std::string> argVec);
int runDbTests(unittest::MainProgress& progress);
} // namespace mongo::dbtests

View File

@ -83,15 +83,6 @@ bool handlePreValidationTestFrameworkOptions(const moe::Environment& params,
return false;
}
if (params.count("list")) {
std::vector<std::string> suiteNames = mongo::unittest::getAllSuiteNames();
for (std::vector<std::string>::const_iterator i = suiteNames.begin(); i != suiteNames.end();
++i) {
std::cout << *i << std::endl;
}
return false;
}
return true;
}

View File

@ -31,6 +31,7 @@
#include "mongo/base/status.h"
#include "mongo/base/string_data.h"
#include "mongo/util/modules.h"
#include <string>
#include <vector>

View File

@ -49,19 +49,6 @@ configs:
debug:
description: "Run tests with verbose output"
arg_vartype: Switch
list:
description: "List available test suites"
arg_vartype: Switch
single_name: l
filter:
description: "String substring filter on test name"
arg_vartype: String
single_name: f
cpp_varname: "frameworkGlobalParams.filter"
verbose:
description: Verbose
arg_vartype: Switch
single_name: v
seed:
description: "Random number seed"
arg_vartype: UnsignedLongLong

View File

@ -70,10 +70,8 @@
#include <fmt/format.h>
namespace mongo {
namespace IndexUpdateTests {
namespace {
const auto kIndexVersion = IndexDescriptor::IndexVersion::kV2;
} // namespace
static const char* const _ns = "unittests.indexupdate";
static const NamespaceString _nss = NamespaceString::createNamespaceString_forTest(_ns);
@ -678,19 +676,14 @@ class IndexUpdateTests : public unittest::OldStyleSuiteSpecification {
public:
IndexUpdateTests() : OldStyleSuiteSpecification("indexupdate") {}
template <typename T>
void addIf() {
addNameCallback(nameForTestClass<T>(), [] { T().run(); });
}
void setupTests() override {
// These tests check that index creation ignores the unique constraint when told to.
// The mobile storage engine does not support duplicate keys in unique indexes so these
// tests are disabled.
addIf<InsertBuildIgnoreUnique<true>>();
addIf<InsertBuildIgnoreUnique<false>>();
addIf<InsertBuildEnforceUnique<true>>();
addIf<InsertBuildEnforceUnique<false>>();
add<InsertBuildIgnoreUnique<true>>();
add<InsertBuildIgnoreUnique<false>>();
add<InsertBuildEnforceUnique<true>>();
add<InsertBuildEnforceUnique<false>>();
add<InsertBuildIndexInterrupt>();
add<InsertBuildIdIndexInterrupt>();
@ -717,5 +710,5 @@ public:
unittest::OldStyleSuiteInitializer<IndexUpdateTests> indexUpdateTests;
} // namespace IndexUpdateTests
} // namespace
} // namespace mongo

View File

@ -204,7 +204,7 @@ public:
query_settings::QuerySettingsService::initializeForTest(_opCtx.getServiceContext());
}
~Base() {
virtual ~Base() {
auto* const sc = _opCtx.getServiceContext();
try {
deleteAll(ns());
@ -436,7 +436,7 @@ namespace Idempotence {
class Base : public ReplTests::Base {
public:
virtual ~Base() {}
virtual ~Base() = default;
void run() {
reset();
doIt();

View File

@ -132,7 +132,7 @@ mongo_cc_unit_test(
copts = [
"-Isrc/mongo/embedded",
],
has_custom_mainline = True,
provides_main = True,
tags = [
"mongo_unittest_third_group",
"stitch_support_test",
@ -145,5 +145,6 @@ mongo_cc_unit_test(
"stitch_support_duplicate",
"//src/mongo/db/shard_role:service_context_non_d",
"//src/mongo/unittest",
"//src/mongo/unittest:unittest_main_core",
],
)

View File

@ -39,6 +39,8 @@
#include "mongo/bson/oid.h"
#include "mongo/bson/timestamp.h"
#include "mongo/unittest/unittest.h"
#include "mongo/unittest/unittest_main_core.h"
#include "mongo/unittest/unittest_options.h"
#include "mongo/util/exit_code.h"
#include "mongo/util/quick_exit.h"
#include "mongo/util/scopeguard.h"
@ -650,23 +652,22 @@ TEST_F(StitchSupportTest, TestUpsertProducesProperStatus) {
// Note that we don't use the main() defined for most other unit tests so that we can avoid double
// calling runGlobalInitializers(), which is called both from the regular unit test main() and from
// the Stitch Support Library intializer function that gets tested here.
int main(const int argc, const char* const* const argv) {
// See comment by the same code block in mongo_embedded_test.cpp
auto ret = mongo::runGlobalInitializers(std::vector<std::string>{argv, argv + argc});
if (!ret.isOK()) {
std::cerr << "Global initilization failed";
int main(int argc, char** argv) {
mongo::unittest::MainProgress progress({.suppressGlobalInitializers = true},
std::vector<std::string>(argv, argv + argc));
progress.initialize();
if (auto ec = progress.parseAndAcceptOptions())
return static_cast<int>(*ec);
if (auto ret = mongo::runGlobalInitializers(progress.args()); !ret.isOK()) {
std::cerr << "Global initilization failed" << ret.toString();
return static_cast<int>(mongo::ExitCode::fail);
}
ret = mongo::runGlobalDeinitializers();
if (!ret.isOK()) {
std::cerr << "Global deinitilization failed";
if (auto ret = mongo::runGlobalDeinitializers(); !ret.isOK()) {
std::cerr << "Global deinitilization failed" << ret.toString();
return static_cast<int>(mongo::ExitCode::fail);
}
const auto result = ::mongo::unittest::Suite::run(std::vector<std::string>(), "", "", 1);
// This is the standard exit path for Mongo processes. See the mongo::quickExit() declaration
// for more information.
mongo::quickExit(result);
return progress.test();
}

View File

@ -46,44 +46,16 @@ namespace {
namespace m = unittest::match;
/** Match that `x` converts to `true` and that `*x` matches `m`. */
template <typename M>
class WhenDereferenced : public m::Matcher {
public:
explicit WhenDereferenced(M&& m) : _m{std::move(m)} {}
std::string describe() const {
return fmt::format("WhenDereferenced({})", _m.describe());
}
template <typename X>
m::MatchResult match(const X& x) const {
if (!x)
return {false, "converts to a false bool value"};
return _m.match(*x);
}
private:
M _m;
};
MATCHER_P(WhenDereferenced, m, "") {
if (!arg)
return false;
return ExplainMatchResult(m, *arg, result_listener);
}
/** Match that `static_cast<bool>(x)` matches `m`. */
template <typename M>
class WhenBool : public m::Matcher {
public:
explicit WhenBool(M&& m) : _m{std::move(m)} {}
std::string describe() const {
return fmt::format("WhenBool({})", _m.describe());
}
template <typename X>
m::MatchResult match(const X& x) const {
return _m.match(static_cast<bool>(x));
}
private:
M _m;
};
MATCHER_P(WhenBool, m, "") {
return ExplainMatchResult(m, static_cast<bool>(arg), result_listener);
}
enum class SomeTimeSplitId : size_t {
a,

View File

@ -125,14 +125,14 @@ public:
: CommonTaskExecutorTestFixture(std::move(makeExecutor)) {} \
\
private: \
void _doTest() override; \
void TestBody() override; \
static const CetRegistrationAgent _agent; \
}; \
const CetRegistrationAgent CET_##TEST_NAME::_agent( \
#TEST_NAME, [](ExecutorFactory makeExecutor) { \
return std::make_unique<CET_##TEST_NAME>(std::move(makeExecutor)); \
}); \
void CET_##TEST_NAME::_doTest()
void CET_##TEST_NAME::TestBody()
auto makeSetStatusClosure(Status* target) {
return [target](const TaskExecutor::CallbackArgs& cbData) {
@ -1142,11 +1142,11 @@ COMMON_EXECUTOR_TEST(ScheduleRemoteCommandAfterNetworkInterfaceShutdown) {
} // namespace
void addTestsForExecutor(const std::string& suiteName, ExecutorFactory makeExecutor) {
auto& suite = unittest::Suite::getSuite(suiteName);
for (const auto& testCase : executorTestCaseRegistry()) {
suite.add(str::stream() << suiteName << "::" << testCase.first,
__FILE__,
[testCase, makeExecutor] { testCase.second(makeExecutor)->run(); });
for (auto&& [name, func] : executorTestCaseRegistry()) {
testing::RegisterTest(
suiteName.c_str(), name.c_str(), nullptr, nullptr, __FILE__, __LINE__, [=] {
return func(makeExecutor).release();
});
}
}

View File

@ -105,10 +105,6 @@ void TaskExecutorTest::joinExecutorThread() {
_executor->join();
}
void TaskExecutorTest::_doTest() {
MONGO_UNREACHABLE;
}
void TaskExecutorTest::postExecutorThreadLaunch() {}
} // namespace executor

View File

@ -91,16 +91,6 @@ public:
void joinExecutorThread();
private:
/**
* Unused implementation of test function. This allows us to instantiate
* TaskExecutorTest on its own without the need to inherit from it in a test.
* This supports using TaskExecutorTest inside another test fixture and works around the
* limitation that tests cannot inherit from multiple test fixtures.
*
* It is an error to call this implementation of _doTest() directly.
*/
void _doTest() override;
virtual std::shared_ptr<TaskExecutor> makeTaskExecutor(
std::unique_ptr<NetworkInterfaceMock> net) = 0;

View File

@ -110,30 +110,64 @@ mongo_cc_library(
],
)
mongo_cc_unit_test(
name = "idl_test",
mongo_cc_library(
name = "idl_test_base",
srcs = [
"command_generic_argument_test.cpp",
"config_option_test.cpp",
"feature_flag_test.cpp",
"idl_test.cpp",
"server_parameter_specialized_test.cpp",
"server_parameter_with_storage_test.cpp",
":config_option_no_init_test_gen",
":config_option_test_gen",
"server_parameter_specialized_test_defs.cpp",
"server_parameter_with_storage_test_defs.cpp",
":idl_test_defs.cpp",
":server_parameter_specialized_test_gen",
":server_parameter_with_storage_test_gen",
":server_parameter_with_storage_test_structs_gen",
":unittest_gen",
":unittest_import_gen",
],
deps = [
":server_parameter_test_util",
"//src/mongo:base",
"//src/mongo/client:connection_string",
"//src/mongo/db/topology/cluster_parameters:cluster_server_parameter",
],
)
mongo_cc_unit_test(
name = "config_option_test",
srcs = [
"config_option_test.cpp",
"config_option_test_main.cpp",
":config_option_no_init_test_gen",
":config_option_test_gen",
],
provides_main = True,
tags = [
"mongo_unittest_fourth_group",
"server-programmability",
],
deps = [
"idl_test_base",
"//src/mongo/db/auth:authprivilege",
"//src/mongo/unittest:unittest_main_core",
"//src/mongo/util/cmdline_utils",
"//src/mongo/util/options_parser",
],
)
mongo_cc_unit_test(
name = "idl_test",
srcs = [
"command_generic_argument_test.cpp",
"feature_flag_test.cpp",
"idl_test.cpp",
"server_parameter_specialized_test.cpp",
"server_parameter_with_storage_test.cpp",
],
tags = [
"mongo_unittest_fifth_group",
"server-programmability",
],
deps = [
":idl_parser",
":server_parameter_test_util",
":idl_test_base",
"//src/mongo/client:connection_string",
"//src/mongo/db:server_base",
"//src/mongo/db:server_feature_flags",
@ -143,7 +177,6 @@ mongo_cc_unit_test(
"//src/mongo/db/shard_role/lock_manager",
"//src/mongo/db/topology/cluster_parameters:cluster_server_parameter",
"//src/mongo/rpc:message",
"//src/mongo/util/cmdline_utils",
"//src/mongo/util/options_parser",
],
)

View File

@ -99,22 +99,6 @@ Status parseMixed(const std::vector<std::string>& argv,
return ex.toStatus();
}
MONGO_STARTUP_OPTIONS_PARSE(ConfigOption)(InitializerContext*) {
// Fake argv for default arg parsing.
const std::vector<std::string> argv = {
"mongo",
"--testConfigOpt2",
"true",
"--testConfigOpt8",
"8",
"--testConfigOpt12",
"command-line option",
"--testConfigOpt14",
"set14",
};
uassertStatusOK(parseArgv(argv, &moe::startupOptionsParsed));
}
template <typename T>
void ASSERT_OPTION_SET(const moe::Environment& env, const moe::Key& name, const T& exp) {
ASSERT_TRUE(env.count(name));

View File

@ -0,0 +1,55 @@
/**
* Copyright (C) 2025-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/unittest/unittest.h"
#include "mongo/unittest/unittest_main_core.h"
#include <memory>
#include <string>
#include <vector>
int main(int argc, char** argv) {
mongo::unittest::MainProgress progress({}, std::vector<std::string>(argv, argv + argc));
progress.initialize();
if (GTEST_FLAG_GET(internal_run_death_test).empty()) {
auto& args = progress.args();
args.insert(args.end(),
{
"--testConfigOpt2",
"true",
"--testConfigOpt8",
"8",
"--testConfigOpt12",
"command-line option",
"--testConfigOpt14",
"set14",
});
}
return progress.test();
}

View File

@ -27,8 +27,6 @@
* it in the license file.
*/
#include "mongo/idl/idl_test.h"
#include "mongo/base/data_range.h"
#include "mongo/base/error_codes.h"
#include "mongo/base/static_assert.h"
@ -59,6 +57,7 @@
#include "mongo/db/tenant_id.h"
#include "mongo/db/write_concern_options_gen.h"
#include "mongo/idl/idl_parser.h"
#include "mongo/idl/idl_test_defs.h"
#include "mongo/idl/idl_test_types.h"
#include "mongo/idl/server_parameter_test_controller.h"
#include "mongo/idl/unittest_gen.h"
@ -101,11 +100,6 @@ using namespace mongo::idl::import;
namespace mongo {
void mongo::idl::test::checkValuesEqual(StructWithValidator* structToValidate) {
uassert(
6253512, "Values not equal", structToValidate->getFirst() == structToValidate->getSecond());
}
namespace {
bool isEquals(ConstDataRange left, const std::vector<uint8_t>& right) {

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2021-present MongoDB, Inc.
* Copyright (C) 2025-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,
@ -27,35 +27,15 @@
* it in the license file.
*/
#include "mongo/unittest/matcher.h"
#include "mongo/idl/idl_test_defs.h"
#include "mongo/util/pcre.h"
#include "mongo/idl/unittest_gen.h"
#include "mongo/idl/unittest_import_gen.h"
#include <memory>
#include <utility>
namespace mongo::idl::test {
#include <fmt/format.h>
namespace mongo::unittest::match {
struct ContainsRegex::Impl {
explicit Impl(std::string pat) : re(std::move(pat)) {}
pcre::Regex re;
};
ContainsRegex::ContainsRegex(std::string pattern)
: _impl{std::make_shared<Impl>(std::move(pattern))} {}
ContainsRegex::~ContainsRegex() = default;
MatchResult ContainsRegex::match(StringData x) const {
if (_impl->re.matchView(x))
return {};
return MatchResult(false, "");
void checkValuesEqual(StructWithValidator* s) {
uassert(6253512, "Values not equal", s->getFirst() == s->getSecond());
}
std::string ContainsRegex::describe() const {
return fmt::format(R"(ContainsRegex("{}"))", _impl->re.pattern());
}
} // namespace mongo::unittest::match
} // namespace mongo::idl::test

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2018-present MongoDB, Inc.
* Copyright (C) 2025-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,

View File

@ -105,20 +105,6 @@ void ASSERT_APPENDED_OBJECT(ServerParameter* sp, const BSONObj& exp) {
});
}
// specializedDummy
void SpecializedDummyServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << "Dummy Value";
}
Status SpecializedDummyServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return Status::OK();
}
TEST(SpecializedServerParameter, dummy) {
auto* dsp = getServerParameter("specializedDummy");
ASSERT_APPENDED_STRING(dsp, "Dummy Value");
@ -127,67 +113,14 @@ TEST(SpecializedServerParameter, dummy) {
ASSERT_OK(dsp->set(BSON("" << "bar").firstElement(), boost::none));
}
// specializedDummy
void SpecializedDeprecatedServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << "Dummy Value";
}
Status SpecializedDeprecatedServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return Status::OK();
}
// specializedWithCtor
namespace {
std::string gSCSP("Initial Value");
} // namespace
SpecializedConstructorServerParameter::SpecializedConstructorServerParameter(
StringData name, ServerParameterType spt)
: ServerParameter(name, spt) {
gSCSP = "Value from ctor";
}
void SpecializedConstructorServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << gSCSP;
}
Status SpecializedConstructorServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
gSCSP = std::string{value};
return Status::OK();
}
TEST(SpecializedServerParameter, withCtor) {
auto* csp = getServerParameter("specializedWithCtor");
ASSERT_APPENDED_STRING(csp, "Value from ctor");
ASSERT_OK(csp->setFromString("Updated Value", boost::none));
ASSERT_EQ(gSCSP, "Updated Value");
ASSERT_EQ(getGlobalSCSP(), "Updated Value");
ASSERT_APPENDED_STRING(csp, "Updated Value");
}
// specializedWithValue
void SpecializedWithValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return NumberParser{}(value, &_data);
}
TEST(SpecializedServerParameter, withValue) {
using cls = SpecializedWithValueServerParameter;
ASSERT_EQ(cls::kDataDefault, 43);
@ -200,21 +133,6 @@ TEST(SpecializedServerParameter, withValue) {
ASSERT_EQ(wv->_data, 102);
}
// specializedWithStringValue
void SpecializedWithStringValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithStringValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
_data = std::string{value};
return Status::OK();
}
TEST(SpecializedServerParameter, withStringValue) {
using cls = SpecializedWithStringValueServerParameter;
ASSERT_EQ(cls::kDataDefault, "Hello World"_sd);
@ -227,28 +145,6 @@ TEST(SpecializedServerParameter, withStringValue) {
ASSERT_EQ(wsv->_data, "Goodbye Land");
}
// specializedWithAtomicValue
void SpecializedWithAtomicValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data.load();
}
Status SpecializedWithAtomicValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
std::uint32_t val;
auto status = NumberParser{}(value, &val);
if (!status.isOK()) {
return status;
}
_data.store(val);
return Status::OK();
}
TEST(SpecializedServerParameter, withAtomicValue) {
using cls = SpecializedWithAtomicValueServerParameter;
ASSERT_EQ(cls::kDataDefault, 42);
@ -263,30 +159,6 @@ TEST(SpecializedServerParameter, withAtomicValue) {
ASSERT_EQ(wv->_data.load(), 101);
}
// specializedWithMultiValue
void SpecializedMultiValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << BSON("value" << _data.value << "flag" << _data.flag);
}
Status SpecializedMultiValueServerParameter::set(const BSONElement& value,
const boost::optional<TenantId>&) try {
auto obj = value.Obj();
_data.value = obj["value"].String();
_data.flag = obj["flag"].Bool();
return Status::OK();
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing extra data"};
}
Status SpecializedMultiValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return set(BSON("" << BSON("value" << value << "flag" << false)).firstElement(), boost::none);
}
TEST(SpecializedServerParameter, multiValue) {
auto* edsp = getServerParameter("specializedWithMultiValue");
ASSERT_APPENDED_OBJECT(edsp,
@ -305,24 +177,6 @@ TEST(SpecializedServerParameter, multiValue) {
<< "flag" << true));
}
// specializedWithCtorAndValue
SpecializedWithCtorAndValueServerParameter::SpecializedWithCtorAndValueServerParameter(
StringData name, ServerParameterType spt)
: ServerParameter(name, spt) {}
void SpecializedWithCtorAndValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithCtorAndValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return NumberParser{}(value, &_data);
}
TEST(SpecializedServerParameter, withCtorAndValue) {
using cls = SpecializedWithCtorAndValueServerParameter;
auto* cvsp = getServerParameter<cls>("specializedWithCtorAndValue");
@ -332,50 +186,21 @@ TEST(SpecializedServerParameter, withCtorAndValue) {
ASSERT_APPENDED_INT(cvsp, cls::kDataDefault + 1);
}
// specializedWithOptions
namespace {
std::string gSWO = "Initial Value";
} // namespace
Status SpecializedWithOptions::setFromString(StringData value, const boost::optional<TenantId>&) {
gSWO = std::string{value};
return Status::OK();
}
TEST(SpecializedServerParameter, withOptions) {
auto* swo = getServerParameter("specializedWithOptions");
ASSERT_APPENDED_STRING(swo, "###");
ASSERT_OK(swo->setFromString("second value", boost::none));
ASSERT_EQ(gSWO, "second value");
ASSERT_EQ(getGlobalSWO(), "second value");
ASSERT_APPENDED_STRING(swo, "###");
auto* dswo = getServerParameter("deprecatedWithOptions");
ASSERT_APPENDED_STRING(dswo, "###");
ASSERT_OK(dswo->setFromString("third value", boost::none));
ASSERT_EQ(gSWO, "third value");
ASSERT_EQ(getGlobalSWO(), "third value");
ASSERT_APPENDED_STRING(dswo, "###");
ASSERT(dswo->getIsDeprecated());
}
// specializedRuntimeOnly
void SpecializedRuntimeOnly::append(OperationContext*,
BSONObjBuilder*,
StringData,
const boost::optional<TenantId>&) {}
Status SpecializedRuntimeOnly::setFromString(StringData value, const boost::optional<TenantId>&) {
return Status::OK();
}
Status SpecializedRedactedSettable::setFromString(StringData value,
const boost::optional<TenantId>&) {
std::cout << "Setting to: " << value << "\n";
_data = std::string{value};
return Status::OK();
}
TEST(SpecializedServerParameter, SpecializedRedactedSettable) {
using namespace std::literals;
using namespace unittest::match;
@ -396,7 +221,10 @@ TEST(SpecializedServerParameter, SpecializedRedactedSettable) {
};
ASSERT_OK(store("", "hello"));
ASSERT_THAT(load(), BSONObjHas(BSONElementIs(Eq(sp->name()), Eq(BSONType::string), Eq("###"))))
ASSERT_THAT(load(), testing::Truly([&](const BSONObj& obj) {
auto elem = obj.getField(sp->name());
return elem.type() == BSONType::string && elem.String() == "###";
}))
<< "value redacted by append";
ASSERT_THAT(dataMember, Eq("hello")) << "value preseved in _data member";
@ -442,33 +270,6 @@ TEST(SpecializedServerParameter, withScope) {
// Pointer now belongs to ServerParameterSet, no need to delete.
}
// specializedWithValidateServerParameter
void SpecializedWithValidateServerParameter::append(OperationContext*,
BSONObjBuilder*,
StringData,
const boost::optional<TenantId>&) {}
Status SpecializedWithValidateServerParameter::setFromString(StringData str,
const boost::optional<TenantId>&) {
return NumberParser{}(str, &_data);
}
Status SpecializedWithValidateServerParameter::validate(
const BSONElement& newValueElement, const boost::optional<TenantId>& tenantId) const {
try {
auto val = newValueElement.Int();
if (val < 0) {
return Status{ErrorCodes::BadValue,
"specializedWithValidate must be a non-negative integer"};
}
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing specializedWithValidate"};
}
return Status::OK();
}
TEST(SpecializedServerParameter, withValidate) {
auto* nodeSet = ServerParameterSet::getNodeParameterSet();
@ -491,55 +292,6 @@ TEST(SpecializedServerParameter, withValidate) {
validateSP->set(BSON(kSpecializedWithValidate << -1).firstElement(), boost::none));
}
// specializedWithClusterServerParameter
void SpecializedClusterServerParameter::append(OperationContext*,
BSONObjBuilder* builder,
StringData name,
const boost::optional<TenantId>& tenantId) {
builder->append("_id"_sd, name);
builder->appendElementsUnique(_data.toBSON());
}
Status SpecializedClusterServerParameter::set(const BSONElement& newValueElement,
const boost::optional<TenantId>& tenantId) {
Status status = validate(newValueElement, tenantId);
if (!status.isOK()) {
return status;
}
_data.parse(newValueElement.Obj());
return Status::OK();
}
Status SpecializedClusterServerParameter::validate(
const BSONElement& newValueElement, const boost::optional<TenantId>& tenantId) const {
try {
auto obj = newValueElement.Obj();
auto strValue = obj["strData"_sd].String();
auto intValue = obj["intData"_sd].Int();
if (strValue.size() == 0 || intValue < 0) {
return Status{ErrorCodes::BadValue,
"Invalid fields provided to specializedCluster parameter"};
}
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing specializedCluster parameter"};
}
return Status::OK();
}
Status SpecializedClusterServerParameter::reset(const boost::optional<TenantId>& tenantId) {
_data.reset();
return Status::OK();
}
LogicalTime SpecializedClusterServerParameter::getClusterParameterTime(
const boost::optional<TenantId>& tenantId) const {
return _data.getClusterParameterTime();
}
TEST(SpecializedServerParameter, clusterServerParameter) {
auto* clusterSet = ServerParameterSet::getClusterParameterSet();
constexpr auto kSpecializedCSPName = "specializedCluster"_sd;

View File

@ -47,6 +47,9 @@
namespace mongo {
namespace test {
const std::string& getGlobalSCSP();
const std::string& getGlobalSWO();
struct ExtraDataForServerParameter {
std::string value = "start value";
bool flag = true;

View File

@ -0,0 +1,292 @@
/**
* Copyright (C) 2025-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/idl/server_parameter_specialized_test.h"
#include "mongo/idl/server_parameter_specialized_test_gen.h"
namespace mongo {
namespace test {
namespace {
std::string gSCSP("Initial Value");
std::string gSWO = "Initial Value";
} // namespace
const std::string& getGlobalSCSP() {
return gSCSP;
}
const std::string& getGlobalSWO() {
return gSWO;
}
// specializedDummy
void SpecializedDummyServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << "Dummy Value";
}
Status SpecializedDummyServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return Status::OK();
}
// specializedDummy
void SpecializedDeprecatedServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << "Dummy Value";
}
Status SpecializedDeprecatedServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return Status::OK();
}
// specializedWithCtor
SpecializedConstructorServerParameter::SpecializedConstructorServerParameter(
StringData name, ServerParameterType spt)
: ServerParameter(name, spt) {
gSCSP = "Value from ctor";
}
void SpecializedConstructorServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << getGlobalSCSP();
}
Status SpecializedConstructorServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
gSCSP = std::string{value};
return Status::OK();
}
// specializedWithValue
void SpecializedWithValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return NumberParser{}(value, &_data);
}
// specializedWithStringValue
void SpecializedWithStringValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithStringValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
_data = std::string{value};
return Status::OK();
}
// specializedWithAtomicValue
void SpecializedWithAtomicValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data.load();
}
Status SpecializedWithAtomicValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
std::uint32_t val;
auto status = NumberParser{}(value, &val);
if (!status.isOK()) {
return status;
}
_data.store(val);
return Status::OK();
}
// specializedWithMultiValue
void SpecializedMultiValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << BSON("value" << _data.value << "flag" << _data.flag);
}
Status SpecializedMultiValueServerParameter::set(const BSONElement& value,
const boost::optional<TenantId>&) try {
auto obj = value.Obj();
_data.value = obj["value"].String();
_data.flag = obj["flag"].Bool();
return Status::OK();
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing extra data"};
}
Status SpecializedMultiValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return set(BSON("" << BSON("value" << value << "flag" << false)).firstElement(), boost::none);
}
// specializedWithCtorAndValue
SpecializedWithCtorAndValueServerParameter::SpecializedWithCtorAndValueServerParameter(
StringData name, ServerParameterType spt)
: ServerParameter(name, spt) {}
void SpecializedWithCtorAndValueServerParameter::append(OperationContext*,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
*b << name << _data;
}
Status SpecializedWithCtorAndValueServerParameter::setFromString(StringData value,
const boost::optional<TenantId>&) {
return NumberParser{}(value, &_data);
}
// specializedWithOptions
Status SpecializedWithOptions::setFromString(StringData value, const boost::optional<TenantId>&) {
gSWO = std::string{value};
return Status::OK();
}
// specializedRuntimeOnly
void SpecializedRuntimeOnly::append(OperationContext*,
BSONObjBuilder*,
StringData,
const boost::optional<TenantId>&) {}
Status SpecializedRuntimeOnly::setFromString(StringData value, const boost::optional<TenantId>&) {
return Status::OK();
}
Status SpecializedRedactedSettable::setFromString(StringData value,
const boost::optional<TenantId>&) {
std::cout << "Setting to: " << value << "\n";
_data = std::string{value};
return Status::OK();
}
// specializedWithValidateServerParameter
void SpecializedWithValidateServerParameter::append(OperationContext*,
BSONObjBuilder*,
StringData,
const boost::optional<TenantId>&) {}
Status SpecializedWithValidateServerParameter::setFromString(StringData str,
const boost::optional<TenantId>&) {
return NumberParser{}(str, &_data);
}
Status SpecializedWithValidateServerParameter::validate(
const BSONElement& newValueElement, const boost::optional<TenantId>& tenantId) const {
try {
auto val = newValueElement.Int();
if (val < 0) {
return Status{ErrorCodes::BadValue,
"specializedWithValidate must be a non-negative integer"};
}
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing specializedWithValidate"};
}
return Status::OK();
}
// specializedWithClusterServerParameter
void SpecializedClusterServerParameter::append(OperationContext*,
BSONObjBuilder* builder,
StringData name,
const boost::optional<TenantId>& tenantId) {
builder->append("_id"_sd, name);
builder->appendElementsUnique(_data.toBSON());
}
Status SpecializedClusterServerParameter::set(const BSONElement& newValueElement,
const boost::optional<TenantId>& tenantId) {
Status status = validate(newValueElement, tenantId);
if (!status.isOK()) {
return status;
}
_data.parse(newValueElement.Obj());
return Status::OK();
}
Status SpecializedClusterServerParameter::validate(
const BSONElement& newValueElement, const boost::optional<TenantId>& tenantId) const {
try {
auto obj = newValueElement.Obj();
auto strValue = obj["strData"_sd].String();
auto intValue = obj["intData"_sd].Int();
if (strValue.size() == 0 || intValue < 0) {
return Status{ErrorCodes::BadValue,
"Invalid fields provided to specializedCluster parameter"};
}
} catch (const AssertionException&) {
return {ErrorCodes::BadValue, "Failed parsing specializedCluster parameter"};
}
return Status::OK();
}
Status SpecializedClusterServerParameter::reset(const boost::optional<TenantId>& tenantId) {
_data.reset();
return Status::OK();
}
LogicalTime SpecializedClusterServerParameter::getClusterParameterTime(
const boost::optional<TenantId>& tenantId) const {
return _data.getClusterParameterTime();
}
} // namespace test
} // namespace mongo

View File

@ -51,10 +51,6 @@
#include <fmt/format.h>
namespace mongo {
AtomicWord<int> test::gStdIntPreallocated;
AtomicWord<int> test::gStdIntPreallocatedUpdateCount;
size_t test::count;
namespace {
using SPT = ServerParameterType;

View File

@ -0,0 +1,37 @@
/**
* Copyright (C) 2025-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/platform/atomic_word.h"
namespace mongo::test {
AtomicWord<int> gStdIntPreallocated;
AtomicWord<int> gStdIntPreallocatedUpdateCount;
size_t count;
} // namespace mongo::test

View File

@ -32,7 +32,7 @@ global:
cpp_namespace: "mongo::idl::test"
cpp_includes:
- "mongo/idl/idl_test_types.h"
- "mongo/idl/idl_test.h"
- "mongo/idl/idl_test_defs.h"
imports:
- "mongo/db/basic_types.idl"

Some files were not shown because too many files have changed in this diff Show More