Skip to content

Commit

Permalink
NODE-840 Added CRUD specification test cases and fix minor issues wit…
Browse files Browse the repository at this point in the history
…h upserts reporting matchedCount > 0
  • Loading branch information
christkv committed Nov 18, 2016
1 parent 40ffae9 commit c5bb3fb
Show file tree
Hide file tree
Showing 68 changed files with 4,324 additions and 18 deletions.
13 changes: 7 additions & 6 deletions lib/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -892,10 +892,10 @@ var updateOne = function(self, filter, update, options, callback) {
if(callback == null) return;
if(err && callback) return callback(err);
if(r == null) return callback(null, {result: {ok:1}});
r.matchedCount = r.result.n;
r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0] : null;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0]._id : null;
r.upsertedCount = Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
r.matchedCount = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
if(callback) callback(null, r);
});
}
Expand Down Expand Up @@ -942,15 +942,16 @@ Collection.prototype.replaceOne = function(filter, doc, options, callback) {
var replaceOne = function(self, filter, doc, options, callback) {
// Set single document update
options.multi = false;

// Execute update
updateDocuments(self, filter, doc, options, function(err, r) {
if(callback == null) return;
if(err && callback) return callback(err);
if(r == null) return callback(null, {result: {ok:1}});
r.matchedCount = r.result.n;
r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0] : null;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0]._id : null;

This comment has been minimized.

Copy link
@jpwilliams

jpwilliams Dec 13, 2016

Is this a breaking change? Made an issue on the JIRA for it here.

This comment has been minimized.

Copy link
@christkv

christkv Dec 13, 2016

Author Contributor

I've added a fix to allow for backward compatibility

r.upsertedCount = Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
r.matchedCount = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
r.ops = [doc];
if(callback) callback(null, r);
});
Expand Down Expand Up @@ -1002,10 +1003,10 @@ var updateMany = function(self, filter, update, options, callback) {
if(callback == null) return;
if(err && callback) return callback(err);
if(r == null) return callback(null, {result: {ok:1}});
r.matchedCount = r.result.n;
r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0] : null;
r.upsertedId = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? r.result.upserted[0]._id : null;
r.upsertedCount = Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
r.matchedCount = Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
if(callback) callback(null, r);
});
}
Expand Down
12 changes: 8 additions & 4 deletions lib/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ var debugFields = ['authSource', 'w', 'wtimeout', 'j', 'native_parser', 'forceSe
, 'serializeFunctions', 'raw', 'promoteLongs', 'promoteValues', 'promoteBuffers', 'bufferMaxEntries', 'numberOfRetries', 'retryMiliSeconds'
, 'readPreference', 'pkFactory', 'parentDb', 'promiseLibrary', 'noListener'];

// Filter out any write concern options
var illegalCommandFields = ['w', 'wtimeout', 'j', 'fsync', 'autoIndexId'
, 'strict', 'serializeFunctions', 'pkFactory', 'raw', 'readPreference'];

