Files
mongo/jstests/core/api_version_test_expression.js

263 lines
9.6 KiB
JavaScript
Raw Normal View History

/**
* Checks that the $_testApiVersion expression used for API versioning testing
* throws errors as expected.
*
* Tests which create views aren't expected to work when collections are implicitly sharded.
* @tags: [
* assumes_against_mongod_not_mongos,
* assumes_unsharded_collection,
* uses_api_parameters,
* no_selinux,
* ]
*/
(function() {
"use strict";
const collName = "api_version_test_expression";
const coll = db[collName];
coll.drop();
const collForeignName = collName + "_foreign";
const collForeign = db[collForeignName];
collForeign.drop();
for (let i = 0; i < 5; i++) {
assert.commandWorked(coll.insert({num: i}));
assert.commandWorked(collForeign.insert({num: i}));
}
// Assert error thrown when command specifies {apiStrict: true} and expression specifies {unstable:
// true}.
let pipeline = [{$project: {v: {$_testApiVersion: {unstable: true}}}}];
assert.commandFailedWithCode(
db.runCommand(
{aggregate: collName, pipeline: pipeline, cursor: {}, apiStrict: true, apiVersion: "1"}),
ErrorCodes.APIStrictError);
// Assert error thrown when command specifies {apiDeprecationErrors: true} and expression specifies
// {deprecated: true}
pipeline = [{$project: {v: {$_testApiVersion: {deprecated: true}}}}];
assert.commandFailedWithCode(db.runCommand({
aggregate: collName,
pipeline: pipeline,
cursor: {},
apiDeprecationErrors: true,
apiVersion: "1"
}),
ErrorCodes.APIDeprecationError);
// Assert error thrown when the command specifies apiStrict:true and an inner pipeline contains an
// unstable expression.
const unstableInnerPipeline = [{$project: {v: {$_testApiVersion: {unstable: true}}}}];
assert.commandFailedWithCode(db.runCommand({
aggregate: collName,
pipeline: [{$lookup: {from: collForeignName, as: "output", pipeline: unstableInnerPipeline}}],
cursor: {},
apiStrict: true,
apiVersion: "1"
}),
ErrorCodes.APIStrictError);
assert.commandFailedWithCode(db.runCommand({
aggregate: collName,
pipeline: [{$unionWith: {coll: collForeignName, pipeline: unstableInnerPipeline}}],
cursor: {},
apiStrict: true,
apiVersion: "1"
}),
ErrorCodes.APIStrictError);
// Assert command worked when the command specifies apiStrict:false and an inner pipeline contains
// an unstable expression.
assert.commandWorked(db.runCommand({
aggregate: collName,
pipeline: [{$lookup: {from: collForeignName, as: "output", pipeline: unstableInnerPipeline}}],
cursor: {},
apiStrict: false,
apiVersion: "1"
}));
assert.commandWorked(db.runCommand({
aggregate: collName,
pipeline: [{$unionWith: {coll: collForeignName, pipeline: unstableInnerPipeline}}],
cursor: {},
apiStrict: false,
apiVersion: "1"
}));
// Assert error thrown when the command specifies apiDeprecationErrors:true and an inner pipeline
// contains a deprecated expression.
const deprecatedInnerPipeline = [{$project: {v: {$_testApiVersion: {deprecated: true}}}}];
assert.commandFailedWithCode(db.runCommand({
aggregate: collName,
pipeline: [{$lookup: {from: collForeignName, as: "output", pipeline: deprecatedInnerPipeline}}],
cursor: {},
apiDeprecationErrors: true,
apiVersion: "1"
}),
ErrorCodes.APIDeprecationError);
assert.commandFailedWithCode(db.runCommand({
aggregate: collName,
pipeline: [{$unionWith: {coll: collForeignName, pipeline: deprecatedInnerPipeline}}],
cursor: {},
apiDeprecationErrors: true,
apiVersion: "1"
}),
ErrorCodes.APIDeprecationError);
// Assert command worked when the command specifies apiDeprecationErrors:false and an inner pipeline
// contains a deprecated expression.
assert.commandWorked(db.runCommand({
aggregate: collName,
pipeline: [{$lookup: {from: collForeignName, as: "output", pipeline: deprecatedInnerPipeline}}],
cursor: {},
apiDeprecationErrors: false,
apiVersion: "1"
}));
assert.commandWorked(db.runCommand({
aggregate: collName,
pipeline: [{$unionWith: {coll: collForeignName, pipeline: deprecatedInnerPipeline}}],
cursor: {},
apiDeprecationErrors: false,
apiVersion: "1"
}));
// Test that command successfully runs to completion without any API parameters.
pipeline = [{$project: {v: {$_testApiVersion: {unstable: true}}}}];
assert.commandWorked(db.runCommand({aggregate: collName, pipeline: pipeline, cursor: {}}));
// Create a view with {apiStrict: true}.
db.view.drop();
assert.commandWorked(db.runCommand(
{create: "view", viewOn: collName, pipeline: [], apiStrict: true, apiVersion: "1"}));
// find() on views should work normally if 'apiStrict' is true.
assert.commandWorked(db.runCommand({find: "view", apiStrict: true, apiVersion: "1"}));
// This command will work because API parameters are not inherited from views.
assert.commandWorked(db.runCommand({aggregate: "view", pipeline: pipeline, cursor: {}}));
assert.commandFailedWithCode(
db.runCommand(
{aggregate: "view", pipeline: pipeline, cursor: {}, apiVersion: "1", apiStrict: true}),
ErrorCodes.APIStrictError);
// Create a view with 'unstable' parameter should fail with 'apiStrict'.
db.unstableView.drop();
assert.commandFailedWithCode(db.runCommand({
create: "unstableView",
viewOn: collName,
pipeline: pipeline,
apiStrict: true,
apiVersion: "1"
}),
ErrorCodes.APIStrictError);
// Create a view with 'unstable' should be allowed without 'apiStrict'.
assert.commandWorked(db.runCommand({
create: "unstableView",
viewOn: collName,
pipeline: pipeline,
apiVersion: "1",
apiStrict: false
}));
assert.commandWorked(db.runCommand({aggregate: "unstableView", pipeline: [], cursor: {}}));
// This commmand will fail even with the empty pipeline because of the view.
assert.commandFailedWithCode(
db.runCommand(
{aggregate: "unstableView", pipeline: [], cursor: {}, apiVersion: "1", apiStrict: true}),
ErrorCodes.APIStrictError);
// Create a validator containing the unstable test expression.
let validator = {$expr: {$_testApiVersion: {unstable: true}}};
let validatedCollName = collName + "_validated";
// Creating a collection with the unstable validator is not allowed with apiStrict:true.
db[validatedCollName].drop();
assert.commandFailedWithCode(
db.runCommand(
{create: validatedCollName, validator: validator, apiVersion: "1", apiStrict: true}),
ErrorCodes.APIStrictError);
// Run create and insert commands without apiStrict:true and verify that it is successful.
assert.commandWorked(db.runCommand(
{create: validatedCollName, validator: validator, apiVersion: "1", apiStrict: false}));
assert.commandWorked(
db[validatedCollName].runCommand({insert: validatedCollName, documents: [{num: 1}]}));
// Specifying apiStrict: true results in an error.
assert.commandFailedWithCode(
db[validatedCollName].runCommand(
{insert: validatedCollName, documents: [{num: 1}], apiVersion: "1", apiStrict: true}),
ErrorCodes.APIStrictError);
// Recreate the validator containing a deprecated test expression.
db[validatedCollName].drop();
validator = {
$expr: {$_testApiVersion: {deprecated: true}}
};
// Creating a collection with the deprecated validator is not allowed with
// apiDeprecationErrors:true.
assert.commandFailedWithCode(db.runCommand({
create: validatedCollName,
validator: validator,
apiVersion: "1",
apiDeprecationErrors: true,
}),
ErrorCodes.APIDeprecationError);
// Run create and insert commands without apiDeprecationErrors:true and verify that it is
// successful.
assert.commandWorked(db.runCommand({
create: validatedCollName,
validator: validator,
apiVersion: "1",
apiDeprecationErrors: false,
}));
assert.commandWorked(
db[validatedCollName].runCommand({insert: validatedCollName, documents: [{num: 1}]}));
// Specifying apiDeprecationErrors: true results in an error.
assert.commandFailedWithCode(db[validatedCollName].runCommand({
insert: validatedCollName,
documents: [{num: 1}],
apiVersion: "1",
apiDeprecationErrors: true
}),
ErrorCodes.APIDeprecationError);
// Test that API version parameters are inherited into the inner command of the explain command.
function checkExplainInnerCommandGetsAPIVersionParameters(explainedCmd, errCode) {
assert.commandFailedWithCode(
db.runCommand(
{explain: explainedCmd, apiVersion: "1", apiDeprecationErrors: true, apiStrict: true}),
errCode);
// If 'apiStrict: false' the inner aggregate command will execute successfully.
const explainRes = db.runCommand({explain: explainedCmd, apiVersion: "1", apiStrict: false});
assert(explainRes.hasOwnProperty('executionStats'), explainRes);
assert.eq(explainRes['executionStats']['executionSuccess'], true, explainRes);
}
pipeline = [{$project: {v: {$_testApiVersion: {unstable: true}}}}];
let aggCmd = {aggregate: collName, pipeline: pipeline, cursor: {}};
checkExplainInnerCommandGetsAPIVersionParameters(aggCmd, ErrorCodes.APIStrictError);
let findCmd = {find: collName, projection: {v: {$_testApiVersion: {unstable: true}}}};
checkExplainInnerCommandGetsAPIVersionParameters(findCmd, ErrorCodes.APIStrictError);
pipeline = [{$project: {v: {$_testApiVersion: {deprecated: true}}}}];
aggCmd = {
aggregate: collName,
pipeline: pipeline,
cursor: {}
};
checkExplainInnerCommandGetsAPIVersionParameters(aggCmd, ErrorCodes.APIDeprecationError);
findCmd = {
find: collName,
projection: {v: {$_testApiVersion: {deprecated: true}}}
};
checkExplainInnerCommandGetsAPIVersionParameters(findCmd, ErrorCodes.APIDeprecationError);
db[validatedCollName].drop();
db.unstableView.drop();
})();