diff --git a/tools/runners/run-mongo.js b/tools/runners/run-mongo.js index 9f9b692a20..551d36d63b 100644 --- a/tools/runners/run-mongo.js +++ b/tools/runners/run-mongo.js @@ -482,15 +482,15 @@ var launchMongo = function (options) { proc = spawnMongod(mongod_path, port, dbPath, replSetName); - subHandles.push({ - stop: function () { - if (proc) { - proc.removeListener('exit', procExitHandler); - proc.kill('SIGINT'); - proc = null; - } + function stop() { + if (proc) { + proc.removeListener('exit', procExitHandler); + proc.kill('SIGINT'); + proc = null; } - }); + } + require("../tool-env/cleanup.js").onExit(stop); + subHandles.push({ stop }); var procExitHandler = fiberHelpers.bindEnvironment(function (code, signal) { // Defang subHandle.stop(). @@ -532,7 +532,8 @@ var launchMongo = function (options) { var stdoutOnData = fiberHelpers.bindEnvironment(function (data) { // note: don't use "else ifs" in this, because 'data' can have multiple // lines - if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data)) { + if (/\[initandlisten\] Did not find local replica set configuration document at startup/.test(data) || + /\[ReplicationExecutor\] Locally stored replica set configuration does not have a valid entry for the current node/.test(data)) { replSetReadyToBeInitiated = true; maybeReadyToTalk(); } @@ -596,10 +597,25 @@ var launchMongo = function (options) { if (stopped) { return; } + var configuration = { _id: replSetName, + version: 1, members: [{_id: 0, host: '127.0.0.1:' + options.port, priority: 100}] }; + + try { + const config = yieldingMethod(db.admin(), "command", { + replSetGetConfig: 1, + }).config; + + // If a replication set configuration already exists, it's + // important that the new version number is greater than the old. + if (config && _.has(config, "version")) { + configuration.version = config.version + 1; + } + } catch (e) {} + if (options.multiple) { // Add two more members: one of which should start as secondary but // could in theory become primary, and one of which can never be @@ -613,10 +629,16 @@ var launchMongo = function (options) { } try { - var initiateResult = yieldingMethod( - db.admin(), 'command', {replSetInitiate: configuration}); + yieldingMethod(db.admin(), 'command', { + replSetInitiate: configuration, + }); } catch (e) { - if (e.message !== 'already initialized') { + if (e.message === 'already initialized') { + yieldingMethod(db.admin(), 'command', { + replSetReconfig: configuration, + force: true, + }); + } else { throw Error("rs.initiate error: " + e.message); } } diff --git a/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders b/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders new file mode 100644 index 0000000000..aa607041da --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.finished-upgraders @@ -0,0 +1,15 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 +0.9.4-platform-file +notices-for-facebook-graph-api-2 +1.2.0-standard-minifiers-package +1.2.0-meteor-platform-split +1.2.0-cordova-changes +1.2.0-breaking-changes +1.3.0-split-minifiers-package +1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package diff --git a/tools/tests/apps/mongo-sanity/.meteor/.gitignore b/tools/tests/apps/mongo-sanity/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/tests/apps/mongo-sanity/.meteor/.id b/tools/tests/apps/mongo-sanity/.meteor/.id new file mode 100644 index 0000000000..789b92d073 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +fgbyyt1b3uxw5u734ug diff --git a/tools/tests/apps/mongo-sanity/.meteor/packages b/tools/tests/apps/mongo-sanity/.meteor/packages new file mode 100644 index 0000000000..6205c4c08c --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/packages @@ -0,0 +1,12 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base # Packages every Meteor app needs to have +mongo # The database Meteor supports right now + +ecmascript # Enable ECMAScript2015+ syntax in app code +shell-server # Server-side component of the `meteor shell` command + diff --git a/tools/tests/apps/mongo-sanity/.meteor/platforms b/tools/tests/apps/mongo-sanity/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tools/tests/apps/mongo-sanity/.meteor/release b/tools/tests/apps/mongo-sanity/.meteor/release new file mode 100644 index 0000000000..621e94f0ec --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/release @@ -0,0 +1 @@ +none diff --git a/tools/tests/apps/mongo-sanity/.meteor/versions b/tools/tests/apps/mongo-sanity/.meteor/versions new file mode 100644 index 0000000000..e675491585 --- /dev/null +++ b/tools/tests/apps/mongo-sanity/.meteor/versions @@ -0,0 +1,54 @@ +allow-deny@1.0.5 +autoupdate@1.3.11 +babel-compiler@6.9.2-beta.5 +babel-runtime@0.1.12-beta.5 +base64@1.0.9 +binary-heap@1.0.9 +blaze@2.1.8 +blaze-tools@1.0.9 +boilerplate-generator@1.0.10 +callback-hook@1.0.9 +check@1.2.3 +ddp@1.2.5 +ddp-client@1.3.2-beta.5 +ddp-common@1.2.6 +ddp-server@1.3.11-beta.5 +deps@1.0.12 +diff-sequence@1.0.6 +ecmascript@0.5.9-beta.5 +ecmascript-runtime@0.3.15-beta.5 +ejson@1.0.12 +geojson-utils@1.0.9 +hot-code-push@1.0.4 +html-tools@1.0.10 +htmljs@1.0.10 +http@1.2.10-beta.5 +id-map@1.0.8 +jquery@1.11.9 +livedata@1.0.18 +logging@1.1.16-beta.5 +meteor@1.2.18-beta.5 +meteor-base@1.0.4 +minimongo@1.0.17 +modules@0.7.7-beta.5 +modules-runtime@0.7.7-beta.5 +mongo@1.1.13-beta.5 +mongo-id@1.0.5 +npm-mongo@1.5.51-beta.5 +observe-sequence@1.0.12 +ordered-dict@1.0.8 +promise@0.8.8-beta.5 +random@1.0.10 +reactive-var@1.0.10 +reload@1.1.10 +retry@1.0.8 +routepolicy@1.0.11 +shell-server@0.2.1 +spacebars@1.0.12 +spacebars-compiler@1.0.12 +tracker@1.1.0 +ui@1.0.11 +underscore@1.0.9 +url@1.0.10 +webapp@1.3.12-beta.5 +webapp-hashing@1.0.9 diff --git a/tools/tests/apps/mongo-sanity/server/main.js b/tools/tests/apps/mongo-sanity/server/main.js new file mode 100644 index 0000000000..45aa6e530a --- /dev/null +++ b/tools/tests/apps/mongo-sanity/server/main.js @@ -0,0 +1,18 @@ +import { Mongo } from 'meteor/mongo'; + +const collection = new Mongo.Collection("sanity"); + +Meteor.startup(() => { + let doc = collection.findOne(); + + if (! doc) { + collection.insert({ count: 0 }); + doc = collection.findOne(); + } + + collection.update(doc._id, { + $inc: { count: 1 } + }); + + console.log("count: " + collection.findOne().count); +}); diff --git a/tools/tests/mongo.js b/tools/tests/mongo.js index eafc5fecd3..eb9794a446 100644 --- a/tools/tests/mongo.js +++ b/tools/tests/mongo.js @@ -56,3 +56,32 @@ selftest.define("meteor mongo", function () { selftest.define("meteor mongo in unicode dir", function () { testMeteorMongo('asdf\u0442asdf'); }); + +selftest.define("mongo with multiple --port numbers (#7563)", function () { + var s = new Sandbox(); + s.createApp("mongo-multiple-ports", "mongo-sanity"); + s.cd("mongo-multiple-ports"); + + function check(args, matches) { + const run = s.run(...args); + run.waitSecs(30); + matches.forEach(m => { + run.waitSecs(10); + run.match(m); + }); + run.stop(); + } + + // Make absolutely sure we're creating the database for the first time. + check(["reset"], ["Project reset."]); + + let count = 0; + function next() { + return ["Started MongoDB", "count: " + (++count)]; + } + + check(["run"], next()); + check(["--port", "4321"], next()); + check(["--port", "4123"], next()); + check([], next()); +}); diff --git a/tools/tests/old/app-with-private/test.js b/tools/tests/old/app-with-private/main.js similarity index 100% rename from tools/tests/old/app-with-private/test.js rename to tools/tests/old/app-with-private/main.js diff --git a/tools/tests/old/test-bundler-assets.js b/tools/tests/old/test-bundler-assets.js index df3a543dbb..3a2ebdccc1 100644 --- a/tools/tests/old/test-bundler-assets.js +++ b/tools/tests/old/test-bundler-assets.js @@ -50,96 +50,95 @@ var runTest = function () { catalog.official.initialize(); console.log("Bundle app with public/ directory"); - assert.doesNotThrow(function () { - var projectContext = makeProjectContext("app-with-public"); - var tmpOutputDir = tmpDir(); - var result = bundler.bundle({ - projectContext: projectContext, - outputPath: tmpOutputDir - }); - var clientManifest = JSON.parse( - files.readFile( - files.pathJoin(tmpOutputDir, "programs", "web.browser", "program.json") - ) - ); + var projectContext = makeProjectContext("app-with-public"); + var tmpOutputDir = tmpDir(); - var testCases = [["/test.txt", "Test\n"], - ["/nested/nested.txt", "Nested\n"]]; - _.each(testCases, function (file) { - var manifestItem = _.find(clientManifest.manifest, function (m) { - return m.url === file[0]; - }); - assert(manifestItem); - var diskPath = files.pathJoin(tmpOutputDir, "programs", "web.browser", - manifestItem.path); - assert(files.exists(diskPath)); - assert.strictEqual(files.readFile(diskPath, "utf8"), file[1]); + var result = bundler.bundle({ + projectContext: projectContext, + outputPath: tmpOutputDir + }); + + var clientManifest = JSON.parse( + files.readFile( + files.pathJoin(tmpOutputDir, "programs", "web.browser", "program.json") + ) + ); + + var testCases = [["/test.txt", "Test\n"], + ["/nested/nested.txt", "Nested\n"]]; + _.each(testCases, function (file) { + var manifestItem = _.find(clientManifest.manifest, function (m) { + return m.url === file[0]; }); + assert(manifestItem); + var diskPath = files.pathJoin(tmpOutputDir, "programs", "web.browser", + manifestItem.path); + assert(files.exists(diskPath)); + assert.strictEqual(files.readFile(diskPath, "utf8"), file[1]); }); console.log("Bundle app with private/ directory and package asset"); - assert.doesNotThrow(function () { - var projectContext = makeProjectContext("app-with-private"); - var tmpOutputDir = tmpDir(); + var projectContext = makeProjectContext("app-with-private"); + var tmpOutputDir = tmpDir(); - var result = bundler.bundle({ - projectContext: projectContext, - outputPath: tmpOutputDir - }); - - var serverManifest = JSON.parse( - files.readFile( - files.pathJoin(tmpOutputDir, "programs", "server", - "program.json") - ) - ); - var testTxtPath; - var nestedTxtPath; - var packageTxtPath; - var unregisteredExtensionPath; - _.each(serverManifest.load, function (item) { - if (item.path === "packages/test-package.js") { - packageTxtPath = files.pathJoin( - tmpOutputDir, "programs", "server", item.assets['test-package.txt']); - unregisteredExtensionPath = files.pathJoin( - tmpOutputDir, "programs", "server", item.assets["test.notregistered"]); - } - if (item.path === "app/test.js") { - testTxtPath = files.pathJoin( - tmpOutputDir, "programs", "server", item.assets['test.txt']); - nestedTxtPath = files.pathJoin( - tmpOutputDir, "programs", "server", item.assets["nested/test.txt"]); - } - }); - // check that the files are where the manifest says they are - assert.strictEqual(result.errors, false, result.errors && result.errors[0]); - assert(files.exists(testTxtPath)); - assert(files.exists(nestedTxtPath)); - assert(files.exists(packageTxtPath)); - assert(files.exists(unregisteredExtensionPath)); - assert.strictEqual(files.readFile(testTxtPath, "utf8"), "Test\n"); - assert.strictEqual(files.readFile(nestedTxtPath, "utf8"), "Nested\n"); - assert.strictEqual(files.readFile(packageTxtPath, "utf8"), "Package\n"); - assert.strictEqual(files.readFile(unregisteredExtensionPath, "utf8"), - "No extension handler\n"); - - // Run the app to check that Assets.getText/Binary do the right things. - var meteorToolPath = files.convertToOSPath(process.env.METEOR_TOOL_PATH); - var fut = new Future(); - require('child_process').execFile( - meteorToolPath, - // use a non-default port so we don't fail if someone is running an app - // now - ["--once", "--port", "4123"], { - cwd: files.convertToOSPath(projectContext.projectDir), - stdio: 'inherit' - }, - fut.resolver() - ); - fut.wait(); // would throw if command failed + var result = bundler.bundle({ + projectContext: projectContext, + outputPath: tmpOutputDir }); + + var serverManifest = JSON.parse( + files.readFile( + files.pathJoin(tmpOutputDir, "programs", "server", + "program.json") + ) + ); + + var testTxtPath; + var nestedTxtPath; + var packageTxtPath; + var unregisteredExtensionPath; + _.each(serverManifest.load, function (item) { + if (item.path === "packages/test-package.js") { + packageTxtPath = files.pathJoin( + tmpOutputDir, "programs", "server", item.assets['test-package.txt']); + unregisteredExtensionPath = files.pathJoin( + tmpOutputDir, "programs", "server", item.assets["test.notregistered"]); + } + if (item.path === "app/main.js") { + testTxtPath = files.pathJoin( + tmpOutputDir, "programs", "server", item.assets['test.txt']); + nestedTxtPath = files.pathJoin( + tmpOutputDir, "programs", "server", item.assets["nested/test.txt"]); + } + }); + // check that the files are where the manifest says they are + assert.strictEqual(result.errors, false, result.errors && result.errors[0]); + assert(files.exists(testTxtPath)); + assert(files.exists(nestedTxtPath)); + assert(files.exists(packageTxtPath)); + assert(files.exists(unregisteredExtensionPath)); + assert.strictEqual(files.readFile(testTxtPath, "utf8"), "Test\n"); + assert.strictEqual(files.readFile(nestedTxtPath, "utf8"), "Nested\n"); + assert.strictEqual(files.readFile(packageTxtPath, "utf8"), "Package\n"); + assert.strictEqual(files.readFile(unregisteredExtensionPath, "utf8"), + "No extension handler\n"); + + // Run the app to check that Assets.getText/Binary do the right things. + var meteorToolPath = files.convertToOSPath(process.env.METEOR_TOOL_PATH); + var fut = new Future(); + require('child_process').execFile( + meteorToolPath, + // use a non-default port so we don't fail if someone is running an app + // now + ["--once", "--port", "4123"], { + cwd: files.convertToOSPath(projectContext.projectDir), + stdio: 'inherit' + }, + fut.resolver() + ); + fut.wait(); // would throw if command failed }; var Fiber = require('fibers'); diff --git a/tools/tests/run.js b/tools/tests/run.js index 908cdc8593..3be4636150 100644 --- a/tools/tests/run.js +++ b/tools/tests/run.js @@ -106,6 +106,7 @@ try { run.match('s.json: parse error reading settings file'); run.match('Waiting for file change'); s.write('s.json', '{}'); + run.waitSecs(15); run.match('App running at'); run.stop();