/**
* @fileOverview The **Db** class is a class that represents a MongoDB Database.
*
Expand Down Expand Up @@ -497,7 +501,6 @@ var createCollection = function(self, name, options, callback) {
var finalOptions = writeConcern(shallowClone(options), self, options);
// Did the user destroy the topology
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));

// Check if we have the name
self.listCollections({name: name})
.setReadPreference(ReadPreference.PRIMARY)
Expand All @@ -515,11 +518,12 @@ var createCollection = function(self, name, options, callback) {

// Decorate command with writeConcern if supported
decorateWithWriteConcern(cmd, self, options);

// Add all optional parameters
for(var n in options) {
if(options[n] != null && typeof options[n] != 'function')
cmd[n] = options[n];
if(options[n] != null
&& typeof options[n] != 'function' && illegalCommandFields.indexOf(n) == -1) {
cmd[n] = options[n];
}
}

// Force a primary read Preference
Expand Down
2 changes: 0 additions & 2 deletions test/functional/collection_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ exports['should correctly list back collection names containing .'] = {
// Let's check that the collection was created correctly
db1.listCollections().toArray(function(err, documents) {
test.equal(null, err);
// console.log("--------------------------------------------------")
// console.dir(documents)
var found = false;
documents.forEach(function(x) {
if(x.name == 'test.game') found = true;
Expand Down
80 changes: 80 additions & 0 deletions test/functional/crud/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
==========
CRUD Tests
==========

The YAML and JSON files in this directory tree are platform-independent tests
meant to exercise the translation from the API to underlying commands that
MongoDB understands. Given the variety of languages and implementations and
limited nature of a description of a test, there are a number of things
that aren't testable. For instance, none of these tests assert that maxTimeMS
was properly sent to the server. This would involve a lot of infrastructure to
define and setup. Therefore, these YAML tests are in no way a replacement for
more thorough testing. However, they can provide an initial verification of
your implementation.


Converting to JSON
==================

The tests are written in YAML
because it is easier for humans to write and read,
and because YAML includes a standard comment format.
A JSONified version of each YAML file is included in this repository.
Whenever you change the YAML, re-convert to JSON.
One method to convert to JSON is using
`yamljs <https://www.npmjs.com/package/yamljs>`_::

npm install -g yamljs
yaml2json -s -p -r .

Version
=======

Files in the "specifications" repository have no version scheme.
They are not tied to a MongoDB server version,
and it is our intention that each specification moves from "draft" to "final"
with no further revisions; it is superseded by a future spec, not revised.

However, implementers must have stable sets of tests to target.
As test files evolve they will occasionally be tagged like
"crud-tests-YYYY-MM-DD", until the spec is final.

Format
======

Each YAML file has the following keys:

- data: The data that should exist in the collection under test before each test run.
- minServerVersion: OPTIONAL: The minimum server version required to successfully run the test. If this field is not
present, it should be assumed that there is no lower bound on the server version required.
- maxServerVersion: OPTIONAL: The max server version against which this test can run successfully. If this field is not
present, it should be assumed that there is no upper bound on the server version required.
- tests:
An array of tests that are to be run independently of each other. Each test will
have some or all of the following fields

- description: The name of the test
- operation:

- name: The name of the operation as defined in the specification.
- arguments: The names and values of arguments from the specification.
- outcome:

- result: The return value from the operation.
- collection:

- name: OPTIONAL: The collection name to verify. If this isn't present
then use the collection under test.
- data: The data that should exist in the collection after the
operation has been run.


Use as integration tests
========================

Running these as integration tests will require a running mongod server.
Each of these tests is valid against a standalone mongod, a replica set, and a
sharded system for server version 3.0.0. Many of them will run against 2.4 and
2.6, but some will require conditional code. For instance, $out is not supported
in an aggregation pipeline in server 2.4, so that test must be skipped.
38 changes: 38 additions & 0 deletions test/functional/crud/read/aggregate-collation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"data": [
{
"_id": 1,
"x": "ping"
}
],
"minServerVersion": "3.4",
"tests": [
{
"description": "Aggregate with collation",
"operation": {
"arguments": {
"collation": {
"locale": "en_US",
"strength": 2
},
"pipeline": [
{
"$match": {
"x": "PING"
}
}
]
},
"name": "aggregate"
},
"outcome": {
"result": [
{
"_id": 1,
"x": "ping"
}
]
}
}
]
}
17 changes: 17 additions & 0 deletions test/functional/crud/read/aggregate-collation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
data:
- {_id: 1, x: 'ping'}
minServerVersion: '3.4'

tests:
-
description: "Aggregate with collation"
operation:
name: aggregate
arguments:
pipeline:
- $match:
x: 'PING'
collation: { locale: 'en_US', strength: 2 } # https://docs.mongodb.com/master/reference/collation/#collation-document
outcome:
result:
- {_id: 1, x: 'ping'}
70 changes: 70 additions & 0 deletions test/functional/crud/read/aggregate-out.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"minServerVersion": "2.6",
"tests": [
{
"description": "Aggregate with $out",
"operation": {
"arguments": {
"batchSize": 2,
"pipeline": [
{
"$sort": {
"x": 1
}
},
{
"$match": {
"_id": {
"$gt": 1
}
}
},
{
"$out": "other_test_collection"
}
]
},
"name": "aggregate"
},
"outcome": {
"collection": {
"data": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"name": "other_test_collection"
},
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
]
}
28 changes: 28 additions & 0 deletions test/functional/crud/read/aggregate-out.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
data:
- {_id: 1, x: 11}
- {_id: 2, x: 22}
- {_id: 3, x: 33}
minServerVersion: '2.6'

tests:
-
description: "Aggregate with $out"
operation:
name: aggregate
arguments:
pipeline:
- $sort: {x: 1}
- $match:
_id: {$gt: 1}
- $out: "other_test_collection"
batchSize: 2

outcome:
result:
- {_id: 2, x: 22}
- {_id: 3, x: 33}
collection:
name: "other_test_collection"
data:
- {_id: 2, x: 22}
- {_id: 3, x: 33}
53 changes: 53 additions & 0 deletions test/functional/crud/read/aggregate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"tests": [
{
"description": "Aggregate with multiple stages",
"operation": {
"arguments": {
"batchSize": 2,
"pipeline": [
{
"$sort": {
"x": 1
}
},
{
"$match": {
"_id": {
"$gt": 1
}
}
}
]
},
"name": "aggregate"
},
"outcome": {
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
]
}
Loading

0 comments on commit c5bb3fb

Please sign in to comment.