Skip to content

Latest commit

 

History

History
277 lines (239 loc) · 9.39 KB

README.md

File metadata and controls

277 lines (239 loc) · 9.39 KB

Assertions in the mongo shell

See Assertions 101 for a very brief overview.

The legacy mongo shell uses its own assertions which are defined here. These deviate from mongosh, which uses the standard Node.js assert module. When you write a small reproducible test and call task testjs the legacy mongo shell will be invoked.

A useful function is assert.commandFailedWithCode which asserts that the command failed with the expected code as the name implies. One should pass the result of a call to the db.runCommand() helper as this provides a result type that the function can parse. This is the preferred method to issue database commands, as it provides a consistent interface between the shell and drivers.

For example, to check if the findAndModify command failed with the error code ImmutableField you would do the following:

> const res = db.runCommand({findAndModify: "foo", query: {}, update: {$set: {_id: 1}}});
> assert.commandFailedWithCode(res, ErrorCodes.ImmutableField);

It is not always necessary use the db.runCommand() helper as some write methods wrap a writeError which the helpers can parse. For example, insert, update, and remove will all return a WriteResult so the function can parse the result and look for a writeError.

See the WriteResult object below:

// WriteResult object
> assert.commandWorked(db.foo.insert({a: 1}));
WriteResult({ "nInserted" : 1 })
> const res = db.foo.insert({a: 1});
> res.hasWriteError();
false
> Object.keys(res);
[
  "ok",
  "nInserted",
  "nUpserted",
  "nMatched",
  "nModified",
  "nRemoved",
  "getUpsertedId",
  "getRawResponse",
  "getWriteError",
  "hasWriteError",
  "getWriteConcernError",
  "hasWriteConcernError",
  "tojson",
  "toString",
  "shellPrint"
]
> res instanceof WriteResult
true
>

The find() method will return an object, the properties of which will not be parsed by the various assert functions:

> const res = db.foo.find({a: 1});
> res._filter
{ "a" : 1 }
> res._db
test
> res._batchSize
0
// all properties are private but the shell will iterate the cursor object when called
> Object.keys(res);
[
  "_mongo",
  "_db",
  "_collection",
  "_ns",
  "_filter",
  "_projection",
  "_limit",
  "_skip",
  "_batchSize",
  "_options",
  "_additionalCmdParams",
  "_cursor",
  "_numReturned"
]
>

But a runCommand() result will return the correct object that can be parsed:

> // use a runCommand instead
> const res = db.runCommand({find: "foo", filter: {a: 1}});
> res.ok
1
> res._commandObj
{
  "find" : "foo",
  "filter" : {
    "a" : 1
  },
  "lsid" : {
    "id" : UUID("cb64879f-6f69-4656-a38e-ce6dbe3ccebc")
  }
}
> assert.commandFailed(res);
uncaught exception: Error: command worked when it should have failed: {
  "cursor" : {
    "firstBatch" : [
      {
        "_id" : ObjectId("6458ec7adb858f891c0b8c68"),
        "a" : 1
      },
      {
        "_id" : ObjectId("6458ec9ddb858f891c0b8c6a"),
        "a" : 1
      }
    ],
    "id" : NumberLong(0),
    "ns" : "test.foo"
  },
  "ok" : 1
} :
_getErrorWithCode@src/mongo/shell/utils.js:24:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandFailed@src/mongo/shell/assert.js:819:25
assert.commandFailed@src/mongo/shell/assert.js:877:16
@(shell):1:8

Some useful functions

assert.eq(a, b, msg)

throws if two values are not equal (tested without strict equality).

assert.isnull(what, msg)

throws if what is not null.

assert.commandFailed(res, msg)

throws if the command did not fail.

assert.commandWorked(res)

throws if the result contained an error.

assert.commandFailedWithCode(res, expectedCode, msg)

throws if the command did not fail with the expected code.

assert.sameMembers(aArr, bArr, msg, compareFn = _isDocEq)

throws if the two arrays do not have the same members, in any order. By default, nested arrays must have the same order to be considered equal. Optionally accepts a compareFn to compare values instead of using docEq.

assert.writeOK(res, msg)

throws if write result contained an error.

assert.docEq(expectedDoc, actualDoc, msg)

throws if actualDoc object is not equal to expectedDoc object. The order of fields (properties) within objects is disregarded. Throws if object representation in BSON exceeds 16793600 bytes.

assert.retry(func, msg, num_attempts, intervalMS)

calls the given function func repeatedly at time intervals specified by intervalMS (milliseconds) until either func() returns true or the number of attempted function calls is equal to num_attempts. Throws an exception with message msg after all attempts are used up. If no intervalMS argument is passed, it defaults to 0.

All assert functions

