From c8778bfa3b21e9f6c6ac125ca48b816dc1994bf0 Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Fri, 25 Aug 2023 18:05:27 +0000 Subject: [PATCH] SERVER-80377 Use hashed jsTestName in multitenancy suites --- .eslintrc.yml | 1 + .git-blame-ignore-revs | 6 ++++ .../multitenancy_jscore_passthrough.yml | 1 + jstests/core/ddl/dropdb.js | 9 +++--- .../aggregation_zero_batchsize.js | 4 +-- src/mongo/shell/shell_utils.cpp | 28 +++++++++++++++++++ src/mongo/shell/utils.js | 11 +++++++- 7 files changed, 53 insertions(+), 7 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index b282aeb6fdc..d5f803949a1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -144,6 +144,7 @@ globals: _getEnv: true indentStr: true _forgetReplSet: true + _fnvHashToHexString: true # likely could be replaced with `path` _copyFileRange: true diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 470bf48321b..8633c29ccdc 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -13,6 +13,12 @@ f63255ee677ecae5896d6f35dd712ed60ae8c39a # SERVER-22470 Format JS code with approved style f5a6c794a0af1a5d57db2617c2e9464eaad9f221 +# SERVER-22469 Format JS code with approved style in src/mongo/shell & src/mongo/scripting +a025d43f3ce2efc1fb1282a718f5d286fa0a4dc1 + +# SERVER-22340 Fix JS lint errors in src/mongo/shell & src/mongo/scripting with ESLint --fix +c3996780b76316793758b43fa1fca5b9d0857b6c + # SERVER-18579: Clang-Format - reformat code 9c2ed42daa8fbbef4a919c21ec564e2db55e8d60 diff --git a/buildscripts/resmokeconfig/suites/multitenancy_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multitenancy_jscore_passthrough.yml index e2f85b1394b..201ff5047c0 100644 --- a/buildscripts/resmokeconfig/suites/multitenancy_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multitenancy_jscore_passthrough.yml @@ -65,6 +65,7 @@ executor: global_vars: TestData: &TestData tenantId: "636d957b2646ddfaf9b5e13f" + hashTestNamesForMultitenancy: true hooks: - class: CheckReplOplogs - class: CheckReplDBHash diff --git a/jstests/core/ddl/dropdb.js b/jstests/core/ddl/dropdb.js index 0ca8e429275..f34f0e45f14 100644 --- a/jstests/core/ddl/dropdb.js +++ b/jstests/core/ddl/dropdb.js @@ -2,9 +2,10 @@ * Test that a db does not exist after it is dropped. * * @tags: [ - * # listDatabases with explicit filter on db names doesn't work on tenant migrations suites - * tenant_migration_incompatible, - * ] + * # listDatabases with explicit filter on db names doesn't work with the simulate_atlas_proxy + * # override. + * simulate_atlas_proxy_incompatible, + * ] */ function listDatabases(options) { @@ -37,4 +38,4 @@ for (var i = 0; i < 3; i++) { } assert.commandWorked(ddb.dropDatabase()); -assertDatabaseDoesNotExist(dbName); \ No newline at end of file +assertDatabaseDoesNotExist(dbName); diff --git a/jstests/noPassthrough/aggregation_zero_batchsize.js b/jstests/noPassthrough/aggregation_zero_batchsize.js index e1d1a47c5ed..955f562c187 100644 --- a/jstests/noPassthrough/aggregation_zero_batchsize.js +++ b/jstests/noPassthrough/aggregation_zero_batchsize.js @@ -7,7 +7,7 @@ const conn = MongoRunner.runMongod(mongodOptions); assert.neq(null, conn, "mongod failed to start with options " + tojson(mongodOptions)); const testDB = conn.getDB("test"); -const coll = testDB[jsTest.name]; +const coll = testDB[jsTest.name()]; coll.drop(); // Test that an aggregate is successful on a non-existent collection. @@ -81,4 +81,4 @@ assert.commandWorked( assert.throws(() => cursor.itcount(), [], "expected getMore to fail"); assertNumOpenCursors(0); -MongoRunner.stopMongod(conn); \ No newline at end of file +MongoRunner.stopMongod(conn); diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp index 797ca772d0b..4c8e8f3ee40 100644 --- a/src/mongo/shell/shell_utils.cpp +++ b/src/mongo/shell/shell_utils.cpp @@ -728,6 +728,33 @@ BSONObj _buildBsonObj(const BSONObj& args, void*) { return BSON("" << builder.obj()); } +/* + * The following code has been updated to remove unnecessary content and better comply + * with MongoDB coding standards. The original source code can be found at: + * FNV 1a 64 bit: http://www.isthe.com/chongo/src/fnv/hash_64a.c + */ +#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) +static inline uint64_t fnv_64a_buf(const void* buf, size_t len, uint64_t hval) { + const unsigned char* bp = (const unsigned char*)buf; /* start of buffer */ + const unsigned char* be = bp + len; /* beyond end of buffer */ + while (bp < be) { + hval ^= (uint64_t)*bp++; + hval += (hval << 1) + (hval << 4) + (hval << 5) + (hval << 7) + (hval << 8) + (hval << 40); + } + + return (hval); +} + +BSONObj _fnvHashToHexString(const BSONObj& args, void*) { + uassert(8423397, + "_fnvHashToHexString expects one string argument", + args.nFields() == 1 && args.firstElement().type() == String); + + auto input = args.firstElement().str(); + auto hashed = fnv_64a_buf(input.c_str(), input.size(), FNV1A_64_INIT); + return BSON("" << fmt::format("{0:x}", hashed)); +} + void installShellUtils(Scope& scope) { scope.injectNative("getMemInfo", JSGetMemInfo); scope.injectNative("_createSecurityToken", _createSecurityToken); @@ -748,6 +775,7 @@ void installShellUtils(Scope& scope) { scope.injectNative("_writeGoldenData", _writeGoldenData); scope.injectNative("_closeGoldenData", _closeGoldenData); scope.injectNative("_buildBsonObj", _buildBsonObj); + scope.injectNative("_fnvHashToHexString", _fnvHashToHexString); installShellUtilsLauncher(scope); installShellUtilsExtended(scope); diff --git a/src/mongo/shell/utils.js b/src/mongo/shell/utils.js index 2aa66de29d2..2edb230fec3 100644 --- a/src/mongo/shell/utils.js +++ b/src/mongo/shell/utils.js @@ -357,8 +357,17 @@ function _isUndefinedBehaviorSanitizerActive() { } jsTestName = function() { - if (TestData) + if (TestData) { + // If we are using the jsTestName as a database name and performing tenant prefixing + // then it's possible that the prefixed database name will exceed the server's dbName + // length. In these cases, hashing the test name improves our chances of success. FNV-1a + // hashes are maximum 16 characters, so don't hash dbNames that are up to 16 characters. + if (TestData.testName.length > 16 && TestData.hashTestNamesForMultitenancy) { + return _fnvHashToHexString(TestData.testName); + } return TestData.testName; + } + return "__unknown_name__"; };