diff options
Diffstat (limited to 'jstests/aggregation/expressions/convert.js')
-rw-r--r-- | jstests/aggregation/expressions/convert.js | 621 |
1 files changed, 304 insertions, 317 deletions
diff --git a/jstests/aggregation/expressions/convert.js b/jstests/aggregation/expressions/convert.js index b32c6639751..4e56bf16265 100644 --- a/jstests/aggregation/expressions/convert.js +++ b/jstests/aggregation/expressions/convert.js @@ -2,325 +2,312 @@ * Tests behavior of $convert aggregation operator. */ (function() { - "use strict"; - - const coll = db.expression_convert; - function populateCollection(documentList) { - coll.drop(); - var bulk = coll.initializeOrderedBulkOp(); - documentList.forEach(doc => bulk.insert(doc)); - assert.writeOK(bulk.execute()); - } - - // - // One test document for each possible conversion. Edge cases for these conversions are tested - // in expression_convert_test.cpp. - // - var conversionTestDocs = [ - {_id: 0, input: 1.9, target: "double", expected: 1.9}, - {_id: 1, input: 1.9, target: "string", expected: "1.9"}, - {_id: 2, input: 1.9, target: "bool", expected: true}, - {_id: 3, input: 1.9, target: "date", expected: ISODate("1970-01-01T00:00:00.001Z")}, - {_id: 4, input: 1.9, target: "int", expected: NumberInt(1)}, - {_id: 5, input: 1.9, target: "long", expected: NumberLong(1)}, - {_id: 6, input: 1.9, target: "decimal", expected: NumberDecimal(1.9)}, - - {_id: 7, input: "1.9", target: "double", expected: 1.9}, - {_id: 8, input: "str", target: "string", expected: "str"}, - { - _id: 9, - input: "0123456789abcdef01234567", - target: "objectId", - expected: ObjectId("0123456789abcdef01234567") - }, - {_id: 10, input: "", target: "bool", expected: true}, - { - _id: 11, - input: "1970-01-01T00:00:00.001Z", - target: "date", - expected: ISODate("1970-01-01T00:00:00.001Z") - }, - {_id: 12, input: "1", target: "int", expected: NumberInt(1)}, - {_id: 13, input: "1", target: "long", expected: NumberLong(1)}, - {_id: 14, input: "1.9", target: "decimal", expected: NumberDecimal("1.9")}, - - { - _id: 15, - input: ObjectId("0123456789abcdef01234567"), - target: "string", - expected: "0123456789abcdef01234567" - }, - {_id: 16, input: ObjectId("0123456789abcdef01234567"), target: "bool", expected: true}, - { - _id: 17, - input: ObjectId("0123456789abcdef01234567"), - target: "objectId", - expected: ObjectId("0123456789abcdef01234567") - }, - { - _id: 18, - input: ObjectId("0123456789abcdef01234567"), - target: "date", - expected: ISODate("1970-08-09T22:25:43Z") - }, - - {_id: 19, input: false, target: "double", expected: 0.0}, - {_id: 20, input: false, target: "string", expected: "false"}, - {_id: 21, input: false, target: "bool", expected: false}, - {_id: 22, input: false, target: "int", expected: NumberInt(0)}, - {_id: 23, input: false, target: "long", expected: NumberLong(0)}, - {_id: 24, input: false, target: "decimal", expected: NumberDecimal(0)}, - - {_id: 25, input: ISODate("1970-01-01T00:00:00.123Z"), target: "double", expected: 123.0}, - { - _id: 26, - input: ISODate("1970-01-01T00:00:00.123Z"), - target: "string", - expected: "1970-01-01T00:00:00.123Z" - }, - {_id: 27, input: ISODate("1970-01-01T00:00:00.123Z"), target: "bool", expected: true}, - { - _id: 28, - input: ISODate("1970-01-01T00:00:00.123Z"), - target: "date", - expected: ISODate("1970-01-01T00:00:00.123Z") - }, - { - _id: 29, - input: ISODate("1970-01-01T00:00:00.123Z"), - target: "long", - expected: NumberLong(123) - }, - { - _id: 30, - input: ISODate("1970-01-01T00:00:00.123Z"), - target: "decimal", - expected: NumberDecimal("123") - }, - - {_id: 31, input: NumberInt(1), target: "double", expected: 1.0}, - {_id: 32, input: NumberInt(1), target: "string", expected: "1"}, - {_id: 33, input: NumberInt(1), target: "bool", expected: true}, - {_id: 34, input: NumberInt(1), target: "int", expected: NumberInt(1)}, - {_id: 35, input: NumberInt(1), target: "long", expected: NumberLong(1)}, - {_id: 36, input: NumberInt(1), target: "decimal", expected: NumberDecimal("1")}, - - {_id: 37, input: NumberLong(1), target: "double", expected: 1.0}, - {_id: 38, input: NumberLong(1), target: "string", expected: "1"}, - {_id: 39, input: NumberLong(1), target: "bool", expected: true}, - { - _id: 40, - input: NumberLong(1), - target: "date", - expected: ISODate("1970-01-01T00:00:00.001Z") - }, - {_id: 41, input: NumberLong(1), target: "int", expected: NumberInt(1)}, - {_id: 42, input: NumberLong(1), target: "long", expected: NumberLong(1)}, - {_id: 43, input: NumberLong(1), target: "decimal", expected: NumberDecimal("1")}, - - {_id: 44, input: NumberDecimal("1.9"), target: "double", expected: 1.9}, - {_id: 45, input: NumberDecimal("1.9"), target: "string", expected: "1.9"}, - {_id: 46, input: NumberDecimal("1.9"), target: "bool", expected: true}, - { - _id: 47, - input: NumberDecimal("1.9"), - target: "date", - expected: ISODate("1970-01-01T00:00:00.001Z") - }, - {_id: 48, input: NumberDecimal("1.9"), target: "int", expected: NumberInt(1)}, - {_id: 49, input: NumberDecimal("1.9"), target: "long", expected: NumberLong(1)}, - {_id: 50, input: NumberDecimal("1.9"), target: "decimal", expected: NumberDecimal("1.9")}, - - {_id: 51, input: MinKey, target: "bool", expected: true}, - {_id: 52, input: {foo: 1, bar: 2}, target: "bool", expected: true}, - {_id: 53, input: [1, 2], target: "bool", expected: true}, - { - _id: 54, - input: BinData(0, "BBBBBBBBBBBBBBBBBBBBBBBBBBBB"), - target: "bool", - expected: true - }, - {_id: 55, input: /B*/, target: "bool", expected: true}, - {_id: 56, input: new DBRef("db.test", "oid"), target: "bool", expected: true}, - {_id: 57, input: function() {}, target: "bool", expected: true}, - // Symbol and CodeWScope are not supported from JavaScript, so we can't test them here. - {_id: 58, input: new Timestamp(1 / 1000, 1), target: "bool", expected: true}, - {_id: 59, input: MinKey, target: "bool", expected: true} - ]; - populateCollection(conversionTestDocs); - - // Test $convert on each document. - var pipeline = [ - { - $project: { - output: {$convert: {to: "$target", input: "$input"}}, - target: "$target", - expected: "$expected" - } - }, - {$addFields: {outputType: {$type: "$output"}}}, - {$sort: {_id: 1}} - ]; - var aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, conversionTestDocs.length); - - aggResult.forEach(doc => { - assert.eq(doc.output, doc.expected, "Unexpected conversion: _id = " + doc._id); - assert.eq(doc.outputType, doc.target, "Conversion to incorrect type: _id = " + doc._id); - }); - - // Test each conversion using the shorthand $toBool, $toString, etc. syntax. +"use strict"; + +const coll = db.expression_convert; +function populateCollection(documentList) { + coll.drop(); + var bulk = coll.initializeOrderedBulkOp(); + documentList.forEach(doc => bulk.insert(doc)); + assert.writeOK(bulk.execute()); +} + +// +// One test document for each possible conversion. Edge cases for these conversions are tested +// in expression_convert_test.cpp. +// +var conversionTestDocs = [ + {_id: 0, input: 1.9, target: "double", expected: 1.9}, + {_id: 1, input: 1.9, target: "string", expected: "1.9"}, + {_id: 2, input: 1.9, target: "bool", expected: true}, + {_id: 3, input: 1.9, target: "date", expected: ISODate("1970-01-01T00:00:00.001Z")}, + {_id: 4, input: 1.9, target: "int", expected: NumberInt(1)}, + {_id: 5, input: 1.9, target: "long", expected: NumberLong(1)}, + {_id: 6, input: 1.9, target: "decimal", expected: NumberDecimal(1.9)}, + + {_id: 7, input: "1.9", target: "double", expected: 1.9}, + {_id: 8, input: "str", target: "string", expected: "str"}, + { + _id: 9, + input: "0123456789abcdef01234567", + target: "objectId", + expected: ObjectId("0123456789abcdef01234567") + }, + {_id: 10, input: "", target: "bool", expected: true}, + { + _id: 11, + input: "1970-01-01T00:00:00.001Z", + target: "date", + expected: ISODate("1970-01-01T00:00:00.001Z") + }, + {_id: 12, input: "1", target: "int", expected: NumberInt(1)}, + {_id: 13, input: "1", target: "long", expected: NumberLong(1)}, + {_id: 14, input: "1.9", target: "decimal", expected: NumberDecimal("1.9")}, + + { + _id: 15, + input: ObjectId("0123456789abcdef01234567"), + target: "string", + expected: "0123456789abcdef01234567" + }, + {_id: 16, input: ObjectId("0123456789abcdef01234567"), target: "bool", expected: true}, + { + _id: 17, + input: ObjectId("0123456789abcdef01234567"), + target: "objectId", + expected: ObjectId("0123456789abcdef01234567") + }, + { + _id: 18, + input: ObjectId("0123456789abcdef01234567"), + target: "date", + expected: ISODate("1970-08-09T22:25:43Z") + }, + + {_id: 19, input: false, target: "double", expected: 0.0}, + {_id: 20, input: false, target: "string", expected: "false"}, + {_id: 21, input: false, target: "bool", expected: false}, + {_id: 22, input: false, target: "int", expected: NumberInt(0)}, + {_id: 23, input: false, target: "long", expected: NumberLong(0)}, + {_id: 24, input: false, target: "decimal", expected: NumberDecimal(0)}, + + {_id: 25, input: ISODate("1970-01-01T00:00:00.123Z"), target: "double", expected: 123.0}, + { + _id: 26, + input: ISODate("1970-01-01T00:00:00.123Z"), + target: "string", + expected: "1970-01-01T00:00:00.123Z" + }, + {_id: 27, input: ISODate("1970-01-01T00:00:00.123Z"), target: "bool", expected: true}, + { + _id: 28, + input: ISODate("1970-01-01T00:00:00.123Z"), + target: "date", + expected: ISODate("1970-01-01T00:00:00.123Z") + }, + { + _id: 29, + input: ISODate("1970-01-01T00:00:00.123Z"), + target: "long", + expected: NumberLong(123) + }, + { + _id: 30, + input: ISODate("1970-01-01T00:00:00.123Z"), + target: "decimal", + expected: NumberDecimal("123") + }, + + {_id: 31, input: NumberInt(1), target: "double", expected: 1.0}, + {_id: 32, input: NumberInt(1), target: "string", expected: "1"}, + {_id: 33, input: NumberInt(1), target: "bool", expected: true}, + {_id: 34, input: NumberInt(1), target: "int", expected: NumberInt(1)}, + {_id: 35, input: NumberInt(1), target: "long", expected: NumberLong(1)}, + {_id: 36, input: NumberInt(1), target: "decimal", expected: NumberDecimal("1")}, + + {_id: 37, input: NumberLong(1), target: "double", expected: 1.0}, + {_id: 38, input: NumberLong(1), target: "string", expected: "1"}, + {_id: 39, input: NumberLong(1), target: "bool", expected: true}, + {_id: 40, input: NumberLong(1), target: "date", expected: ISODate("1970-01-01T00:00:00.001Z")}, + {_id: 41, input: NumberLong(1), target: "int", expected: NumberInt(1)}, + {_id: 42, input: NumberLong(1), target: "long", expected: NumberLong(1)}, + {_id: 43, input: NumberLong(1), target: "decimal", expected: NumberDecimal("1")}, + + {_id: 44, input: NumberDecimal("1.9"), target: "double", expected: 1.9}, + {_id: 45, input: NumberDecimal("1.9"), target: "string", expected: "1.9"}, + {_id: 46, input: NumberDecimal("1.9"), target: "bool", expected: true}, + { + _id: 47, + input: NumberDecimal("1.9"), + target: "date", + expected: ISODate("1970-01-01T00:00:00.001Z") + }, + {_id: 48, input: NumberDecimal("1.9"), target: "int", expected: NumberInt(1)}, + {_id: 49, input: NumberDecimal("1.9"), target: "long", expected: NumberLong(1)}, + {_id: 50, input: NumberDecimal("1.9"), target: "decimal", expected: NumberDecimal("1.9")}, + + {_id: 51, input: MinKey, target: "bool", expected: true}, + {_id: 52, input: {foo: 1, bar: 2}, target: "bool", expected: true}, + {_id: 53, input: [1, 2], target: "bool", expected: true}, + {_id: 54, input: BinData(0, "BBBBBBBBBBBBBBBBBBBBBBBBBBBB"), target: "bool", expected: true}, + {_id: 55, input: /B*/, target: "bool", expected: true}, + {_id: 56, input: new DBRef("db.test", "oid"), target: "bool", expected: true}, + {_id: 57, input: function() {}, target: "bool", expected: true}, + // Symbol and CodeWScope are not supported from JavaScript, so we can't test them here. + {_id: 58, input: new Timestamp(1 / 1000, 1), target: "bool", expected: true}, + {_id: 59, input: MinKey, target: "bool", expected: true} +]; +populateCollection(conversionTestDocs); + +// Test $convert on each document. +var pipeline = [ + { + $project: { + output: {$convert: {to: "$target", input: "$input"}}, + target: "$target", + expected: "$expected" + } + }, + {$addFields: {outputType: {$type: "$output"}}}, + {$sort: {_id: 1}} +]; +var aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, conversionTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc.output, doc.expected, "Unexpected conversion: _id = " + doc._id); + assert.eq(doc.outputType, doc.target, "Conversion to incorrect type: _id = " + doc._id); +}); + +// Test each conversion using the shorthand $toBool, $toString, etc. syntax. +pipeline = [ + { + $project: { + output: { + $switch: { + branches: [ + {case: {$eq: ["$target", "double"]}, then: {$toDouble: "$input"}}, + {case: {$eq: ["$target", "string"]}, then: {$toString: "$input"}}, + {case: {$eq: ["$target", "objectId"]}, then: {$toObjectId: "$input"}}, + {case: {$eq: ["$target", "bool"]}, then: {$toBool: "$input"}}, + {case: {$eq: ["$target", "date"]}, then: {$toDate: "$input"}}, + {case: {$eq: ["$target", "int"]}, then: {$toInt: "$input"}}, + {case: {$eq: ["$target", "long"]}, then: {$toLong: "$input"}}, + {case: {$eq: ["$target", "decimal"]}, then: {$toDecimal: "$input"}} + ] + } + }, + target: "$target", + expected: "$expected" + } + }, + {$addFields: {outputType: {$type: "$output"}}}, + {$sort: {_id: 1}} +]; +aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, conversionTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc.output, doc.expected, "Unexpected conversion: _id = " + doc._id); + assert.eq(doc.outputType, doc.target, "Conversion to incorrect type: _id = " + doc._id); +}); + +// Test a $convert expression with "onError" to make sure that error handling still allows an +// error in the "input" expression to propagate. +assert.throws(function() { + coll.aggregate([ + {$project: {output: {$convert: {to: "string", input: {$divide: [1, 0]}, onError: "ERROR"}}}} + ]); +}, [], "Pipeline should have failed"); + +// +// Unsupported conversions. +// +var illegalConversionTestDocs = [ + {_id: 0, input: 1.9, target: "objectId"}, + + {_id: 1, input: ObjectId("0123456789abcdef01234567"), target: "double"}, + {_id: 2, input: ObjectId("0123456789abcdef01234567"), target: "int"}, + {_id: 3, input: ObjectId("0123456789abcdef01234567"), target: "long"}, + {_id: 4, input: ObjectId("0123456789abcdef01234567"), target: "decimal"}, + + {_id: 5, input: false, target: "objectId"}, + {_id: 6, input: false, target: "date"}, + + {_id: 7, input: ISODate("1970-01-01T00:00:00.123Z"), target: "objectId"}, + {_id: 8, input: ISODate("1970-01-01T00:00:00.123Z"), target: "int"}, + + {_id: 9, input: NumberInt(1), target: "objectId"}, + {_id: 10, input: NumberInt(1), target: "date"}, + + {_id: 11, input: NumberLong(1), target: "objectId"}, + + {_id: 12, input: NumberDecimal("1.9"), target: "objectId"}, + + {_id: 13, input: 1.9, target: "minKey"}, + {_id: 14, input: 1.9, target: "missing"}, + {_id: 15, input: 1.9, target: "object"}, + {_id: 16, input: 1.9, target: "array"}, + {_id: 17, input: 1.9, target: "binData"}, + {_id: 18, input: 1.9, target: "undefined"}, + {_id: 19, input: 1.9, target: "null"}, + {_id: 20, input: 1.9, target: "regex"}, + {_id: 21, input: 1.9, target: "dbPointer"}, + {_id: 22, input: 1.9, target: "javascript"}, + {_id: 23, input: 1.9, target: "symbol"}, + {_id: 24, input: 1.9, target: "javascriptWithScope"}, + {_id: 25, input: 1.9, target: "timestamp"}, + {_id: 26, input: 1.9, target: "maxKey"}, +]; +populateCollection(illegalConversionTestDocs); + +// Test each document to ensure that the conversion throws an error. +illegalConversionTestDocs.forEach(doc => { pipeline = [ - { - $project: { - output: { - $switch: { - branches: [ - {case: {$eq: ["$target", "double"]}, then: {$toDouble: "$input"}}, - {case: {$eq: ["$target", "string"]}, then: {$toString: "$input"}}, - {case: {$eq: ["$target", "objectId"]}, then: {$toObjectId: "$input"}}, - {case: {$eq: ["$target", "bool"]}, then: {$toBool: "$input"}}, - {case: {$eq: ["$target", "date"]}, then: {$toDate: "$input"}}, - {case: {$eq: ["$target", "int"]}, then: {$toInt: "$input"}}, - {case: {$eq: ["$target", "long"]}, then: {$toLong: "$input"}}, - {case: {$eq: ["$target", "decimal"]}, then: {$toDecimal: "$input"}} - ] - } - }, - target: "$target", - expected: "$expected" - } - }, - {$addFields: {outputType: {$type: "$output"}}}, - {$sort: {_id: 1}} + {$match: {_id: doc._id}}, + {$project: {output: {$convert: {to: "$target", input: "$input"}}}} ]; - aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, conversionTestDocs.length); - aggResult.forEach(doc => { - assert.eq(doc.output, doc.expected, "Unexpected conversion: _id = " + doc._id); - assert.eq(doc.outputType, doc.target, "Conversion to incorrect type: _id = " + doc._id); - }); - - // Test a $convert expression with "onError" to make sure that error handling still allows an - // error in the "input" expression to propagate. assert.throws(function() { - coll.aggregate([{ - $project: - {output: {$convert: {to: "string", input: {$divide: [1, 0]}, onError: "ERROR"}}} - }]); - }, [], "Pipeline should have failed"); - - // - // Unsupported conversions. - // - var illegalConversionTestDocs = [ - {_id: 0, input: 1.9, target: "objectId"}, - - {_id: 1, input: ObjectId("0123456789abcdef01234567"), target: "double"}, - {_id: 2, input: ObjectId("0123456789abcdef01234567"), target: "int"}, - {_id: 3, input: ObjectId("0123456789abcdef01234567"), target: "long"}, - {_id: 4, input: ObjectId("0123456789abcdef01234567"), target: "decimal"}, - - {_id: 5, input: false, target: "objectId"}, - {_id: 6, input: false, target: "date"}, - - {_id: 7, input: ISODate("1970-01-01T00:00:00.123Z"), target: "objectId"}, - {_id: 8, input: ISODate("1970-01-01T00:00:00.123Z"), target: "int"}, - - {_id: 9, input: NumberInt(1), target: "objectId"}, - {_id: 10, input: NumberInt(1), target: "date"}, - - {_id: 11, input: NumberLong(1), target: "objectId"}, - - {_id: 12, input: NumberDecimal("1.9"), target: "objectId"}, - - {_id: 13, input: 1.9, target: "minKey"}, - {_id: 14, input: 1.9, target: "missing"}, - {_id: 15, input: 1.9, target: "object"}, - {_id: 16, input: 1.9, target: "array"}, - {_id: 17, input: 1.9, target: "binData"}, - {_id: 18, input: 1.9, target: "undefined"}, - {_id: 19, input: 1.9, target: "null"}, - {_id: 20, input: 1.9, target: "regex"}, - {_id: 21, input: 1.9, target: "dbPointer"}, - {_id: 22, input: 1.9, target: "javascript"}, - {_id: 23, input: 1.9, target: "symbol"}, - {_id: 24, input: 1.9, target: "javascriptWithScope"}, - {_id: 25, input: 1.9, target: "timestamp"}, - {_id: 26, input: 1.9, target: "maxKey"}, - ]; - populateCollection(illegalConversionTestDocs); - - // Test each document to ensure that the conversion throws an error. - illegalConversionTestDocs.forEach(doc => { - pipeline = [ - {$match: {_id: doc._id}}, - {$project: {output: {$convert: {to: "$target", input: "$input"}}}} - ]; - - assert.throws(function() { - coll.aggregate(pipeline); - }, [], "Conversion should have failed: _id = " + doc._id); - }); - - // Test that each illegal conversion uses the 'onError' value. - pipeline = [ - {$project: {output: {$convert: {to: "$target", input: "$input", onError: "ERROR"}}}}, - {$sort: {_id: 1}} - ]; - var aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, illegalConversionTestDocs.length); - - aggResult.forEach(doc => { - assert.eq(doc.output, "ERROR", "Unexpected result: _id = " + doc._id); - }); - - // Test that, when onError is missing, the missing value propagates to the result. - pipeline = [ - { - $project: { - _id: false, - output: {$convert: {to: "$target", input: "$input", onError: "$$REMOVE"}} - } - }, - {$sort: {_id: 1}} - ]; - var aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, illegalConversionTestDocs.length); - - aggResult.forEach(doc => { - assert.eq(doc, {}); - }); - - // - // One test document for each "nullish" value. - // - var nullTestDocs = - [{_id: 0, input: null}, {_id: 1, input: undefined}, {_id: 2, /* input is missing */}]; - populateCollection(nullTestDocs); - - // Test that all nullish inputs result in the 'onNull' output. - pipeline = [ - {$project: {output: {$convert: {to: "int", input: "$input", onNull: "NULL"}}}}, - {$sort: {_id: 1}} - ]; - var aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, nullTestDocs.length); - - aggResult.forEach(doc => { - assert.eq(doc.output, "NULL", "Unexpected result: _id = " + doc._id); - }); - - // Test that all nullish inputs result in the 'onNull' output _even_ if 'to' is nullish. - pipeline = [ - {$project: {output: {$convert: {to: null, input: "$input", onNull: "NULL"}}}}, - {$sort: {_id: 1}} - ]; - var aggResult = coll.aggregate(pipeline).toArray(); - assert.eq(aggResult.length, nullTestDocs.length); - - aggResult.forEach(doc => { - assert.eq(doc.output, "NULL", "Unexpected result: _id = " + doc._id); - }); + coll.aggregate(pipeline); + }, [], "Conversion should have failed: _id = " + doc._id); +}); + +// Test that each illegal conversion uses the 'onError' value. +pipeline = [ + {$project: {output: {$convert: {to: "$target", input: "$input", onError: "ERROR"}}}}, + {$sort: {_id: 1}} +]; +var aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, illegalConversionTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc.output, "ERROR", "Unexpected result: _id = " + doc._id); +}); + +// Test that, when onError is missing, the missing value propagates to the result. +pipeline = [ + { + $project: + {_id: false, output: {$convert: {to: "$target", input: "$input", onError: "$$REMOVE"}}} + }, + {$sort: {_id: 1}} +]; +var aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, illegalConversionTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc, {}); +}); + +// +// One test document for each "nullish" value. +// +var nullTestDocs = + [{_id: 0, input: null}, {_id: 1, input: undefined}, {_id: 2, /* input is missing */}]; +populateCollection(nullTestDocs); + +// Test that all nullish inputs result in the 'onNull' output. +pipeline = [ + {$project: {output: {$convert: {to: "int", input: "$input", onNull: "NULL"}}}}, + {$sort: {_id: 1}} +]; +var aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, nullTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc.output, "NULL", "Unexpected result: _id = " + doc._id); +}); + +// Test that all nullish inputs result in the 'onNull' output _even_ if 'to' is nullish. +pipeline = [ + {$project: {output: {$convert: {to: null, input: "$input", onNull: "NULL"}}}}, + {$sort: {_id: 1}} +]; +var aggResult = coll.aggregate(pipeline).toArray(); +assert.eq(aggResult.length, nullTestDocs.length); + +aggResult.forEach(doc => { + assert.eq(doc.output, "NULL", "Unexpected result: _id = " + doc._id); +}); }()); |