assert.adminCommandWorkedAllowingNetworkError
assert.between
assert.betweenEx
assert.betweenIn
assert.bind
assert.call
assert.close
assert.closeWithinMS
assert.commandFailed
assert.commandFailedWithCode
assert.commandWorked
assert.commandWorkedIgnoringWriteConcernErrors
assert.commandWorkedIgnoringWriteErrors
assert.commandWorkedIgnoringWriteErrorsAndWriteConcernErrors
assert.commandWorkedOrFailedWithCode
assert.contains
assert.containsPrefix
assert.docEq
assert.doesNotThrow
assert.dropExceptionsWithCode
assert.eq
assert.gt
assert.gte
assert.hasFields
assert.includes
assert.isnull
assert.lt
assert.lte
assert.neq
assert.noAPIParams
assert.retry
assert.retryNoExcept
assert.sameMembers
assert.setEq
assert.soon
assert.soonNoExcept
assert.throws
assert.throwsWithCode
assert.time
assert.toLocaleString
assert.toString
assert.valueOf
assert.writeError
assert.writeErrorWithCode
assert.writeOK

Error Codes

ErrorCodes is an object that is generated from various source files. It provides error names that correspond to their respective codes.

// tab in the shell after typing the below to display all 443 error codes
> ErrorCodes.
Display all 443 possibilities? (y or n)
ErrorCodes.APIDeprecationError                                          ErrorCodes.NetworkInterfaceExceededTimeLimit
ErrorCodes.APIMismatchError                                             ErrorCodes.NetworkTimeout
ErrorCodes.APIStrictError                                               ErrorCodes.NewReplicaSetConfigurationIncompatible
ErrorCodes.APIVersionError                                              ErrorCodes.NoConfigPrimary
ErrorCodes.AlarmAlreadyFulfilled                                        ErrorCodes.NoMatchParseContext
ErrorCodes.AlreadyInitialized                                           ErrorCodes.NoMatchingDocument
ErrorCodes.AmbiguousIndexKeyPattern                                     ErrorCodes.NoProgressMade
ErrorCodes.AtomicityFailure                                             ErrorCodes.NoProjectionFound
ErrorCodes.AuditingNotEnabled                                           ErrorCodes.NoQueryExecutionPlans
ErrorCodes.AuthSchemaIncompatible                                       ErrorCodes.NoReplicationEnabled
ErrorCodes.AuthenticationAbandoned                                      ErrorCodes.NoShardingEnabled
ErrorCodes.AuthenticationFailed                                         ErrorCodes.NoSuchKey
ErrorCodes.AuthenticationRestrictionUnmet                               ErrorCodes.NoSuchReshardCollection
ErrorCodes.BSONObjectTooLarge                                           ErrorCodes.NoSuchSession
ErrorCodes.BackgroundOperationInProgressForDatabase                     ErrorCodes.NoSuchTenantMigration
ErrorCodes.BackgroundOperationInProgressForNamespace                    ErrorCodes.NoSuchTransaction
ErrorCodes.BackupCursorOpenConflictWithCheckpoint                       ErrorCodes.NodeNotElectable
ErrorCodes.BadPerfCounterPath                                           ErrorCodes.NodeNotFound
ErrorCodes.BadValue                                                     ErrorCodes.NonConformantBSON
ErrorCodes.BalancerInterrupted                                          ErrorCodes.NonExistentPath
ErrorCodes.BrokenPromise                                                ErrorCodes.NonRetryableTenantMigrationConflict
ErrorCodes.CallbackCanceled                                             ErrorCodes.NotAReplicaSet
ErrorCodes.CanRepairToDowngrade                                         ErrorCodes.NotARetryableWriteCommand
ErrorCodes.CannotApplyOplogWhilePrimary                                 ErrorCodes.NotExactValueField
ErrorCodes.CannotBackfillArray                                          ErrorCodes.NotImplemented
ErrorCodes.CannotBackup                                                 ErrorCodes.NotPrimaryNoSecondaryOk
ErrorCodes.CannotBuildIndexKeys                                         ErrorCodes.NotPrimaryOrSecondary
ErrorCodes.CannotConvertIndexToUnique                                   ErrorCodes.NotSecondary
ErrorCodes.CannotCreateCollection                                       ErrorCodes.NotSingleValueField
ErrorCodes.CannotCreateIndex                                            ErrorCodes.NotWritablePrimary
ErrorCodes.CannotDowngrade                                              ErrorCodes.NotYetInitialized
ErrorCodes.CannotDropShardKeyIndex                                      ErrorCodes.OBSOLETE_BalancerLostDistributedLock

ErrorCodeStrings is an object with the reverse mapping of the above.

> ErrorCodeStrings[0]
OK
> ErrorCodeStrings[2]
BadValue
> ErrorCodeStrings[66]
ImmutableField