Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git://github.com/christkv/node-mongodb-nativ…

…e into tailing
  • Loading branch information...
commit 4ed7b3beb91111e6e8cc5aaa50dc7724b90a0fba 2 parents b83709d + a346a6a
Aaron Heckmann aheckmann authored
1  .gitignore
View
@@ -1,6 +1,7 @@
.DS_Store
*.swp
*.seed
+*.tmp
.project
.settings
data
1  .npmignore
View
@@ -3,6 +3,7 @@
.buildinfo
.mongodb
.DS_Store
+*,tmp
HISTORY
Readme.md
4 HISTORY
View
@@ -1,4 +1,8 @@
- _id=0 is being turned into an ObjectID (Issue #551)
+- fix for error in GridStore write method (Issue #559)
+- Fix for reading a GridStore from arbitrary, non-chunk aligned offsets, added test (Issue #563, https://github.com/subroutine)
+- Modified limitRequest to allow negative limits to pass through to Mongo, added test (Issue #561)
+- Corrupt GridFS files when chunkSize < fileSize, fixed concurrency issue (Issue #555)
0.9.9.7 2012-03-16
------------------
8 dev/benchmark/grid_fs_write_benchmark.js
View
@@ -1,7 +1,7 @@
-var Db = require('../lib/mongodb').Db,
- Server = require('../lib/mongodb').Server,
- ObjectID = require('../lib/mongodb').ObjectID,
- GridStore = require('../lib/mongodb').GridStore;
+var Db = require('../../lib/mongodb').Db,
+ Server = require('../../lib/mongodb').Server,
+ ObjectID = require('../../lib/mongodb').ObjectID,
+ GridStore = require('../../lib/mongodb').GridStore;
var simulated_buffer = new Buffer(1024*1000*10).toString();
15 dev/benchmark/gridfs_benchmark.js
View
@@ -1,15 +1,16 @@
-var Db = require('../lib/mongodb').Db,
- Server = require('../lib/mongodb').Server,
- ObjectID = require('../lib/mongodb').ObjectID,
- GridStore = require('../lib/mongodb').GridStore;
+var Db = require('../../lib/mongodb').Db,
+ Server = require('../../lib/mongodb').Server,
+ ObjectID = require('../../lib/mongodb').ObjectID,
+ GridStore = require('../../lib/mongodb').GridStore;
var Mongolian = require('mongolian');
var COUNT = 1000;
var currentWritingIndex = 0;
var server = new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSize:1, native_parser:true});
+var server2 = new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSize:1, native_parser:true});
// Read in the test file
-var fileData = require('fs').readFileSync("./test/gridstore/iya_logo_final_bw.jpg");
+var fileData = require('fs').readFileSync("../../test/gridstore/iya_logo_final_bw.jpg");
// ------------------------------------------------------------------------------
// TEST MONGODB NATIVE
@@ -19,7 +20,7 @@ new Db('gridfs_benchmark', server, {}).open(function(err, new_client) {
new_client.dropDatabase(function(err, result) {
new_client.close();
- new Db('gridfs_benchmark', server, {}).open(function(err, client) {
+ new Db('gridfs_benchmark', server2, {}).open(function(err, client) {
// Start Time
var startTime = new Date().getTime();
@@ -27,7 +28,7 @@ new Db('gridfs_benchmark', server, {}).open(function(err, new_client) {
for(var i = 0; i < COUNT; i++) {
var gridStore = new GridStore(client, "foobar" + i, "w");
gridStore.open(function(err, gridStore) {
- gridStore.writeBuffer(fileData, true, function(err, gridStore) {
+ gridStore.write(fileData, true, function(err, gridStore) {
// Update current write index
currentWritingIndex = currentWritingIndex + 1;
4 dev/benchmark/hammer.js
View
@@ -28,7 +28,7 @@ new Db('hammer_db', new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSi
// Execute an insert
db.collection('hammer_collection', function(err, collection) {
collection.insert(randomDoc(), {safe:false}, function(err, result) {
- // debug("---------------------------------------- INSERT")
+ debug("---------------------------------------- INSERT")
});
});
} else if(command == 2) {
@@ -69,7 +69,7 @@ new Db('hammer_db', new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSi
})
})
}
- }, 0);
+ }, 1000);
})
});
});
112 dev/tools/connection_proxy_emulator.js
View
@@ -0,0 +1,112 @@
+/**
+ * Parameters for the proxy
+ **/
+var inputHost = 'localhost';
+var inputPort = 27017;
+var outputHost = 'localhost';
+var outputPort = 27018;
+var webServerPort = 8080;
+
+/**
+ * Proxy handling
+ **/
+var net = require('net'),
+ http = require('http'),
+ format = require('util').format;
+var connectionNumber = 0,
+ incomingConnections = {},
+ outgoingConnections = {};
+
+// Server instance
+var server = net.createServer(function(connection) {
+ console.log("=============================================== server connected");
+ // console.dir(connection)
+ // Set the id
+ connection.id = connectionNumber++;
+ // Outgoing connection
+ var outgoingConnection = net.createConnection(outputPort, outputHost);
+ outgoingConnection.id = connection.id;
+ // Create a connection
+ outgoingConnections[connection.id] = outgoingConnection;
+ incomingConnections[connection.id] = connection;
+ // Listen to incoming data
+ connection.on("data", function(data) {
+ outgoingConnections[this.id].write(data);
+ });
+
+ connection.on("close", function() {
+ console.log("===================================== closing incoming connection :: " + this.id)
+ if(outgoingConnections[this.id]) outgoingConnections[this.id].destroy();
+ delete outgoingConnections[this.id];
+ })
+
+ outgoingConnections[connection.id].on("data", function(data) {
+ incomingConnections[this.id].write(data);
+ });
+
+ outgoingConnections[connection.id].on("close", function(data) {
+ console.log("===================================== closing outgoing connection :: " + this.id)
+ if(incomingConnections[this.id]) incomingConnections[this.id].destroy();
+ delete incomingConnections[this.id];
+ });
+});
+
+// Boot up server letting you control the connection
+var webserver = http.createServer(function(request, response) {
+ console.log("----------------------------------------------------------- 8080")
+ // console.dir(request.url.)
+ if(request.url == '/sockets') {
+ renderSocketList(incomingConnections, response);
+ } else if(request.url.indexOf('/sockets/close') != -1) {
+ // Get the id and kill it
+ var id = request.url.split("/").pop();
+ id = id != null ? parseInt(id) : null;
+ if(id != null && incomingConnections[id] != null) {
+ }
+ // Render the socket list
+ renderSocketList(incomingConnections, response);
+ } else if(request.url.indexOf('/rest/kill_random_socket')) {
+ // Grab all the connection ids
+ var keys = Object.keys(incomingConnections);
+ // Grab a random one in the space
+ var id = keys[Math.floor(Math.random(keys.length))];
+ // Terminate the connection
+
+ } else {
+ // Write 401 error out
+ response.writeHead(401, { 'Content-Type': 'text/plain'});
+ response.write("No such page found");
+ response.end();
+ }
+});
+// Listen
+webserver.listen(webServerPort);
+
+var renderSocketList = function(_incomingConnections, _response) {
+ // Write out the list of available sockets we can kill if we wish
+ _response.writeHead(200, { 'Content-Type': 'text/html'});
+ // Map the array
+ var socketids = Object.keys(_incomingConnections).map(function(item) {
+ return format("<li>Socket %s <a href='/sockets/close/%s'>[Close]</a></li>", item, item);
+ });
+ // Write out the data
+ _response.write(format("<head></head><body><ul>%s</ul></body>", socketids.join("")))
+ _response.end();
+}
+
+var terminateConnection = function(id) {
+ // Get the connections
+ var incomingConnection = incomingConnections[id];
+ var outgoingConnection = outgoingConnections[id];
+ // Remove from the list
+ delete incomingConnections[id];
+ delete outgoingConnections[id];
+ // Kill them
+ incomingConnection.destroy();
+ outgoingConnection.destroy();
+}
+
+// Listen to port
+server.listen(inputPort, inputHost, function() {
+ console.log("server bound")
+});
4 lib/mongodb/collection.js
View
@@ -878,7 +878,7 @@ Collection.prototype.findOne = function findOne () {
var self = this;
var args = Array.prototype.slice.call(arguments, 0);
var callback = args.pop();
- var cursor = this.find.apply(this, args).limit(1).batchSize(1);
+ var cursor = this.find.apply(this, args).limit(-1).batchSize(1);
// Return the item
cursor.toArray(function(err, items) {
if(err != null) return callback(err instanceof Error ? err : self.db.wrap(new Error(err)), null);
@@ -1038,7 +1038,7 @@ Collection.prototype.reIndex = function(callback) {
}
/**
- * Run Map Reduce across a collection.
+ * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
*
* Options
* - **out** {Object, default:*{inline:1}*}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}*
6 lib/mongodb/connection/connection.js
View
@@ -37,7 +37,7 @@ var Connection = exports.Connection = function(id, socketOptions) {
}
// Set max bson size
-Connection.DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024 * 4 * 3;
+Connection.DEFAULT_MAX_BSON_SIZE = 16777216;
// Inherit event emitter so we can emit stuff wohoo
inherits(Connection, EventEmitter);
@@ -122,6 +122,9 @@ Connection.prototype.isConnected = function() {
// Write the data out to the socket
Connection.prototype.write = function(command, callback) {
+ // console.log("=====================================================")
+ // console.log("this.maxBsonSize = " + this.maxBsonSize)
+
try {
// If we have a list off commands to be executed on the same socket
if(Array.isArray(command)) {
@@ -388,6 +391,7 @@ var errorHandler = function(self) {
var closeHandler = function(self) {
return function(hadError) {
+ console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
// If we have an error during the connection phase
if(hadError && !self.connected) {
// Set disconnected
36 lib/mongodb/connection/connection_pool.js
View
@@ -18,6 +18,7 @@ var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bso
this.bson = bson;
// PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc)
this.poolSize = poolSize;
+ this.minPoolSize = Math.floor(this.poolSize / 2) + 1;
// Set default settings for the socket options
utils.setIntegerParameter(this.socketOptions, 'timeout', 0);
@@ -32,7 +33,7 @@ var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bso
// Internal structures
this.openConnections = [];
- this.connections = [];
+ // this.connections = [];
// Assign connection id's
this.connectionId = 0;
@@ -69,15 +70,15 @@ var _connect = function(_self) {
connection.on("connect", function(err, connection) {
// Add connection to list of open connections
_self.openConnections.push(connection);
- _self.connections.push(connection)
+ // _self.connections.push(connection)
// If the number of open connections is equal to the poolSize signal ready pool
- if(_self.connections.length === _self.poolSize && _self._poolState !== 'disconnected') {
+ if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') {
// Set connected
_self._poolState = 'connected';
// Emit pool ready
_self.emit("poolReady");
- } else if(_self.connections.length < _self.poolSize) {
+ } else if(_self.openConnections.length < _self.poolSize) {
// We need to open another connection, make sure it's in the next
// tick so we don't get a cascade of errors
process.nextTick(function() {
@@ -90,6 +91,9 @@ var _connect = function(_self) {
// Error handler
connection.on("error", function(err, connection) {
+ console.log("-------------------------------------------------------- error :: " + _self.openConnections.indexOf(this))
+ console.dir(this)
+
numberOfErrors++;
// If we are already disconnected ignore the event
if(connectionStatus != 'disconnected' && _self.listeners("error").length > 0) {
@@ -102,11 +106,16 @@ var _connect = function(_self) {
_self._poolState = 'disconnected';
// Clean up
_self.openConnections = [];
- _self.connections = [];
+ // _self.connections = [];
});
// Close handler
connection.on("close", function() {
+ console.log("-------------------------------------------------------- close")
+ console.dir(this)
+ // Only close when we have no more connections
+ // if(_self.minPoolSize)
+
// If we are already disconnected ignore the event
if(connectionStatus !== 'disconnected' && _self.listeners("close").length > 0) {
_self.emit("close");
@@ -118,11 +127,13 @@ var _connect = function(_self) {
_self._poolState = 'disconnected';
// Clean up
_self.openConnections = [];
- _self.connections = [];
+ // _self.connections = [];
});
// Timeout handler
connection.on("timeout", function(err, connection) {
+ console.log("-------------------------------------------------------- timeout")
+ console.dir(this)
// If we are already disconnected ignore the event
if(connectionStatus !== 'disconnected' && _self.listeners("timeout").length > 0) {
_self.emit("timeout", err);
@@ -134,11 +145,13 @@ var _connect = function(_self) {
_self._poolState = 'disconnected';
// Clean up
_self.openConnections = [];
- _self.connections = [];
+ // _self.connections = [];
});
// Parse error, needs a complete shutdown of the pool
connection.on("parseError", function() {
+ console.log("-------------------------------------------------------- parseError")
+ console.dir(this)
// If we are already disconnected ignore the event
if(connectionStatus !== 'disconnected' && _self.listeners("parseError").length > 0) {
// if(connectionStatus == 'connected') {
@@ -198,14 +211,14 @@ ConnectionPool.prototype.stop = function(removeListeners) {
}
// Close all connections
- for(var i = 0; i < this.connections.length; i++) {
- this.connections[i].close();
+ for(var i = 0; i < this.openConnections.length; i++) {
+ this.openConnections[i].close();
}
// Clean up
// this.connectionsWithErrors = [];
this.openConnections = [];
- this.connections = [];
+ // this.connections = [];
}
// Check the status of the connection
@@ -221,7 +234,8 @@ ConnectionPool.prototype.checkoutConnection = function(id) {
}
ConnectionPool.prototype.getAllConnections = function() {
- return this.connections;
+ // return this.connections;
+ return this.openConnections;
}
// Remove all non-needed event listeners
39 lib/mongodb/cursor.js
View
@@ -228,23 +228,33 @@ Cursor.prototype.sort = function(keyOrList, direction, callback) {
* Sets the limit parameter of this cursor to the given value.
*
* @param {Number} limit the new limit.
- * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
+ * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
* @return {Cursor} an instance of this object.
* @api public
*/
Cursor.prototype.limit = function(limit, callback) {
- callback = callback || function(){};
-
if(this.tailable) {
- callback(new Error("Tailable cursor doesn't support limit"), null);
+ if(callback) {
+ callback(new Error("Tailable cursor doesn't support limit"), null);
+ } else {
+ throw new Error("Tailable cursor doesn't support limit");
+ }
} else if(this.queryRun == true || this.state == Cursor.CLOSED) {
- callback(new Error("Cursor is closed"), null);
+ if(callback) {
+ callback(new Error("Cursor is closed"), null);
+ } else {
+ throw new Error("Cursor is closed");
+ }
} else {
if(limit != null && limit.constructor != Number) {
- callback(new Error("limit requires an integer"), null);
+ if(callback) {
+ callback(new Error("limit requires an integer"), null);
+ } else {
+ throw new Error("limit requires an integer");
+ }
} else {
this.limitValue = limit;
- callback(null, this);
+ if(callback) return callback(null, this);
}
}
@@ -255,7 +265,7 @@ Cursor.prototype.limit = function(limit, callback) {
* Sets the skip parameter of this cursor to the given value.
*
* @param {Number} skip the new skip value.
- * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
+ * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
* @return {Cursor} an instance of this object.
* @api public
*/
@@ -282,7 +292,7 @@ Cursor.prototype.skip = function(skip, callback) {
* Sets the batch size parameter of this cursor to the given value.
*
* @param {Number} batchSize the new batch size.
- * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
+ * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
* @return {Cursor} an instance of this object.
* @api public
*/
@@ -316,11 +326,12 @@ Cursor.prototype.batchSize = function(batchSize, callback) {
*/
var limitRequest = function(self) {
var requestedLimit = self.limitValue;
-
- if(self.limitValue > 0) {
- if (self.batchSizeValue > 0) {
- requestedLimit = self.limitValue < self.batchSizeValue ?
- self.limitValue : self.batchSizeValue;
+ var absLimitValue = Math.abs(self.limitValue);
+ var absBatchValue = Math.abs(self.batchSizeValue);
+
+ if(absLimitValue > 0) {
+ if (absBatchValue > 0) {
+ requestedLimit = Math.min(absLimitValue, absBatchValue);
}
} else {
requestedLimit = self.batchSizeValue;
5 lib/mongodb/db.js
View
@@ -1442,12 +1442,13 @@ var __retryCommandOnFailure = function(self, retryInMilliseconds, numberOfTimes,
// If we have no more authentications to replay
if(numberOfAuths == 0) {
if(err != null || !authenticated) {
- return _callback(err, null);
+ if(typeof _callback == 'function') _callback(err, null);
+ return;
} else {
// Execute command
command(_self, _db_command, _options, function(err, result) {
// Peform the command callback
- _callback(err, result);
+ if(typeof _callback == 'function') _callback(err, result);
// Execute any backed up commands
while(_self.commands.length > 0) {
// Fetch the command
3  lib/mongodb/gridfs/chunk.js
View
@@ -72,7 +72,8 @@ var Chunk = exports.Chunk = function(file, mongoObject) {
Chunk.prototype.write = function(data, callback) {
this.data.write(data, this.internalPosition);
this.internalPosition = this.data.length();
- callback(null, this);
+ if(callback != null) return callback(null, this);
+ return this;
};
/**
185 lib/mongodb/gridfs/gridstore.js
View
@@ -61,7 +61,7 @@ function GridStore(db, id, filename, mode, options) {
// set grid referencetype
this.referenceBy = typeof id == 'string' ? 0 : 1;
this.filename = _filename;
- this.fileId = id;
+ this.fileId = typeof id == 'string' ? new ObjectID() : id;
// Set up the rest
this.mode = mode == null ? "r" : mode;
@@ -70,6 +70,8 @@ function GridStore(db, id, filename, mode, options) {
this.position = 0;
// Set default chunk size
this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize'];
+ // Previous chunk size
+ this.previousChunkSize = 0;
/**
* Returns the current chunksize of the file.
@@ -155,7 +157,7 @@ var _open = function(self, callback) {
// Create the query
var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename};
- query = self.fileId == null && this.filename == null ? null : query;
+ query = null == self.fileId && this.filename == null ? null : query;
// Fetch the chunks
if(query != null) {
@@ -173,7 +175,9 @@ var _open = function(self, callback) {
self.metadata = doc.metadata;
self.internalMd5 = doc.md5;
} else {
- self.fileId = self.fileId instanceof ObjectID ? self.fileId : new ObjectID();
+ // self.fileId =
+ // self.fileId = self.fileId instanceof ObjectID ? self.fileId : new ObjectID();
+ self.fileId = self.fileId == null ? new ObjectID() : self.fileId;
self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
self.length = 0;
@@ -210,7 +214,7 @@ var _open = function(self, callback) {
});
} else {
// Write only mode
- self.fileId = new ObjectID();
+ self.fileId = null == self.fileId ? new ObjectID() : self.fileId;
self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
self.length = 0;
@@ -274,6 +278,7 @@ GridStore.prototype.writeFile = function (file, callback) {
var chunk = new Chunk(self, {n:index++});
chunk.write(data, function(err, chunk) {
chunk.save(function(err, result) {
+ self.position = self.position + data.length;
// Point to current chunk
self.currentChunk = chunk;
@@ -307,53 +312,11 @@ GridStore.prototype.writeFile = function (file, callback) {
*/
GridStore.prototype.write = function(data, close, callback) {
// If we have a buffer write it using the writeBuffer method
- if(Buffer.isBuffer(data)) return writeBuffer(this, data, close, callback);
- // Otherwise check for the callback
- if(typeof close === "function") { callback = close; close = null; }
- var self = this;
- var finalClose = close == null ? false : close;
- // Otherwise let's write the data
- if(self.mode[0] != "w") {
- callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null);
+ if(Buffer.isBuffer(data)) {
+ return writeBuffer(this, data, close, callback);
} else {
- if((self.currentChunk.position + data.length) > self.chunkSize) {
- var previousChunkNumber = self.currentChunk.chunkNumber;
- var leftOverDataSize = self.chunkSize - self.currentChunk.position;
- var previousChunkData = data.slice(0, leftOverDataSize);
- var leftOverData = data.slice(leftOverDataSize, (data.length - leftOverDataSize));
- // Save out current Chunk as another variable and assign a new Chunk for overflow data
- var saveChunk = self.currentChunk;
- // Create a new chunk at once (avoid wrong writing of chunks)
- self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)});
-
- // Let's finish the current chunk and then call write again for the remaining data
- saveChunk.write(previousChunkData, function(err, chunk) {
- chunk.save(function(err, result) {
- self.position = self.position + leftOverDataSize;
- // Write the remaining data
- self.write(leftOverData, function(err, gridStore) {
- if(finalClose) {
- self.close(function(err, result) {
- callback(null, gridStore);
- });
- } else {
- callback(null, gridStore);
- }
- });
- });
- });
- } else {
- self.currentChunk.write(data, function(err, chunk) {
- self.position = self.position + data.length;
- if(finalClose) {
- self.close(function(err, result) {
- callback(null, self);
- });
- } else {
- callback(null, self);
- }
- });
- }
+ // Wrap the string in a buffer and write
+ return writeBuffer(this, new Buffer(data, 'binary'), close, callback);
}
};
@@ -373,57 +336,62 @@ GridStore.prototype.write = function(data, close, callback) {
*/
var writeBuffer = function(self, buffer, close, callback) {
if(typeof close === "function") { callback = close; close = null; }
- var finalClose = (close == null) ? false : close;
+ var finalClose = (close == null) ? false : close;
if(self.mode[0] != "w") {
callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null);
} else {
- if((self.currentChunk.position + buffer.length) > self.chunkSize) {
- // Data exceeds current chunk remaining free size; fill up current chunk and write the rest
- // to a new chunk (recursively)
- var previousChunkNumber = self.currentChunk.chunkNumber;
- var leftOverDataSize = self.chunkSize - self.currentChunk.position;
- var firstChunkData = buffer.slice(0, leftOverDataSize);
- var leftOverData = buffer.slice(leftOverDataSize);
- // Save out current Chunk as another variable and assign a new Chunk for overflow data
- var saveChunk = self.currentChunk;
- // Create a new chunk at once (avoid wrong writing of chunks)
+ if(self.currentChunk.position + buffer.length >= self.chunkSize) {
+ // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left
+ // to a new chunk (recursively)
+ var previousChunkNumber = self.currentChunk.chunkNumber;
+ var leftOverDataSize = self.chunkSize - self.currentChunk.position;
+ var firstChunkData = buffer.slice(0, leftOverDataSize);
+ var leftOverData = buffer.slice(leftOverDataSize);
+ // A list of chunks to write out
+ var chunksToWrite = [self.currentChunk.write(firstChunkData)];
+ // If we have more data left than the chunk size let's keep writing new chunks
+ while(leftOverData.length >= self.chunkSize) {
+ // Create a new chunk and write to it
+ var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)});
+ var firstChunkData = leftOverData.slice(0, self.chunkSize);
+ leftOverData = leftOverData.slice(self.chunkSize);
+ // Update chunk number
+ previousChunkNumber = previousChunkNumber + 1;
+ // Write data
+ newChunk.write(firstChunkData);
+ // Push chunk to save list
+ chunksToWrite.push(newChunk);
+ }
+
+ // Set current chunk with remaining data
self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)});
-
- // Let's finish the current chunk and then call write again for the remaining data
- saveChunk.write(firstChunkData, function(err, chunk) {
- chunk.save(function(err, result) {
- self.position = self.position + leftOverDataSize;
-
- // Write the remaining data
- writeBuffer(self, leftOverData, function(err, gridStore) {
- if(finalClose) {
- self.close(function(err, result) {
- callback(null, gridStore);
- });
- }
- else {
- callback(null, gridStore);
- }
- });
- });
- });
- }
- else {
- // Write buffer to chunk all at once
- self.currentChunk.write(buffer, function(err, chunk) {
- self.position = self.position + buffer.length;
- if(finalClose) {
- self.close(function(err, result) {
- callback(null, self);
- });
- }
- else {
- callback(null, self);
- }
- });
- }
- }
+ // If we have left over data write it
+ if(leftOverData.length > 0) self.currentChunk.write(leftOverData);
+
+ // Update the position for the gridstore
+ self.position = self.position + buffer.length;
+ // Total number of chunks to write
+ var numberOfChunksToWrite = chunksToWrite.length;
+ // Write out all the chunks and then return
+ for(var i = 0; i < chunksToWrite.length; i++) {
+ var chunk = chunksToWrite[i];
+ chunk.save(function(err, result) {
+ numberOfChunksToWrite = numberOfChunksToWrite - 1;
+
+ if(numberOfChunksToWrite <= 0) {
+ return callback(null, self);
+ }
+ })
+ }
+ } else {
+ // Update the position for the gridstore
+ self.position = self.position + buffer.length;
+ // We have less data than the chunk size just write it and callback
+ self.currentChunk.write(buffer);
+ callback(null, self);
+ }
+ }
};
/**
@@ -450,12 +418,28 @@ var writeBuffer = function(self, buffer, close, callback) {
* @api private
*/
var buildMongoObject = function(self, callback) {
- var length = self.currentChunk != null ? (self.currentChunk.chunkNumber * self.chunkSize + self.currentChunk.position) : 0;
+ // Keeps the final chunk number
+ var chunkNumber = 0;
+ var previousChunkSize = self.previousChunkSize;
+ // Get the correct chunk Number, if we have an empty chunk return the previous chunk number
+ if(null != self.currentChunk && self.currentChunk.chunkNumber > 0 && self.currentChunk.position == 0) {
+ chunkNumber = self.currentChunk.chunkNumber - 1;
+ } else {
+ chunkNumber = self.currentChunk.chunkNumber;
+ previousChunkSize = self.currentChunk.position;
+ }
+
+ // console.log("============================== self.currentChunk.chunkNumber :: " + self.currentChunk.chunkNumber)
+ // console.log("============================== self.currentChunk.position :: " + self.currentChunk.position)
+ // console.log(self.position)
+
+ // Calcuate the length
+ var length = self.currentChunk != null ? (chunkNumber * self.chunkSize + previousChunkSize) : 0;
var mongoObject = {
'_id': self.fileId,
'filename': self.filename,
'contentType': self.contentType,
- 'length': length < 0 ? 0 : length,
+ 'length': self.position ? self.position : 0,
'chunkSize': self.chunkSize,
'uploadDate': self.uploadDate,
'aliases': self.aliases,
@@ -483,7 +467,7 @@ GridStore.prototype.close = function(callback) {
if(self.mode[0] == "w") {
if(self.currentChunk != null && self.currentChunk.position > 0) {
- self.currentChunk.save(function(err, chuck) {
+ self.currentChunk.save(function(err, chunk) {
self.collection(function(err, files) {
// Build the mongo object
if(self.uploadDate != null) {
@@ -736,7 +720,8 @@ GridStore.prototype.read = function(length, buffer, callback) {
// Else return data
callback(null, finalBuffer);
} else {
- var slice = self.currentChunk.readSlice(self.currentChunk.length());
+ // console.dir(self.currentChunk)
+ var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position);
// Copy content to final buffer
slice.copy(finalBuffer, finalBuffer._index);
// Update index position
30 test/admin_test.js
View
@@ -403,22 +403,20 @@ exports.shouldCorrectlySetAndExtractProfilingInfo = function(test) {
adminDb.setProfilingLevel('all', function(err, level) {
// Execute a query command
- collection.find(function(err, cursor) {
- cursor.toArray(function(err, items) {
-
- // Turn off profiling
- adminDb.setProfilingLevel('off', function(err, level) {
-
- // Retrive the profiling information
- adminDb.profilingInfo(function(err, infos) {
- test.ok(infos.constructor == Array);
- test.ok(infos.length >= 1);
- test.ok(infos[0].ts.constructor == Date);
- test.ok(infos[0].millis.constructor == Number);
-
- db.close();
- test.done();
- });
+ collection.find().toArray(function(err, items) {
+
+ // Turn off profiling
+ adminDb.setProfilingLevel('off', function(err, level) {
+
+ // Retrive the profiling information
+ adminDb.profilingInfo(function(err, infos) {
+ test.ok(infos.constructor == Array);
+ test.ok(infos.length >= 1);
+ test.ok(infos[0].ts.constructor == Date);
+ test.ok(infos[0].millis.constructor == Number);
+
+ db.close();
+ test.done();
});
});
});
2,226 test/collection_test.js
View
@@ -53,1119 +53,1119 @@ exports.tearDown = function(callback) {
callback();
}
-// /**
-// * Example of a simple document save with safe set to false
-// *
-// * @_class collection
-// * @_function save
-// * @ignore
-// */
-// exports.shouldCorrectlySaveASimpleDocument = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Fetch the collection
-// db.collection("save_a_simple_document", function(err, collection) {
-//
-// // Save a document with no safe option
-// collection.save({hello:'world'});
-//
-// // Wait for a second
-// setTimeout(function() {
-//
-// // Find the saved document
-// collection.findOne({hello:'world'}, function(err, item) {
-// test.equal(null, err);
-// test.equal('world', item.hello);
-// db.close();
-// test.done();
-// });
-// }, 1000);
-// });
-// });
-// }
-//
-// /**
-// * Example of a simple document save and then resave with safe set to true
-// *
-// * @_class collection
-// * @_function save
-// * @ignore
-// */
-// exports.shouldCorrectlySaveASimpleDocumentModifyItAndResaveIt = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Fetch the collection
-// db.collection("save_a_simple_document_modify_it_and_resave_it", function(err, collection) {
-//
-// // Save a document with no safe option
-// collection.save({hello:'world'}, {safe:true}, function(err, result) {
-//
-// // Find the saved document
-// collection.findOne({hello:'world'}, function(err, item) {
-// test.equal(null, err);
-// test.equal('world', item.hello);
-//
-// // Update the document
-// item['hello2'] = 'world2';
-//
-// // Save the item with the additional field
-// collection.save(item, {safe:true}, function(err, result) {
-//
-// // Find the changed document
-// collection.findOne({hello:'world'}, function(err, item) {
-// test.equal(null, err);
-// test.equal('world', item.hello);
-// test.equal('world2', item.hello2);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectExecuteBasicCollectionMethods = function(test) {
-// client.createCollection('test_collection_methods', function(err, collection) {
-// // Verify that all the result are correct coming back (should contain the value ok)
-// test.equal('test_collection_methods', collection.collectionName);
-// // Let's check that the collection was created correctly
-// client.collectionNames(function(err, documents) {
-// var found = false;
-// documents.forEach(function(document) {
-// if(document.name == "integration_tests_.test_collection_methods") found = true;
-// });
-// test.ok(true, found);
-// // Rename the collection and check that it's gone
-// client.renameCollection("test_collection_methods", "test_collection_methods2", function(err, reply) {
-// test.equal(null, err);
-// // Drop the collection and check that it's gone
-// client.dropCollection("test_collection_methods2", function(err, result) {
-// test.equal(true, result);
-// test.done();
-// })
-// });
-// });
-// })
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldAccessToCollections = function(test) {
-// // Create two collections
-// client.createCollection('test.spiderman', function(r) {
-// client.createCollection('test.mario', function(r) {
-// // Insert test documents (creates collections)
-// client.collection('test.spiderman', function(err, spiderman_collection) {
-// spiderman_collection.insert({foo:5}, {safe:true}, function(err, r) {
-//
-// client.collection('test.mario', function(err, mario_collection) {
-// mario_collection.insert({bar:0}, {safe:true}, function(err, r) {
-// // Assert collections
-// client.collections(function(err, collections) {
-// var found_spiderman = false;
-// var found_mario = false;
-// var found_does_not_exist = false;
-//
-// collections.forEach(function(collection) {
-// if(collection.collectionName == "test.spiderman") found_spiderman = true;
-// if(collection.collectionName == "test.mario") found_mario = true;
-// if(collection.collectionName == "does_not_exist") found_does_not_exist = true;
-// });
-//
-// test.ok(found_spiderman);
-// test.ok(found_mario);
-// test.ok(!found_does_not_exist);
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyDropCollection = function(test) {
-// client.createCollection('test_drop_collection2', function(err, r) {
-// client.dropCollection('test_drop_collection', function(err, r) {
-// test.ok(err instanceof Error);
-// test.equal("ns not found", err.message);
-// var found = false;
-// // Ensure we don't have the collection in the set of names
-// client.collectionNames(function(err, replies) {
-// replies.forEach(function(err, document) {
-// if(document.name == "test_drop_collection") {
-// found = true;
-// return;
-// }
-// });
-// // If we have an instance of the index throw and error
-// if(found) throw new Error("should not fail");
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * Example of a simple document save and then resave with safe set to true
-// *
-// * @_class collection
-// * @_function drop
-// * @ignore
-// */
-// exports.shouldCorrectlyDropCollectionWithDropFunction = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Create a collection we want to drop later
-// db.createCollection('test_other_drop', function(err, collection) {
-// test.equal(null, err);
-//
-// // Drop the collection
-// collection.drop(function(err, reply) {
-//
-// // Ensure we don't have the collection in the set of names
-// db.collectionNames(function(err, replies) {
-//
-// var found = false;
-// // For each collection in the list of collection names in this db look for the
-// // dropped collection
-// replies.forEach(function(document) {
-// if(document.name == "test_other_drop") {
-// found = true;
-// return;
-// }
-// });
-//
-// // Ensure the collection is not found
-// test.equal(false, found);
-//
-// // Let's close the db
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyRetriveCollectionNames = function(test) {
-// client.createCollection('test_collection_names', function(err, r) {
-// client.collectionNames(function(err, documents) {
-// var found = false;
-// var found2 = false;
-// documents.forEach(function(document) {
-// if(document.name == MONGODB + '.test_collection_names') found = true;
-// });
-// test.ok(found);
-// // Insert a document in an non-existing collection should create the collection
-// client.collection('test_collection_names2', function(err, collection) {
-// collection.insert({a:1}, {safe:true}, function(err, r) {
-// client.collectionNames(function(err, documents) {
-// documents.forEach(function(document) {
-// if(document.name == MONGODB + '.test_collection_names2') found = true;
-// if(document.name == MONGODB + '.test_collection_names') found2 = true;
-// });
-//
-// test.ok(found);
-// test.ok(found2);
-// // Let's close the db
-// test.done();
-// });
-// })
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyRetrieveCollectionInfo = function(test) {
-// client.createCollection('test_collections_info', function(err, r) {
-// client.collectionsInfo(function(err, cursor) {
-// test.ok((cursor instanceof Cursor));
-// // Fetch all the collection info
-// cursor.toArray(function(err, documents) {
-// test.ok(documents.length > 1);
-//
-// var found = false;
-// documents.forEach(function(document) {
-// if(document.name == MONGODB + '.test_collections_info') found = true;
-// });
-// test.ok(found);
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * An example returning the options for a collection.
-// *
-// * @_class collection
-// * @_function options
-// */
-// exports.shouldCorrectlyRetriveCollectionOptions = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Create a test collection that we are getting the options back from
-// db.createCollection('test_collection_options', {'capped':true, 'size':1024}, function(err, collection) {
-// test.ok(collection instanceof Collection);
-// test.equal('test_collection_options', collection.collectionName);
-//
-// // Let's fetch the collection options
-// collection.options(function(err, options) {
-// test.equal(true, options.capped);
-// test.equal(1024, options.size);
-// test.equal("test_collection_options", options.create);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * An example showing how to establish if it's a capped collection
-// *
-// * @_class collection
-// * @_function isCapped
-// */
-// exports.shouldCorrectlyExecuteIsCapped = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Create a test collection that we are getting the options back from
-// db.createCollection('test_collection_is_capped', {'capped':true, 'size':1024}, function(err, collection) {
-// test.ok(collection instanceof Collection);
-// test.equal('test_collection_is_capped', collection.collectionName);
-//
-// // Let's fetch the collection options
-// collection.isCapped(function(err, capped) {
-// test.equal(true, capped);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * An example showing the use of the indexExists function for a single index name and a list of index names.
-// *
-// * @_class collection
-// * @_function indexExists
-// */
-// exports.shouldCorrectlyExecuteIndexExists = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Create a test collection that we are getting the options back from
-// db.createCollection('test_collection_index_exists', function(err, collection) {
-// test.equal(null, err);
-//
-// // Create an index on the collection
-// collection.createIndex('a', function(err, indexName) {
-//
-// // Let's test to check if a single index exists
-// collection.indexExists("a_1", function(err, result) {
-// test.equal(true, result);
-//
-// // Let's test to check if multiple indexes are available
-// collection.indexExists(["a_1", "_id_"], function(err, result) {
-// test.equal(true, result);
-//
-// // Check if a non existing index exists
-// collection.indexExists("c_1", function(err, result) {
-// test.equal(false, result);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldEnsureStrictAccessCollection = function(test) {
-// var error_client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, ssl:useSSL}), {strict:true, native_parser: (process.env['TEST_NATIVE'] != null)});
-// test.equal(true, error_client.strict);
-//
-// error_client.open(function(err, error_client) {
-// error_client.collection('does-not-exist', function(err, collection) {
-// test.ok(err instanceof Error);
-// test.equal("Collection does-not-exist does not exist. Currently in strict mode.", err.message);
-// });
-//
-// error_client.createCollection('test_strict_access_collection', function(err, collection) {
-// error_client.collection('test_strict_access_collection', function(err, collection) {
-// test.ok(collection instanceof Collection);
-// // Let's close the db
-// error_client.close();
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldPerformStrictCreateCollection = function(test) {
-// var error_client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, ssl:useSSL}), {strict:true, native_parser: (process.env['TEST_NATIVE'] != null)});
-// test.equal(true, error_client.strict);
-//
-// error_client.open(function(err, error_client) {
-// error_client.createCollection('test_strict_create_collection', function(err, collection) {
-// test.ok(collection instanceof Collection);
-//
-// // Creating an existing collection should fail
-// error_client.createCollection('test_strict_create_collection', function(err, collection) {
-// test.ok(err instanceof Error);
-// test.equal("Collection test_strict_create_collection already exists. Currently in strict mode.", err.message);
-//
-// // Switch out of strict mode and try to re-create collection
-// error_client.strict = false;
-// error_client.createCollection('test_strict_create_collection', function(err, collection) {
-// test.ok(collection instanceof Collection);
-//
-// // Let's close the db
-// error_client.close();
-// test.done();
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldFailToInsertDueToIllegalKeys = function(test) {
-// client.createCollection('test_invalid_key_names', function(err, collection) {
-// // Legal inserts
-// collection.insert([{'hello':'world'}, {'hello':{'hello':'world'}}], {safe:true}, function(err, r) {
-// // Illegal insert for key
-// collection.insert({'$hello':'world'}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key $hello must not start with '$'", err.message);
-//
-// collection.insert({'hello':{'$hello':'world'}}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key $hello must not start with '$'", err.message);
-//
-// collection.insert({'he$llo':'world'}, {safe:true}, function(err, docs) {
-// test.ok(docs[0].constructor == Object);
-//
-// collection.insert({'hello':{'hell$o':'world'}}, {safe:true}, function(err, docs) {
-// test.ok(err == null);
-//
-// collection.insert({'.hello':'world'}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key .hello must not contain '.'", err.message);
-//
-// collection.insert({'hello':{'.hello':'world'}}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key .hello must not contain '.'", err.message);
-//
-// collection.insert({'hello.':'world'}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key hello. must not contain '.'", err.message);
-//
-// collection.insert({'hello':{'hello.':'world'}}, {safe:true}, function(err, doc) {
-// test.ok(err instanceof Error);
-// test.equal("key hello. must not contain '.'", err.message);
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// });
-// })
-// })
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldFailDueToIllegalCollectionNames = function(test) {
-// client.collection(5, function(err, collection) {
-// test.equal("collection name must be a String", err.message);
-// });
-//
-// client.collection("", function(err, collection) {
-// test.equal("collection names cannot be empty", err.message);
-// });
-//
-// client.collection("te$t", function(err, collection) {
-// test.equal("collection names must not contain '$'", err.message);
-// });
-//
-// client.collection(".test", function(err, collection) {
-// test.equal("collection names must not start or end with '.'", err.message);
-// });
-//
-// client.collection("test.", function(err, collection) {
-// test.equal("collection names must not start or end with '.'", err.message);
-// });
-//
-// client.collection("test..t", function(err, collection) {
-// test.equal("collection names cannot be empty", err.message);
-// test.done();
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyCountOnNonExistingCollection = function(test) {
-// client.collection('test_multiple_insert_2', function(err, collection) {
-// collection.count(function(err, count) {
-// test.equal(0, count);
-// // Let's close the db
-// test.done();
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyExecuteSave = function(test) {
-// client.createCollection('test_save', function(err, collection) {
-// var doc = {'hello':'world'};
-// collection.save(doc, {safe:true}, function(err, docs) {
-// test.ok(docs._id instanceof ObjectID || Object.prototype.toString.call(docs._id) === '[object ObjectID]');
-//
-// collection.count(function(err, count) {
-// test.equal(1, count);
-// doc = docs;
-//
-// collection.save(doc, {safe:true}, function(err, doc2) {
-//
-// collection.count(function(err, count) {
-// test.equal(1, count);
-//
-// collection.findOne(function(err, doc3) {
-// test.equal('world', doc3.hello);
-//
-// doc3.hello = 'mike';
-//
-// collection.save(doc3, {safe:true}, function(err, doc4) {
-// collection.count(function(err, count) {
-// test.equal(1, count);
-//
-// collection.findOne(function(err, doc5) {
-// test.equal('mike', doc5.hello);
-//
-// // Save another document
-// collection.save({hello:'world'}, {safe:true}, function(err, doc) {
-// collection.count(function(err, count) {
-// test.equal(2, count);
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlySaveDocumentWithLongValue = function(test) {
-// client.createCollection('test_save_long', function(err, collection) {
-// collection.insert({'x':Long.fromNumber(9223372036854775807)}, {safe:true}, function(err, r) {
-// collection.findOne(function(err, doc) {
-// test.ok(Long.fromNumber(9223372036854775807).equals(doc.x));
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldSaveObjectThatHasIdButDoesNotExistInCollection = function(test) {
-// client.createCollection('test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection', function(err, collection) {
-// var a = {'_id':'1', 'hello':'world'};
-// collection.save(a, {safe:true}, function(err, docs) {
-// collection.count(function(err, count) {
-// test.equal(1, count);
-//
-// collection.findOne(function(err, doc) {
-// test.equal('world', doc.hello);
-//
-// doc.hello = 'mike';
-// collection.save(doc, {safe:true}, function(err, doc) {
-// collection.count(function(err, count) {
-// test.equal(1, count);
-// });
-//
-// collection.findOne(function(err, doc) {
-// test.equal('mike', doc.hello);
-// // Let's close the db
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyPerformUpsert = function(test) {
-// client.createCollection('test_should_correctly_do_upsert', function(err, collection) {
-// var id = new ObjectID(null)
-// var doc = {_id:id, a:1};
-//
-// Step(
-// function test1() {
-// var self = this;
-//
-// collection.update({"_id":id}, doc, {upsert:true, safe:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// collection.findOne({"_id":id}, self);
-// });
-// },
-//
-// function test2(err, doc) {
-// var self = this;
-// test.equal(1, doc.a);
-//
-// id = new ObjectID(null)
-// doc = {_id:id, a:2};
-//
-// collection.update({"_id":id}, doc, {safe:true, upsert:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// collection.findOne({"_id":id}, self);
-// });
-// },
-//
-// function test3(err, doc2) {
-// var self = this;
-// test.equal(2, doc2.a);
-//
-// collection.update({"_id":id}, doc2, {safe:true, upsert:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// collection.findOne({"_id":id}, function(err, doc) {
-// test.equal(2, doc.a);
-// test.done();
-// });
-// });
-// }
-// );
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyUpdateWithNoDocs = function(test) {
-// client.createCollection('test_should_correctly_do_update_with_no_docs', function(err, collection) {
-// var id = new ObjectID(null)
-// var doc = {_id:id, a:1};
-// collection.update({"_id":id}, doc, {safe:true}, function(err, numberofupdateddocs) {
-// test.equal(null, err);
-// test.equal(0, numberofupdateddocs);
-//
-// test.done();
-// });
-// });
-// }
-//
-// /**
-// * Example of a simple document update with safe set to false on an existing document
-// *
-// * @_class collection
-// * @_function update
-// */
-// exports.shouldCorrectlyUpdateASimpleDocument = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Get a collection
-// db.collection('update_a_simple_document', function(err, collection) {
-//
-// // Insert a document, then update it
-// collection.insert({a:1}, {safe:true}, function(err, doc) {
-//
-// // Update the document with an atomic operator
-// collection.update({a:1}, {$set:{b:2}});
-//
-// // Wait for a second then fetch the document
-// setTimeout(function() {
-//
-// // Fetch the document that we modified
-// collection.findOne({a:1}, function(err, item) {
-// test.equal(null, err);
-// test.equal(1, item.a);
-// test.equal(2, item.b);
-// db.close();
-// test.done();
-// });
-// }, 1000);
-// })
-// });
-// });
-// }
-//
-// /**
-// * Example of a simple document update using upsert (the document will be inserted if it does not exist)
-// *
-// * @_class collection
-// * @_function update
-// * @ignore
-// */
-// exports.shouldCorrectlyUpsertASimpleDocument = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Get a collection
-// db.collection('update_a_simple_document_upsert', function(err, collection) {
-//
-// // Update the document using an upsert operation, ensuring creation if it does not exist
-// collection.update({a:1}, {b:2, a:1}, {upsert:true, safe:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// // Fetch the document that we modified and check if it got inserted correctly
-// collection.findOne({a:1}, function(err, item) {
-// test.equal(null, err);
-// test.equal(1, item.a);
-// test.equal(2, item.b);
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * Example of an update across multiple documents using the multi option.
-// *
-// * @_class collection
-// * @_function update
-// * @ignore
-// */
-// exports.shouldCorrectlyUpdateMultipleDocuments = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Get a collection
-// db.collection('update_a_simple_document_multi', function(err, collection) {
-//
-// // Insert a couple of documentations
-// collection.insert([{a:1, b:1}, {a:1, b:2}], {safe:true}, function(err, result) {
-//
-// // Update multiple documents using the multi option
-// collection.update({a:1}, {$set:{b:0}}, {safe:true, multi:true}, function(err, numberUpdated) {
-// test.equal(null, err);
-// test.equal(2, numberUpdated);
-//
-// // Fetch all the documents and verify that we have changed the b value
-// collection.find().toArray(function(err, items) {
-// test.equal(null, err);
-// test.equal(1, items[0].a);
-// test.equal(0, items[0].b);
-// test.equal(1, items[1].a);
-// test.equal(0, items[1].b);
-//
-// db.close();
-// test.done();
-// });
-// })
-// });
-// });
-// });
-// }
-//
-// /**
-// * Example of running the distinct command against a collection
-// *
-// * @_class collection
-// * @_function distinct
-// * @ignore
-// */
-// exports.shouldCorrectlyHandleDistinctIndexes = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Crete the collection for the distinct example
-// db.createCollection('simple_key_based_distinct', function(err, collection) {
-//
-// // Insert documents to perform distinct against
-// collection.insert([{a:0, b:{c:'a'}}, {a:1, b:{c:'b'}}, {a:1, b:{c:'c'}},
-// {a:2, b:{c:'a'}}, {a:3}, {a:3}], {safe:true}, function(err, ids) {
-//
-// // Peform a distinct query against the a field
-// collection.distinct('a', function(err, docs) {
-// test.deepEqual([0, 1, 2, 3], docs.sort());
-//
-// // Perform a distinct query against the sub-field b.c
-// collection.distinct('b.c', function(err, docs) {
-// test.deepEqual(['a', 'b', 'c'], docs.sort());
-//
-// db.close();
-// test.done();
-// });
-// });
-// })
-// });
-// });
-// }
-//
-// /**
-// * Example of running the distinct command against a collection with a filter query
-// *
-// * @_class collection
-// * @_function distinct
-// * @ignore
-// */
-// exports.shouldCorrectlyHandleDistinctIndexesWithSubQueryFilter = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Crete the collection for the distinct example
-// db.createCollection('simple_key_based_distinct_sub_query_filter', function(err, collection) {
-//
-// // Insert documents to perform distinct against
-// collection.insert([{a:0, b:{c:'a'}}, {a:1, b:{c:'b'}}, {a:1, b:{c:'c'}},
-// {a:2, b:{c:'a'}}, {a:3}, {a:3}, {a:5, c:1}], {safe:true}, function(err, ids) {
-//
-// // Peform a distinct query with a filter against the documents
-// collection.distinct('a', {c:1}, function(err, docs) {
-// test.deepEqual([5], docs.sort());
-//
-// db.close();
-// test.done();
-// });
-// })
-// });
-// });
-// }
-//
-// /**
-// * Example of running simple count commands against a collection.
-// *
-// * @_class collection
-// * @_function count
-// * @ignore
-// */
-// exports.shouldCorrectlyDoSimpleCountExamples = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Crete the collection for the distinct example
-// db.createCollection('simple_count_example', function(err, collection) {
-//
-// // Insert documents to perform distinct against
-// collection.insert([{a:1}, {a:2}, {a:3}, {a:4, b:1}], {safe:true}, function(err, ids) {
-//
-// // Perform a total count command
-// collection.count(function(err, count) {
-// test.equal(null, err);
-// test.equal(4, count);
-//
-// // Peform a partial account where b=1
-// collection.count({b:1}, function(err, count) {
-// test.equal(null, err);
-// test.equal(1, count);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlyExecuteInsertUpdateDeleteSafeMode = function(test) {
-// client.createCollection('test_should_execute_insert_update_delete_safe_mode', function(err, collection) {
-// test.ok(collection instanceof Collection);
-// test.equal('test_should_execute_insert_update_delete_safe_mode', collection.collectionName);
-//
-// collection.insert({i:1}, {safe:true}, function(err, ids) {
-// test.equal(1, ids.length);
-// test.ok(ids[0]._id.toHexString().length == 24);
-//
-// // Update the record
-// collection.update({i:1}, {"$set":{i:2}}, {safe:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// // Remove safely
-// collection.remove({}, {safe:true}, function(err, result) {
-// test.equal(null, err);
-//
-// test.done();
-// });
-// });
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldPerformMultipleSaves = function(test) {
-// client.createCollection("multiple_save_test", function(err, collection) {
-// var doc = {
-// name: 'amit',
-// text: 'some text'
-// };
-//
-// //insert new user
-// collection.save(doc, {safe:true}, function(err, r) {
-// collection.find({}, {name: 1}).limit(1).toArray(function(err, users){
-// var user = users[0]
-//
-// if(err) {
-// throw new Error(err)
-// } else if(user) {
-// user.pants = 'worn'
-//
-// collection.save(user, {safe:true}, function(err, result){
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// test.done();
-// })
-// }
-// });
-// })
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldCorrectlySaveDocumentWithNestedArray = function(test) {
-// var db = new Db(MONGODB, new Server('localhost', 27017, {auto_reconnect: true, ssl:useSSL}), {native_parser: (process.env['TEST_NATIVE'] != null)});
-// db.open(function(err, db) {
-// db.createCollection("save_error_on_save_test", function(err, collection) {
-// // Create unique index for username
-// collection.createIndex([['username', 1]], true, function(err, result) {
-// var doc = {
-// email: 'email@email.com',
-// encrypted_password: 'password',
-// friends:
-// [ '4db96b973d01205364000006',
-// '4db94a1948a683a176000001',
-// '4dc77b24c5ba38be14000002' ],
-// location: [ 72.4930088, 23.0431957 ],
-// name: 'Amit Kumar',
-// password_salt: 'salty',
-// profile_fields: [],
-// username: 'amit' };
-// //insert new user
-// collection.save(doc, {safe:true}, function(err, doc) {
-//
-// collection.find({}).limit(1).toArray(function(err, users) {
-// test.equal(null, err);
-// var user = users[0]
-// user.friends.splice(1,1)
-//
-// collection.save(user, function(err, doc) {
-// test.equal(null, err);
-//
-// // Update again
-// collection.update({_id:new ObjectID(user._id.toString())}, {friends:user.friends}, {upsert:true, safe:true}, function(err, result) {
-// test.equal(null, err);
-// test.equal(1, result);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// })
-// });
-// });
-// }
-//
-// /**
-// * @ignore
-// */
-// exports.shouldPeformCollectionRemoveWithNoCallback = function(test) {
-// client.collection("remove_with_no_callback_bug_test", function(err, collection) {
-// collection.save({a:1}, {safe:true}, function(){
-// collection.save({b:1}, {safe:true}, function(){
-// collection.save({c:1}, {safe:true}, function(){
-// collection.remove({a:1}, {safe:true}, function() {
-// // Let's perform a count
-// collection.count(function(err, count) {
-// test.equal(null, err);
-// test.equal(2, count);
-// test.done();
-// });
-// })
-// });
-// });
-// });
-// });
-// },
-//
-// /**
-// * Example of retrieving a collections indexes
-// *
-// * @_class collection
-// * @_function indexes
-// * @ignore
-// */
-// exports.shouldCorrectlyRetriveACollectionsIndexes = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Crete the collection for the distinct example
-// db.createCollection('simple_key_based_distinct', function(err, collection) {
-//
-// // Create a geo 2d index
-// collection.ensureIndex({loc:"2d"}, function(err, result) {
-// test.equal(null, err);
-//
-// // Create a simple single field index
-// collection.ensureIndex({a:1}, function(err, result) {
-// test.equal(null, err);
-//
-// // List all of the indexes on the collection
-// collection.indexes(function(err, indexes) {
-// test.equal(3, indexes.length);
-//
-// db.close();
-// test.done();
-// });
-// })
-// })
-// });
-// });
-// }
-//
-// /**
-// * Example of retrieving a collections stats
-// *
-// * @_class collection
-// * @_function stats
-// * @ignore
-// */
-// exports.shouldCorrectlyReturnACollectionsStats = function(test) {
-// var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
-// {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
-//
-// // Establish connection to db
-// db.open(function(err, db) {
-//
-// // Crete the collection for the distinct example
-// db.createCollection('collection_stats_test', function(err, collection) {
-//
-// // Insert some documents
-// collection.insert([{a:1}, {hello:'world'}], {safe:true}, function(err, result) {
-//
-// // Retrieve the statistics for the collection
-// collection.stats(function(err, stats) {
-// test.equal(2, stats.count);
-//
-// db.close();
-// test.done();
-// });
-// });
-// });
-// });
-// }
+/**
+ * Example of a simple document save with safe set to false
+ *
+ * @_class collection
+ * @_function save
+ * @ignore
+ */
+exports.shouldCorrectlySaveASimpleDocument = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Fetch the collection
+ db.collection("save_a_simple_document", function(err, collection) {
+
+ // Save a document with no safe option
+ collection.save({hello:'world'});
+
+ // Wait for a second
+ setTimeout(function() {
+
+ // Find the saved document
+ collection.findOne({hello:'world'}, function(err, item) {
+ test.equal(null, err);
+ test.equal('world', item.hello);
+ db.close();
+ test.done();
+ });
+ }, 1000);
+ });
+ });
+}
+
+/**
+ * Example of a simple document save and then resave with safe set to true
+ *
+ * @_class collection
+ * @_function save
+ * @ignore
+ */
+exports.shouldCorrectlySaveASimpleDocumentModifyItAndResaveIt = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Fetch the collection
+ db.collection("save_a_simple_document_modify_it_and_resave_it", function(err, collection) {
+
+ // Save a document with no safe option
+ collection.save({hello:'world'}, {safe:true}, function(err, result) {
+
+ // Find the saved document
+ collection.findOne({hello:'world'}, function(err, item) {
+ test.equal(null, err);
+ test.equal('world', item.hello);
+
+ // Update the document
+ item['hello2'] = 'world2';
+
+ // Save the item with the additional field
+ collection.save(item, {safe:true}, function(err, result) {
+
+ // Find the changed document
+ collection.findOne({hello:'world'}, function(err, item) {
+ test.equal(null, err);
+ test.equal('world', item.hello);
+ test.equal('world2', item.hello2);
+
+ db.close();
+ test.done();
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldCorrectExecuteBasicCollectionMethods = function(test) {
+ client.createCollection('test_collection_methods', function(err, collection) {
+ // Verify that all the result are correct coming back (should contain the value ok)
+ test.equal('test_collection_methods', collection.collectionName);
+ // Let's check that the collection was created correctly
+ client.collectionNames(function(err, documents) {
+ var found = false;
+ documents.forEach(function(document) {
+ if(document.name == "integration_tests_.test_collection_methods") found = true;
+ });
+ test.ok(true, found);
+ // Rename the collection and check that it's gone
+ client.renameCollection("test_collection_methods", "test_collection_methods2", function(err, reply) {
+ test.equal(null, err);
+ // Drop the collection and check that it's gone
+ client.dropCollection("test_collection_methods2", function(err, result) {
+ test.equal(true, result);
+ test.done();
+ })
+ });
+ });
+ })
+}
+
+/**
+ * @ignore
+ */
+exports.shouldAccessToCollections = function(test) {
+ // Create two collections
+ client.createCollection('test.spiderman', function(r) {
+ client.createCollection('test.mario', function(r) {
+ // Insert test documents (creates collections)
+ client.collection('test.spiderman', function(err, spiderman_collection) {
+ spiderman_collection.insert({foo:5}, {safe:true}, function(err, r) {
+
+ client.collection('test.mario', function(err, mario_collection) {
+ mario_collection.insert({bar:0}, {safe:true}, function(err, r) {
+ // Assert collections
+ client.collections(function(err, collections) {
+ var found_spiderman = false;
+ var found_mario = false;
+ var found_does_not_exist = false;
+
+ collections.forEach(function(collection) {
+ if(collection.collectionName == "test.spiderman") found_spiderman = true;
+ if(collection.collectionName == "test.mario") found_mario = true;
+ if(collection.collectionName == "does_not_exist") found_does_not_exist = true;
+ });
+
+ test.ok(found_spiderman);
+ test.ok(found_mario);
+ test.ok(!found_does_not_exist);
+ test.done();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldCorrectlyDropCollection = function(test) {
+ client.createCollection('test_drop_collection2', function(err, r) {
+ client.dropCollection('test_drop_collection', function(err, r) {
+ test.ok(err instanceof Error);
+ test.equal("ns not found", err.message);
+ var found = false;
+ // Ensure we don't have the collection in the set of names
+ client.collectionNames(function(err, replies) {
+ replies.forEach(function(err, document) {
+ if(document.name == "test_drop_collection") {
+ found = true;
+ return;
+ }
+ });
+ // If we have an instance of the index throw and error
+ if(found) throw new Error("should not fail");
+ // Let's close the db
+ test.done();
+ });
+ });
+ });
+}
+
+/**
+ * Example of a simple document save and then resave with safe set to true
+ *
+ * @_class collection
+ * @_function drop
+ * @ignore
+ */
+exports.shouldCorrectlyDropCollectionWithDropFunction = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Create a collection we want to drop later
+ db.createCollection('test_other_drop', function(err, collection) {
+ test.equal(null, err);
+
+ // Drop the collection
+ collection.drop(function(err, reply) {
+
+ // Ensure we don't have the collection in the set of names
+ db.collectionNames(function(err, replies) {
+
+ var found = false;
+ // For each collection in the list of collection names in this db look for the
+ // dropped collection
+ replies.forEach(function(document) {
+ if(document.name == "test_other_drop") {
+ found = true;
+ return;
+ }
+ });
+
+ // Ensure the collection is not found
+ test.equal(false, found);
+
+ // Let's close the db
+ db.close();
+ test.done();
+ });
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldCorrectlyRetriveCollectionNames = function(test) {
+ client.createCollection('test_collection_names', function(err, r) {
+ client.collectionNames(function(err, documents) {
+ var found = false;
+ var found2 = false;
+ documents.forEach(function(document) {
+ if(document.name == MONGODB + '.test_collection_names') found = true;
+ });
+ test.ok(found);
+ // Insert a document in an non-existing collection should create the collection
+ client.collection('test_collection_names2', function(err, collection) {
+ collection.insert({a:1}, {safe:true}, function(err, r) {
+ client.collectionNames(function(err, documents) {
+ documents.forEach(function(document) {
+ if(document.name == MONGODB + '.test_collection_names2') found = true;
+ if(document.name == MONGODB + '.test_collection_names') found2 = true;
+ });
+
+ test.ok(found);
+ test.ok(found2);
+ // Let's close the db
+ test.done();
+ });
+ })
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldCorrectlyRetrieveCollectionInfo = function(test) {
+ client.createCollection('test_collections_info', function(err, r) {
+ client.collectionsInfo(function(err, cursor) {
+ test.ok((cursor instanceof Cursor));
+ // Fetch all the collection info
+ cursor.toArray(function(err, documents) {
+ test.ok(documents.length > 1);
+
+ var found = false;
+ documents.forEach(function(document) {
+ if(document.name == MONGODB + '.test_collections_info') found = true;
+ });
+ test.ok(found);
+ // Let's close the db
+ test.done();
+ });
+ });
+ });
+}
+
+/**
+ * An example returning the options for a collection.
+ *
+ * @_class collection
+ * @_function options
+ */
+exports.shouldCorrectlyRetriveCollectionOptions = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Create a test collection that we are getting the options back from
+ db.createCollection('test_collection_options', {'capped':true, 'size':1024}, function(err, collection) {
+ test.ok(collection instanceof Collection);
+ test.equal('test_collection_options', collection.collectionName);
+
+ // Let's fetch the collection options
+ collection.options(function(err, options) {
+ test.equal(true, options.capped);
+ test.equal(1024, options.size);
+ test.equal("test_collection_options", options.create);
+
+ db.close();
+ test.done();
+ });
+ });
+ });
+}
+
+/**
+ * An example showing how to establish if it's a capped collection
+ *
+ * @_class collection
+ * @_function isCapped
+ */
+exports.shouldCorrectlyExecuteIsCapped = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Create a test collection that we are getting the options back from
+ db.createCollection('test_collection_is_capped', {'capped':true, 'size':1024}, function(err, collection) {
+ test.ok(collection instanceof Collection);
+ test.equal('test_collection_is_capped', collection.collectionName);
+
+ // Let's fetch the collection options
+ collection.isCapped(function(err, capped) {
+ test.equal(true, capped);
+
+ db.close();
+ test.done();
+ });
+ });
+ });
+}
+
+/**
+ * An example showing the use of the indexExists function for a single index name and a list of index names.
+ *
+ * @_class collection
+ * @_function indexExists
+ */
+exports.shouldCorrectlyExecuteIndexExists = function(test) {
+ var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
+ {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});
+
+ // Establish connection to db
+ db.open(function(err, db) {
+
+ // Create a test collection that we are getting the options back from
+ db.createCollection('test_collection_index_exists', function(err, collection) {
+ test.equal(null, err);
+
+ // Create an index on the collection
+ collection.createIndex('a', function(err, indexName) {
+
+ // Let's test to check if a single index exists
+ collection.indexExists("a_1", function(err, result) {
+ test.equal(true, result);
+
+ // Let's test to check if multiple indexes are available
+ collection.indexExists(["a_1", "_id_"], function(err, result) {
+ test.equal(true, result);
+
+ // Check if a non existing index exists
+ collection.indexExists("c_1", function(err, result) {
+ test.equal(false, result);
+
+ db.close();
+ test.done();
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldEnsureStrictAccessCollection = function(test) {
+ var error_client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, ssl:useSSL}), {strict:true, native_parser: (process.env['TEST_NATIVE'] != null)});
+ test.equal(true, error_client.strict);
+
+ error_client.open(function(err, error_client) {
+ error_client.collection('does-not-exist', function(err, collection) {
+ test.ok(err instanceof Error);
+ test.equal("Collection does-not-exist does not exist. Currently in strict mode.", err.message);
+ });
+
+ error_client.createCollection('test_strict_access_collection', function(err, collection) {
+ error_client.collection('test_strict_access_collection', function(err, collection) {
+ test.ok(collection instanceof Collection);
+ // Let's close the db
+ error_client.close();
+ test.done();
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldPerformStrictCreateCollection = function(test) {
+ var error_client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, ssl:useSSL}), {strict:true, native_parser: (process.env['TEST_NATIVE'] != null)});
+ test.equal(true, error_client.strict);
+
+ error_client.open(function(err, error_client) {
+ error_client.createCollection('test_strict_create_collection', function(err, collection) {
+ test.ok(collection instanceof Collection);
+
+ // Creating an existing collection should fail
+ error_client.createCollection('test_strict_create_collection', function(err, collection) {
+ test.ok(err instanceof Error);
+ test.equal("Collection test_strict_create_collection already exists. Currently in strict mode.", err.message);
+
+ // Switch out of strict mode and try to re-create collection
+ error_client.strict = false;
+ error_client.createCollection('test_strict_create_collection', function(err, collection) {
+ test.ok(collection instanceof Collection);
+
+ // Let's close the db
+ error_client.close();
+ test.done();
+ });
+ });
+ });
+ });
+}
+
+/**
+ * @ignore
+ */
+exports.shouldFailToInsertDueToIllegalKeys = function(test) {