From 83f5d68e98d012db0846425ec66a72e328c79a52 Mon Sep 17 00:00:00 2001 From: David Hatch Date: Wed, 15 Jul 2015 11:32:37 -0400 Subject: [PATCH] SERVER-19629 Add Decimal128 roundtrip and CRUD jstests --- etc/evergreen.yml | 9 +++ jstests/decimal/decimal_constructors.js | 25 ++++++ jstests/decimal/decimal_find_basic.js | 57 ++++++++++++++ jstests/decimal/decimal_find_mixed.js | 100 ++++++++++++++++++++++++ jstests/decimal/decimal_find_query.js | 49 ++++++++++++ jstests/decimal/decimal_update.js | 41 ++++++++++ jstests/decimal/placeholder.js | 2 - 7 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 jstests/decimal/decimal_constructors.js create mode 100644 jstests/decimal/decimal_find_basic.js create mode 100644 jstests/decimal/decimal_find_mixed.js create mode 100644 jstests/decimal/decimal_find_query.js create mode 100644 jstests/decimal/decimal_update.js delete mode 100644 jstests/decimal/placeholder.js diff --git a/etc/evergreen.yml b/etc/evergreen.yml index ed94c82ff4fa7..bdff492fa209e 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -1202,6 +1202,14 @@ tasks: vars: resmoke_args: --suites=decimal +- <<: *task_template + name: jsDecimalCore_WT + commands: + - func: "do setup" + - func: "run tests" + vars: + resmoke_args: --suites=decimal --storageEngine=wiredTiger + - name: push depends_on: - name: "*" @@ -2329,6 +2337,7 @@ buildvariants: - name: dbtest_WT - name: jsCore - name: jsDecimalCore + - name: jsDecimalCore_WT - name: jstestfuzz - name: push distros: diff --git a/jstests/decimal/decimal_constructors.js b/jstests/decimal/decimal_constructors.js new file mode 100644 index 0000000000000..b07fc38ca819f --- /dev/null +++ b/jstests/decimal/decimal_constructors.js @@ -0,0 +1,25 @@ +// Tests constructing NumberDecimal with various types + +(function() { + "use strict"; + var col = db.decimal_constructors; + col.drop(); + + // Insert some sample data. + + assert.writeOK(col.insert([ + { "decimal" : NumberDecimal("1") }, + { "decimal" : NumberDecimal(1) }, + { "decimal" : NumberDecimal(NumberLong("1")) }, + { "decimal" : NumberDecimal(NumberInt("1")) }, + ]), "Initial insertion of decimals failed"); + + // Find values with various types and NumberDecimal constructed types + assert.eq(col.find({ "decimal" : NumberDecimal("1") }).count(), "4"); + assert.eq(col.find({ "decimal" : NumberDecimal(1) }).count(), "4"); + assert.eq(col.find({ "decimal" : NumberDecimal(NumberLong(1)) }).count(), "4"); + assert.eq(col.find({ "decimal" : NumberDecimal(NumberInt(1)) }).count(), "4"); + assert.eq(col.find({ "decimal" : 1 }).count(), "4"); + assert.eq(col.find({ "decimal" : NumberLong(1) }).count(), "4"); + assert.eq(col.find({ "decimal" : NumberInt(1) }).count(), "4"); +}()); diff --git a/jstests/decimal/decimal_find_basic.js b/jstests/decimal/decimal_find_basic.js new file mode 100644 index 0000000000000..ab09ad654173c --- /dev/null +++ b/jstests/decimal/decimal_find_basic.js @@ -0,0 +1,57 @@ +// Tests finding NumberDecimal from the shell. + +(function() { + "use strict"; + var col = db.decimal_find_basic; + col.drop(); + + // Insert some sample data. + + assert.writeOK(col.insert([ + { "decimal" : NumberDecimal("0") }, + { "decimal" : NumberDecimal("0.00") }, + { "decimal" : NumberDecimal("-0") }, + { "decimal" : NumberDecimal("1.0") }, + { "decimal" : NumberDecimal("1.00") }, + { "decimal" : NumberDecimal("2.00") }, + { "decimal" : NumberDecimal("12345678901234567890.12345678901234") }, + { "decimal" : NumberDecimal("NaN") }, + { "decimal" : NumberDecimal("-NaN") }, + { "decimal" : NumberDecimal("-Infinity") }, + { "decimal" : NumberDecimal("Infinity") }, + ]), "Initial insertion of decimals failed"); + + // Zeros + assert.eq(col.find({ "decimal" : NumberDecimal("0") }).count(), "3"); + + // NaNs + assert.eq(col.find({ "decimal" : NumberDecimal("NaN") }).count(), 2, "NaN find failed"); + + var theNaNs = [{ "decimal" : NumberDecimal("NaN") }, { "decimal" : NumberDecimal("-NaN") }]; + + assert(bsonWoCompare(theNaNs[0], theNaNs[1]) == 0, "NaN compares equal"); + + // Infinity + assert.eq(col.find({ "decimal" : NumberDecimal("Infinity") }).count(), 1, + "Infinity count wrong"); + assert.eq(col.find({ "decimal" : NumberDecimal("-Infinity") }).count(), 1, + "Infinity count wrong"); + + // Maximum Precision + assert.eq( + col.find({ "decimal" : NumberDecimal("12345678901234567890.12345678901234") }).count(), 1, + "Maximum precision decimal not found."); + + col.drop(); + + // Maximum and Minimum Values + assert.writeOK(col.insert([ + { "max" : NumberDecimal("9999999999999999999999999999999999E6144") }, + { "min" : NumberDecimal("1E-6176") } + ])); + + assert.eq(col.find({ "max" : NumberDecimal("9999999999999999999999999999999999E6144") }).count(), + 1); + assert.eq(col.find({ "min" : NumberDecimal("1E-6176") }).count(), + 1); +}()); diff --git a/jstests/decimal/decimal_find_mixed.js b/jstests/decimal/decimal_find_mixed.js new file mode 100644 index 0000000000000..c93c7f5676d30 --- /dev/null +++ b/jstests/decimal/decimal_find_mixed.js @@ -0,0 +1,100 @@ +// Tests finding NumberDecimal from the shell in mixed collections. + +(function () { + "use strict"; + var col = db.decimal_find_mixed; + col.drop(); + + // Insert some sample data. + + assert.writeOK(col.insert([ + { "a" : -1 }, + { "a" : NumberDecimal("-1") }, + { "a" : NumberLong("-1") }, + { "a" : NumberInt("-1") }, + { "a" : -0.3 }, + { "a" : NumberDecimal("-0.3") }, + { "a" : -0.1 }, + { "a" : NumberDecimal("-0.1") }, + { "a": NumberDecimal("0") }, + { "a" : 0 }, + { "a" : NumberDecimal("-0") }, + { "a": NumberDecimal("0.00") }, + { "a" : NumberDecimal("0.1") }, + { "a" : 0.1 }, + { "a" : NumberDecimal("0.3") }, + { "a" : 0.3 }, + { "a" : NumberDecimal("0.5") }, + { "a" : 0.5 }, + { "a" : NumberDecimal("1.0") }, + { "a" : NumberLong("1") }, + { "a" : NumberDecimal("1.00") }, + { "a" : NumberDecimal("2.00") }, + { "a" : NumberDecimal("12345678901234567890.12345678901234") }, + { "a" : NumberDecimal("NaN") }, + { "a" : NumberDecimal("-NaN") }, + { "a" : NaN }, + { "a" : NumberDecimal("Infinity") }, + { "a" : Infinity } + ]), "Initial decimal insertion failed"); + + // Simple finds + assert.eq(col.find({ "a" : -1 }).count(), 4, "A1"); + assert.eq(col.find({ "a" : NumberLong("-1") }).count(), 4, "A2"); + assert.eq(col.find({ "a" : NumberInt("-1") }).count(), 4, "A3"); + assert.eq(col.find({ "a" : NumberDecimal("-1") }).count(), 4, "A4"); + + assert.eq(col.find({ "a": NaN }).count(), 3, "B1"); + assert.eq(col.find({ "a": NumberDecimal("NaN") }).count(), 3, "B2"); + assert.eq(col.find({ "a": Infinity }).count(), 2, "B3"); + assert.eq(col.find({ "a": NumberDecimal("Infinity") }).count(), 2, "B4"); + + assert.eq(col.find({ $and : [ { "a": { $gte : 0 }}, { "a" : { $lte: 2 }}]}).count(), + 14, "C1"); + + // Proper mixed ordering of decimals and doubles + col.drop(); + assert.writeOK(col.insert([ + { "a" : NumberDecimal("0.3") }, + { "a" : 0.3 } + ], "2 insertion failed")); + + assert.eq(col.find({ "a" : { $lt : NumberDecimal("0.3") }}).count(), 1, "D1"); + assert.eq(col.find({ "a" : { $gt : 0.3 }}).count(), 1, "D1"); + + // Find with NumberLong, but not Double + col.drop(); + assert.writeOK(col.insert([ + { "a" : NumberDecimal("36028797018963967") } + ], "3 insertion failed")); + + assert.eq(col.find({ "a" : NumberDecimal("36028797018963967") }).count(), 1, "E1"); + // Not representable as double + assert.eq(col.find({ "a" : 36028797018963967 }).count(), 0, "E2"); + assert.eq(col.find({ "a" : NumberLong("36028797018963967") }).count(), 1, "E3"); + + // Doubles not representable as decimal + col.drop(); + var exactDouble = 1427247692705959881058285969449495136382746624; + var exactDoubleString = "1427247692705959881058285969449495136382746624"; + + assert.writeOK(col.insert([ + { "a" : exactDouble } // Exact double (46 digits) + ], "4 insertion failed")); + + assert.eq(col.find({ "a" : NumberDecimal(exactDoubleString) }).count(), 0, "F1"); + assert.eq(col.find({ "a" : { $gt : NumberDecimal(exactDoubleString) }}).count(), 1, "E2"); + + var exactDoubleTiny = 1/1606938044258990275541962092341162602522202993782792835301376; + var exactDoubleTinyString = "0.00000000000000000000000000000000000000000000000000000000000062230152778611417071440640537801242405902521687211671331011166147896988340353834411839448231257136169569665895551224821247160434722900390625"; + + col.drop(); + assert.writeOK(col.insert([ + { "a" : exactDoubleTiny } + ], "5 insertion failed")); + + assert.eq(col.find({ "a" : NumberDecimal(exactDoubleTinyString) }).count(), + 0, "F1"); + assert.eq(col.find({ "a" : { $gt : NumberDecimal(exactDoubleTinyString) }}).count(), + 1, "F2"); +}()); diff --git a/jstests/decimal/decimal_find_query.js b/jstests/decimal/decimal_find_query.js new file mode 100644 index 0000000000000..23689074ec9a9 --- /dev/null +++ b/jstests/decimal/decimal_find_query.js @@ -0,0 +1,49 @@ +// Find the decimal using query operators + +(function () { + 'use strict'; + var col = db.decimal_find_query; + col.drop(); + + // Insert some sample data. + + assert.writeOK(col.insert([ + { 'decimal': NumberDecimal('0') }, + { 'decimal': NumberDecimal('0.00') }, + { 'decimal' : NumberDecimal('-0') }, + { 'decimal' : NumberDecimal('1.0') }, + { 'decimal' : NumberDecimal('1.00') }, + { 'decimal' : NumberDecimal('2.00') }, + { 'decimal' : NumberDecimal('1234567890123456789012.12345678901234') }, + { 'decimal' : NumberDecimal('NaN') }, + { 'decimal' : NumberDecimal('-NaN') }, + { 'decimal' : NumberDecimal('Infinity') }, + { 'decimal' : NumberDecimal('-Infinity') }, + ]), 'Initial insertion failed'); + + assert.eq(col.find({ 'decimal' : { $eq: NumberDecimal('1') }}).count(), '2'); + assert.eq(col.find({ 'decimal': { $lt: NumberDecimal('1.00000000000001') }}).count(), + 6); + assert.eq(col.find({ 'decimal': { $gt: NumberDecimal('1.5')}}).count(), 3); + + assert.eq(col.find({ 'decimal' : { $gte: NumberDecimal('2.000') }}).count(), 3); + assert.eq(col.find({ 'decimal' : { $lte : NumberDecimal('0.9999999999999999')}}).count(), + 4); + + assert.eq( + col.find({ 'decimal': { $nin: [NumberDecimal('Infinity'), + NumberDecimal('-Infinity')]}}).count(), 9, + 'Infinity count incorrect'); + + // Test $mod + col.drop(); + assert.writeOK(col.insert([ + { 'decimal': NumberDecimal('0') }, + { 'decimal': NumberDecimal('0.00') }, + { 'decimal' : NumberDecimal('-0') }, + { 'decimal' : NumberDecimal('1.0') }, + { 'decimal' : NumberDecimal('1.00') }, + { 'decimal' : NumberDecimal('2.00') }, + ]), '2 insertion failed'); + assert.eq(col.find({'decimal' : { $mod: [2, 0] }}).count(), 4, "$mod count incorrect"); +}()); diff --git a/jstests/decimal/decimal_update.js b/jstests/decimal/decimal_update.js new file mode 100644 index 0000000000000..32824f8e0b9fa --- /dev/null +++ b/jstests/decimal/decimal_update.js @@ -0,0 +1,41 @@ +// Test decimal updates + +(function () { + "use strict"; + var col = db.decimal_updates; + col.drop(); + + // Insert some sample data. + var docs = [ + { 'a' : NumberDecimal("1.0") }, + { 'a' : NumberDecimal("0.0") }, + { 'a' : NumberDecimal("1.00") }, + { 'a' : NumberLong("1") }, + { 'a' : 1 } + ]; + + assert.writeOK(col.insert(docs), "Initial insertion failed"); + + assert.writeOK(col.update({}, { $inc: { 'a' : NumberDecimal("10") }}, { multi : true }), + "update $inc failed"); + assert.eq(col.find({ a : 11 }).count(), 4, "count after $inc incorrect"); + assert.writeOK(col.update({}, { $inc: { 'a' : NumberDecimal("0") }}, { multi : true }), + "update $inc 0 failed"); + assert.eq(col.find({ a : 11 }).count(), 4, "count after $inc 0 incorrect"); + + col.drop(); + assert.writeOK(col.insert(docs), "Second insertion failed"); + + assert.writeOK(col.update({}, { $mul: { 'a' : NumberDecimal("1") }}, { multi : true }), + "update $mul failed"); + assert.eq(col.find({ a : 1 }).count(), 4, "count after $mul incorrect"); + assert.writeOK(col.update({}, { $mul: { 'a' : NumberDecimal("2") }}, { multi : true }), + "update $mul 2 failed"); + assert.eq(col.find({ a : 2 }).count(), 4, "count after $mul incorrect"); + assert.writeOK(col.update({}, { $mul: { 'a' : NumberDecimal("0") }}, { multi : true }), + "update $mul 0 failed"); + assert.eq(col.find({ a : 0 }).count(), 5, "count after $mul 0 incorrect"); + + assert.writeError(col.update({}, { $bit: { 'a': { and : 1 }}}, { multi : true }), + "$bit should fail"); +}()); diff --git a/jstests/decimal/placeholder.js b/jstests/decimal/placeholder.js deleted file mode 100644 index bc8c790473844..0000000000000 --- a/jstests/decimal/placeholder.js +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: Replace this file with decimal JS tests -// when experimental decimal support is available \ No newline at end of file