diff options
author | Adam Midvidy <amidvidy@gmail.com> | 2016-02-26 16:33:23 -0500 |
---|---|---|
committer | Adam Midvidy <amidvidy@gmail.com> | 2016-03-10 11:03:15 -0500 |
commit | 6efa681435ec30467ca88edc449b241bb2c326bf (patch) | |
tree | 41f788b7cb9f2058247266f0f51f3b7947fa267b | |
parent | 947307dbf80d59313e8c154eea1612fedb01a321 (diff) | |
download | mongo-6efa681435ec30467ca88edc449b241bb2c326bf.tar.gz |
SERVER-22356 add read_only_sharded suite
-rw-r--r-- | buildscripts/resmokeconfig/suites/read_only.yml | 3 | ||||
-rw-r--r-- | buildscripts/resmokeconfig/suites/read_only_sharded.yml | 14 | ||||
-rw-r--r-- | etc/evergreen.yml | 30 | ||||
-rw-r--r-- | jstests/readonly/aggregate.js | 14 | ||||
-rw-r--r-- | jstests/readonly/geo.js | 16 | ||||
-rw-r--r-- | jstests/readonly/lib/read_only_test.js | 122 | ||||
-rw-r--r-- | src/mongo/shell/shardingtest.js | 50 |
7 files changed, 198 insertions, 51 deletions
diff --git a/buildscripts/resmokeconfig/suites/read_only.yml b/buildscripts/resmokeconfig/suites/read_only.yml index 7ae7cd5286a..f5c3a373fd9 100644 --- a/buildscripts/resmokeconfig/suites/read_only.yml +++ b/buildscripts/resmokeconfig/suites/read_only.yml @@ -7,5 +7,8 @@ executor: js_test: config: shell_options: + global_vars: + TestData: + fixture: standalone readMode: commands nodb: "" diff --git a/buildscripts/resmokeconfig/suites/read_only_sharded.yml b/buildscripts/resmokeconfig/suites/read_only_sharded.yml new file mode 100644 index 00000000000..58ab7df836e --- /dev/null +++ b/buildscripts/resmokeconfig/suites/read_only_sharded.yml @@ -0,0 +1,14 @@ +selector: + js_test: + roots: + - jstests/readonly/*.js + +executor: + js_test: + config: + shell_options: + global_vars: + TestData: + fixture: sharded + readMode: commands + nodb: "" diff --git a/etc/evergreen.yml b/etc/evergreen.yml index b581b4691a5..c9229e595ea 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -1719,6 +1719,24 @@ tasks: resmoke_args: --suites=read_only --storageEngine=wiredTiger run_multiple_jobs: true +- <<: *task_template + name: read_only_sharded + commands: + - func: "do setup" + - func: "run tests" + vars: + resmoke_args: --suites=read_only_sharded --storageEngine=mmapv1 + run_multiple_jobs: true + +- <<: *task_template + name: read_only_sharded_WT + commands: + - func: "do setup" + - func: "run tests" + vars: + resmoke_args: --suites=read_only_sharded --storageEngine=wiredTiger + run_multiple_jobs: true + - name: push patchable: false depends_on: @@ -2239,6 +2257,8 @@ buildvariants: - name: read_concern_majority_passthrough_WT - name: read_only - name: read_only_WT + - name: read_only_sharded + - name: read_only_sharded_WT - name: replicasets - name: replicasets_WT - name: replicasets_auth @@ -3258,6 +3278,8 @@ buildvariants: - name: read_concern_majority_passthrough_WT - name: read_only - name: read_only_WT + - name: read_only_sharded + - name: read_only_sharded_WT - name: replicasets - name: replicasets_WT - name: replication @@ -3927,6 +3949,8 @@ buildvariants: - name: read_concern_majority_passthrough_WT - name: read_only - name: read_only_WT + - name: read_only_sharded + - name: read_only_sharded_WT - name: replicasets - name: replicasets_WT - name: replicasets_WT_ese @@ -4531,6 +4555,10 @@ buildvariants: - name: parallel_compatibility - name: parallel_compatibility_WT - name: read_concern_majority_passthrough_WT + - name: read_only + - name: read_only_WT + - name: read_only_sharded + - name: read_only_sharded_WT - name: replicasets - name: replicasets_WT - name: replicasets_WT_ese @@ -5604,6 +5632,8 @@ buildvariants: - name: read_concern_majority_passthrough_WT - name: read_only - name: read_only_WT + - name: read_only_sharded + - name: read_only_sharded_WT - name: replicasets - name: replicasets_WT - name: replicasets_WT_ese diff --git a/jstests/readonly/aggregate.js b/jstests/readonly/aggregate.js index 9f74f739c4d..aba6a7aa3a3 100644 --- a/jstests/readonly/aggregate.js +++ b/jstests/readonly/aggregate.js @@ -69,13 +69,17 @@ runReadOnlyTest(function() { // Find titles nominated for the most awards. var mostAwardsPipeline = [ {$unwind: "$nominations"}, - {$group: {_id: "$nominations.title", count: {$sum: 1}}}, - {$sort: {count: -1}}, - {$limit: 2} + {$group: { + _id: "$nominations.title", + count: {$sum: 1}}}, + {$sort: {count: -1, _id: 1}}, + {$limit: 2}, ]; - assert.docEq(readableCollection.aggregate(mostAwardsPipeline).toArray(), - [{_id: "The Revenant", count: 3}, {_id: "Spotlight", count: 3}]); + assert.docEq(readableCollection.aggregate(mostAwardsPipeline).toArray(), [ + {_id: "Spotlight", count: 3}, + {_id: "The Revenant", count: 3} + ]); // Check that pipelines fail with allowDiskUse true. We use runCommand manually because // the helper has conflicting error handling logic. diff --git a/jstests/readonly/geo.js b/jstests/readonly/geo.js index 367cb89be96..f8113dabb06 100644 --- a/jstests/readonly/geo.js +++ b/jstests/readonly/geo.js @@ -33,11 +33,17 @@ runReadOnlyTest(function() { writableCollection.insertMany(locDocs); }, exec: function(readableCollection) { - var res = readableCollection.find({ - loc: - {$near: {$geometry: {type: "Point", coordinates: [40.7211404, -73.9591494]}}} - }).limit(1).toArray(); - assert.eq(res[0].name, "The Counting Room"); + var res = readableCollection.runCommand({ + geoNear: readableCollection.getName(), + near: { + type: "Point", + coordinates: [40.7211404, -73.9591494] + }, + spherical: true, + limit: 1 + }); + assert.commandWorked(res); + assert.eq(res.results[0].obj.name, "The Counting Room", printjson(res)); } }; }()); diff --git a/jstests/readonly/lib/read_only_test.js b/jstests/readonly/lib/read_only_test.js index 55af207a399..c0ee79a7370 100644 --- a/jstests/readonly/lib/read_only_test.js +++ b/jstests/readonly/lib/read_only_test.js @@ -1,4 +1,4 @@ -'use_strict'; +"use_strict"; function makeDirectoryReadOnly(dir) { if (_isWindows()) { @@ -16,44 +16,114 @@ function makeDirectoryWritable(dir) { } } -function runReadOnlyTest(test) { - printjson(test); +function StandaloneFixture() { +} + +StandaloneFixture.prototype.runLoadPhase = function runLoadPhase(test) { + this.mongod = MongoRunner.runMongod({}); + this.dbpath = this.mongod.dbpath; + + test.load(this.mongod.getDB("test")[test.name]); + MongoRunner.stopMongod(this.mongod); +}; + +StandaloneFixture.prototype.runExecPhase = function runExecPhase(test) { + try { + makeDirectoryReadOnly(this.dbpath); - assert.eq(typeof(test.exec), 'function'); - assert.eq(typeof(test.load), 'function'); - assert.eq(typeof(test.name), 'string'); + var options = { + readOnly: "", + noCleanData: true, + dbpath: this.dbpath + }; + + this.mongod = MongoRunner.runMongod(options); + + test.exec(this.mongod.getDB("test")[test.name]); + + MongoRunner.stopMongod(this.mongod); + } finally { + makeDirectoryWritable(this.dbpath); + } +}; + +function ShardedFixture() { + this.nShards = 3; +} - var options = { - storageEngine: TestData.storageEngine, - nopreallocj: '' - }; +ShardedFixture.prototype.runLoadPhase = function runLoadPhase(test) { + this.shardingTest = new ShardingTest({ + nopreallocj: true, + mongos: 1, + shards: this.nShards + }); - var writableMongod = MongoRunner.runMongod(options); - var dbpath = writableMongod.dbpath; + this.paths = this.shardingTest.getDBPaths(); - jsTest.log('starting load phase for test: ' + test.name); - test.load(writableMongod.getDB('test')[test.name]); + jsTest.log("sharding test collection..."); - MongoRunner.stopMongod(writableMongod); + // Use a hashed shard key so we actually hit multiple shards. + this.shardingTest.shardColl(test.name, {_id: "hashed"}); - makeDirectoryReadOnly(dbpath); + test.load(this.shardingTest.getDB("test")[test.name]); +}; +ShardedFixture.prototype.runExecPhase = function runExecPhase(test) { + jsTest.log("restarting shards..."); try { - var readOnlyOptions = - Object.extend(options, {readOnly: '', dbpath: dbpath, noCleanData: true}); + for (var i = 0; i < this.nShards; ++i) { + var opts = { + readOnly: "", + dbpath: this.paths[i] + }; + + this.shardingTest.restartMongod(i, opts, () => { + makeDirectoryReadOnly(this.paths[i]); + }); + } + + jsTest.log("restarting mongos..."); - var readOnlyMongod = MongoRunner.runMongod(readOnlyOptions); + this.shardingTest.restartMongos(0); - jsTest.log('starting execution phase for test: ' + test.name); - test.exec(readOnlyMongod.getDB('test')[test.name]); + test.exec(this.shardingTest.getDB("test")[test.name]); - // We need to make the directory writable so that MongoRunner can clean the dbpath. - makeDirectoryWritable(dbpath); - MongoRunner.stopMongod(readOnlyMongod); + this.paths.forEach((path) => { + makeDirectoryWritable(path); + }); + + this.shardingTest.stop(); } finally { - // One last time, just in case. - makeDirectoryWritable(dbpath); + this.paths.forEach((path) => { + makeDirectoryWritable(path); + }); + } +}; + +function runReadOnlyTest(test) { + + printjson(test); + + assert.eq(typeof(test.exec), "function"); + assert.eq(typeof(test.load), "function"); + assert.eq(typeof(test.name), "string"); + + var fixtureType = TestData.fixture || "standalone"; + + var fixture = null; + if (fixtureType === "standalone") { + fixture = new StandaloneFixture(); + } else if (fixtureType === "sharded") { + fixture = new ShardedFixture(); + } else { + throw new Error("fixtureType must be one of either 'standalone' or 'sharded'"); } + + jsTest.log("starting load phase for test: " + test.name); + fixture.runLoadPhase(test); + + jsTest.log("starting execution phase for test: " + test.name); + fixture.runExecPhase(test); } function * cycleN(arr, N) { diff --git a/src/mongo/shell/shardingtest.js b/src/mongo/shell/shardingtest.js index 4d38aa88544..6651057143e 100644 --- a/src/mongo/shell/shardingtest.js +++ b/src/mongo/shell/shardingtest.js @@ -369,6 +369,12 @@ var ShardingTest = function(params) { (timeMillis / 1000) + " seconds ***"); }; + this.getDBPaths = function() { + return _alldbpaths.map((path) => { + return MongoRunner.dataPath + path; + }); + }; + this.adminCommand = function(cmd) { var res = this.admin.runCommand(cmd); if (res && res.ok == 1) @@ -820,11 +826,14 @@ var ShardingTest = function(params) { * Stops and restarts a shard mongod process. * * If opts is specified, the new mongod is started using those options. Otherwise, it is started - * with its previous parameters. + * with its previous parameters. The 'beforeRestartCallback' parameter is an optional function + * that will be run after the MongoD is stopped, but before it is restarted. The intended uses + * of the callback are modifications to the dbpath of the mongod that must be made while it is + * stopped. * * Warning: Overwrites the old dn/shardn member variables. */ - this.restartMongod = function(n) { + this.restartMongod = function(n, opts, beforeRestartCallback) { var mongod; if (otherParams.useBridge) { @@ -833,26 +842,37 @@ var ShardingTest = function(params) { mongod = this["d" + n]; } + opts = opts || mongod; + opts.port = opts.port || mongod.port; + this.stopMongod(n); if (otherParams.useBridge) { - var bridgeOptions = - Object.merge(otherParams.bridgeOptions, mongod.fullOptions.bridgeOptions || {}); - bridgeOptions = Object.merge( - bridgeOptions, - { - hostName: otherParams.useHostname ? hostName : "localhost", - port: this._connections[n].port, - // The mongod processes identify themselves to mongobridge as host:port, where the - // host is the actual hostname of the machine and not localhost. - dest: hostName + ":" + mongod.port, - }); + var bridgeOptions = (opts !== mongod) ? opts.bridgeOptions + : mongod.fullOptions.bridgeOptions; + bridgeOptions = Object.merge(otherParams.bridgeOptions, bridgeOptions || {}); + bridgeOptions = Object.merge(bridgeOptions, { + hostName: otherParams.useHostname ? hostName : "localhost", + port: this._connections[n].port, + // The mongod processes identify themselves to mongobridge as host:port, where the + // host is the actual hostname of the machine and not localhost. + dest: hostName + ":" + opts.port, + }); this._connections[n] = new MongoBridge(bridgeOptions); } - mongod.restart = true; - var newConn = MongoRunner.runMongod(mongod); + if (arguments.length >= 3) { + if (typeof(beforeRestartCallback) !== "function") { + throw new Error("beforeRestartCallback must be a function but was of type " + + typeof(beforeRestartCallback)); + } + beforeRestartCallback(); + } + + opts.restart = true; + + var newConn = MongoRunner.runMongod(opts); if (!newConn) { throw new Error("Failed to restart shard " + n); } |