Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

First commit with skeletal implementation.

  • Loading branch information...
commit f0dea38015c3633b5cfd7c494f2c4c1f7de40726 0 parents
@mbostock authored
26 LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2011, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 Makefile
@@ -0,0 +1,12 @@
+test: \
+ test/test-collection.test \
+ test/test-cursor.test \
+ test/test-db.test \
+ test/test-server.test
+
+%.test: %.js %.out
+ @/bin/echo -n "test: $* "
+ @node $< > $*.actual
+ @diff -U 3 $*.out $*.actual && rm -f $*.actual \
+ && echo '\033[1;32mPASS\033[0m' \
+ || echo test: $* '\033[1;31mFAIL\033[0m'
3  README.md
@@ -0,0 +1,3 @@
+# Mongo-Mock
+
+An in-memory, pure JavaScript mock implementation of a MongoDB driver. This is a work in progress. This implementation is designed to be a drop-in replacement for node-mongodb-native for the purpose of unit testing.
53 lib/mongo-mock/collection.js
@@ -0,0 +1,53 @@
+var cursor = require("./cursor"),
+ ObjectId = require("./object_id");
+
+module.exports = collection;
+
+function collection(id, options) {
+ var collection = [];
+
+ function find(query, options, callback) {
+ if (!callback) { callback = options; options = null; }
+ callback(null, cursor(collection));
+ }
+
+ function insert(objects, options, callback) {
+ if (!callback) { callback = options; options = null; }
+ if (Array.isArray(objects)) {
+ var i = -1, n = objects.length, object;
+ while (++i < n) {
+ object = objects[i];
+ if (!("_id" in object)) object._id = new ObjectId();
+ collection.push(object);
+ }
+ } else {
+ if (!("_id" in objects)) objects._id = new ObjectId();
+ collection.push(objects);
+ }
+ if (callback) callback(null);
+ }
+
+ function update(query, object, options, callback) {
+ if (!callback) { callback = options; options = null; }
+ callback({message: "Not yet implemented."});
+ }
+
+ function save(object, options, callback) {
+ if ("_id" in object) update({_id: object._id}, object, options, callback);
+ else insert(object, options, callback);
+ }
+
+ function remove(query, options, callback) {
+ if (!callback) { callback = options; options = null; }
+ callback({message: "Not yet implemented."});
+ }
+
+ return {
+ find: find,
+ insert: insert,
+ update: update,
+ save: save,
+ remove: remove,
+ toString: function() { return id; }
+ };
+}
17 lib/mongo-mock/cursor.js
@@ -0,0 +1,17 @@
+module.exports = cursor;
+
+function cursor(objects) {
+ var i = -1;
+ return {
+ each: function(callback) {
+ objects.forEach(function(object) { callback(null, object); });
+ callback(null, null);
+ },
+ toArray: function(callback) {
+ callback(null, objects);
+ },
+ nextObject: function(callback) {
+ callback(null, ++i < objects.length? objects[i] : null);
+ }
+ };
+}
26 lib/mongo-mock/db.js
@@ -0,0 +1,26 @@
+var collection = require("./collection");
+
+module.exports = Db;
+
+var databases = {};
+
+function Db(name, server, options) {
+ var id = server + "/" + name, database = databases[id] || (databases[id] = db(id));
+ for (var key in database) this[key] = database[key];
+}
+
+function db(id) {
+ var collections = {};
+ return {
+ open: function(callback) {
+ callback(null);
+ },
+ collection: function(name, options, callback) {
+ if (!callback) { callback = options; options = null; }
+ callback(null, collections[name] || (collections[name] = collection(id + "/" + name, options)));
+ },
+ toString: function() {
+ return id;
+ }
+ };
+}
4 lib/mongo-mock/index.js
@@ -0,0 +1,4 @@
+module.exports = {
+ Server: require("./server"),
+ Db: require("./db")
+};
17 lib/mongo-mock/object_id.js
@@ -0,0 +1,17 @@
+var now = 0x4e21d7d4,
+ machine_id = 0x0123ab,
+ process_id = 0x0123,
+ increment = 0;
+
+module.exports = function ObjectId(id) {
+ if (id == null) id = hex(++now, 8)
+ + hex(machine_id, 6)
+ + hex(process_id, 4)
+ + hex(++increment, 6);
+ this.toString = this.toJSON = function() { return id; };
+};
+
+function hex(n, width) {
+ var length = (n = n.toString(16)).length;
+ return length < width ? new Array(width - length + 1).join("0") + n : n;
+}
6 lib/mongo-mock/server.js
@@ -0,0 +1,6 @@
+module.exports = Server;
+
+function Server(host, port, options) {
+ var id = host + ":" + port;
+ this.toString = function() { return id; };
+}
10 package.json
@@ -0,0 +1,10 @@
+{
+ "name": "mongo-mock",
+ "description": "In-memory mock implementation of a MongoDB driver.",
+ "version": "0.0.1",
+ "author": "Mike Bostock <mbostock@gmail.com>",
+ "keywords": ["mongo", "mongodb", "mock"],
+ "repository": "git://github.com/mbostock/mongo-mock",
+ "engines": { "node": "0.4.x" },
+ "main": "./lib/mongo-mock/index.js"
+}
52 test/test-collection.js
@@ -0,0 +1,52 @@
+var mongodb = require("../");
+
+var server = new mongodb.Server("host", 27017),
+ db = new mongodb.Db("database", server);
+
+console.log("collection:");
+db.open(function(error) {
+ db.collection("collection", function(error, collection) {
+ console.log(" host:27017/database/collection -> " + collection);
+ });
+});
+console.log("");
+
+console.log("empty + find:");
+db.open(function(error) {
+ db.collection("empty", function(error, collection) {
+ collection.find({}, function(error, cursor) {
+ cursor.each(function(error, object) {
+ if (object) console.log(" " + JSON.stringify(object));
+ });
+ });
+ });
+});
+console.log("");
+
+console.log("insert(object) + find:");
+db.open(function(error) {
+ db.collection("insert", function(error, collection) {
+ collection.insert({hello: "world"}, function(error) {
+ collection.find({}, function(error, cursor) {
+ cursor.each(function(error, object) {
+ if (object) console.log(" " + JSON.stringify(object));
+ });
+ });
+ });
+ });
+});
+console.log("");
+
+console.log("save(object) + find:");
+db.open(function(error) {
+ db.collection("save", function(error, collection) {
+ collection.save({hello: "world"}, function(error) {
+ collection.find({}, function(error, cursor) {
+ cursor.each(function(error, object) {
+ if (object) console.log(" " + JSON.stringify(object));
+ });
+ });
+ });
+ });
+});
+console.log("");
11 test/test-collection.out
@@ -0,0 +1,11 @@
+collection:
+ host:27017/database/collection -> host:27017/database/collection
+
+empty + find:
+
+insert(object) + find:
+ {"hello":"world","_id":"4e21d7d50123ab0123000001"}
+
+save(object) + find:
+ {"hello":"world","_id":"4e21d7d60123ab0123000002"}
+
31 test/test-cursor.js
@@ -0,0 +1,31 @@
+var cursor = require("../lib/mongo-mock/cursor"); // Internal API!
+
+var c = cursor([1, 2, 3]);
+console.log("cursor([1, 2, 3]).each:");
+c.each(function(error, object) {
+ console.log(" " + object);
+});
+console.log("");
+
+var c = cursor([1, 2, 3]);
+console.log("cursor([1, 2, 3]).nextObject:");
+c.nextObject(function(error, object) {
+ console.log(" " + object);
+ c.nextObject(function(error, object) {
+ console.log(" " + object);
+ c.nextObject(function(error, object) {
+ console.log(" " + object);
+ c.nextObject(function(error, object) {
+ console.log(" " + object);
+ });
+ });
+ });
+});
+console.log("");
+
+var c = cursor([1, 2, 3]);
+console.log("cursor([1, 2, 3]).toArray:");
+c.toArray(function(error, objects) {
+ console.log(" " + objects);
+});
+console.log("");
15 test/test-cursor.out
@@ -0,0 +1,15 @@
+cursor([1, 2, 3]).each:
+ 1
+ 2
+ 3
+ null
+
+cursor([1, 2, 3]).nextObject:
+ 1
+ 2
+ 3
+ null
+
+cursor([1, 2, 3]).toArray:
+ 1,2,3
+
8 test/test-db.js
@@ -0,0 +1,8 @@
+var mongodb = require("../");
+
+var server = new mongodb.Server("host", 27017),
+ db = new mongodb.Db("database", server);
+
+console.log("db:");
+console.log(" host:27017/database -> " + db);
+console.log("");
3  test/test-db.out
@@ -0,0 +1,3 @@
+db:
+ host:27017/database -> host:27017/database
+
5 test/test-server.js
@@ -0,0 +1,5 @@
+var mongodb = require("../");
+
+console.log("server:");
+console.log(" host:27017 -> " + new mongodb.Server("host", 27017));
+console.log("");
3  test/test-server.out
@@ -0,0 +1,3 @@
+server:
+ host:27017 -> host:27017
+
Please sign in to comment.
Something went wrong with that request. Please try again.