diff options
-rw-r--r-- | jstests/aggregation/expressions/date_from_parts.js | 110 | ||||
-rw-r--r-- | jstests/aggregation/extras/utils.js | 33 | ||||
-rw-r--r-- | jstests/libs/sbe_assert_error_override.js | 92 |
3 files changed, 140 insertions, 95 deletions
diff --git a/jstests/aggregation/expressions/date_from_parts.js b/jstests/aggregation/expressions/date_from_parts.js index c457ec69b46..812e2a1b2d7 100644 --- a/jstests/aggregation/expressions/date_from_parts.js +++ b/jstests/aggregation/expressions/date_from_parts.js @@ -1,4 +1,5 @@ -load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertErrMsgContains. +load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertErrMsgContains. +load("jstests/libs/sbe_assert_error_override.js"); // Override error-code-checking APIs. (function() { "use strict"; @@ -442,11 +443,11 @@ pipelines = [ ]; pipelines.forEach(function(pipeline) { - assertErrorCodes(coll, pipeline, [40515, 4848979]); + assertErrorCode(coll, pipeline, 40515); }); pipeline = [{'$project': {date: {'$dateFromParts': {year: 2017, timezone: "$falseValue"}}}}]; -assertErrorCodes(coll, pipeline, [40517, 4848979, 4848980]); +assertErrorCode(coll, pipeline, 40517); // Testing whether it throws the right assert for uncoersable values @@ -464,7 +465,7 @@ pipelines = [ ]; pipelines.forEach(function(pipeline) { - assertErrorCodes(coll, pipeline, [40523, 4848972]); + assertErrorCode(coll, pipeline, 40523); }); // Testing "out of range" under and overflows @@ -566,13 +567,11 @@ assertErrCodeAndErrMsgContains( "Overflow casting from a lower-precision duration to a higher-precision duration"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDoubleB"}}}}]; -assertErrCodeAndErrMsgContains( - coll, pipeline, [40515, 4848979], "'millisecond' must evaluate to an integer"); +assertErrCodeAndErrMsgContains(coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDecimal128B"}}}}]; -assertErrCodeAndErrMsgContains( - coll, pipeline, [40515, 4848979], "'millisecond' must evaluate to an integer"); +assertErrCodeAndErrMsgContains(coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); // Testing that year values are only allowed in the range [0, 9999] and that month, day, hour, // and minute values are only allowed in the range [-32,768, 32,767]. @@ -583,111 +582,78 @@ assert.commandWorked(coll.insert( pipeline = [{$project: {date: {"$dateFromParts": {year: "$bigYear"}}}}]; assertErrCodeAndErrMsgContains( - coll, pipeline, [40523, 4848972], "'year' must evaluate to an integer in the range 1 to 9999"); + coll, pipeline, 40523, "'year' must evaluate to an integer in the range 1 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {year: "$smallYear"}}}}]; assertErrCodeAndErrMsgContains( - coll, pipeline, [40523, 4848972], "'year' must evaluate to an integer in the range 1 to 9999"); + coll, pipeline, 40523, "'year' must evaluate to an integer in the range 1 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: "$prettyBigInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'month' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'month' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: "$prettyBigNegativeInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'month' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'month' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: 1, day: "$prettyBigInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'day' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'day' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: 1, day: "$prettyBigNegativeInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'day' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'day' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: "$prettyBigInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'hour' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'hour' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: "$prettyBigNegativeInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'hour' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'hour' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: 0, minute: "$prettyBigInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'minute' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'minute' must evaluate to a value in the range [-32768, 32767]"); pipeline = [ {$project: {date: {"$dateFromParts": {year: 1970, hour: 0, minute: "$prettyBigNegativeInt"}}}} ]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'minute' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'minute' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: "$bigYear"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31095, 4848972], - "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31095, "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: "$bigYear"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31095, 4848972], - "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31095, "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: "$smallYear"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31095, 4848972], - "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31095, "'isoWeekYear' must evaluate to an integer in the range 1 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoWeek: "$prettyBigInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoWeek: "$prettyBigNegativeInt"}}}}]; -assertErrCodeAndErrMsgContains(coll, - pipeline, - [31034, 4848972], - "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); +assertErrCodeAndErrMsgContains( + coll, pipeline, 31034, "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoDayOfWeek: "$prettyBigInt"}}}}]; -assertErrorCodes(coll, pipeline, [31034, 4848972]); assertErrCodeAndErrMsgContains( - coll, - pipeline, - [31034, 4848972], - "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); + coll, pipeline, 31034, "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{ $project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoDayOfWeek: "$prettyBigNegativeInt"}}} }]; assertErrCodeAndErrMsgContains( - coll, - pipeline, - [31034, 4848972], - "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); + coll, pipeline, 31034, "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); // Testing wrong arguments @@ -749,7 +715,7 @@ pipelines = [ ]; pipelines.forEach(function(item) { - assertErrorCodes(coll, [item.pipeline], [item.code, 4848979]); + assertErrorCode(coll, [item.pipeline], item.code); }); coll.drop(); diff --git a/jstests/aggregation/extras/utils.js b/jstests/aggregation/extras/utils.js index 885ff9b1188..1d5f5dee228 100644 --- a/jstests/aggregation/extras/utils.js +++ b/jstests/aggregation/extras/utils.js @@ -244,46 +244,33 @@ function orderedArrayEq(al, ar, verbose = false) { } /** - * Asserts that the given aggregation fails with a specific code. Error message is optional. + * Assert that the given aggregation fails with a specific code. Error message is optional. Note + * that 'code' can be an array of possible codes. */ function assertErrorCode(coll, pipe, code, errmsg, options = {}) { if (!Array.isArray(pipe)) { pipe = [pipe]; } - let cmd = {pipeline: pipe}; - cmd.cursor = {batchSize: 0}; - + let cmd = {pipeline: pipe, cursor: {batchSize: 0}}; for (let opt of Object.keys(options)) { cmd[opt] = options[opt]; } - let cursorRes = coll.runCommand("aggregate", cmd); - if (cursorRes.ok) { + let resultObj = coll.runCommand("aggregate", cmd); + if (resultObj.ok) { let followupBatchSize = 0; // default - let cursor = new DBCommandCursor(coll.getDB(), cursorRes, followupBatchSize); - - let error = assert.throws(function() { - cursor.itcount(); - }, [], "expected error: " + code); - - assert.eq(error.code, code, tojson(error)); - } else { - assert.eq(cursorRes.code, code, tojson(cursorRes)); + let cursor = new DBCommandCursor(coll.getDB(), resultObj, followupBatchSize); + let assertThrowsMsg = "expected one of the following error codes: " + tojson(code); + resultObj = assert.throws(() => cursor.itcount(), [], assertThrowsMsg); } -} -/** - * Assert that an aggregation fails with a list of specific codes. - */ -function assertErrorCodes(coll, pipe, codes) { - const response = assert.commandFailedWithCode( - coll.getDB().runCommand({aggregate: coll.getName(), pipeline: pipe, cursor: {}}), codes); + assert.commandFailedWithCode(resultObj, code, errmsg); } /** * Assert that an aggregation fails with a specific code and the error message contains the given - * string. + * string. Note that 'code' can be an array of possible codes. */ function assertErrCodeAndErrMsgContains(coll, pipe, code, expectedMessage) { const response = assert.commandFailedWithCode( diff --git a/jstests/libs/sbe_assert_error_override.js b/jstests/libs/sbe_assert_error_override.js new file mode 100644 index 00000000000..c8cf6de9f87 --- /dev/null +++ b/jstests/libs/sbe_assert_error_override.js @@ -0,0 +1,92 @@ +/** + * For a number of errors, the engine will raise different error codes when SBE mode is enabled vs. + * disabled. When SBE mode is enabled, these differences in error codes can cause tests to fail that + * otherwise would have passed. + * + * To expedite efforts to enable more tests under SBE mode, this file provides overrides for the + * assert.commandFailedWithCode() and assert.writeErrorWithCode() APIs so that they treat certain + * groups of error codes as being equivalent to each other. Note that these overrides also affect + * how assertError(), assertErrorCode(), and assertErrCodeAndErrMsgContains() behave. + * + * Below the 'equivalentErrorCodesList' variable contains all known groups of error codes that + * should be treated as equivalent to each other. As new groups of equivalent error codes are + * discovered, they should be added to the list below. + * + * Note: This file should _only_ be included in a test if it has been observed that the test fails + * due to differences in error codes when SBE mode is enabled. + */ +(function() { +"use strict"; + +// Below is the list of known equivalent error code groups. As new groups of equivalent error codes +// are discovered, they should be added to this list. +const equivalentErrorCodesList = [ + [28765, 4822870], + [31034, 4848972], + [31095, 4848972], + [40515, 4848979], + [40517, 4848980], + [40523, 4848972], +]; + +// This map is generated based on the contents of 'equivalentErrorCodesList'. This map should _not_ +// be modified. If you need to change which error codes are considered equivalent to each other, you +// should modify 'equivalentErrorCodesList' above. +const equivalentErrorCodesMap = function() { + let mapOfSets = {}; + for (const arr of equivalentErrorCodesList) { + for (const errorCode1 of arr) { + if (!mapOfSets.hasOwnProperty(errorCode1)) { + mapOfSets[errorCode1] = new Set(); + } + + for (const errorCode2 of arr) { + if (errorCode1 != errorCode2) { + mapOfSets[errorCode1].add(errorCode2); + } + } + } + } + + let mapOfLists = {}; + for (const errorCode1 in mapOfSets) { + let arr = []; + for (const errorCode2 of mapOfSets[errorCode1]) { + arr.push(errorCode2); + } + mapOfLists[errorCode1] = arr; + } + + return mapOfLists; +}(); + +const lookupEquivalentErrorCodes = function(errorCodes) { + if (!Array.isArray(errorCodes)) { + errorCodes = [errorCodes]; + } + + let result = []; + for (const errorCode1 of errorCodes) { + result.push(errorCode1); + if (equivalentErrorCodesMap.hasOwnProperty(errorCode1)) { + for (const errorCode2 of equivalentErrorCodesMap[errorCode1]) { + result.push(errorCode2); + } + } + } + + return result; +}; + +// Override the assert.commandFailedWithCode() function. +const assertCommandFailedWithCodeOriginal = assert.commandFailedWithCode; +assert.commandFailedWithCode = function(res, expectedCode, msg) { + return assertCommandFailedWithCodeOriginal(res, lookupEquivalentErrorCodes(expectedCode), msg); +}; + +// Override the assert.writeErrorWithCode() function. +const assertWriteErrorWithCodeOriginal = assert.writeErrorWithCode; +assert.writeErrorWithCode = function(res, expectedCode, msg) { + return assertWriteErrorWithCodeOriginal(res, lookupEquivalentErrorCodes(expectedCode), msg); +}; +}()); |