Co-authored-by: auto-revert-processor <devprod-si-team@mongodb.com> GitOrigin-RevId: 3e4d6c3a8e56ad19beced101f8f82dce3d759f32
This commit is contained in:
parent
2e04fd57a7
commit
cb16dc433c
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@ -364,7 +364,6 @@ 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
|
||||
@ -3314,7 +3313,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 @10gen/server-programmability @svc-auto-approve-bot
|
||||
/src/third_party/**/googletest_restricted_for_disagg_only @10gen/server-disagg-storage @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
|
||||
|
||||
@ -20,12 +20,6 @@
|
||||
"*.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"
|
||||
@ -71,34 +65,6 @@
|
||||
],
|
||||
},
|
||||
"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": [
|
||||
@ -116,8 +82,7 @@
|
||||
"bazelbuild.vscode-bazel",
|
||||
"rioj7.command-variable",
|
||||
"augustocdias.tasks-shell-input",
|
||||
"ms-vscode.cpptools",
|
||||
"matepek.vscode-catch2-test-adapter",
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
},
|
||||
"tasks": {
|
||||
@ -157,31 +122,6 @@
|
||||
"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": {
|
||||
|
||||
@ -926,7 +926,6 @@ 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
|
||||
@ -958,12 +957,12 @@ def mongo_cc_unit_test(
|
||||
additional_linker_inputs = [],
|
||||
features = [],
|
||||
exec_properties = {},
|
||||
provides_main = False,
|
||||
has_custom_mainline = False,
|
||||
**kwargs):
|
||||
mongo_cc_test(
|
||||
name = name,
|
||||
srcs = srcs,
|
||||
deps = deps + ([] if provides_main else ["//src/mongo/unittest:unittest_main"]),
|
||||
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:unittest_main"]),
|
||||
private_hdrs = private_hdrs,
|
||||
visibility = visibility,
|
||||
data = data,
|
||||
@ -1343,12 +1342,12 @@ def mongo_cc_benchmark(
|
||||
additional_linker_inputs = [],
|
||||
features = [],
|
||||
exec_properties = {},
|
||||
provides_main = False,
|
||||
has_custom_mainline = False,
|
||||
**kwargs):
|
||||
mongo_cc_test(
|
||||
name = name,
|
||||
srcs = srcs,
|
||||
deps = deps + ([] if provides_main else ["//src/mongo/unittest:benchmark_main"]),
|
||||
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:benchmark_main"]),
|
||||
private_hdrs = private_hdrs,
|
||||
visibility = visibility,
|
||||
data = data,
|
||||
@ -1384,12 +1383,12 @@ def mongo_cc_integration_test(
|
||||
additional_linker_inputs = [],
|
||||
features = [],
|
||||
exec_properties = {},
|
||||
provides_main = False,
|
||||
has_custom_mainline = False,
|
||||
**kwargs):
|
||||
mongo_cc_test(
|
||||
name = name,
|
||||
srcs = srcs,
|
||||
deps = deps + ([] if provides_main else ["//src/mongo/unittest:integration_test_main"]),
|
||||
deps = deps + ([] if has_custom_mainline else ["//src/mongo/unittest:integration_test_main"]),
|
||||
private_hdrs = private_hdrs,
|
||||
visibility = visibility,
|
||||
data = data,
|
||||
@ -1425,7 +1424,7 @@ def mongo_cc_fuzzer_test(
|
||||
additional_linker_inputs = [],
|
||||
features = [],
|
||||
exec_properties = {},
|
||||
provides_main = False,
|
||||
has_custom_mainline = False,
|
||||
**kwargs):
|
||||
mongo_cc_test(
|
||||
name = name,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import json
|
||||
import time
|
||||
from glob import glob
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import typer
|
||||
@ -49,7 +48,7 @@ def main(testlog_dir: str):
|
||||
else:
|
||||
status = "pass"
|
||||
|
||||
log_raw = Path(test_xml).with_suffix(".log").read_text()
|
||||
log_raw = testsuite.find("system-out").text
|
||||
|
||||
# Bazel gives just a duration, while Evergreen expects a start and end
|
||||
# time to calculate the duration. Evergreen itself does something similar
|
||||
|
||||
@ -3360,17 +3360,12 @@ return std::move({varname});"""
|
||||
|
||||
with self._condition(opt.condition):
|
||||
with self._block(section, ";"):
|
||||
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})")
|
||||
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})
|
||||
""")
|
||||
if opt.hidden:
|
||||
self._writer.write_line(".hidden()")
|
||||
if opt.redact:
|
||||
|
||||
@ -1023,7 +1023,6 @@ 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"),
|
||||
|
||||
@ -932,7 +932,6 @@ 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]
|
||||
|
||||
@ -42,7 +42,5 @@ class CPPIntegrationTestCase(interface.ProcessTestCase):
|
||||
|
||||
def _make_process(self):
|
||||
return core.programs.generic_program(
|
||||
self.logger,
|
||||
[self.program_executable, "--enhancedReporter=false"],
|
||||
**self.program_options,
|
||||
self.logger, [self.program_executable], **self.program_options
|
||||
)
|
||||
|
||||
@ -29,7 +29,5 @@ class CPPUnitTestCase(interface.ProcessTestCase):
|
||||
|
||||
def _make_process(self):
|
||||
return core.programs.make_process(
|
||||
self.logger,
|
||||
[self.program_executable, "--enhancedReporter=false"],
|
||||
**self.program_options,
|
||||
self.logger, [self.program_executable], **self.program_options
|
||||
)
|
||||
|
||||
@ -39,6 +39,3 @@ filters:
|
||||
- "server_parameters.md":
|
||||
approvers:
|
||||
- 10gen/server-programmability
|
||||
- "unit_test.md":
|
||||
approvers:
|
||||
- 10gen/server-programmability
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
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
|
||||
@ -1216,8 +1216,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_tests_remote_exec_incompatible
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1245,8 +1243,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group1
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1274,8 +1270,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group2
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1303,8 +1297,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group3
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1332,8 +1324,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group4
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1361,8 +1351,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group5
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1390,8 +1378,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group6
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1419,8 +1405,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group7
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1448,8 +1432,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: unit_test_group8
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
@ -1477,8 +1459,6 @@ 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=--enhancedReporter=false
|
||||
|
||||
- name: monitor_build_status
|
||||
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
|
||||
|
||||
96
sbom.json
96
sbom.json
@ -1165,6 +1165,59 @@
|
||||
},
|
||||
"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",
|
||||
@ -1319,49 +1372,6 @@
|
||||
},
|
||||
"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",
|
||||
|
||||
@ -1271,17 +1271,6 @@ 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.
|
||||
@ -1298,6 +1287,7 @@ 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",
|
||||
@ -1345,20 +1335,19 @@ 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",
|
||||
],
|
||||
|
||||
@ -450,7 +450,6 @@ mongo_cc_library(
|
||||
"//src/mongo/db:query_matcher",
|
||||
"//src/mongo/db:service_context",
|
||||
"//src/mongo/db/update:update_driver",
|
||||
"//src/mongo/unittest",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -150,13 +150,6 @@ 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) {
|
||||
@ -179,14 +172,14 @@ public:
|
||||
/*recordIds*/ {},
|
||||
/*fromMigrate=*/std::vector<bool>(stmts.size(), false),
|
||||
/*defaultFromMigrate=*/false);
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
wuow.commit();
|
||||
|
||||
// The cache should only invalidate after the WUOW commits if shouldInvalidateCache is true.
|
||||
if (shouldInvalidateCache) {
|
||||
assertCounts(0, 1, 0);
|
||||
mockRouter->assertCounts(0, 1, 0);
|
||||
} else {
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,13 +203,13 @@ public:
|
||||
OplogUpdateEntryArgs entryArgs(&updateArgs, *autoColl);
|
||||
opObserver.onUpdate(opCtx.get(), entryArgs);
|
||||
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
wuow.commit();
|
||||
|
||||
if (shouldInvalidateCache) {
|
||||
assertCounts(0, 1, 0);
|
||||
mockRouter->assertCounts(0, 1, 0);
|
||||
} else {
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,13 +225,13 @@ public:
|
||||
|
||||
const auto& deleteDocumentKey = getDocumentKey(*coll, deleteDoc);
|
||||
opObserver.onDelete(opCtx.get(), *coll, {}, deleteDoc, deleteDocumentKey, args);
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
wuow.commit();
|
||||
|
||||
if (shouldInvalidateCache) {
|
||||
assertCounts(0, 1, 0);
|
||||
mockRouter->assertCounts(0, 1, 0);
|
||||
} else {
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,13 +242,13 @@ public:
|
||||
|
||||
WriteUnitOfWork wuow(opCtx.get());
|
||||
opObserver.onDropDatabase(opCtx.get(), dbname, false /*fromMigrate*/);
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
wuow.commit();
|
||||
|
||||
if (shouldInvalidateCache) {
|
||||
assertCounts(1, 0, 0);
|
||||
mockRouter->assertCounts(1, 0, 0);
|
||||
} else {
|
||||
assertCounts(0, 0, 0);
|
||||
mockRouter->assertCounts(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -39,10 +39,6 @@ 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 {
|
||||
@ -66,8 +62,10 @@ public:
|
||||
_wholeCacheCount.store(0);
|
||||
}
|
||||
|
||||
Counts counts() const {
|
||||
return {_byNameCount.load(), _byTenantCount.load(), _wholeCacheCount.load()};
|
||||
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());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -197,7 +197,7 @@ struct SCRAMStepsResult {
|
||||
}
|
||||
};
|
||||
|
||||
class SCRAMFixture : public mongo::unittest::Test, public testing::WithParamInterface<bool> {
|
||||
class SCRAMFixture : public mongo::unittest::Test {
|
||||
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() override {
|
||||
void setUp() final {
|
||||
auto serviceContextHolder = ServiceContext::make();
|
||||
serviceContext = serviceContextHolder.get();
|
||||
setGlobalServiceContext(std::move(serviceContextHolder));
|
||||
@ -238,14 +238,6 @@ 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());
|
||||
@ -256,7 +248,7 @@ protected:
|
||||
"MockServer.test:27017");
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
void tearDown() final {
|
||||
opCtx.reset();
|
||||
client.reset();
|
||||
setGlobalServiceContext(nullptr);
|
||||
@ -267,7 +259,7 @@ protected:
|
||||
}
|
||||
|
||||
std::string createPasswordDigest(StringData username, StringData password) {
|
||||
if (_digestPassword()) {
|
||||
if (_digestPassword) {
|
||||
return mongo::createPasswordDigest(username, password);
|
||||
} else {
|
||||
return std::string{password};
|
||||
@ -309,14 +301,24 @@ protected:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool _digestPassword() const {
|
||||
return GetParam();
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(, SCRAMFixture, testing::Values(false, true));
|
||||
|
||||
TEST_P(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
|
||||
TEST_F(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -338,7 +340,7 @@ TEST_P(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
|
||||
TEST_F(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -360,7 +362,7 @@ TEST_P(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testClientStep2GivesBadProof) {
|
||||
TEST_F(SCRAMFixture, testClientStep2GivesBadProof) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -385,7 +387,7 @@ TEST_P(SCRAMFixture, testClientStep2GivesBadProof) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testServerStep2GivesBadVerifier) {
|
||||
TEST_F(SCRAMFixture, testServerStep2GivesBadVerifier) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -418,7 +420,7 @@ TEST_P(SCRAMFixture, testServerStep2GivesBadVerifier) {
|
||||
}
|
||||
|
||||
|
||||
TEST_P(SCRAMFixture, testSCRAM) {
|
||||
TEST_F(SCRAMFixture, testSCRAM) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -431,7 +433,7 @@ TEST_P(SCRAMFixture, testSCRAM) {
|
||||
ASSERT_EQ(goalState, runSteps());
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
|
||||
TEST_F(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -449,7 +451,7 @@ TEST_P(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) {
|
||||
ASSERT_EQ(goalState, runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
|
||||
TEST_F(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -470,7 +472,7 @@ TEST_P(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
|
||||
TEST_F(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -491,7 +493,7 @@ TEST_P(SCRAMFixture, testSCRAMWithInvalidChannelBinding) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testNULLInPassword) {
|
||||
TEST_F(SCRAMFixture, testNULLInPassword) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "saj\0ack"), BSONObj()));
|
||||
|
||||
@ -505,7 +507,7 @@ TEST_P(SCRAMFixture, testNULLInPassword) {
|
||||
}
|
||||
|
||||
|
||||
TEST_P(SCRAMFixture, testCommasInUsernameAndPassword) {
|
||||
TEST_F(SCRAMFixture, testCommasInUsernameAndPassword) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("s,a,jack", "s,a,jack"), BSONObj()));
|
||||
|
||||
@ -518,7 +520,7 @@ TEST_P(SCRAMFixture, testCommasInUsernameAndPassword) {
|
||||
ASSERT_EQ(goalState, runSteps());
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testIncorrectUser) {
|
||||
TEST_F(SCRAMFixture, testIncorrectUser) {
|
||||
saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack");
|
||||
saslClientSession->setParameter(NativeSaslClientSession::parameterPassword,
|
||||
createPasswordDigest("sajack", "sajack"));
|
||||
@ -531,7 +533,7 @@ TEST_P(SCRAMFixture, testIncorrectUser) {
|
||||
runSteps());
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testIncorrectPassword) {
|
||||
TEST_F(SCRAMFixture, testIncorrectPassword) {
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
|
||||
@ -547,7 +549,7 @@ TEST_P(SCRAMFixture, testIncorrectPassword) {
|
||||
runSteps());
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testOptionalClientExtensions) {
|
||||
TEST_F(SCRAMFixture, testOptionalClientExtensions) {
|
||||
// Verify server ignores unknown/optional extensions sent by client.
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
@ -571,7 +573,7 @@ TEST_P(SCRAMFixture, testOptionalClientExtensions) {
|
||||
runSteps(mutator));
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testOptionalServerExtensions) {
|
||||
TEST_F(SCRAMFixture, testOptionalServerExtensions) {
|
||||
// Verify client errors on unknown/optional extensions sent by server.
|
||||
ASSERT_OK(authzBackend->insertUserDocument(
|
||||
opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()));
|
||||
@ -658,11 +660,11 @@ void runTestClientConversationUsesCacheTest(SaslClientSession* saslClientSession
|
||||
assertCacheStats(cache, 5, 4, 2);
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testClientConversationUsesCacheSHA1) {
|
||||
TEST_F(SCRAMFixture, testClientConversationUsesCacheSHA1) {
|
||||
runTestClientConversationUsesCacheTest<SHA1Block>(saslClientSession.get());
|
||||
}
|
||||
|
||||
TEST_P(SCRAMFixture, testClientConversationUsesCacheSHA256) {
|
||||
TEST_F(SCRAMFixture, testClientConversationUsesCacheSHA256) {
|
||||
runTestClientConversationUsesCacheTest<SHA256Block>(saslClientSession.get());
|
||||
}
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ void setX509PeerInfo(const std::shared_ptr<transport::Session>& session, SSLPeer
|
||||
|
||||
class SASLX509Test : public mongo::unittest::Test {
|
||||
protected:
|
||||
void SetUp() override try {
|
||||
void setUp() final try {
|
||||
auto serviceContextHolder = ServiceContext::make();
|
||||
serviceContext = serviceContextHolder.get();
|
||||
setGlobalServiceContext(std::move(serviceContextHolder));
|
||||
@ -158,7 +158,6 @@ 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();
|
||||
@ -190,6 +189,12 @@ protected:
|
||||
saslServerSession.reset();
|
||||
}
|
||||
|
||||
public:
|
||||
void run() {
|
||||
LOGV2(82092, "X509 variant");
|
||||
Test::run();
|
||||
}
|
||||
|
||||
protected:
|
||||
ServiceContext* serviceContext;
|
||||
Client* client;
|
||||
|
||||
@ -63,8 +63,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
using FeatureCompatibilityVersionTestFixtureDeathTest = FeatureCompatibilityVersionTestFixture;
|
||||
DEATH_TEST_F(FeatureCompatibilityVersionTestFixtureDeathTest, NotInitialized, "invariant") {
|
||||
DEATH_TEST_F(FeatureCompatibilityVersionTestFixture, NotInitialized, "invariant") {
|
||||
FeatureCompatibilityVersion::fassertInitializedAfterStartup(operationContext());
|
||||
}
|
||||
|
||||
|
||||
@ -142,7 +142,7 @@ enum ShardFilteringStrategy { NoShardFilter, ShardFilter };
|
||||
|
||||
class ShardFilteringDistinctScanPerfTestFixture : public QueryShardServerTestFixture {
|
||||
public:
|
||||
void TestBody() override {}
|
||||
void _doTest() final { /* Unused. */ }
|
||||
|
||||
struct DistinctScanParamsForTest {
|
||||
// Collection & sharding set-up.
|
||||
|
||||
@ -48,10 +48,7 @@ namespace unittest {
|
||||
std::ostringstream os; \
|
||||
os << "Expected [ " << aExpression << " " #OPERATOR " " << bExpression \
|
||||
<< " ] but found [ " << aValue << " " #OPERATOR " " << bValue << "]"; \
|
||||
GTEST_MESSAGE_AT_(theFile.c_str(), \
|
||||
theLine, \
|
||||
os.str().c_str(), \
|
||||
::testing::TestPartResult::kFatalFailure); \
|
||||
TestAssertionFailure(theFile, theLine, os.str()).stream(); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@ -66,20 +66,37 @@ BSONObj wrapInLiteral(const T& arg) {
|
||||
return BSON("$literal" << arg);
|
||||
}
|
||||
|
||||
enum AllowFallBackToDefault : bool {};
|
||||
enum AllowFastPath : bool {};
|
||||
|
||||
class BaseInclusionProjectionExecutionTest : public mongo::unittest::Test,
|
||||
public testing::WithParamInterface<AllowFastPath> {
|
||||
/**
|
||||
* 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 {
|
||||
public:
|
||||
/**
|
||||
* 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()} {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
auto createProjectionExecutor(const BSONObj& projSpec,
|
||||
@ -113,7 +130,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);
|
||||
}
|
||||
@ -156,34 +173,21 @@ protected:
|
||||
projSpec, matchSpec, ProjectionPolicies::findProjectionPolicies());
|
||||
}
|
||||
|
||||
AllowFallBackToDefault _allowFallBackToDefault;
|
||||
// True, if the projection executor is allowed to use the fast-path inclusion projection
|
||||
// implementation.
|
||||
AllowFastPath _allowFastPath;
|
||||
bool _allowFastPath{true};
|
||||
// Run the test using fast-path projection mode.
|
||||
bool _runFastPath{true};
|
||||
// Run the test using default projection mode.
|
||||
bool _runDefault{true};
|
||||
};
|
||||
|
||||
class InclusionProjectionExecutionTestWithFallBackToDefault
|
||||
: public BaseInclusionProjectionExecutionTest {
|
||||
public:
|
||||
InclusionProjectionExecutionTestWithFallBackToDefault()
|
||||
: BaseInclusionProjectionExecutionTest{AllowFallBackToDefault{true}} {}
|
||||
};
|
||||
INSTANTIATE_TEST_SUITE_P(,
|
||||
InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
|
||||
using InclusionProjectionExecutionTestWithFallBackToDefault =
|
||||
BaseInclusionProjectionExecutionTest<true>;
|
||||
using InclusionProjectionExecutionTestWithoutFallBackToDefault =
|
||||
BaseInclusionProjectionExecutionTest<false>;
|
||||
|
||||
class InclusionProjectionExecutionTestWithoutFallBackToDefault
|
||||
: public BaseInclusionProjectionExecutionTest {
|
||||
public:
|
||||
InclusionProjectionExecutionTestWithoutFallBackToDefault()
|
||||
: BaseInclusionProjectionExecutionTest{AllowFallBackToDefault{false}} {}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(,
|
||||
InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
testing::Values(AllowFastPath{true}, AllowFastPath{false}));
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldAddIncludedFieldsToDependencies) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("_id" << false << "a" << true << "x.y" << true));
|
||||
@ -197,7 +201,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("x.y"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldAddIdToDependenciesIfNotSpecified) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
|
||||
|
||||
@ -209,7 +213,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("a"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddDependenciesOfComputedFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$a"
|
||||
<< "x"
|
||||
@ -224,7 +228,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("z"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddPathToDependenciesForNestedComputedFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a.b.c" << BSON("$add" << BSON_ARRAY(1 << 2))));
|
||||
@ -238,7 +242,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("a.b"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldNotAddTopLevelDependencyWithExpressionOnTopLevelPath) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a" << BSON("$add" << BSON_ARRAY(1 << 2))));
|
||||
@ -250,7 +254,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("_id"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddPathToDependenciesForNestedComputedFieldsUsingVariableReferences) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("x.y" << "$z"));
|
||||
|
||||
@ -266,7 +270,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_EQ(deps.fields.count("x"), 1UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldSerializeToEquivalentProjection) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
fromjson("{a: {$add: ['$a', 2]}, b: {d: 3}, 'x.y': {$literal: 4}}"));
|
||||
@ -289,7 +293,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldSerializeExplicitExclusionOfId) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << false << "a" << true));
|
||||
@ -310,7 +314,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerializeWithTopLevelID) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerializeWithTopLevelID) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << 1 << "b" << 1));
|
||||
auto serialization = inclusion->serializeTransformation();
|
||||
ASSERT_VALUE_EQ(serialization["a"], Value(true));
|
||||
@ -347,7 +351,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldSerialize
|
||||
ASSERT_VALUE_EQ(serialization["_id"], Value(true));
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopLevelExpressions) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopLevelExpressions) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a" << BSON("$add" << BSON_ARRAY(1 << 2))));
|
||||
|
||||
@ -368,7 +372,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeTopL
|
||||
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNestedExpressions) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNestedExpressions) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a.b" << BSON("$add" << BSON_ARRAY(1 << 2))));
|
||||
|
||||
@ -390,7 +394,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldOptimizeNest
|
||||
.verbosity = ExplainOptions::Verbosity::kExecAllPlans}));
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldReportThatAllExceptIncludedFieldsAreModified) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << wrapInLiteral("computedVal") << "b.c" << wrapInLiteral("computedVal") << "d"
|
||||
@ -408,7 +412,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_EQ(modifiedPaths.paths.size(), 3UL);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldReportThatAllExceptIncludedFieldsAreModifiedWithIdExclusion) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("_id" << false << "a" << wrapInLiteral("computedVal") << "b.c"
|
||||
@ -432,7 +436,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
// Top-level only.
|
||||
//
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTopLevelField) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTopLevelField) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
|
||||
|
||||
// More than one field in document.
|
||||
@ -456,7 +460,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeTo
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedTopLevelField) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedTopLevelField) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("newField" << wrapInLiteral("computedVal")));
|
||||
auto result = inclusion->applyTransformation(Document{});
|
||||
@ -469,7 +473,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddComputedT
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldApplyBothInclusionsAndComputedFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << true << "newField" << wrapInLiteral("computedVal")));
|
||||
@ -478,7 +482,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldIncludeFieldsInOrderOfInputDoc) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("first" << true << "second" << true << "third" << true));
|
||||
@ -487,7 +491,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, inputDoc);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldApplyComputedFieldsInOrderSpecified) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON(
|
||||
"firstComputed" << wrapInLiteral("FIRST") << "secondComputed" << wrapInLiteral("SECOND")));
|
||||
@ -497,7 +501,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldImplicitlyIncludeId) {
|
||||
TEST_F(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}};
|
||||
@ -509,7 +513,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldImplicitl
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldImplicitlyIncludeIdWithComputedFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("newField" << wrapInLiteral("computedVal")));
|
||||
@ -518,7 +522,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldIncludeIdIfExplicitlyIncluded) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << true << "_id" << true << "b" << true));
|
||||
@ -528,7 +532,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldExcludeIdIfExplicitlyExcluded) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a" << true << "_id" << false));
|
||||
@ -537,7 +541,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWithComputedId) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWithComputedId) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << wrapInLiteral("newId")));
|
||||
auto result = inclusion->applyTransformation(Document{{"a", 1}, {"b", 2}, {"_id", "ID"_sd}});
|
||||
@ -549,7 +553,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldReplaceIdWit
|
||||
// Projections with nested fields.
|
||||
//
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldIncludeSimpleDottedFieldFromSubDoc) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
|
||||
|
||||
@ -574,7 +578,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldNotCreateSubDocIfDottedIncludedFieldDoesNotExist) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("sub.target" << true));
|
||||
|
||||
@ -589,7 +593,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldApplyDottedInclusionToEachElementInArray) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
|
||||
|
||||
@ -607,7 +611,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddComputedDottedFieldToSubDocument) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("sub.target" << wrapInLiteral("computedVal")));
|
||||
@ -629,7 +633,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldCreateSubDocIfDottedComputedFieldDoesntExist) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("sub.target" << wrapInLiteral("computedVal")));
|
||||
@ -644,7 +648,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldCreateNestedSubDocumentsAllTheWayToComputedField) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a.b.c.d" << wrapInLiteral("computedVal")));
|
||||
@ -660,7 +664,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddComputedDottedFieldToEachElementInArray) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << wrapInLiteral("COMPUTED")));
|
||||
@ -683,7 +687,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldApplyInclusionsAndAdditionsToEachElementInArray) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a.inc" << true << "a.comp" << wrapInLiteral("COMPUTED")));
|
||||
@ -711,7 +715,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrIncludeSubFieldsOfId) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrIncludeSubFieldsOfId) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("_id.X" << true << "_id.Z" << wrapInLiteral("NEW")));
|
||||
auto result = inclusion->applyTransformation(Document{{"_id", Document{{"X", 1}, {"Y", 2}}}});
|
||||
@ -719,7 +723,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldAddOrInclude
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(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".
|
||||
@ -743,7 +747,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldApplyNestedComputedFieldsInOrderSpecified) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << wrapInLiteral("FIRST") << "b.c" << wrapInLiteral("SECOND")));
|
||||
@ -752,7 +756,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldApplyComputedFieldsAfterAllInclusions) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("b.c" << wrapInLiteral("NEW") << "a" << true));
|
||||
@ -772,7 +776,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ComputedFieldReplacingExistingShouldAppearAfterInclusions) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("b" << wrapInLiteral("NEW") << "a" << true));
|
||||
@ -788,7 +792,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
// Metadata inclusion.
|
||||
//
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldAlwaysKeepMetadataFromOriginalDoc) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
|
||||
|
||||
@ -804,7 +808,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedDoc.freeze());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
MetaDependenciesFalseWhenNotIncluded) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1}"));
|
||||
|
||||
@ -828,7 +832,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_FALSE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddSingleMetaExpressionDependency) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$meta: 'geoNearPoint'}}"));
|
||||
@ -855,7 +859,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_FALSE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ShouldAddMetaExpressionsToDependencies) {
|
||||
// Used to set 'score' metadata.
|
||||
RAIIServerParameterControllerForTest featureFlagController("featureFlagRankFusionFull", true);
|
||||
@ -895,7 +899,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_TRUE(deps.metadataDeps()[DocumentMetadataFields::kScore]);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMetaExpressions) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMetaExpressions) {
|
||||
// Used to set 'score' metadata.
|
||||
RAIIServerParameterControllerForTest featureFlagController("featureFlagRankFusionFull", true);
|
||||
auto inclusion =
|
||||
@ -942,7 +946,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ShouldEvaluateMeta
|
||||
// _id inclusion policy.
|
||||
//
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdByDefault) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdByDefault) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
|
||||
|
||||
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
|
||||
@ -951,7 +955,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeId
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdWithIncludePolicy) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeIdWithIncludePolicy) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << true));
|
||||
|
||||
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
|
||||
@ -960,7 +964,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldIncludeId
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeIdWithExcludePolicy) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeIdWithExcludePolicy) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultIdExclusion(BSON("a" << true));
|
||||
|
||||
auto result = inclusion->applyTransformation(Document{{"_id", 2}, {"a", 3}});
|
||||
@ -969,7 +973,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault, ShouldExcludeId
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldOverrideIncludePolicyWithExplicitExcludeIdSpec) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("_id" << false << "a" << true));
|
||||
@ -980,7 +984,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldOverrideExcludePolicyWithExplicitIncludeIdSpec) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultIdExclusion(BSON("_id" << true << "a" << true));
|
||||
@ -991,7 +995,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldAllowInclusionOfIdSubfieldWithDefaultIncludePolicy) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("_id.id1" << true << "a" << true));
|
||||
@ -1003,7 +1007,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldAllowInclusionOfIdSubfieldWithDefaultExcludePolicy) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultIdExclusion(BSON("_id.id1" << true << "a" << true));
|
||||
@ -1019,7 +1023,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
// Nested array recursion.
|
||||
//
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldRecurseNestedArraysByDefault) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << true));
|
||||
|
||||
@ -1033,7 +1037,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldNotRecurseNestedArraysForNoRecursePolicy) {
|
||||
auto inclusion = makeInclusionProjectionWithNoArrayRecursion(BSON("a.b" << true));
|
||||
|
||||
@ -1047,7 +1051,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ShouldRetainNestedArraysIfNoRecursionNeeded) {
|
||||
auto inclusion = makeInclusionProjectionWithNoArrayRecursion(BSON("a" << true));
|
||||
|
||||
@ -1062,7 +1066,7 @@ TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ComputedFieldIsAddedToNestedArrayElementsForRecursePolicy) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a.b" << wrapInLiteral("COMPUTED")));
|
||||
@ -1085,7 +1089,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ComputedFieldShouldReplaceNestedArrayForNoRecursePolicy) {
|
||||
auto inclusion =
|
||||
makeInclusionProjectionWithNoArrayRecursion(BSON("a.b" << wrapInLiteral("COMPUTED")));
|
||||
@ -1112,7 +1116,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedProjections) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedProjections) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("computedMeta1" << BSON("$toUpper" << "$myMeta.x") << "computed2"
|
||||
<< BSON("$add" << BSON_ARRAY(1 << "$c")) << "computedMeta3"
|
||||
@ -1136,7 +1140,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ExtractComputedPro
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ExtractComputedProjectionInProjectShouldNotHideDependentFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
|
||||
<< "b"
|
||||
@ -1154,7 +1158,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ExtractComputedProjectionInProjectShouldNotIncludeId) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << BSON("$sum" << BSON_ARRAY("$myMeta" << "$_id"))));
|
||||
@ -1171,7 +1175,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ExtractComputedProjectionInProjectShouldNotHideDependentSubFields) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
|
||||
<< "b"
|
||||
@ -1189,7 +1193,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ExtractComputedProjectionInProjectShouldNotHideDependentSubFieldsWithDottedSibling) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(BSON("a" << "$myMeta"
|
||||
<< "c.b"
|
||||
@ -1207,7 +1211,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault,
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAfterSplit) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAfterSplit) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << true << "computedMeta1" << BSON("$toUpper" << "$myMeta.x") << "computed2"
|
||||
<< BSON("$add" << BSON_ARRAY(1 << "$c")) << "c" << true << "computedMeta3"
|
||||
@ -1227,7 +1231,7 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, ApplyProjectionAft
|
||||
ASSERT_DOCUMENT_EQ(result, expectedResult);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReservedNames) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReservedNames) {
|
||||
auto inclusion = makeInclusionProjectionWithDefaultPolicies(
|
||||
BSON("a" << true << "data" << BSON("$toUpper" << "$myMeta.x") << "newMeta"
|
||||
<< "$myMeta"));
|
||||
@ -1246,67 +1250,71 @@ TEST_P(InclusionProjectionExecutionTestWithFallBackToDefault, DoNotExtractReserv
|
||||
"{_id: true, a: true, data: {\"$toUpper\" : [\"$myMeta.x\"]}, newMeta: \"$newMeta\"}"));
|
||||
ASSERT_DOCUMENT_EQ(expectedProjection, inclusion->serializeTransformation());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly
|
||||
: public InclusionProjectionExecutionTestWithoutFallBackToDefault {};
|
||||
INSTANTIATE_TEST_SUITE_P(,
|
||||
InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
testing::Values(AllowFastPath{true}));
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
// 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,
|
||||
CannotUseFastPathWithFindPositional) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, 'b.$': 1}"), fromjson("{b: 1}")),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
CannotUseFastPathWithFindSlice) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, CannotUseFastPathWithFindSlice) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, b: {$slice: 2}}"), {}),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
CannotUseFastPathWithFindElemMatch) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithFindPolicies(fromjson("{a: 1, b: {$elemMatch: {c: 1}}}"), {}),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
CannotUseFastPathWithRegularExpression) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$add: ['$c', 1]}}")),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
CannotUseFastPathWithMetadataExpression) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: {$meta: 'randVal'}}")),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
CannotUseFastPathWithLiteral) {
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault, CannotUseFastPathWithLiteral) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(
|
||||
makeInclusionProjectionWithDefaultPolicies(BSON("a" << 1 << "b" << wrapInLiteral("abc"))),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
TEST_P(InclusionProjectionExecutionTestWithoutFallBackToDefaultFastPathOnly,
|
||||
TEST_F(InclusionProjectionExecutionTestWithoutFallBackToDefault,
|
||||
CannotUseFastPathWithFieldPathExpression) {
|
||||
_runDefault = false;
|
||||
ASSERT_THROWS_CODE(makeInclusionProjectionWithDefaultPolicies(fromjson("{a: 1, b: '$c'}")),
|
||||
AssertionException,
|
||||
51752);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fast_path_projection_only_tests
|
||||
} // namespace mongo::projection_executor
|
||||
|
||||
@ -60,23 +60,35 @@
|
||||
|
||||
namespace mongo::projection_executor {
|
||||
namespace {
|
||||
|
||||
enum AllowFastPath : bool {};
|
||||
enum AllowFallBackToDefault : bool {};
|
||||
|
||||
class BaseProjectionExecutorTest : public AggregationContextFixture,
|
||||
public testing::WithParamInterface<AllowFastPath> {
|
||||
/**
|
||||
* 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:
|
||||
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()} {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
projection_ast::Projection parseWithDefaultPolicies(
|
||||
const BSONObj& projectionBson, boost::optional<BSONObj> matchExprBson = boost::none) {
|
||||
return parseWithPolicies(projectionBson, matchExprBson, ProjectionPolicies{});
|
||||
@ -130,39 +142,21 @@ 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.
|
||||
AllowFastPath _allowFastPath;
|
||||
bool _allowFastPath{true};
|
||||
};
|
||||
|
||||
class ProjectionExecutorTestWithFallBackToDefault : public BaseProjectionExecutorTest {
|
||||
public:
|
||||
ProjectionExecutorTestWithFallBackToDefault()
|
||||
: BaseProjectionExecutorTest{AllowFallBackToDefault{true}} {}
|
||||
};
|
||||
using ProjectionExecutorTestWithFallBackToDefault = BaseProjectionExecutorTest<true>;
|
||||
using ProjectionExecutorTestWithoutFallBackToDefault = BaseProjectionExecutorTest<false>;
|
||||
|
||||
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) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionWithIdPath) {
|
||||
auto projWithId = parseWithDefaultPolicies(fromjson("{a: 1, _id: 1}"));
|
||||
auto executor = createProjectionExecutor(projWithId);
|
||||
ASSERT_DOCUMENT_EQ(Document{fromjson("{_id: 123, a: 'abc'}")},
|
||||
@ -176,7 +170,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionWithId
|
||||
Document{fromjson("{_id: 123, a: 'abc', b: 'def', c: 'ghi'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndottedPath) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndottedPath) {
|
||||
auto proj = parseWithDefaultPolicies(fromjson("{a: 1, b: 1}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -184,7 +178,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionUndott
|
||||
executor->applyTransformation(Document{fromjson("{a: 'abc', b: 'def', c: 'ghi'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPath) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPath) {
|
||||
auto proj = parseWithDefaultPolicies(fromjson("{'a.b': 1, 'a.d': 1}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -192,7 +186,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDotted
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: 'abc', c: 'def', d: 'ghi'}}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDottedPathNestedArrays) {
|
||||
TEST_F(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']}")};
|
||||
@ -204,14 +198,14 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectInclusionDotted
|
||||
ASSERT_BSONOBJ_EQ(expected, found);
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpression) {
|
||||
TEST_F(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_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpressionWithCommonParent) {
|
||||
TEST_F(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);
|
||||
@ -219,7 +213,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectExpressionWithComm
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: {e: 4}, p: 2}}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithIdPath) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithIdPath) {
|
||||
auto projWithoutId = parseWithDefaultPolicies(fromjson("{a: 0, _id: 0}"));
|
||||
auto executor = createProjectionExecutor(projWithoutId);
|
||||
ASSERT_DOCUMENT_EQ(Document{fromjson("{b: 'def', c: 'ghi'}")},
|
||||
@ -227,7 +221,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionWithId
|
||||
Document{fromjson("{_id: 123, a: 'abc', b: 'def', c: 'ghi'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndottedPath) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndottedPath) {
|
||||
auto proj = parseWithDefaultPolicies(fromjson("{a: 0, b: 0}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -235,7 +229,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionUndott
|
||||
executor->applyTransformation(Document{fromjson("{a: 'abc', b: 'def', c: 'ghi'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPath) {
|
||||
TEST_F(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPath) {
|
||||
auto proj = parseWithDefaultPolicies(fromjson("{'a.b': 0, 'a.d': 0}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -243,7 +237,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDotted
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: 'abc', c: 'def', d: 'ghi'}}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDottedPathNestedArrays) {
|
||||
TEST_F(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']}")},
|
||||
@ -251,7 +245,7 @@ TEST_P(ProjectionExecutorTestWithoutFallBackToDefault, CanProjectExclusionDotted
|
||||
"{a: [{b: 'abc', c: 'def'}, [{b: 'abc', c: 'def'}, 'd'], 'd']}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
|
||||
auto proj =
|
||||
parseWithFindFeaturesEnabled(fromjson("{'a.b.$': 1}"), fromjson("{'a.b': {$gte: 3}}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
@ -262,7 +256,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindPositional) {
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [4, 3, 2]}}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithInclusion) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithInclusion) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{a: {$elemMatch: {b: {$gte: 3}}}, c: 1}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -270,7 +264,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithI
|
||||
executor->applyTransformation(Document{fromjson("{a: [{b: 1}, {b: 2}, {b: 3}]}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatch) {
|
||||
TEST_F(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}}}"));
|
||||
@ -287,7 +281,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatch) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
|
||||
auto collator =
|
||||
std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString);
|
||||
getExpCtx()->setCollator(std::move(collator));
|
||||
@ -300,7 +294,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, ElemMatchRespectsCollator) {
|
||||
executor->applyTransformation(Document{fromjson("{a: ['zaa', 'zbb', 'zdd', 'zee']}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithExclusion) {
|
||||
TEST_F(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'}")},
|
||||
@ -308,7 +302,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindElemMatchWithE
|
||||
fromjson("{a: [{b: 1}, {b: 2}, {b: 3}], c: 'abc', d: 'def'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclusion) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclusion) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 1}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -316,7 +310,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceWithInclu
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3]}, c: 'abc'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithInclusion) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithInclusion) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 1}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -324,7 +318,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimit
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWithExclusion) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWithExclusion) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: 3}, c: 0}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -332,7 +326,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceBasicWith
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithExclusion) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimitWithExclusion) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, c: 0}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
ASSERT_DOCUMENT_EQ(
|
||||
@ -340,7 +334,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceSkipLimit
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: 'abc'}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositional) {
|
||||
TEST_F(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositional) {
|
||||
auto proj = parseWithFindFeaturesEnabled(fromjson("{'a.b': {$slice: [1,2]}, 'c.$': 1}"),
|
||||
fromjson("{c: {$gte: 6}}"));
|
||||
auto executor = createProjectionExecutor(proj);
|
||||
@ -349,7 +343,7 @@ TEST_P(ProjectionExecutorTestWithFallBackToDefault, CanProjectFindSliceAndPositi
|
||||
executor->applyTransformation(Document{fromjson("{a: {b: [1,2,3,4]}, c: [5,6,7]}")}));
|
||||
}
|
||||
|
||||
TEST_P(ProjectionExecutorTestWithFallBackToDefault, ExecutorOptimizesExpression) {
|
||||
TEST_F(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}}")},
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#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>
|
||||
|
||||
@ -42,19 +41,11 @@ public:
|
||||
void runVariation(const RunVariationParams& params) override {
|
||||
return;
|
||||
}
|
||||
void TestBody() override {
|
||||
void _doTest() 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,
|
||||
@ -148,15 +139,14 @@ public:
|
||||
|
||||
sharedTest.tearDown();
|
||||
} // runVariation
|
||||
void TestBody() {
|
||||
void _doTest() {
|
||||
return;
|
||||
}
|
||||
unittest::GoldenTestContext getGoldenTestContext() {
|
||||
// GoldenTestContext not used in this benchmark, create a dummy GoldenTestContext.
|
||||
static const ::testing::TestInfo* dummyTestInfo =
|
||||
::testing::UnitTest::GetInstance()->GetTestSuite(0)->GetTestInfo(0);
|
||||
TestInfo testInfo(
|
||||
"HashLookupBenchmarkFixture", "runVariation", "sbe_hash_lookup_bm.cpp", __LINE__);
|
||||
return unittest::GoldenTestContext(
|
||||
&goldenTestConfigSbe, dummyTestInfo, false /* validateOnClose */);
|
||||
&goldenTestConfigSbe, &testInfo, false /* validateOnClose */);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ public:
|
||||
}
|
||||
|
||||
// virtual function needs to be defined
|
||||
void TestBody() override {}
|
||||
void _doTest() override {}
|
||||
|
||||
const NamespaceString _nss =
|
||||
NamespaceString::createNamespaceString_forTest("testdb.sbe_scan_stage");
|
||||
|
||||
@ -98,8 +98,8 @@ protected:
|
||||
};
|
||||
|
||||
TEST_F(SBENumericTest, Compile) {
|
||||
unittest::GoldenTestContext gctx(&goldenTestConfigSbe);
|
||||
gctx.printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
GoldenTestContext gctx(&goldenTestConfigSbe);
|
||||
gctx.printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
auto& os = gctx.outStream();
|
||||
|
||||
auto expr = test_detail::makeEFromNumber(
|
||||
|
||||
@ -87,7 +87,7 @@ public:
|
||||
return colls;
|
||||
}
|
||||
|
||||
void TestBody() override {}
|
||||
void _doTest() override {}
|
||||
|
||||
const NamespaceString _nss =
|
||||
NamespaceString::createNamespaceString_forTest("testdb.sbe_scan_stage");
|
||||
|
||||
@ -491,8 +491,8 @@ TEST(SBEVM, CodeFragmentToStringSanity) {
|
||||
}
|
||||
|
||||
TEST(SBEVM, CodeFragmentPrintStable) {
|
||||
unittest::GoldenTestContext ctx(&goldenTestConfigSbe);
|
||||
ctx.printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
GoldenTestContext ctx(&goldenTestConfigSbe);
|
||||
ctx.printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
|
||||
auto& os = ctx.outStream();
|
||||
|
||||
|
||||
@ -40,15 +40,27 @@ namespace mongo::sbe {
|
||||
|
||||
unittest::GoldenTestConfig goldenTestConfigSbe{"src/mongo/db/test_output/exec/sbe"};
|
||||
|
||||
void GoldenSBETestFixture::setUp() {
|
||||
gctx = std::make_unique<unittest::GoldenTestContext>(&goldenTestConfigSbe);
|
||||
gctx->validateOnClose(false);
|
||||
gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
}
|
||||
void GoldenSBETestFixture::run() {
|
||||
GoldenTestContext ctx(&goldenTestConfigSbe);
|
||||
ctx.validateOnClose(false);
|
||||
auto guard = ScopeGuard([&] { gctx = nullptr; });
|
||||
gctx = &ctx;
|
||||
gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
|
||||
void GoldenSBETestFixture::tearDown() {
|
||||
gctx->verifyOutput();
|
||||
gctx.reset();
|
||||
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::printVariation(const std::string& name) {
|
||||
|
||||
@ -44,6 +44,9 @@
|
||||
|
||||
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;
|
||||
|
||||
@ -66,14 +69,11 @@ class GoldenSBETestFixture : public virtual SBETestFixture {
|
||||
public:
|
||||
GoldenSBETestFixture(bool debug = false) : _debug(debug), _variationCount(0) {}
|
||||
|
||||
void setUp() override;
|
||||
|
||||
void tearDown() override;
|
||||
|
||||
void run();
|
||||
void printVariation(const std::string& name = "");
|
||||
|
||||
protected:
|
||||
std::unique_ptr<unittest::GoldenTestContext> gctx;
|
||||
GoldenTestContext* gctx;
|
||||
|
||||
private:
|
||||
bool _debug;
|
||||
@ -81,60 +81,66 @@ private:
|
||||
};
|
||||
|
||||
/** SBE Value Equal to. */
|
||||
class ValueEqMatcher {
|
||||
class ValueEq : public mongo::unittest::match::Matcher {
|
||||
public:
|
||||
explicit ValueEqMatcher(TypedValue v) : _v{v} {}
|
||||
explicit ValueEqMatcher(value::TagValueView v) : _v{v.tag, v.value} {}
|
||||
explicit ValueEq(TypedValue v) : _v{v} {}
|
||||
explicit ValueEq(value::TagValueView v) : _v{v.tag, v.value} {}
|
||||
|
||||
void DescribeTo(std::ostream* os) const {
|
||||
*os << "ValueEq(" << _v << ")";
|
||||
std::string describe() const {
|
||||
std::stringstream ss;
|
||||
ss << "ValueEq(" << _v << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const {
|
||||
*os << "not ValueEq(" << _v << ")";
|
||||
}
|
||||
|
||||
bool MatchAndExplain(const TypedValue& x, ::testing::MatchResultListener* listener) const {
|
||||
MatchResult match(const TypedValue x) const {
|
||||
auto [tag, val] = sbe::value::compareValue(_v.first, _v.second, x.first, x.second);
|
||||
return tag == sbe::value::TypeTags::NumberInt32 && sbe::value::bitcastTo<int>(val) == 0;
|
||||
return MatchResult{tag == sbe::value::TypeTags::NumberInt32 &&
|
||||
sbe::value::bitcastTo<int>(val) == 0};
|
||||
}
|
||||
|
||||
bool MatchAndExplain(const value::TagValueView& x,
|
||||
::testing::MatchResultListener* listener) const {
|
||||
return MatchAndExplain(std::make_pair(x.tag, x.value), listener);
|
||||
MatchResult match(const value::TagValueView x) const {
|
||||
return match(std::make_pair(x.tag, x.value));
|
||||
}
|
||||
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return MatchResult{equal};
|
||||
}
|
||||
|
||||
private:
|
||||
TypedValue _v;
|
||||
double _limit;
|
||||
};
|
||||
|
||||
class ValueVectorGuard {
|
||||
ValueVectorGuard() = delete;
|
||||
|
||||
@ -127,6 +127,13 @@ 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) {
|
||||
|
||||
@ -186,8 +186,6 @@ 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();
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
namespace mongo::extension::sdk {
|
||||
namespace {
|
||||
|
||||
class AggStageErrorFixture : public unittest::Test {
|
||||
class AggStageDeathTest : public unittest::Test {
|
||||
public:
|
||||
void setUp() override {
|
||||
// Initialize HostServices so that aggregation stages will be able to access member
|
||||
@ -151,8 +151,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
using AggStageErrorFixtureDeathTest = AggStageErrorFixture;
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, EmptyDesugarExpansionFails, "11113803") {
|
||||
DEATH_TEST_F(AggStageDeathTest, EmptyDesugarExpansionFails, "11113803") {
|
||||
auto emptyDesugarParseNode =
|
||||
new ExtensionAggStageParseNode(shared_test_stages::DesugarToEmptyParseNode::make());
|
||||
auto handle = extension::AggStageParseNodeHandle{emptyDesugarParseNode};
|
||||
@ -160,7 +159,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, EmptyDesugarExpansionFails, "1111380
|
||||
[[maybe_unused]] auto expanded = handle->expand();
|
||||
}
|
||||
|
||||
TEST_F(AggStageErrorFixture, GetExpandedSizeLessThanActualExpansionSizeFails) {
|
||||
TEST_F(AggStageDeathTest, GetExpandedSizeLessThanActualExpansionSizeFails) {
|
||||
auto getExpandedSizeLessThanActualExpansionSizeParseNode = new ExtensionAggStageParseNode(
|
||||
shared_test_stages::GetExpandedSizeLessThanActualExpansionSizeParseNode::make());
|
||||
auto handle =
|
||||
@ -174,7 +173,7 @@ TEST_F(AggStageErrorFixture, GetExpandedSizeLessThanActualExpansionSizeFails) {
|
||||
11113802);
|
||||
}
|
||||
|
||||
TEST_F(AggStageErrorFixture, GetExpandedSizeGreaterThanActualExpansionSizeFails) {
|
||||
TEST_F(AggStageDeathTest, GetExpandedSizeGreaterThanActualExpansionSizeFails) {
|
||||
auto getExpandedSizeGreaterThanActualExpansionSizeParseNode = new ExtensionAggStageParseNode(
|
||||
shared_test_stages::GetExpandedSizeGreaterThanActualExpansionSizeParseNode::make());
|
||||
auto handle =
|
||||
@ -188,7 +187,7 @@ TEST_F(AggStageErrorFixture, GetExpandedSizeGreaterThanActualExpansionSizeFails)
|
||||
11113802);
|
||||
}
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, DescriptorAndParseNodeNameMismatchFails, "11217602") {
|
||||
DEATH_TEST_F(AggStageDeathTest, DescriptorAndParseNodeNameMismatchFails, "11217602") {
|
||||
auto descriptor = std::make_unique<ExtensionAggStageDescriptor>(
|
||||
shared_test_stages::NameMismatchStageDescriptor::make());
|
||||
auto handle = extension::AggStageDescriptorHandle{descriptor.get()};
|
||||
@ -319,7 +318,7 @@ DEATH_TEST(ExecAggStageVTableDeathTest, InvalidExecAggStageVTableFailsClose, "11
|
||||
};
|
||||
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultAdvanced, "10956801") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultAdvanced, "10956801") {
|
||||
auto invalidExtensionExecAggStageAdvancedState = new extension::sdk::ExtensionExecAggStage(
|
||||
InvalidExtensionExecAggStageAdvancedState::make());
|
||||
|
||||
@ -327,9 +326,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultAdvance
|
||||
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
InvalidExtensionGetNextResultPauseExecution,
|
||||
"10956802") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultPauseExecution, "10956802") {
|
||||
auto invalidExtensionExecAggStagePauseExecutionState =
|
||||
new extension::sdk::ExtensionExecAggStage(
|
||||
InvalidExtensionExecAggStagePauseExecutionState::make());
|
||||
@ -338,7 +335,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultEOF, "10956805") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidExtensionGetNextResultEOF, "10956805") {
|
||||
auto invalidExtensionExecAggStageEofState =
|
||||
new extension::sdk::ExtensionExecAggStage(InvalidExtensionExecAggStageEofState::make());
|
||||
|
||||
@ -346,14 +343,14 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidExtensionGetNextResultEOF, "1
|
||||
[[maybe_unused]] auto getNext = handle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidMongoExtensionGetNextResultCode, "10956803") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidMongoExtensionGetNextResultCode, "10956803") {
|
||||
::MongoExtensionGetNextResult result = {.code =
|
||||
static_cast<::MongoExtensionGetNextResultCode>(10),
|
||||
.resultDocument = createEmptyByteContainer()};
|
||||
[[maybe_unused]] auto converted = extension::ExtensionGetNextResult::makeFromApiResult(result);
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidGetNextCode, "10956804") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidGetNextCode, "10956804") {
|
||||
auto invalidExtensionExecAggStageGetNextCode =
|
||||
new extension::sdk::ExtensionExecAggStage(InvalidExtensionExecAggStageGetNextCode::make());
|
||||
|
||||
@ -405,7 +402,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
DEATH_TEST_F(AggStageDeathTest,
|
||||
InvalidExtensionGetNextResultAdvancedFromCompiledExecAggStage,
|
||||
"10956801") {
|
||||
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
|
||||
@ -417,7 +414,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
DEATH_TEST_F(AggStageDeathTest,
|
||||
InvalidExtensionGetNextResultPauseExecutionFromCompiledExecAggStage,
|
||||
"10956802") {
|
||||
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
|
||||
@ -429,7 +426,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
DEATH_TEST_F(AggStageDeathTest,
|
||||
InvalidExtensionGetNextResultEOFFromCompiledExecAggStage,
|
||||
"10956805") {
|
||||
auto logicalStage = new extension::sdk::ExtensionLogicalAggStage(
|
||||
@ -441,7 +438,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
[[maybe_unused]] auto getNext = compiledExecAggStageHandle->getNext(_execCtx.get());
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidDPLArrayContainerVTableFailsSize, "11368301") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsSize, "11368301") {
|
||||
auto handle = DPLArrayContainerHandle{new sdk::ExtensionDPLArrayContainerAdapter(
|
||||
sdk::DPLArrayContainer(std::vector<VariantDPLHandle>{}))};
|
||||
|
||||
@ -450,9 +447,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, InvalidDPLArrayContainerVTableFailsS
|
||||
DPLArrayContainerAPI::assertVTableConstraints(vtable);
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
InvalidDPLArrayContainerVTableFailsTransfer,
|
||||
"11368302") {
|
||||
DEATH_TEST_F(AggStageDeathTest, InvalidDPLArrayContainerVTableFailsTransfer, "11368302") {
|
||||
auto handle = DPLArrayContainerHandle{new sdk::ExtensionDPLArrayContainerAdapter(
|
||||
sdk::DPLArrayContainer(std::vector<VariantDPLHandle>{}))};
|
||||
|
||||
@ -461,9 +456,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
DPLArrayContainerAPI::assertVTableConstraints(vtable);
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
DPLArrayContainerExtensionToHostWrongSizeFails,
|
||||
"11368303") {
|
||||
DEATH_TEST_F(AggStageDeathTest, DPLArrayContainerExtensionToHostWrongSizeFails, "11368303") {
|
||||
auto logicalStage =
|
||||
new sdk::ExtensionLogicalAggStage(shared_test_stages::CountingLogicalStage::make());
|
||||
auto parseNode = new sdk::ExtensionAggStageParseNode(shared_test_stages::CountingParse::make());
|
||||
@ -527,9 +520,7 @@ DEATH_TEST(DistributedPlanLogicVTableDeathTest, InvalidDPLVTableFailsGetSortPatt
|
||||
DistributedPlanLogicAPI::assertVTableConstraints(vtable);
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
SourceStageForTransformExtensionStageBecomesInvalid,
|
||||
"10957209") {
|
||||
DEATH_TEST_F(AggStageDeathTest, 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;
|
||||
@ -572,7 +563,7 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest,
|
||||
result = extensionStage->getNext();
|
||||
};
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, NoSourceStageForTransformStage, "10957209") {
|
||||
DEATH_TEST_F(AggStageDeathTest, NoSourceStageForTransformStage, "10957209") {
|
||||
auto transformStage = shared_test_stages::AddFruitsToDocumentsExecStage::make();
|
||||
|
||||
QueryTestServiceContext testCtx;
|
||||
@ -589,11 +580,11 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, NoSourceStageForTransformStage, "109
|
||||
[[maybe_unused]] auto result = transformStage->getNext(&ctxAdapter, nullptr);
|
||||
}
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, HostExecAggStageAdapterNullStageAsserts, "10957207") {
|
||||
DEATH_TEST_F(AggStageDeathTest, HostExecAggStageAdapterNullStageAsserts, "10957207") {
|
||||
[[maybe_unused]] auto adapter = host_connector::HostExecAggStageAdapter{nullptr};
|
||||
}
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, SetSourceOnSourceStageFails, "10957210") {
|
||||
DEATH_TEST_F(AggStageDeathTest, 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(
|
||||
@ -606,14 +597,14 @@ DEATH_TEST_F(AggStageErrorFixtureDeathTest, SetSourceOnSourceStageFails, "109572
|
||||
handle->setSource(sourceHandle);
|
||||
}
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, GetSourceOnSourceStageFails, "10957208") {
|
||||
DEATH_TEST_F(AggStageDeathTest, GetSourceOnSourceStageFails, "10957208") {
|
||||
|
||||
shared_test_stages::FruitsAsDocumentsExecStage sourceStage{};
|
||||
// Calling getSource on a source stage should fail.
|
||||
[[maybe_unused]] auto source = sourceStage._getSource();
|
||||
}
|
||||
|
||||
DEATH_TEST_F(AggStageErrorFixtureDeathTest, GetNameOnMovedHandleFails, "10596403") {
|
||||
DEATH_TEST_F(AggStageDeathTest, GetNameOnMovedHandleFails, "10596403") {
|
||||
auto sourceHandle = extension::ExecAggStageHandle{new extension::sdk::ExtensionExecAggStage(
|
||||
shared_test_stages::AddFruitsToDocumentsExecStage::make())};
|
||||
|
||||
|
||||
@ -176,42 +176,42 @@ TEST(ExtensionStatusTest, extensionStatusInvokeCAndConvertStatusToException_Exte
|
||||
kErrorString);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsGetCode, "10930105") {
|
||||
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsGetCode, "10930105") {
|
||||
StatusHandle status(new ExtensionGenericStatus());
|
||||
auto vtable = status->vtable();
|
||||
vtable.get_code = nullptr;
|
||||
StatusAPI::assertVTableConstraints(vtable);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsGetReason, "10930106") {
|
||||
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsGetReason, "10930106") {
|
||||
StatusHandle status(new ExtensionGenericStatus());
|
||||
auto vtable = status->vtable();
|
||||
vtable.get_reason = nullptr;
|
||||
StatusAPI::assertVTableConstraints(vtable);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsSetCode, "11186306") {
|
||||
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsSetCode, "11186306") {
|
||||
StatusHandle status(new ExtensionGenericStatus());
|
||||
auto vtable = status->vtable();
|
||||
vtable.set_code = nullptr;
|
||||
StatusAPI::assertVTableConstraints(vtable);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsSetReason, "11186309") {
|
||||
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsSetReason, "11186309") {
|
||||
StatusHandle status(new ExtensionGenericStatus());
|
||||
auto vtable = status->vtable();
|
||||
vtable.set_reason = nullptr;
|
||||
StatusAPI::assertVTableConstraints(vtable);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, InvalidExtensionStatusVTableFailsClone, "11186310") {
|
||||
DEATH_TEST(ExtensionStatusTest, InvalidExtensionStatusVTableFailsClone, "11186310") {
|
||||
StatusHandle status(new ExtensionGenericStatus());
|
||||
auto vtable = status->vtable();
|
||||
vtable.clone = nullptr;
|
||||
StatusAPI::assertVTableConstraints(vtable);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, ExtensionStatusOKSetReasonFails, "11186303") {
|
||||
DEATH_TEST(ExtensionStatusTest, ExtensionStatusOKSetReasonFails, "11186303") {
|
||||
StatusHandle status(&ExtensionStatusOK::getInstance());
|
||||
status->setReason("");
|
||||
}
|
||||
@ -222,7 +222,7 @@ TEST(ExtensionStatusTest, ExtensionStatusOKSetCodeNoOp) {
|
||||
ASSERT_EQ(status->getCode(), 0);
|
||||
}
|
||||
|
||||
DEATH_TEST(ExtensionStatusTestDeathTest, ExtensionStatusExceptionSetReasonFails, "11186304") {
|
||||
DEATH_TEST(ExtensionStatusTest, ExtensionStatusExceptionSetReasonFails, "11186304") {
|
||||
StatusHandle status(wrapCXXAndConvertExceptionToStatus(
|
||||
[&]() { uasserted(11186311, "Failed with uassert in $noOpExtension parse."); }));
|
||||
status->setReason("");
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#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"
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
|
||||
const Date_t kDate = Date_t::now();
|
||||
const std::vector<BSONObj> kField1Elements = {
|
||||
BSON("logLevel" << 2),
|
||||
|
||||
@ -75,6 +75,8 @@ 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() {
|
||||
@ -174,7 +176,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void TestBody() override {}
|
||||
void _doTest() override {};
|
||||
|
||||
std::vector<BSONObj> _generateConfigShardSampleData(int nShards) const {
|
||||
std::vector<BSONObj> configShardData;
|
||||
|
||||
@ -284,7 +284,7 @@ TEST(ChunkType, ParseFromNetworkRequest) {
|
||||
<< onCurrentShardSince << ChunkHistoryBase::kShardFieldName
|
||||
<< "shard0001")))));
|
||||
|
||||
ASSERT_EQ("shard0001"_sd, chunk.getShard());
|
||||
ASSERT_EQ("shard0001", chunk.getShard());
|
||||
ASSERT_EQ(chunkVersion, chunk.getVersion());
|
||||
}
|
||||
|
||||
|
||||
@ -1116,7 +1116,7 @@ private:
|
||||
class ParseErrorBase : public Base {
|
||||
public:
|
||||
~ParseErrorBase() override {}
|
||||
void TestBody() final {
|
||||
void _doTest() final {
|
||||
ASSERT_THROWS(createGroup(spec()), AssertionException);
|
||||
}
|
||||
|
||||
@ -1127,7 +1127,7 @@ protected:
|
||||
class ExpressionBase : public Base {
|
||||
public:
|
||||
~ExpressionBase() override {}
|
||||
void TestBody() final {
|
||||
void _doTest() 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 TestBody() final {
|
||||
void _doTest() 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 TestBody() override {
|
||||
void _doTest() 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 TestBody() final {
|
||||
void _doTest() 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 TestBody() final {
|
||||
void _doTest() 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 TestBody() final {
|
||||
void _doTest() 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::TestBody();
|
||||
CheckResultsBase::_doTest();
|
||||
}
|
||||
std::deque<DocumentSource::GetNextResult> inputData() override {
|
||||
return {Document()};
|
||||
@ -1691,7 +1691,7 @@ public:
|
||||
CheckResultsAndSpills(GroupStageType groupStageType, uint64_t expectedSpills)
|
||||
: CheckResultsBase(groupStageType), _expectedSpills(expectedSpills) {}
|
||||
|
||||
void TestBody() final {
|
||||
void _doTest() final {
|
||||
for (int sharded = 0; sharded < 2; ++sharded) {
|
||||
runSharded(sharded);
|
||||
const auto* groupStats =
|
||||
|
||||
@ -191,9 +191,7 @@ TEST_F(LiteParsedDocumentSourceParseTest, CanRegisterBothPrimaryAndFallback) {
|
||||
registerPrimaryParser();
|
||||
}
|
||||
|
||||
using LiteParsedDocumentSourceParseDeathTest = LiteParsedDocumentSourceParseTest;
|
||||
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, MustRegisterPrimaryAfterFallback, "11395100") {
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, MustRegisterPrimaryAfterFallback, "11395100") {
|
||||
_stageName = "$mustRegisterPrimaryAfterFallback";
|
||||
|
||||
IncrementalRolloutFeatureFlag mockFlag("testFlag"_sd, RolloutPhase::inDevelopment, false);
|
||||
@ -201,7 +199,7 @@ DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, MustRegisterPrimaryAfterFal
|
||||
registerFallbackParser(&mockFlag);
|
||||
}
|
||||
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, CannotOverridePrimaryParser, "11534800") {
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, CannotOverridePrimaryParser, "11534800") {
|
||||
_stageName = "$cannotOverridePrimaryParser";
|
||||
|
||||
// Register the primary parser first.
|
||||
@ -253,7 +251,7 @@ TEST_F(LiteParsedDocumentSourceParseTest, FirstFallbackParserTakesPrecedenceWith
|
||||
}
|
||||
|
||||
// TODO SERVER-114028 Remove the following test when fallback parsing supports all feature flags.
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseDeathTest, IFRFlagIsRequired, "11395101") {
|
||||
DEATH_TEST_F(LiteParsedDocumentSourceParseTest, IFRFlagIsRequired, "11395101") {
|
||||
_stageName = "$IFRFlagIsRequired";
|
||||
|
||||
BinaryCompatibleFeatureFlag mockFlag(false);
|
||||
@ -373,3 +371,4 @@ TEST(ViewPolicy, CanSpecifyDisallowViewPolicyCustomValues) {
|
||||
}
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
|
||||
@ -42,10 +42,7 @@ namespace {
|
||||
|
||||
using MakePipelineBSONElementTest = AggregationContextFixture;
|
||||
|
||||
using MakePipelineBSONElementTestDeathTest = MakePipelineBSONElementTest;
|
||||
DEATH_TEST_F(MakePipelineBSONElementTestDeathTest,
|
||||
TassertFailsWhenBSONElementIsNotArray,
|
||||
"11524600") {
|
||||
DEATH_TEST_F(MakePipelineBSONElementTest, TassertFailsWhenBSONElementIsNotArray, "11524600") {
|
||||
auto expCtx = getExpCtx();
|
||||
BSONObj cmdObj = BSON("pipeline" << 123); // Not an array
|
||||
BSONElement pipelineElem = cmdObj["pipeline"];
|
||||
|
||||
@ -77,7 +77,7 @@ public:
|
||||
* Test that buildDocumentSource tasserts for stages that are not registered
|
||||
* in the StageParams to DocumentSource registry.
|
||||
*/
|
||||
DEATH_TEST(StageParamsToDocumentSourceRegistryDeathTest, UnregisteredStageReturnsNone, "11434300") {
|
||||
DEATH_TEST(StageParamsToDocumentSourceRegistryTest, 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(StageParamsToDocumentSourceRegistryDeathTest, DuplicateRegistrationFails, "11458700") {
|
||||
DEATH_TEST(StageParamsToDocumentSourceRegistryTest, DuplicateRegistrationFails, "11458700") {
|
||||
// Attempt to register a second mapping function for the same StageParams::Id.
|
||||
// This should trigger a tassert.
|
||||
registerStageParamsToDocumentSourceFn(DuplicateRegistrationTestStageParams::id, dummyMappingFn);
|
||||
@ -140,3 +140,4 @@ DEATH_TEST(StageParamsToDocumentSourceRegistryDeathTest, DuplicateRegistrationFa
|
||||
|
||||
} // namespace
|
||||
} // namespace mongo
|
||||
|
||||
|
||||
@ -279,7 +279,7 @@ TEST_F(CanonicalDistinctTest, CopyMaintainsDistinctProperties) {
|
||||
originalDistinct->setSortRequirement(SortPattern(BSON("x" << 1), expCtx));
|
||||
|
||||
const auto& copyDistinct = CanonicalDistinct(*originalDistinct);
|
||||
ASSERT_NE(originalDistinct, ©Distinct);
|
||||
ASSERT_NE(&originalDistinct, ©Distinct);
|
||||
|
||||
ASSERT_EQ(originalDistinct->getKey(), copyDistinct.getKey());
|
||||
ASSERT_EQ(originalDistinct->isMirrored(), copyDistinct.isMirrored());
|
||||
|
||||
@ -172,7 +172,7 @@ public:
|
||||
return CardinalityEstimate(CardinalityType{estimate}, source);
|
||||
}
|
||||
|
||||
void TestBody() override {}
|
||||
void _doTest() override {}
|
||||
|
||||
OperationContext* getOperationContext() const {
|
||||
return operationContext();
|
||||
|
||||
@ -232,14 +232,14 @@ TEST(PlannerWildcardHelpersTest, Expand_CompoundWildcardIndex_NumericComponents)
|
||||
ASSERT_EQ(expectedMks, expandedIndexes.front().multikeyPaths);
|
||||
}
|
||||
|
||||
DEATH_TEST(PlannerWildcardHelpersTestDeathTest, InvalidIndexExpansion, "11390001") {
|
||||
DEATH_TEST(PlannerWildcardHelpersTest, 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(PlannerWildcardHelpersTestDeathTest, AnotherInvalidIndexExpansion, "11390001") {
|
||||
DEATH_TEST(PlannerWildcardHelpersTest, AnotherInvalidIndexExpansion, "11390001") {
|
||||
WildcardIndexEntryMock wildcardIndex{BSON("$**" << 1 << "a" << 1), BSON("_id" << 0), {}};
|
||||
std::set<std::string> fields{"a"};
|
||||
std::vector<IndexEntry> expandedIndexes{};
|
||||
|
||||
@ -78,7 +78,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void TestBody() override {}
|
||||
void _doTest() override {}
|
||||
|
||||
void setUp() final {
|
||||
CatalogTestFixture::setUp();
|
||||
|
||||
@ -94,7 +94,7 @@ public:
|
||||
ASSERT_EQ(resultSlots.size(), 1);
|
||||
|
||||
// Print the stage explain output and verify.
|
||||
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
sbe::DebugPrintInfo debugPrintInfo{};
|
||||
_gctx->outStream() << sbe::DebugPrinter().print(*stage.get(), debugPrintInfo);
|
||||
_gctx->outStream() << std::endl;
|
||||
|
||||
@ -649,7 +649,7 @@ public:
|
||||
void setUp() override {
|
||||
GoldenSbeStageBuilderTest::setUp();
|
||||
_gctx->validateOnClose(true);
|
||||
_gctx->printTestHeader(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
}
|
||||
|
||||
void tearDown() override {
|
||||
|
||||
@ -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(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
_gctx->printTestHeader(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(unittest::GoldenTestContext::HeaderFormat::Text);
|
||||
_gctx->printTestHeader(GoldenTestContext::HeaderFormat::Text);
|
||||
_gctx->outStream() << test << std::endl;
|
||||
_gctx->outStream() << sbe::DebugPrinter().print(sbeEExpr->debugPrint());
|
||||
_gctx->outStream() << std::endl;
|
||||
|
||||
@ -54,6 +54,9 @@
|
||||
|
||||
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.
|
||||
@ -140,7 +143,7 @@ extern unittest::GoldenTestConfig goldenTestConfigSbe;
|
||||
class GoldenSbeStageBuilderTestFixture : public SbeStageBuilderTestFixture {
|
||||
public:
|
||||
GoldenSbeStageBuilderTestFixture()
|
||||
: _gctx(std::make_unique<unittest::GoldenTestContext>(&goldenTestConfigSbe)) {
|
||||
: _gctx(std::make_unique<GoldenTestContext>(&goldenTestConfigSbe)) {
|
||||
_gctx->validateOnClose(false);
|
||||
}
|
||||
|
||||
@ -154,7 +157,7 @@ protected:
|
||||
const mongo::BSONArray& expectedValue,
|
||||
BuildPlanStageParam param = {});
|
||||
|
||||
std::unique_ptr<unittest::GoldenTestContext> _gctx;
|
||||
std::unique_ptr<GoldenTestContext> _gctx;
|
||||
bool _collInitialized = false;
|
||||
};
|
||||
|
||||
|
||||
@ -623,7 +623,8 @@ DEATH_TEST_F(ApplyOpsDeathTest, ApplyOpsRidOnNonRridCollection, "11454700") {
|
||||
|
||||
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
|
||||
BSONObjBuilder resultBuilder;
|
||||
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
|
||||
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
|
||||
}
|
||||
|
||||
DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateNoRidOnRridCollection, "11454701") {
|
||||
@ -642,7 +643,8 @@ DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateNoRidOnRridCollection, "11454701") {
|
||||
|
||||
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
|
||||
BSONObjBuilder resultBuilder;
|
||||
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
|
||||
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
|
||||
}
|
||||
|
||||
DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateRidOnNonRridCollection, "11454701") {
|
||||
@ -659,7 +661,8 @@ DEATH_TEST_F(ApplyOpsDeathTest, SteadyStateRidOnNonRridCollection, "11454701") {
|
||||
|
||||
auto applyOpsCmdObj = BSON("applyOps" << BSON_ARRAY(insertOp));
|
||||
BSONObjBuilder resultBuilder;
|
||||
(void)applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
|
||||
applyOps(opCtx.get(), nss.dbName(), applyOpsCmdObj, mode, &resultBuilder));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -1249,8 +1249,8 @@ DEATH_TEST_F(OplogApplierImplTestDeathTest, ApplyOpsRidOnNonRridCollectionGroupe
|
||||
std::vector<ApplierOperation> ops = {ApplierOperation{&op1}, ApplierOperation{&op2}};
|
||||
OplogEntryOrGroupedInserts groupedInserts(ops.begin(), ops.end());
|
||||
|
||||
(void)_applyOplogEntryOrGroupedInsertsWrapper(
|
||||
_opCtx.get(), groupedInserts, OplogApplication::Mode::kApplyOpsCmd);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_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());
|
||||
|
||||
(void)_applyOplogEntryOrGroupedInsertsWrapper(
|
||||
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_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());
|
||||
|
||||
(void)_applyOplogEntryOrGroupedInsertsWrapper(
|
||||
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary);
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(_applyOplogEntryOrGroupedInsertsWrapper(
|
||||
_opCtx.get(), groupedInserts, OplogApplication::Mode::kSecondary));
|
||||
}
|
||||
|
||||
bool _testOplogEntryIsForCappedCollection(OperationContext* opCtx,
|
||||
|
||||
@ -560,7 +560,8 @@ TEST_F(OplogEntryTest, OpTimeBaseNonStrictParsing) {
|
||||
|
||||
// OpTimeBase should be successfully created from an OplogEntry, even though it has
|
||||
// extraneous fields.
|
||||
(void)OpTimeBase::parse(oplogEntryExtraField, IDLParserContext("OpTimeBase"));
|
||||
UNIT_TEST_INTERNALS_IGNORE_UNUSED_RESULT_WARNINGS(
|
||||
OpTimeBase::parse(oplogEntryExtraField, IDLParserContext("OpTimeBase")));
|
||||
|
||||
// OplogEntryBase should still use strict parsing and throw an error when it has extraneous
|
||||
// fields.
|
||||
|
||||
@ -77,7 +77,7 @@ void FailingOplogWriter::waitForScheduledWrites(OperationContext* opCtx) {};
|
||||
* Tests for the parent class behavior for OplogWriter.
|
||||
* Uses a default ThreadPoolExecutor.
|
||||
*/
|
||||
class OplogWriterTest : public executor::ThreadPoolExecutorTest {};
|
||||
class OplogWriterTest : public ServiceContextMongoDTest {};
|
||||
|
||||
|
||||
/**
|
||||
@ -95,7 +95,11 @@ using OplogWriterTestDeathTest = OplogWriterTest;
|
||||
DEATH_TEST_F(OplogWriterTestDeathTest,
|
||||
ThrowingInRunLoopLogsUsefulError,
|
||||
"OplogWriter threw a DBException") {
|
||||
auto& executor = getExecutor();
|
||||
executor::ThreadPoolMock::Options threadPoolMockOptions;
|
||||
|
||||
executor::ThreadPoolExecutorTest executorFixture{threadPoolMockOptions};
|
||||
executorFixture.setUp();
|
||||
auto& executor = executorFixture.getExecutor();
|
||||
executor.startup();
|
||||
|
||||
OplogWriter::Options options(false /* skipWritesToOplogColl */);
|
||||
|
||||
@ -115,7 +115,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void TestBody() override {}
|
||||
void _doTest() override {};
|
||||
|
||||
void setUp() override {
|
||||
ServiceContextMongoDTest::setUp();
|
||||
|
||||
@ -221,7 +221,7 @@ public:
|
||||
assertStartSuccess(configObj, HostAndPort("node1", 12345));
|
||||
}
|
||||
|
||||
void TestBody() override {}
|
||||
void _doTest() final {}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
@ -1806,7 +1806,7 @@ TEST_F(StorageTimestampTest, SetMinValidAppliedThrough) {
|
||||
*/
|
||||
class KVDropDatabase : public StorageTimestampTest {
|
||||
private:
|
||||
void TestBody() override {
|
||||
void _doTest() override {
|
||||
// Not actually called.
|
||||
}
|
||||
|
||||
@ -1928,7 +1928,12 @@ 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, public testing::WithParamInterface<bool> {
|
||||
class TimestampIndexBuilds : public StorageTimestampTest {
|
||||
private:
|
||||
void _doTest() override {
|
||||
// Not actually called.
|
||||
}
|
||||
|
||||
public:
|
||||
void run(bool simulatePrimary) {
|
||||
const bool simulateSecondary = !simulatePrimary;
|
||||
@ -2066,10 +2071,17 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
INSTANTIATE_TEST_SUITE_P(, TimestampIndexBuilds, testing::Values(false, true));
|
||||
|
||||
TEST_P(TimestampIndexBuilds, Build) {
|
||||
run(GetParam());
|
||||
TEST(SimpleStorageTimestampTest, TimestampIndexBuilds) {
|
||||
{
|
||||
TimestampIndexBuilds test;
|
||||
test.run(false);
|
||||
}
|
||||
// Reconstruct the datafiles from scratch across tests.
|
||||
{
|
||||
TimestampIndexBuilds test;
|
||||
test.run(true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(StorageTimestampTest, TimestampMultiIndexBuilds) {
|
||||
|
||||
@ -102,8 +102,7 @@ TEST(RangeDeletionRecoveryTracker, AddJobForCompletedTermDoesNothing) {
|
||||
ASSERT_EQ(tracker.getTrackedTermsCount(), 0);
|
||||
}
|
||||
|
||||
using RangeDeletionRecoveryTrackerDeathTest = RangeDeletionRecoveryTracker;
|
||||
DEATH_TEST(RangeDeletionRecoveryTrackerDeathTest,
|
||||
DEATH_TEST(RangeDeletionRecoveryTracker,
|
||||
NotifyMoreJobsThanRegisteredAsserts,
|
||||
"Tripwire assertion") {
|
||||
RangeDeletionRecoveryTracker tracker;
|
||||
@ -138,7 +137,7 @@ TEST(RangeDeletionRecoveryTracker, EndTermAfterAllJobsComplete) {
|
||||
ASSERT_EQ(future.get(), RangeDeletionRecoveryTracker::Outcome::kComplete);
|
||||
}
|
||||
|
||||
DEATH_TEST(RangeDeletionRecoveryTrackerDeathTest,
|
||||
DEATH_TEST(RangeDeletionRecoveryTracker,
|
||||
RegisterJobAfterRecoveryCompleteAsserts,
|
||||
"Tripwire assertion") {
|
||||
const auto term = 0;
|
||||
|
||||
@ -1594,8 +1594,7 @@ TEST_F(TransactionCoordinatorTest,
|
||||
executor::NetworkInterfaceMock::InNetworkGuard(network())->runReadyNetworkOperations();
|
||||
}
|
||||
|
||||
using TransactionCoordinatorTestDeathTest = TransactionCoordinatorTest;
|
||||
DEATH_TEST_REGEX_F(TransactionCoordinatorTestDeathTest,
|
||||
DEATH_TEST_REGEX_F(TransactionCoordinatorTest,
|
||||
CoordinatorTerminatedWithUnexpectedErrorAfterDurablyWritingDecision,
|
||||
"Fatal assertion.*11353000") {
|
||||
// Create the coordinator.
|
||||
|
||||
@ -136,7 +136,7 @@ private:
|
||||
/** A `unittest::Test` fixture being overloaded as a benchmark harness. */
|
||||
class Test : public ServiceContextMongoDTest {
|
||||
public:
|
||||
void TestBody() override {}
|
||||
void _doTest() override {}
|
||||
|
||||
void setUp() override {
|
||||
ServiceContextMongoDTest::setUp();
|
||||
|
||||
@ -106,10 +106,17 @@ 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>();
|
||||
}
|
||||
@ -117,5 +124,4 @@ public:
|
||||
|
||||
unittest::OldStyleSuiteInitializer<AllCatalogTests> allCatalogTests;
|
||||
|
||||
} // namespace
|
||||
} // namespace mongo
|
||||
|
||||
@ -537,8 +537,7 @@ TEST_F(CollectionShardingRuntimeTest, ShardVersionCheckDetectsClusterTimeConflic
|
||||
}
|
||||
}
|
||||
|
||||
using CollectionShardingRuntimeTestDeathTest = CollectionShardingRuntimeTest;
|
||||
DEATH_TEST_REGEX_F(CollectionShardingRuntimeTestDeathTest,
|
||||
DEATH_TEST_REGEX_F(CollectionShardingRuntimeTest,
|
||||
TestsShouldTassertIfPlacementConflictTimeIsNotPresentInTxns,
|
||||
"Tripwire assertion.*10206300") {
|
||||
CollectionShardingRuntime csr(getServiceContext(), kTestNss);
|
||||
|
||||
@ -432,9 +432,7 @@ TEST_F(DatabaseShardingRuntimeTestWithMockedLoader,
|
||||
}
|
||||
}
|
||||
|
||||
using DatabaseShardingRuntimeTestWithMockedLoaderDeathTest =
|
||||
DatabaseShardingRuntimeTestWithMockedLoader;
|
||||
DEATH_TEST_REGEX_F(DatabaseShardingRuntimeTestWithMockedLoaderDeathTest,
|
||||
DEATH_TEST_REGEX_F(DatabaseShardingRuntimeTestWithMockedLoader,
|
||||
TestsShouldTassertIfPlacementConflictTimeIsNotPresentInTxns,
|
||||
"Tripwire assertion.*9758701") {
|
||||
const auto installedDbVersion = DatabaseVersion(UUID::gen(), Timestamp(10, 0));
|
||||
|
||||
@ -404,8 +404,7 @@ TEST_F(ShardRemoteTest, TargeterMarksHostAsDownWhenConfigShuttingDown) {
|
||||
ASSERT_EQ(1UL, configTargeter()->getAndClearMarkedDownHosts().size());
|
||||
}
|
||||
|
||||
TEST_F(ShardRemoteTest, FindOnConfigFromShardRespectsDefaultConfigCommandTimeout) {
|
||||
serverGlobalParams.clusterRole = ClusterRole::ShardServer;
|
||||
TEST_F(ShardRemoteTest, FindOnConfigRespectsDefaultConfigCommandTimeout) {
|
||||
// Set the timeout for config commands to 1 second.
|
||||
auto timeoutMs = 1000;
|
||||
RAIIServerParameterControllerForTest configCommandTimeout{"defaultConfigCommandTimeoutMS",
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
|
||||
namespace mongo::key_string_test {
|
||||
|
||||
TEST_P(KeyStringBuilderTest, CommonIntPerf) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, CommonIntPerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, UniformInt64Perf) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, UniformInt64Perf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, CommonDoublePerf) {
|
||||
TEST_F(KeyStringBuilderTest, CommonDoublePerf) {
|
||||
std::mt19937 gen(newSeed());
|
||||
std::exponential_distribution<double> expReal(1e-3);
|
||||
|
||||
@ -71,7 +71,7 @@ TEST_P(KeyStringBuilderTest, CommonDoublePerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, UniformDoublePerf) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, UniformDoublePerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, CommonDecimalPerf) {
|
||||
TEST_F(KeyStringBuilderTest, CommonDecimalPerf) {
|
||||
std::mt19937 gen(newSeed());
|
||||
std::exponential_distribution<double> expReal(1e-3);
|
||||
|
||||
@ -104,7 +104,7 @@ TEST_P(KeyStringBuilderTest, CommonDecimalPerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, UniformDecimalPerf) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, UniformDecimalPerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, DecimalFromUniformDoublePerf) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, DecimalFromUniformDoublePerf) {
|
||||
perfTest(version, numbers);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, AllPermCompare) {
|
||||
TEST_F(KeyStringBuilderTest, AllPermCompare) {
|
||||
std::vector<BSONObj> elements = getInterestingElements(version);
|
||||
|
||||
for (size_t i = 0; i < elements.size(); i++) {
|
||||
@ -165,7 +165,7 @@ TEST_P(KeyStringBuilderTest, AllPermCompare) {
|
||||
testPermutation(version, elements, orderings, false);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, AllPerm2Compare) {
|
||||
TEST_F(KeyStringBuilderTest, AllPerm2Compare) {
|
||||
std::vector<BSONObj> baseElements = getInterestingElements(version);
|
||||
auto seed = newSeed();
|
||||
|
||||
@ -207,7 +207,7 @@ TEST_P(KeyStringBuilderTest, AllPerm2Compare) {
|
||||
testPermutation(version, elements, orderings, false);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, LotsOfNumbers3) {
|
||||
TEST_F(KeyStringBuilderTest, LotsOfNumbers3) {
|
||||
std::vector<stdx::future<void>> futures;
|
||||
|
||||
for (double k = 0; k < 8; k++) {
|
||||
@ -251,7 +251,7 @@ TEST_P(KeyStringBuilderTest, LotsOfNumbers3) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, NumberOrderLots) {
|
||||
TEST_F(KeyStringBuilderTest, NumberOrderLots) {
|
||||
std::vector<BSONObj> numbers;
|
||||
{
|
||||
numbers.push_back(BSON("" << 0));
|
||||
@ -330,8 +330,4 @@ TEST_P(KeyStringBuilderTest, NumberOrderLots) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(KeyStringBuilderLongRunningTest,
|
||||
KeyStringBuilderTest,
|
||||
testing::Values(key_string::Version::V0, key_string::Version::V1));
|
||||
} // namespace mongo::key_string_test
|
||||
|
||||
@ -183,7 +183,7 @@ TEST(TypeBitsTest, AppendLotsOfZeroTypeBits) {
|
||||
ASSERT(!typeBits.isLongEncoding());
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, TooManyElementsInCompoundKey) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, TooManyElementsInCompoundKey) {
|
||||
ASSERT_EQ(size, key_string::getKeySize(ks.getView(), ALL_ASCENDING, ks.version));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, MaxElementsInCompoundKey) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, MaxElementsInCompoundKey) {
|
||||
ASSERT_EQ(size, key_string::getKeySize(ks.getView(), ALL_ASCENDING, ks.version));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, SizeOfIncompleteKey) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, SizeOfIncompleteKey) {
|
||||
ASSERT_EQ(0, key_string::getKeySize({data, size - 1}, ALL_ASCENDING, key_string::Version::V1));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, SizeWithTrailingDataInBuffer) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, EmbeddedkEnd) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, EmbeddedkEnd) {
|
||||
ASSERT_EQ(key_string::getKeySize(buffer, ALL_ASCENDING, version), buffer.size());
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, EmbeddedNullString) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, EmbeddedNullString) {
|
||||
BSON("" << StringData("\x00", 1)));
|
||||
};
|
||||
|
||||
TEST_P(KeyStringBuilderTest, ExceededBSONDepth) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, ExceededBSONDepth) {
|
||||
ErrorCodes::Overflow);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, Simple1) {
|
||||
TEST_F(KeyStringBuilderTest, Simple1) {
|
||||
BSONObj a = BSON("" << 5);
|
||||
BSONObj b = BSON("" << 6);
|
||||
|
||||
@ -287,11 +287,11 @@ TEST_P(KeyStringBuilderTest, Simple1) {
|
||||
key_string::Builder(version, b, ALL_ASCENDING, RecordId(1)));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, DeprecatedBinData) {
|
||||
TEST_F(KeyStringBuilderTest, DeprecatedBinData) {
|
||||
ROUNDTRIP(version, BSON("" << BSONBinData(nullptr, 0, ByteArrayDeprecated)));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, ValidColumn) {
|
||||
TEST_F(KeyStringBuilderTest, ValidColumn) {
|
||||
BSONColumnBuilder cb;
|
||||
cb.append(BSON("a" << "deadbeef").getField("a"));
|
||||
cb.append(BSON("a" << 1).getField("a"));
|
||||
@ -303,7 +303,7 @@ TEST_P(KeyStringBuilderTest, ValidColumn) {
|
||||
ROUNDTRIP(version, objData);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, InvalidColumn) {
|
||||
TEST_F(KeyStringBuilderTest, InvalidColumn) {
|
||||
const BSONObj objData = BSON("" << BSONBinData("foobar", 6, Column));
|
||||
const key_string::Builder builder(version, objData, ALL_ASCENDING);
|
||||
|
||||
@ -313,7 +313,7 @@ TEST_P(KeyStringBuilderTest, InvalidColumn) {
|
||||
50833);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, ActualBytesDouble) {
|
||||
TEST_F(KeyStringBuilderTest, ActualBytesDouble) {
|
||||
// just one test like this for utter sanity
|
||||
|
||||
BSONObj a = BSON("" << 5.5);
|
||||
@ -355,7 +355,7 @@ TEST_P(KeyStringBuilderTest, ActualBytesDouble) {
|
||||
ASSERT_EQUALS(hexFlipped, ks.toString());
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, AllTypesSimple) {
|
||||
TEST_F(KeyStringBuilderTest, AllTypesSimple) {
|
||||
ROUNDTRIP(version, BSON("" << 5.5));
|
||||
ROUNDTRIP(version, BSON("" << "abc"));
|
||||
ROUNDTRIP(version, BSON("" << BSON("a" << 5)));
|
||||
@ -375,7 +375,7 @@ TEST_P(KeyStringBuilderTest, AllTypesSimple) {
|
||||
ROUNDTRIP(version, BSON("" << 1235123123123LL));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, Array1) {
|
||||
TEST_F(KeyStringBuilderTest, Array1) {
|
||||
BSONObj emptyArray = BSON("" << BSONArray());
|
||||
|
||||
ASSERT_EQUALS(BSONType::array, emptyArray.firstElement().type());
|
||||
@ -399,7 +399,7 @@ TEST_P(KeyStringBuilderTest, Array1) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, SubDoc1) {
|
||||
TEST_F(KeyStringBuilderTest, SubDoc1) {
|
||||
ROUNDTRIP(version, BSON("" << BSON("foo" << 2)));
|
||||
ROUNDTRIP(version,
|
||||
BSON("" << BSON("foo" << 2 << "bar"
|
||||
@ -407,7 +407,7 @@ TEST_P(KeyStringBuilderTest, SubDoc1) {
|
||||
ROUNDTRIP(version, BSON("" << BSON("foo" << BSON_ARRAY(2 << 4))));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, SubDoc2) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, SubDoc2) {
|
||||
}
|
||||
|
||||
|
||||
TEST_P(KeyStringBuilderTest, Compound1) {
|
||||
TEST_F(KeyStringBuilderTest, Compound1) {
|
||||
ROUNDTRIP(version, BSON("" << BSON("a" << 5) << "" << 1));
|
||||
ROUNDTRIP(version, BSON("" << BSON("" << 5) << "" << 1));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, Undef1) {
|
||||
TEST_F(KeyStringBuilderTest, Undef1) {
|
||||
ROUNDTRIP(version, BSON("" << BSONUndefined));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, NumberLong0) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, NumbersNearInt32Max) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, NumbersNearInt32Max) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, DecimalNumbers) {
|
||||
TEST_F(KeyStringBuilderTest, DecimalNumbers) {
|
||||
if (version == key_string::Version::V0) {
|
||||
LOGV2(22228, "not testing DecimalNumbers for KeyStringBuilder V0");
|
||||
return;
|
||||
@ -519,7 +519,7 @@ TEST_P(KeyStringBuilderTest, DecimalNumbers) {
|
||||
ROUNDTRIP(V1, BSON("" << BSONNULL << "" << BSON("a" << Decimal128::kPositiveInfinity)));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringValue) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringValue) {
|
||||
ASSERT_EQ(data2.compare(dataCopy), 0);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringValueReleaseReusableTest) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringValueReleaseReusableTest) {
|
||||
COMPARE_KS_BSON(data2, bson2, ALL_ASCENDING);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringGetValueCopyTest) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringGetValueCopyTest) {
|
||||
COMPARE_KS_BSON(data2, BSON("" << 1), ALL_ASCENDING);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
|
||||
TEST_F(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
|
||||
// Test that appendBsonElement works.
|
||||
{
|
||||
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
|
||||
@ -611,7 +611,7 @@ TEST_P(KeyStringBuilderTest, KeyStringBuilderAppendBsonElement) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringBuilderOrdering) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringBuilderOrdering) {
|
||||
ASSERT_FALSE(std::ranges::equal(data1.getView(), data2.getView()));
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringBuilderExclusiveBeforeDiscriminator) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringBuilderExclusiveBeforeDiscriminator) {
|
||||
ASSERT_EQ(1, appendedDiscriminator);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringBuilderExclusiveAfterDiscriminator) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringBuilderExclusiveAfterDiscriminator) {
|
||||
ASSERT_EQ(254, appendedDiscriminator);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringBuilderInclusiveDiscriminator) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, KeyStringBuilderInclusiveDiscriminator) {
|
||||
ASSERT_EQ(4, appendedDiscriminator);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
|
||||
TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
|
||||
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
|
||||
|
||||
key_string::HeapBuilder ks1(
|
||||
@ -681,7 +681,7 @@ TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator1) {
|
||||
ASSERT_EQ(data1.compareWithoutDiscriminator(data2), 0);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
|
||||
TEST_F(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
|
||||
BSONObj doc = BSON("fieldA" << 1 << "fieldB" << 2);
|
||||
|
||||
key_string::HeapBuilder ks1(
|
||||
@ -699,7 +699,7 @@ TEST_P(KeyStringBuilderTest, KeyStringValueCompareWithoutDiscriminator2) {
|
||||
ASSERT(data1.compareWithoutDiscriminator(data2) > 0);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
|
||||
TEST_F(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
|
||||
// Test that an illegally encoded double throws an error.
|
||||
const char data[8] = {
|
||||
// kNumericPositive7ByteInt
|
||||
@ -724,7 +724,7 @@ TEST_P(KeyStringBuilderTest, DoubleInvalidIntegerPartV0) {
|
||||
31209);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, InvalidInfinityDecimalV0) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, InvalidInfinityDecimalV0) {
|
||||
mongo::key_string::toBsonSafe(ks.getView(), ALL_ASCENDING, tb), AssertionException, 31231);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, CannotEncodeDecimalInV0) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, CannotEncodeDecimalInV0) {
|
||||
ErrorCodes::UnsupportedFormat);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, ReasonableSize) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, ReasonableSize) {
|
||||
ASSERT_LTE(fragmentBuilder.memUsage(), 64);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, DiscardIfNotReleased) {
|
||||
TEST_F(KeyStringBuilderTest, DiscardIfNotReleased) {
|
||||
SharedBufferFragmentBuilder fragmentBuilder(1024);
|
||||
{
|
||||
// Intentially not released, but the data should be discarded correctly.
|
||||
@ -812,7 +812,7 @@ TEST_P(KeyStringBuilderTest, DiscardIfNotReleased) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, LotsOfNumbers1) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, LotsOfNumbers1) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, LotsOfNumbers2) {
|
||||
TEST_F(KeyStringBuilderTest, LotsOfNumbers2) {
|
||||
for (double i = -1100; i < 1100; i++) {
|
||||
double x = pow(2, i);
|
||||
ROUNDTRIP(version, BSON("" << x));
|
||||
@ -853,7 +853,7 @@ TEST_P(KeyStringBuilderTest, LotsOfNumbers2) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdOrder1) {
|
||||
TEST_F(KeyStringBuilderTest, RecordIdOrder1) {
|
||||
Ordering ordering = Ordering::make(BSON("a" << 1));
|
||||
|
||||
key_string::Builder a(version, BSON("" << 5), ordering, RecordId::minLong());
|
||||
@ -868,7 +868,7 @@ TEST_P(KeyStringBuilderTest, RecordIdOrder1) {
|
||||
ASSERT_LESS_THAN(e, d);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdOrder2) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdOrder2) {
|
||||
ASSERT_LESS_THAN(b, d);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdOrder2Double) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdOrder2Double) {
|
||||
ASSERT_LESS_THAN(a, c);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, Timestamp) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, Timestamp) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, AllTypesRoundtrip) {
|
||||
TEST_F(KeyStringBuilderTest, AllTypesRoundtrip) {
|
||||
for (int i = 1; i <= stdx::to_underlying(BSONType::jsTypeMax); i++) {
|
||||
{
|
||||
BSONObjBuilder b;
|
||||
@ -963,7 +963,7 @@ TEST_P(KeyStringBuilderTest, AllTypesRoundtrip) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, SerializeDeserialize) {
|
||||
TEST_F(KeyStringBuilderTest, SerializeDeserialize) {
|
||||
BSONObj doc = BSON("a" << 1 << "b" << 2.0);
|
||||
// Round trip through serialize and deserialize
|
||||
{
|
||||
@ -1001,7 +1001,7 @@ TEST_P(KeyStringBuilderTest, SerializeDeserialize) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStr) {
|
||||
TEST_F(KeyStringBuilderTest, RecordIdStr) {
|
||||
const int kSize = 12;
|
||||
for (int i = 0; i < kSize; i++) {
|
||||
unsigned char buf[kSize];
|
||||
@ -1056,7 +1056,7 @@ TEST_P(KeyStringBuilderTest, RecordIdStr) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
|
||||
TEST_F(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
|
||||
const int pad = 3; // kStringLike CType + StringData terminator + RecordId len
|
||||
{
|
||||
const int size = 90;
|
||||
@ -1079,7 +1079,7 @@ TEST_P(KeyStringBuilderTest, RecordIdStrBig1SizeSegment) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStrBig2SizeSegments) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdStrBig2SizeSegments) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStrBig3SizeSegments) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdStrBig3SizeSegments) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStrBig4SizeSegments) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdStrBig4SizeSegments) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIdStrBigSizeWithoutRecordIdStr) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, RecordIdStrBigSizeWithoutRecordIdStr) {
|
||||
}
|
||||
|
||||
|
||||
TEST_P(KeyStringBuilderTest, NaNs) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, NaNs) {
|
||||
ASSERT(toBson(ks4d, ONE_DESCENDING)[""].Decimal().isNaN());
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RecordIds) {
|
||||
TEST_F(KeyStringBuilderTest, RecordIds) {
|
||||
for (int i = 0; i < 63; i++) {
|
||||
const RecordId rid = RecordId(1ll << i);
|
||||
|
||||
@ -1303,7 +1303,7 @@ TEST_P(KeyStringBuilderTest, RecordIds) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
|
||||
TEST_F(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
|
||||
BSONObj obj;
|
||||
{
|
||||
BSONObjBuilder builder;
|
||||
@ -1320,7 +1320,7 @@ TEST_P(KeyStringBuilderTest, KeyWithLotsOfTypeBits) {
|
||||
ROUNDTRIP(version, obj);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
|
||||
TEST_F(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
|
||||
checkKeyWithNByteOfTypeBits(version, 0, false);
|
||||
checkKeyWithNByteOfTypeBits(version, 1, false);
|
||||
checkKeyWithNByteOfTypeBits(version, 1, true);
|
||||
@ -1332,12 +1332,12 @@ TEST_P(KeyStringBuilderTest, KeysWithNBytesTypeBits) {
|
||||
checkKeyWithNByteOfTypeBits(version, 129, true);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, VeryLargeString) {
|
||||
TEST_F(KeyStringBuilderTest, VeryLargeString) {
|
||||
BSONObj obj = BSON("" << std::string(123456, 'x'));
|
||||
ROUNDTRIP(version, obj);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
|
||||
TEST_F(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
|
||||
key_string::TypeBits typeBits(key_string::Version::V1);
|
||||
|
||||
const char invalidString[] = {
|
||||
@ -1363,7 +1363,7 @@ TEST_P(KeyStringBuilderTest, ToBsonSafeShouldNotTerminate) {
|
||||
key_string::toBsonSafe(invalidNumber, ALL_ASCENDING, typeBits), AssertionException, 50810);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, InvalidDecimalExponent) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, InvalidDecimalExponent) {
|
||||
50814);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, InvalidDecimalZero) {
|
||||
TEST_F(KeyStringBuilderTest, InvalidDecimalZero) {
|
||||
const key_string::Builder ks(
|
||||
key_string::Version::V1, BSON("" << Decimal128("-0")), ALL_ASCENDING);
|
||||
|
||||
@ -1389,7 +1389,7 @@ TEST_P(KeyStringBuilderTest, InvalidDecimalZero) {
|
||||
50846);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, InvalidDecimalContinuation) {
|
||||
TEST_F(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_P(KeyStringBuilderTest, InvalidDecimalContinuation) {
|
||||
50850);
|
||||
}
|
||||
|
||||
TEST_P(KeyStringBuilderTest, RandomizedInputsForToBsonSafe) {
|
||||
TEST_F(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,10 +1458,6 @@ TEST_P(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.") {
|
||||
|
||||
@ -53,6 +53,22 @@ 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());
|
||||
}
|
||||
|
||||
@ -35,11 +35,9 @@
|
||||
|
||||
namespace MONGO_MOD_PRIVATE mongo {
|
||||
namespace key_string_test {
|
||||
class KeyStringBuilderTest : public testing::TestWithParam<key_string::Version> {
|
||||
class KeyStringBuilderTest : public unittest::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
version = GetParam();
|
||||
}
|
||||
void run();
|
||||
|
||||
protected:
|
||||
key_string::Version version;
|
||||
|
||||
@ -276,7 +276,6 @@ DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, AbortMustBeInUnitOfWork, "invaria
|
||||
|
||||
DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, CannotHaveUnfinishedUnitOfWorkOnExit, "invariant") {
|
||||
ru->beginUnitOfWork(opCtx->readOnly());
|
||||
opCtx.reset();
|
||||
}
|
||||
|
||||
DEATH_TEST_F(RecoveryUnitTestHarnessDeathTest, PrepareMustBeInUnitOfWork, "invariant") {
|
||||
|
||||
@ -167,16 +167,7 @@ private:
|
||||
class WiredTigerKVEngineTest : public ServiceContextTest {
|
||||
public:
|
||||
WiredTigerKVEngineTest(bool repair = false, bool preciseCheckpoints = false)
|
||||
: _repair(repair), _preciseCheckpoints(preciseCheckpoints) {}
|
||||
|
||||
void setUp() override {
|
||||
_helper = std::make_unique<WiredTigerKVHarnessHelper>(
|
||||
getServiceContext(), _repair, _preciseCheckpoints);
|
||||
}
|
||||
|
||||
void tearDown() override {
|
||||
_helper.reset();
|
||||
}
|
||||
: _helper(getServiceContext(), repair, preciseCheckpoints) {}
|
||||
|
||||
protected:
|
||||
using ClientAndCtx =
|
||||
@ -185,7 +176,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;
|
||||
}
|
||||
@ -194,16 +185,14 @@ 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));
|
||||
}
|
||||
|
||||
bool _repair;
|
||||
bool _preciseCheckpoints;
|
||||
std::unique_ptr<WiredTigerKVHarnessHelper> _helper;
|
||||
WiredTigerKVHarnessHelper _helper;
|
||||
};
|
||||
|
||||
class WiredTigerKVEngineRepairTest : public WiredTigerKVEngineTest {
|
||||
@ -220,8 +209,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);
|
||||
|
||||
@ -241,7 +230,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));
|
||||
@ -251,12 +240,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
|
||||
@ -265,7 +254,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
|
||||
@ -274,7 +263,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
|
||||
}
|
||||
@ -288,11 +277,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;
|
||||
@ -311,20 +300,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.
|
||||
@ -343,14 +332,13 @@ 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));
|
||||
@ -378,7 +366,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;
|
||||
@ -392,7 +380,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.
|
||||
@ -400,7 +388,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);
|
||||
}
|
||||
@ -408,9 +396,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;
|
||||
}
|
||||
@ -422,34 +410,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));
|
||||
}
|
||||
@ -463,7 +451,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
|
||||
@ -473,7 +461,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);
|
||||
}
|
||||
@ -493,27 +481,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.
|
||||
@ -532,36 +520,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -572,37 +560,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -613,8 +601,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.
|
||||
@ -622,15 +610,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -642,26 +630,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);
|
||||
}
|
||||
@ -675,8 +663,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())));
|
||||
}
|
||||
|
||||
@ -789,11 +777,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().
|
||||
@ -812,13 +800,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.
|
||||
@ -836,8 +824,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 =
|
||||
@ -848,7 +836,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());
|
||||
@ -858,7 +846,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) {
|
||||
@ -870,14 +858,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();
|
||||
@ -892,7 +880,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();
|
||||
@ -914,7 +902,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());
|
||||
@ -923,7 +911,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();
|
||||
@ -944,7 +932,7 @@ TEST_F(WiredTigerKVEngineTest, TestHandlerCleanShutdownBeforeActivityReleaseRAII
|
||||
}
|
||||
|
||||
TEST_F(WiredTigerKVEngineTest, TestRestartUsesNewConn) {
|
||||
auto* engine = _helper->getWiredTigerKVEngine();
|
||||
auto* engine = _helper.getWiredTigerKVEngine();
|
||||
ASSERT(engine->isWtConnReadyForStatsCollection_UNSAFE());
|
||||
|
||||
{
|
||||
@ -953,8 +941,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);
|
||||
@ -962,7 +950,7 @@ TEST_F(WiredTigerKVEngineTest, TestRestartUsesNewConn) {
|
||||
}
|
||||
|
||||
TEST_F(WiredTigerKVEngineTest, TestGetBackupCheckpointTimestampWithoutOpenBackupCursor) {
|
||||
auto* engine = _helper->getWiredTigerKVEngine();
|
||||
auto* engine = _helper.getWiredTigerKVEngine();
|
||||
ASSERT_EQ(Timestamp::min(), engine->getBackupCheckpointTimestamp());
|
||||
}
|
||||
|
||||
@ -989,18 +977,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);
|
||||
}
|
||||
|
||||
@ -1073,9 +1061,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.
|
||||
@ -1128,7 +1116,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();
|
||||
@ -1142,8 +1130,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.
|
||||
@ -1193,7 +1181,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();
|
||||
@ -1211,8 +1199,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.
|
||||
@ -1260,7 +1248,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();
|
||||
@ -1269,8 +1257,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.
|
||||
@ -1296,7 +1284,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();
|
||||
@ -1305,8 +1293,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()));
|
||||
@ -1344,7 +1332,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();
|
||||
@ -1359,8 +1347,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.
|
||||
|
||||
@ -66,10 +66,6 @@ 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;
|
||||
@ -294,12 +290,8 @@ public:
|
||||
*/
|
||||
class iterator {
|
||||
public:
|
||||
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;
|
||||
|
||||
using value_type = std::pair<Int, Int>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
iterator() = default;
|
||||
|
||||
const std::pair<Int, Int>& operator*() const {
|
||||
@ -328,7 +320,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);
|
||||
|
||||
@ -36,7 +36,6 @@ 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",
|
||||
],
|
||||
|
||||
@ -152,12 +152,11 @@ 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();
|
||||
|
||||
runGlobalInitializersOrDie(progress.args());
|
||||
mongo::runGlobalInitializersOrDie(std::vector<std::string>(argv, argv + argc));
|
||||
// (Generic FCV reference): This FCV reference should exist across LTS binary versions.
|
||||
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
|
||||
repl::ReplSettings replSettings;
|
||||
@ -205,7 +204,7 @@ int dbtestsMain(int argc, char** argv) {
|
||||
|
||||
query_settings::QuerySettingsService::initializeForTest(service);
|
||||
|
||||
return runDbTests(progress);
|
||||
return mongo::dbtests::runDbTests(argc, argv);
|
||||
}
|
||||
|
||||
} // namespace dbtests
|
||||
|
||||
@ -62,15 +62,9 @@ namespace DirectClientTests {
|
||||
|
||||
const NamespaceString nss = NamespaceString::createNamespaceString_forTest("a.b");
|
||||
|
||||
class Base {
|
||||
class InsertMany {
|
||||
public:
|
||||
virtual ~Base() = default;
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
class InsertMany : public Base {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -94,9 +88,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSCmd : public Base {
|
||||
class BadNSCmd {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -110,9 +104,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSQuery : public Base {
|
||||
class BadNSQuery {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -125,9 +119,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSGetMore : public Base {
|
||||
class BadNSGetMore {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -139,9 +133,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSInsert : public Base {
|
||||
class BadNSInsert {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -152,9 +146,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSUpdate : public Base {
|
||||
class BadNSUpdate {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
@ -167,9 +161,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BadNSRemove : public Base {
|
||||
class BadNSRemove {
|
||||
public:
|
||||
void run() override {
|
||||
virtual void run() {
|
||||
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
|
||||
OperationContext& opCtx = *opCtxPtr;
|
||||
DBDirectClient client(&opCtx);
|
||||
|
||||
@ -54,7 +54,6 @@
|
||||
#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"
|
||||
@ -72,21 +71,12 @@
|
||||
namespace mongo {
|
||||
namespace dbtests {
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
int runDbTests(unittest::MainProgress& progress) {
|
||||
frameworkGlobalParams.perfHist = 1;
|
||||
frameworkGlobalParams.seed = time(nullptr);
|
||||
frameworkGlobalParams.runsPerTest = 1;
|
||||
@ -134,7 +124,10 @@ int runDbTests(unittest::MainProgress& progress) {
|
||||
DatabaseShardingStateFactory::set(serviceContext,
|
||||
std::make_unique<DatabaseShardingStateFactoryShard>());
|
||||
|
||||
int ret = progress.test();
|
||||
int ret = unittest::Suite::run(frameworkGlobalParams.suites,
|
||||
frameworkGlobalParams.filter,
|
||||
"",
|
||||
frameworkGlobalParams.runsPerTest);
|
||||
|
||||
// So everything shuts down cleanly
|
||||
CollectionShardingStateFactory::clear(serviceContext);
|
||||
|
||||
@ -29,9 +29,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mongo/unittest/unittest_main_core.h"
|
||||
/*
|
||||
|
||||
namespace mongo::dbtests {
|
||||
unittest::MainProgress initializeDbTests(std::vector<std::string> argVec);
|
||||
int runDbTests(unittest::MainProgress& progress);
|
||||
} // namespace mongo::dbtests
|
||||
simple portable regression system
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mongo {
|
||||
namespace dbtests {
|
||||
int runDbTests(int argc, char** argv);
|
||||
} // namespace dbtests
|
||||
} // namespace mongo
|
||||
|
||||
@ -83,6 +83,15 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
|
||||
#include "mongo/base/status.h"
|
||||
#include "mongo/base/string_data.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -49,6 +49,19 @@ 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
|
||||
|
||||
@ -70,8 +70,10 @@
|
||||
#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);
|
||||
@ -676,14 +678,19 @@ 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.
|
||||
add<InsertBuildIgnoreUnique<true>>();
|
||||
add<InsertBuildIgnoreUnique<false>>();
|
||||
add<InsertBuildEnforceUnique<true>>();
|
||||
add<InsertBuildEnforceUnique<false>>();
|
||||
addIf<InsertBuildIgnoreUnique<true>>();
|
||||
addIf<InsertBuildIgnoreUnique<false>>();
|
||||
addIf<InsertBuildEnforceUnique<true>>();
|
||||
addIf<InsertBuildEnforceUnique<false>>();
|
||||
|
||||
add<InsertBuildIndexInterrupt>();
|
||||
add<InsertBuildIdIndexInterrupt>();
|
||||
@ -710,5 +717,5 @@ public:
|
||||
|
||||
unittest::OldStyleSuiteInitializer<IndexUpdateTests> indexUpdateTests;
|
||||
|
||||
} // namespace
|
||||
} // namespace IndexUpdateTests
|
||||
} // namespace mongo
|
||||
|
||||
@ -204,7 +204,7 @@ public:
|
||||
query_settings::QuerySettingsService::initializeForTest(_opCtx.getServiceContext());
|
||||
}
|
||||
|
||||
virtual ~Base() {
|
||||
~Base() {
|
||||
auto* const sc = _opCtx.getServiceContext();
|
||||
try {
|
||||
deleteAll(ns());
|
||||
@ -436,7 +436,7 @@ namespace Idempotence {
|
||||
|
||||
class Base : public ReplTests::Base {
|
||||
public:
|
||||
virtual ~Base() = default;
|
||||
virtual ~Base() {}
|
||||
void run() {
|
||||
reset();
|
||||
doIt();
|
||||
|
||||
@ -132,7 +132,7 @@ mongo_cc_unit_test(
|
||||
copts = [
|
||||
"-Isrc/mongo/embedded",
|
||||
],
|
||||
provides_main = True,
|
||||
has_custom_mainline = True,
|
||||
tags = [
|
||||
"mongo_unittest_third_group",
|
||||
"stitch_support_test",
|
||||
@ -145,6 +145,5 @@ 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",
|
||||
],
|
||||
)
|
||||
|
||||
@ -39,8 +39,6 @@
|
||||
#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"
|
||||
@ -652,22 +650,23 @@ 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(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();
|
||||
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";
|
||||
return static_cast<int>(mongo::ExitCode::fail);
|
||||
}
|
||||
|
||||
if (auto ret = mongo::runGlobalDeinitializers(); !ret.isOK()) {
|
||||
std::cerr << "Global deinitilization failed" << ret.toString();
|
||||
ret = mongo::runGlobalDeinitializers();
|
||||
if (!ret.isOK()) {
|
||||
std::cerr << "Global deinitilization failed";
|
||||
return static_cast<int>(mongo::ExitCode::fail);
|
||||
}
|
||||
|
||||
return progress.test();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -46,16 +46,44 @@ namespace {
|
||||
namespace m = unittest::match;
|
||||
|
||||
/** Match that `x` converts to `true` and that `*x` matches `m`. */
|
||||
MATCHER_P(WhenDereferenced, m, "") {
|
||||
if (!arg)
|
||||
return false;
|
||||
return ExplainMatchResult(m, *arg, result_listener);
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
/** Match that `static_cast<bool>(x)` matches `m`. */
|
||||
MATCHER_P(WhenBool, m, "") {
|
||||
return ExplainMatchResult(m, static_cast<bool>(arg), result_listener);
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
enum class SomeTimeSplitId : size_t {
|
||||
a,
|
||||
|
||||
@ -125,14 +125,14 @@ public:
|
||||
: CommonTaskExecutorTestFixture(std::move(makeExecutor)) {} \
|
||||
\
|
||||
private: \
|
||||
void TestBody() override; \
|
||||
void _doTest() 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::TestBody()
|
||||
void CET_##TEST_NAME::_doTest()
|
||||
|
||||
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) {
|
||||
for (auto&& [name, func] : executorTestCaseRegistry()) {
|
||||
testing::RegisterTest(
|
||||
suiteName.c_str(), name.c_str(), nullptr, nullptr, __FILE__, __LINE__, [=] {
|
||||
return func(makeExecutor).release();
|
||||
});
|
||||
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(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,10 @@ void TaskExecutorTest::joinExecutorThread() {
|
||||
_executor->join();
|
||||
}
|
||||
|
||||
void TaskExecutorTest::_doTest() {
|
||||
MONGO_UNREACHABLE;
|
||||
}
|
||||
|
||||
void TaskExecutorTest::postExecutorThreadLaunch() {}
|
||||
|
||||
} // namespace executor
|
||||
|
||||
@ -91,6 +91,16 @@ 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;
|
||||
|
||||
|
||||
@ -110,64 +110,30 @@ mongo_cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
mongo_cc_library(
|
||||
name = "idl_test_base",
|
||||
mongo_cc_unit_test(
|
||||
name = "idl_test",
|
||||
srcs = [
|
||||
"server_parameter_specialized_test_defs.cpp",
|
||||
"server_parameter_with_storage_test_defs.cpp",
|
||||
":idl_test_defs.cpp",
|
||||
"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_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",
|
||||
":idl_test_base",
|
||||
":server_parameter_test_util",
|
||||
"//src/mongo/client:connection_string",
|
||||
"//src/mongo/db:server_base",
|
||||
"//src/mongo/db:server_feature_flags",
|
||||
@ -177,6 +143,7 @@ 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",
|
||||
],
|
||||
)
|
||||
|
||||
@ -99,6 +99,22 @@ 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));
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
@ -27,6 +27,8 @@
|
||||
* 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"
|
||||
@ -57,7 +59,6 @@
|
||||
#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"
|
||||
@ -100,6 +101,11 @@ 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) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2025-present MongoDB, Inc.
|
||||
* Copyright (C) 2018-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
@ -105,6 +105,20 @@ 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");
|
||||
@ -113,14 +127,67 @@ 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(getGlobalSCSP(), "Updated Value");
|
||||
ASSERT_EQ(gSCSP, "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);
|
||||
@ -133,6 +200,21 @@ 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);
|
||||
@ -145,6 +227,28 @@ 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);
|
||||
@ -159,6 +263,30 @@ 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,
|
||||
@ -177,6 +305,24 @@ 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");
|
||||
@ -186,21 +332,50 @@ 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(getGlobalSWO(), "second value");
|
||||
ASSERT_EQ(gSWO, "second value");
|
||||
ASSERT_APPENDED_STRING(swo, "###");
|
||||
|
||||
auto* dswo = getServerParameter("deprecatedWithOptions");
|
||||
ASSERT_APPENDED_STRING(dswo, "###");
|
||||
ASSERT_OK(dswo->setFromString("third value", boost::none));
|
||||
ASSERT_EQ(getGlobalSWO(), "third value");
|
||||
ASSERT_EQ(gSWO, "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;
|
||||
@ -221,10 +396,7 @@ TEST(SpecializedServerParameter, SpecializedRedactedSettable) {
|
||||
};
|
||||
|
||||
ASSERT_OK(store("", "hello"));
|
||||
ASSERT_THAT(load(), testing::Truly([&](const BSONObj& obj) {
|
||||
auto elem = obj.getField(sp->name());
|
||||
return elem.type() == BSONType::string && elem.String() == "###";
|
||||
}))
|
||||
ASSERT_THAT(load(), BSONObjHas(BSONElementIs(Eq(sp->name()), Eq(BSONType::string), Eq("###"))))
|
||||
<< "value redacted by append";
|
||||
ASSERT_THAT(dataMember, Eq("hello")) << "value preseved in _data member";
|
||||
|
||||
@ -270,6 +442,33 @@ 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();
|
||||
|
||||
@ -292,6 +491,55 @@ 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;
|
||||
|
||||
@ -47,9 +47,6 @@
|
||||
namespace mongo {
|
||||
namespace test {
|
||||
|
||||
const std::string& getGlobalSCSP();
|
||||
const std::string& getGlobalSWO();
|
||||
|
||||
struct ExtraDataForServerParameter {
|
||||
std::string value = "start value";
|
||||
bool flag = true;
|
||||
|
||||
@ -1,292 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@ -51,6 +51,10 @@
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace mongo {
|
||||
AtomicWord<int> test::gStdIntPreallocated;
|
||||
AtomicWord<int> test::gStdIntPreallocatedUpdateCount;
|
||||
size_t test::count;
|
||||
|
||||
namespace {
|
||||
|
||||
using SPT = ServerParameterType;
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@ -32,7 +32,7 @@ global:
|
||||
cpp_namespace: "mongo::idl::test"
|
||||
cpp_includes:
|
||||
- "mongo/idl/idl_test_types.h"
|
||||
- "mongo/idl/idl_test_defs.h"
|
||||
- "mongo/idl/idl_test.h"
|
||||
|
||||
imports:
|
||||
- "mongo/db/basic_types.idl"
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
namespace mongo::logv2 {
|
||||
|
||||
template <typename... Backend>
|
||||
class MONGO_MOD_NEEDS_REPLACEMENT CompositeBackend
|
||||
class CompositeBackend
|
||||
: public boost::log::sinks::basic_formatted_sink_backend<
|
||||
char,
|
||||
boost::log::sinks::combine_requirements<boost::log::sinks::concurrent_feeding,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user