Skip to content
Browse files

Updated test framework to Mocha.

Change-Id: I854d777ae2316f6e590a975c09a7144e523d68ac
Reviewed-on: http://review.couchbase.org/28987
Reviewed-by: Mark Nunberg <mnunberg@haskalah.org>
Tested-by: Brett Lawson <brett19@gmail.com>
  • Loading branch information...
1 parent b2ccdc0 commit fac5ad621cc5fd70ea6c522e1a6c5dc780dbfa9d @brett19 brett19 committed Sep 15, 2013
View
2 Makefile
@@ -23,7 +23,7 @@ node_modules:
@npm install
check: node_modules
- (cd tests && ./runtests.sh *-*.js)
+ mocha
reformat:
@astyle --mode=c \
View
6 README.md
@@ -104,6 +104,12 @@ The basic method summary is:
console.log("Got result for key.. " + result.value);
});
+## Running Tests
+
+To run the unit tests built into the Node.js driver. Make sure you have
+mocha installed globally on your system, then execute mocha in the root
+directory of your couchnode installation.
+
## Contributing changes
See CONTRIBUTING.md
View
23 test/add.js
@@ -0,0 +1,23 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#add', function() {
+
+ it('should work with basic inputs', function(done) {
+ var testkey = H.genKey("add");
+
+ cb.remove(testkey, function(){
+ cb.add(testkey, "bar", H.okCallback(function() {
+ // try to add existing key, should fail
+ cb.add(testkey, "baz", function (err, meta) {
+ assert(err, "Can't add object at empty key");
+ done();
+ });
+ }));
+ });
+ });
+
+});
View
453 test/designdoc.js
@@ -0,0 +1,453 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+var async = require('async');
+var u = require("underscore");
+
+var cb = H.newClient();
+
+var ddoc = {
+ "views": {
+ "test-view": {
+ "map": "function(doc,meta){emit(meta.id)}"
+ }
+ }
+};
+
+describe('#design documents', function() {
+
+ it('should successfully manipulate design documents', function(done) {
+ var docname = "dev_ddoc-test";
+
+ // We don't know the state of the server so just
+ // do an unconditional delete
+ cb.removeDesignDoc(docname, function() {
+ // Ok, the design document should be done
+ cb.setDesignDoc(docname, ddoc, function(err, data) {
+ var util=require("util");
+ assert(!err, "error creating design document");
+ cb.getDesignDoc(docname, function(err, data) {
+ assert(!err, "error getting design document");
+ cb.removeDesignDoc(docname, function(err, data) {
+ assert(!err, "Failed deleting design document");
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ it('should successfully page results', function(done) {
+ this.timeout(10000);
+
+ var docname = "querytest";
+ var ddoc1 = {
+ "views": {
+ "simple": {
+ "map": "function(doc,meta){doc.type==10 ? emit( Number( meta.id.slice(6, meta.id.length))) : null }"
+ },
+ "compound": {
+ "map": "function(doc,meta){doc.type==10 ? emit([doc.name, Number(meta.id.slice(6, meta.id.length))]) : null}",
+ "reduce" : "_count"
+ }
+ }
+ };
+
+ // Popolate sample set of documents. documents are of the format
+ // id : { "name" : <"alpha" | "beta" | "kappa" | "pi" | "epsilon"> }
+ function TestPopulate(callback) {
+ var values = ["alpha", "beta", "kappa", "pi", "epsilon"];
+ var valueof = function(i) {
+ return "{ \"type\": 10, \"name\": \""+values[i%values.length]+ "\" }";
+ };
+ var multikv = {};
+ for (var i=0; i< 10000; i++) {
+ multikv["query-"+i.toString()] = { value: valueof(i) };
+ }
+ cb.setMulti(multikv, {spooled:true}, function(){
+ callback(null, 1);
+ });
+ }
+
+ // Populate design-document with two views by name "simple" and "compound"
+ function TestDD(callback) {
+ cb.setDesignDoc(docname, ddoc1, function() {
+ callback(null, 2);
+ });
+ }
+
+ function TestPaginate(callback) {
+ var pages = [];
+ var q = cb.view(docname, "simple", {
+ limit: 140,
+ stale: false
+ });
+ q.firstPage(function(err, results, p) {
+ assert(!err, "TestPaginate firstpage() failed");
+ nextpages(results, p);
+ });
+
+ function nextpages(results, p) {
+ pages.push( results );
+ if (p.hasNext()) {
+ p.next( function(err, results) {
+ assert(!err, "TestPaginate next() failed");
+ nextpages(results, p);
+ });
+ } else {
+ assert( pages.length === 72, "TestPaginate failed" );
+ var last = pages.pop();
+ assert( last.length === 60, "TestPaginate failed" );
+
+ p.prev( function(err, results) {
+ assert(!err, "TestPaginate prev() failed");
+ prevpages(results, p);
+ });
+ }
+ };
+
+ function prevpages(results, p) {
+ var page = pages.pop();
+ if (results.length > 0 ) {
+ assert( u.isEqual(results, page) );
+ p.prev( function(err, results) {
+ assert(!err, "TestPaginate prev() failed");
+ prevpages(results, p);
+ });
+ } else {
+ p.next( function(err, results) {
+ assert(!err, "TestPaginate next() failed");
+ assert(results.length===140, "TestPaginate 1 next() failed");
+ var l = results.pop();
+ assert(l.id==="query-279", "TestPaginate 1 next() failed");
+ callback(null, 4);
+ });
+ }
+ };
+ };
+
+ function Shutdown(callback) {
+ done();
+ callback(null, 5);
+ }
+
+ async.series([
+ TestPopulate,
+ TestDD,
+ TestPaginate,
+ Shutdown
+ ]);
+ });
+
+ it('should work with queries', function(done) {
+ this.timeout(10000);
+
+ var docname = "querytest";
+ var ddoc1 = {
+ "views": {
+ "simple": {
+ "map": "function(doc,meta){doc.type==10 ? emit( Number( meta.id.slice(6, meta.id.length))) : null }"
+ },
+ "compound": {
+ "map": "function(doc,meta){doc.type==10 ? emit([doc.name, Number(meta.id.slice(6, meta.id.length))]) : null}",
+ "reduce" : "_count"
+ }
+ }
+ };
+
+ // Popolate sample set of documents. documents are of the format
+ // id : { "name" : <"alpha" | "beta" | "kappa" | "pi" | "epsilon"> }
+ function TestPopulate(callback) {
+ var values = ["alpha", "beta", "kappa", "pi", "epsilon"];
+ var valueof = function(i) {
+ return "{ \"type\": 10, \"name\": \""+values[i%values.length]+ "\" }";
+ };
+ var multikv = {};
+ for (var i=0; i< 10000; i++) {
+ multikv["query-"+i.toString()] = { value: valueof(i) };
+ }
+ cb.setMulti(multikv, {spooled:true}, function(){
+ callback(null, 1);
+ });
+ }
+
+ // Populate design-document with two views by name "simple" and "compound"
+ function TestDD(callback) {
+ cb.setDesignDoc(docname, ddoc1, function() {
+ callback(null, 2);
+ });
+ }
+
+ // Test `startkey`, `endkey` and `inclusive_end`
+ function TestRange(callback) {
+ var q = cb.view(docname, "simple", {
+ startkey : 1,
+ endkey : 5,
+ stale: false,
+ inclusive_end: false,
+ });
+ q.query(function(err, results) {
+ var sum = u.reduce(
+ u.pluck(results, 'key'),
+ function(acc, n){ return acc + n; }, 0
+ );
+ assert(!err, "TestRange query failed");
+ assert(sum===10, "TestRange without inclusive_end does not add up");
+
+ // Along with it use `limit` parameter
+ q.query({limit: 3}, function(err, results) {
+ assert(!err, "TestRange query with limit failed");
+ assert(results[0].key === 1, "TestRange first key is not 1");
+ assert(results.length === 3, "TestRange lenght is not 3");
+
+ // Along with it use `skip` parameter
+ q.query({skip: 2}, function(err, results) {
+ assert(!err, "TestRange query with skip failed");
+ assert(results[0].key === 3, "TestRange first key is not 3");
+ assert(results.length === 2, "TestRange lenght is not 2");
+ callback(null, 3);
+ });
+ });
+ });
+ }
+
+ // Range query in descending order.
+ function TestRangeD(callback) {
+ var q = cb.view(docname, "simple", {
+ endkey : 3,
+ startkey : 10,
+ stale: false,
+ descending : true,
+ limit : 10
+ });
+ q.query(function(err, results) {
+ assert(!err, "TestRangeD query failed");
+ assert(results[0].key > results[1].key, "TestRangeD not descending");
+ var sum = u.reduce(
+ u.pluck(results, 'key'),
+ function(acc, n){ return acc + n; }, 0
+ );
+ assert(sum===52, "TestRange without inclusive_end does not add up");
+
+ // Apply `limit`
+ q.query({limit: 3}, function(err, results) {
+ assert(!err, "TestRange query with limit failed");
+ assert(results[0].key === 10, "TestRange first key is not 10");
+ assert(results.length === 3, "TestRange lenght is not 3");
+
+ // Apply `skip`
+ q.query({skip: 2}, function(err, results) {
+ assert(!err, "TestRange query with skip failed");
+ assert(results[0].key === 8, "TestRange first key is not 8");
+ assert(results.length === 6, "TestRange lenght is not 6");
+ callback(null, 6);
+ });
+ });
+ });
+ }
+
+ // Test key and keys
+ function TestKeys(callback) {
+ var q = cb.view(docname, "simple", {
+ key : 1,
+ stale: false,
+ });
+ var cq = cb.view(docname, "simple", {
+ keys : [1, 10],
+ stale: false,
+ });
+ q.query(function(err, results) {
+ assert(!err, "TestKeys query failed");
+ assert(results.length === 1, "TestKeys expected only one result");
+
+ // Fetch key within a range.
+ var q1 = q.clone({startkey:1, endkey:5, key:1});
+ q1.query(function(err, results) {
+ // console.log(results);
+
+ // Fetch more than one keys.
+ cq.query(function(err, results) {
+ assert(!err, "TestKeys query failed");
+ assert(results.length === 2,
+ "TestKeys expected only two result");
+ assert(results[0].id === "query-1", "TestKeys query-1");
+ assert(results[1].id === "query-10", "TestKeys query-1");
+
+ callback(null, 4);
+ });
+ });
+ });
+ }
+
+ // Include full document while querying for them.
+ function TestIncludeDocs(callback) {
+ var q = cb.view(docname, "simple", {
+ startkey : 1,
+ endkey : 5,
+ stale: false,
+ include_docs : true,
+ inclusive_end: false,
+ });
+ q.query(function(err, results) {
+ assert(!err, "TestIncludeDocs query failed");
+ assert(
+ results[0].doc.meta.id === 'query-1',
+ "TestIncludeDocs meta.id mismatch" );
+ assert(
+ results[0].doc.json.name === 'beta',
+ "TestIncludeDocs meta.id mismatch" );
+ callback(null, 5);
+ });
+ }
+
+ // Test compound keys.
+ function TestCompound(callback) {
+ var q1 = cb.view( docname, "compound", {
+ startkey : ["beta"],
+ endkey : ["epsilon"],
+ stale: false,
+ reduce : false,
+ limit : 10000
+ });
+ var q2 = q1.clone({
+ startkey : ["epsilon"],
+ endkey : ["beta"],
+ stale: false,
+ reduce : false,
+ descending : true,
+ limit : 10000
+ });
+ q1.query( function(err, results) {
+ assert(!err, "TestCompound query failed");
+ assert( results.length === 2000,
+ "Failed TestCompound without reduce" );
+
+ // With decending
+ q2.query( function(err, results) {
+ assert(!err, "TestCompound query with descending failed");
+ assert(
+ results.length === 2000,
+ "Failed TestCompound descending without reduce" );
+ assert(
+ results[0].key > results[1].key,
+ "Failed TestCompound descending without reduce" );
+ callback(null, 7);
+ });
+ });
+ }
+
+ function TestGroup(callback) {
+ var results1 = null;
+ var q = cb.view( docname, "compound", {
+ startkey: ["beta"],
+ endkey: ["pi"],
+ stale: false,
+ });
+ var q1 = q.clone({ group: true, skip: 10, limit: 10 });
+ var q2 = q.clone({ group_level: 2, skip: 10, limit: 10 });
+ var q3 = q.clone({ group_level: 1, endkey: ["beta"], startkey: ["pi"],
+ descending: true, inclusive_end: true});
+
+ // Plain reduce
+ q.query(function(err, results) {
+ assert(!err, "TestGroup failed ");
+ assert(results[0].value === 6000, "TestGroup reduce query failed ");
+
+ // with group = true, `skip` and `limit` parameters.
+ q1.query(function(err, results) {
+ var results1 = results;
+ assert(!err, "TestGroup failed ");
+
+ // With group_level = 2 and `skip` and `limit` parameters.
+ q2.query(function(err, results) {
+ assert(!err, "TestGroup failed ");
+ assert(
+ results.length === results1.length,
+ "TestGroup level 2 failed");
+
+ // With decending.
+ q3.query(function(err, results) {
+ assert(!err, "TestGroup failed ");
+ assert(results.length===3, "TestGroup level 1 failed");
+ assert(
+ results[0].key[0] === 'kappa',
+ "TestGroup level 1 failed"
+ );
+ assert(
+ results[2].key[0] === 'beta',
+ "TestGroup level 1 failed"
+ );
+ callback(null, 8);
+ });
+ });
+ });
+ });
+ }
+
+ function Shutdown(callback) {
+ done();
+ callback(null, 5);
+ }
+
+ async.series([
+ TestPopulate,
+ TestDD,
+ TestRange,
+ TestRangeD,
+ TestKeys,
+ TestIncludeDocs,
+ TestCompound,
+ TestGroup,
+ Shutdown
+ ]);
+ });
+
+ it('should successfully see new keys?', function(done) {
+ this.timeout(10000);
+
+ var testkey = H.genKey('dd-views');
+ var designdoc = "dev_test-design";
+
+ function do_run_view(cb) {
+ // now lets find our key in the view.
+ // We need to add stale=false in order to force the
+ // view to be generated (since we're trying to look
+ // for our key and it may not be in the view yet due
+ // to race conditions..
+ var params = {key : testkey, full_set : "true", stale : "false"};
+ var q = cb.view(designdoc, "test-view", params);
+ q.query(function(err, view) {
+ if (err && err.reason == "view_undefined") {
+ // Lets assume that the view isn't created yet... try again..
+ do_run_view(cb);
+ } else {
+ assert(!err, "error fetching view");
+ assert(view.length == 1);
+ assert.equal(testkey, view[0].key);
+ cb.removeDesignDoc(designdoc, function() { cb.shutdown(); });
+ done();
+ }
+ });
+ }
+
+ H.setGet(testkey, "bar", function(doc) {
+ var ddoc = {
+ "views": {
+ "test-view": {
+ "map": "function(doc,meta){emit(meta.id)}"
+ }
+ }
+ };
+ cb.removeDesignDoc(designdoc, function() {
+ cb.setDesignDoc(designdoc, ddoc, function(err, data) {
+ assert(!err, "error creating design document");
+ // The ns_server API is async here for some reason,
+ // so the view may not be ready to use yet...
+ // Try to poll the vire
+ do_run_view(cb);
+ });
+ });
+ });
+ });
+
+});
View
40 test/durability.js
@@ -0,0 +1,40 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#durability', function() {
+
+ it('should successfully observe', function(done) {
+ var key = H.genKey("observe");
+
+ cb.set(key, "value", H.okCallback(function(meta){
+ cb.observeMulti([key], {}, H.okCallback(function(meta){
+ assert(typeof meta == "object");
+ assert(key in meta);
+ assert(typeof meta[key] == 'object');
+ assert('cas' in meta[key][0]);
+ done();
+ }));
+ }));
+ });
+
+ // skip because durability requirements does not currently work property
+ it.skip('should successfully set with durability requirements',
+ function(done) {
+ var key = H.genKey("endure");
+
+ cb.set(key, "value", {persist_to:1, replicate_to:0},
+ H.okCallback(function(meta){
+ cb.remove(key, {persist_to:1, replicate_to:0},
+ H.okCallback(function(mera) {
+ cb.add(key, "value", {persist_to:1, replicate_to:0},
+ H.okCallback(function(meta){
+ done();
+ }));
+ }));
+ }));
+ });
+
+});
View
146 test/get-set.js
@@ -0,0 +1,146 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#get/set', function() {
+
+ it('should work in basic cases', function(done) {
+ var key = H.genKey("set");
+ cb.set(key, "bar", H.okCallback(function(firstmeta){
+ // nothing broke
+ cb.set(key, "baz", H.okCallback(function(secondmeta){
+ assert.notDeepEqual(firstmeta.cas, secondmeta.cas, "CAS should change");
+ cb.set(key, "bam", firstmeta, function(err, meta){
+ assert(err, "Key should fail with stale CAS");
+ cb.get(key, H.okCallback(function(result){
+ assert.equal(result.value, "baz");
+ cb.set(key, "grr", secondmeta, H.okCallback(function(meta){
+ cb.get(key, H.okCallback(function(result){
+ assert.equal("grr", result.value);
+ done();
+ }));
+ }));
+ }));
+ });
+ }));
+ }));
+ });
+
+ it('should work when passing json strings', function(done) {
+ var key = H.genKey("set-json");
+ cb.set(key, JSON.stringify({foo: "bar"}), H.okCallback(function(){
+ cb.set(key, JSON.stringify({foo: "baz"}), H.okCallback(function(){
+ cb.get(key, H.okCallback(function(result){
+ assert.equal(JSON.stringify({foo: "baz"}), result.value);
+ done();
+ }));
+ }));
+ }));
+ });
+
+ it('should work when passing large values', function(done) {
+ var key = H.genKey("set-big");
+
+ var value = "";
+ for (var ii = 0; ii < 8192; ++ii) {
+ value += "012345678\n";
+ }
+
+ cb.set(key, value, H.okCallback(function(setres) {
+ cb.get(key, H.okCallback(function(getres) {
+ assert.equal(value, getres.value);
+ done();
+ }));
+ }));
+ });
+
+ it('should convert objects to json and back', function(done) {
+ var key = H.genKey("set-format");
+
+ H.setGet(key, {foo: "bar"}, function(doc) {
+ assert.equal("bar", doc.foo);
+ done();
+ });
+ });
+
+ it('should round-trip Unicode values', function(done) {
+ var key = H.genKey("set-unicode");
+ var value = [''];
+
+ H.setGet(key, value, function(doc){
+ assert.deepEqual(value, doc);
+ done();
+ });
+ });
+
+ it('should return raw string when using format option', function(done) {
+ var value = [1,2,3,4,5,6];
+ var key = H.genKey("set-raw");
+
+ cb.set(key, value, H.okCallback(function(){
+ cb.get(key, { format: 'raw' }, H.okCallback(function(result){
+ assert.equal(result.value, JSON.stringify(value));
+ done();
+ }));
+ }));
+ });
+
+ it('should properly handle setting raw strings', function(done) {
+ var value = "hello";
+ var key = H.genKey("set-json-strings");
+
+ cb.set(key, value, { format: 'json' }, H.okCallback(function(){
+ cb.get(key, H.okCallback(function(result){
+ assert.equal(result.value, value);
+ cb.get(key, { format: 'raw' }, H.okCallback(function(result){
+ assert.equal(result.value, '"hello"');
+ done();
+ }));
+ }));
+ }));
+ });
+
+ it('should handle setting unencodable values', function(done) {
+ var value = [1,2,3,4];
+ var key = H.genKey("set-utf8-unconvertible");
+
+ cb.set(key, value, { format: 'raw' }, function(err, meta){
+ assert(err);
+ done();
+ });
+ });
+
+ it('should round-trip raw Buffers', function(done) {
+ var buf = new Buffer([0, 1, 2]);
+ // \x00, \x01, \x02
+ var key = H.genKey("set-raw-format");
+
+ cb.set(key, buf, H.okCallback(function(){
+ cb.get(key, H.okCallback(function(meta){
+ var doc = meta.value;
+ assert(Buffer.isBuffer(doc));
+ assert.deepEqual(buf, doc);
+ assert.equal(meta.flags, couchbase.format.raw);
+ done();
+ }));
+ }));
+ });
+
+ it('should allow overriding of flags', function(done) {
+ var value = {val:"value"};
+ var key = H.genKey("set-flags-override");
+
+ // Note that we must specify the format as the flags no longer carries it
+ cb.set(key, value, {flags: 14}, H.okCallback(function(){
+ cb.get(key, {format: couchbase.format.json},
+ H.okCallback(function(result){
+ assert.deepEqual(result.value, value);
+ assert.equal(result.flags, 14);
+ done();
+ }));
+ }));
+ });
+
+});
View
72 test/getmulti-setmulti.js
@@ -0,0 +1,72 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#getMulti/setMulti', function() {
+
+ it('should work in basic cases', function(done) {
+ var calledTimes = 0;
+ var keys = [];
+ var values = {};
+
+ for (var i = 0; i < 10; i++) {
+ var k = H.genKey("multiget-" + i);
+ var v = {value: "value" + i};
+ keys.push(k);
+ values[k] = v;
+ }
+
+ function doGets() {
+ cb.get(keys[0], H.okCallback(function(doc){
+ assert.equal(doc.value, values[keys[0]].value);
+ }));
+
+ cb.getMulti(keys, null, H.okCallback(function(meta){
+ assert.equal(keys.length, Object.keys(meta).length);
+ Object.keys(meta).forEach(function(k){
+ assert(values[k] !== undefined);
+ assert(meta[k] !== undefined);
+ assert(meta[k].value === values[k].value);
+ });
+
+ done();
+ }));
+ }
+
+ var setHandler = H.okCallback(function(meta) {
+ calledTimes++;
+ if (calledTimes > 9) {
+ calledTimes = 0;
+ doGets();
+ }
+ });
+
+ // Finally, put it all together
+ cb.setMulti(values, { spooled: false }, setHandler);
+ });
+
+ it('should fail with an invalid key', function(done) {
+ var badKey = H.genKey("test-multiget-error");
+ var goodKey = H.genKey("test-multiget-spooled");
+ var goodValue = 'foo';
+
+ cb.set(goodKey, goodValue, function(err, meta) {
+ assert.ifError(err);
+ var keys = [badKey, goodKey];
+
+ cb.getMulti(keys, null, function(err, meta) {
+ assert.strictEqual(err.code, couchbase.errors.checkResults);
+ var goodResult = meta[goodKey];
+ assert.equal(goodResult.value, goodValue);
+
+ var badResult = meta[badKey];
+ assert.strictEqual(badResult.error.code, couchbase.errors.keyNotFound);
+
+ done();
+ });
+ });
+ });
+
+});
View
26 test/hashkeys.js
@@ -0,0 +1,26 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#hashkeys', function() {
+
+ // No way to accurately test hashkeys with single node cluster
+ it.skip('should work with basic inputs', function(done) {
+ var key = H.genKey("hashkey");
+ var hashkey = key + "_hashkey";
+
+ cb.set(key, "bar", { hashkey: hashkey }, H.okCallback(function(){
+ cb.get(key, { hashkey: hashkey }, H.okCallback(function(result){
+ assert.equal(result.value, "bar");
+ cb.get(key, function(err, meta){
+ assert.ok(err);
+ assert.equal(err.code, couchbase.errors.keyNotFound);
+ done();
+ });
+ }));
+ }));
+ });
+
+});
View
82 test/incr-decr.js
@@ -0,0 +1,82 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#incr/decr', function() {
+
+ it('should work with basic inputs', function(done) {
+ var key = H.genKey("incrdecr1");
+
+ cb.remove(key, function(err) {
+ cb.incr(key, {initial: 0}, H.okCallback(function(result){
+ assert.equal(result.value, 0, "Initial value should be 0");
+
+ cb.incr(key, H.okCallback(function(result){
+ assert.equal(result.value, 1, "Increment by one");
+
+ cb.decr(key, H.okCallback(function(result){
+ assert.equal(result.value, 0, "Decrement by 0");
+ done();
+ }));
+ }));
+ }));
+ });
+ });
+
+ it('should work with offsets', function(done) {
+ var key = H.genKey("incrdecr2");
+
+ cb.remove(key, function(){
+ cb.incr(key, {initial: 0, offset: 100}, H.okCallback(function(result){
+ assert.equal(0, result.value, "Offset ignored when doing default");
+ cb.incr(key, {offset: 20}, H.okCallback(function(result){
+ assert.equal(result.value, 20, "Increment by 20");
+ cb.decr(key, {offset: 15}, H.okCallback(function(result){
+ assert.equal(result.value, 5, "Decrement by 5");
+ done();
+ }));
+ }));
+ }));
+ });
+ });
+
+ it('should work with default values', function(done) {
+ var key = H.genKey("incrdecr3");
+
+ cb.remove(key, function(){
+ cb.incr(key, function(err, meta){
+ assert(err, "Error when incrementing key that does not exist");
+ cb.incr(key, {initial: 500, offset: 20}, H.okCallback(function(result){
+ assert.equal(result.value, 500, "Offset is ignored when default is used");
+ cb.decr(key, {initial: 999, offset: 10}, H.okCallback(function(result){
+ assert.equal(result.value, 490, "Initial is ignored when value exists");
+ done();
+ }));
+ }));
+ });
+ });
+ });
+
+ it('should work with expiries', function(done) {
+ this.timeout(3000);
+
+ var key = H.genKey("incrdecr4");
+
+ cb.remove(key, function(){
+ cb.incr(key, {offset:20, initial:0, expiry:1}, H.okCallback(function(result){
+ cb.incr(key, H.okCallback(function(result){
+ assert.equal(result.value, 1);
+ setTimeout(function(){
+ cb.get(key, function(err, meta){
+ assert(err, "Expiry with arithmetic");
+ done();
+ });
+ }, 2000);
+ }));
+ }));
+ });
+ });
+
+});
View
102 test/locks.js
@@ -0,0 +1,102 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#lock/unlock', function() {
+
+ it('should deny second lock', function(done) {
+ var testkey1 = H.genKey('lock1');
+
+ cb.set(testkey1, "{bar}", H.okCallback(function(meta) {
+ cb.lock(testkey1, {locktime: 1 }, H.okCallback(function(result) {
+ assert.equal("{bar}", result.value, "Callback called with wrong value!");
+ cb.lock(testkey1, {locktime: 1 }, function (err, meta) {
+ assert(err);
+ assert.equal(err.code, couchbase.errors.temporaryError);
+ done();
+ });
+ }));
+ }));
+ });
+
+ it('should unlock after expiry', function(done) {
+ this.timeout(3000);
+
+ var testkey2 = H.genKey("lock2");
+
+ cb.set(testkey2, "{baz}", H.okCallback(function(meta) {
+ cb.lock(testkey2, { locktime: 1}, H.okCallback(function(result) {
+ assert.equal("{baz}", result.value, "Callback called with wrong value!");
+ setTimeout(function () {
+ cb.lock(testkey2, {locktime: 1 }, function(err, meta) {
+ assert(!err, "Should be able to reset lock after expiry.");
+ done();
+ });
+ }, 2000);
+ }));
+ }));
+ });
+
+ it('should not affect normal gets', function(done) {
+ var testkey3 = H.genKey("lock3");
+
+ cb.set(testkey3, "{bat}", H.okCallback(function() {
+ cb.lock(testkey3, {locktime: 1}, H.okCallback(function(result) {
+ assert.equal("{bat}", result.value, "Callback called with wrong value!");
+ cb.get(testkey3, H.okCallback(function(result) {
+ done();
+ }));
+ }));
+ }));
+ });
+
+ it('should not affect normal sets', function(done) {
+ var testkey4 = H.genKey("lock4");
+
+ cb.set(testkey4, "{bam}", H.okCallback(function(result) {
+ cb.lock(testkey4, {locktime: 1}, H.okCallback(function(result) {
+ assert.equal("{bam}", result.value, "Callback called with wrong value!");
+ cb.set(testkey4, 'nothing', function (err, meta) {
+ assert(err);
+ done();
+ });
+ }));
+ }));
+ });
+
+ it('shouldnt block block sets with cas', function(done) {
+ var testkey5 = H.genKey("lock5");
+
+ cb.set(testkey5, "{bark}", H.okCallback(function(meta) {
+ cb.lock(testkey5, {locktime: 1}, H.okCallback(function(meta) {
+ assert.equal("{bark}", meta.value, "Callback called with wrong value!");
+ cb.set(testkey5, "nothing", meta, function (err, meta) {
+ assert(!err, "Failed to overwrite locked key by using cas.");
+ cb.get(testkey5, H.okCallback(function(result) {
+ assert.equal("nothing", result.value, "Callback called with wrong value!");
+ done();
+ }));
+ });
+ }));
+ }));
+ });
+
+ it('should properly unlock locked keys', function(done) {
+ var testkey6 = H.genKey("lock6");
+
+ cb.set(testkey6, "{boo}", H.okCallback(function(meta) {
+ cb.lock(testkey6, {locktime: 20}, H.okCallback(function(meta) {
+ assert.equal("{boo}", meta.value, "Callback called with wrong value!");
+ assert('cas' in meta);
+ cb.unlock(testkey6, meta, H.okCallback(function() {
+ cb.set(testkey6, 'hello', H.okCallback(function(){
+ done();
+ }));
+ }));
+ }));
+ }));
+ });
+
+});
View
2 test/mocha.opts
@@ -0,0 +1,2 @@
+--reporter spec
+--check-leaks
View
29 test/prepend-append.js
@@ -0,0 +1,29 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#prepend/append', function() {
+
+ it('should fail to prepend to missing key', function(done) {
+ var key = H.genKey("append");
+
+ cb.remove(key, function(){});
+
+ cb.append(key, 'willnotwork', function(err, meta){
+ assert.equal(err.code, couchbase.errors.notStored);
+ done();
+ });
+ });
+
+ it('should fail to append to missing key', function(done) {
+ var key = H.genKey("prepend");
+ cb.remove(key, function(){});
+ cb.prepend(key, 'willnotwork', function(err, meta){
+ assert.equal(err.code, couchbase.errors.notStored);
+ done();
+ });
+ });
+
+});
View
100 test/regressions.js
@@ -0,0 +1,100 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+describe('#regressions', function() {
+
+ it('JSCBC-4', function(done) {
+ var cb = H.newClient();
+
+ var key = H.genKey("jscbc-4");
+
+ // Remove the key to ensure that it is missing when we're trying
+ // to do the incr
+ cb.remove(key, function(){});
+
+ // Calling increment on a missing key will create the key with
+ // the default value (0)
+ cb.incr(key, {initial: 0 }, function(){});
+
+ // Retrieve the key and validate that the value is set to the
+ // default value
+ cb.get(key, H.okCallback(function(result){
+ assert.equal(result.value, "0");
+ }));
+
+ // Finally remove the key and terminate
+ cb.remove(key, function(){
+ done();
+ });
+ });
+
+ it('JSCBC-14', function(done) {
+ var cb = H.newClient();
+
+ cb.on("error", function (message) {
+ done(message);
+ });
+
+ var current = 0;
+ var max = 10;
+ for (var i=0; i < max; ++i){
+ var key = H.genKey('jscbc-14');
+
+ cb.set(key, "something", function(err, meta) {
+ if (err) {
+ process.abort();
+ }
+ assert(!err, "Failed to store value" + err);
+ ++current;
+ if (current == max) {
+ done();
+ }
+ });
+ }
+ });
+
+ // Skipped for now as mocha does not allow gracefully handling
+ // uncaught exceptions
+ it.skip('JSCBC-24', function(done) {
+ var cb = H.newClient();
+
+ var d = require('domain').create();
+ d.on('error', function(err) {
+ if (err.message!='expected-error') {
+ throw err;
+ }
+ done();
+ });
+
+ d.run(function() {
+ var testkey = "18-cb-error.js";
+ cb.get(testkey, function(err, meta) {
+ throw new Error('expected-error');
+ });
+ });
+ });
+
+ it('JSCBC-25', function(done) {
+ var cb = H.newClient();
+
+ var keys = [[1,2,3],[4,6,3]];
+ try {
+ cb.get(keys, function (err, doc, meta) {
+ });
+ assert(false, "Invalid keys should throw exceptions");
+ } catch (err) {
+ }
+
+ var keys = [1];
+ try {
+ cb.get(keys, function (err, doc, meta) {
+ });
+ assert(false, "Invalid keys should throw exceptions");
+ } catch (err) {
+ }
+
+ done();
+ });
+
+});
View
66 test/remove.js
@@ -0,0 +1,66 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#remove', function() {
+
+ it('should work with basic inputs', function(done) {
+ var key = H.genKey();
+
+ cb.set(key, "a value", H.okCallback(function(meta){
+ cb.get(key, H.okCallback(function(meta){
+ cb.remove(key, H.okCallback(function(meta) {
+ cb.get(key, function(err, meta) {
+ assert.equal(err.code, couchbase.errors.keyNotFound);
+ done();
+ });
+ }));
+ }));
+ }));
+ });
+
+ it('should work with cas values', function(done) {
+ var key = H.genKey();
+ var value = "Value";
+
+ cb.set(key, value, H.okCallback(function(meta1){
+ cb.set(key, "new value", H.okCallback(function(meta2){
+ cb.remove(key, { cas: meta1.cas }, function(err, meta){
+ assert(err, "Remove fails with bad CAS");
+ cb.remove(key, {cas: meta2.cas}, H.okCallback(function(meta){
+ done();
+ }));
+ });
+ }));
+ }));
+ });
+
+ it('should fail for non-existent keys', function(done) {
+ var key = H.genKey();
+ var value = "some value";
+
+ cb.set(key, value, H.okCallback(function(meta) {
+ cb.remove(key, H.okCallback(function(meta){
+ cb.remove(key, function(err, meta) {
+ assert(err, "Can't remove key twice");
+ done();
+ });
+ }));
+ }));
+ });
+
+ it('should work with multiple values', function(done) {
+ var kv = H.genMultiKeys(10, "removeMulti");
+
+ cb.setMulti(kv, {spooled: true}, H.okCallback(function(results){
+ cb.getMulti(Object.keys(kv), {spooled: true}, H.okCallback(function(results){
+ cb.removeMulti(results, {spooled: true}, H.okCallback(function(results){
+ done();
+ }));
+ }));
+ }));
+ });
+
+});
View
34 test/replace.js
@@ -0,0 +1,34 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#replace', function() {
+
+ it('should work with basic inputs', function(done) {
+ var testkey = H.genKey("replace");
+
+ cb.remove(testkey, function(){
+ // try to replace a missing key, should fail
+ cb.replace(testkey, "bar", function(err, meta) {
+ assert(err, "Can't replace object that is already removed");
+
+ cb.set(testkey, "bar", function (err, meta) {
+ assert(!err, "Failed to store object");
+
+ cb.replace(testkey, "bazz", function (err, meta) {
+ assert(!err, "Failed to replace object");
+
+ cb.get(testkey, function (err, doc) {
+ assert(!err, "Failed to get object");
+ assert.equal("bazz", doc.value, "Replace didn't work");
+ done();
+ });
+ });
+ });
+ });
+ });
+ });
+
+});
View
45 test/shutdown.js
@@ -0,0 +1,45 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+// Generates a new client for each test as the tests
+// meddle with the state of the connection.
+
+describe('#shutdown', function() {
+
+ it('should work', function(done) {
+ var cb = H.newClient();
+ var key = H.genKey("shutdown-1");
+
+ H.setGet(key, "foo", function(doc){
+ cb.shutdown();
+ done();
+ });
+ });
+
+ it('should not fail when calling shutdown multiple times', function(done) {
+ var cb = H.newClient();
+
+ cb.set("key", "value", H.okCallback(function(meta){
+ cb.shutdown();
+ cb.get("key", function(err, meta){});
+ cb.shutdown();
+ done();
+ }));
+ });
+
+ it('should fail operations after shutdown', function(done) {
+ var cb = H.newClient();
+
+ cb.set("key", "value", function(err, meta) {
+ cb.shutdown();
+ setTimeout(function() {
+ cb.get("key", function(err, meta){
+ assert(err, "Operation fails after shutdown");
+ done();
+ });
+ }, 10);
+ });
+ });
+
+});
View
25 test/strerror.js
@@ -0,0 +1,25 @@
+var assert = require('assert');
+var H = require('../test_harness.js');
+var couchbase = require('../lib/couchbase.js');
+
+var cb = H.newClient();
+
+describe('#strerror', function() {
+
+ it('should work for all error types', function(done) {
+ cb.strError(1000); // don't crash on bad values
+ assert.equal(cb.strError(0), 'Success');
+
+ // Should still work with shutdown connection
+ cb.shutdown();
+
+ for (var errKey in couchbase.errors) {
+ var errValue = couchbase.errors[errKey];
+ assert.equal(typeof errValue, "number", "Bad constant for : " + errKey);
+ assert(errValue >= 0);
+ }
+
+ done();
+ });
+
+});
View
72 test_harness.js
@@ -0,0 +1,72 @@
+var couchbase = require('./lib/couchbase.js'),
+ fs = require('fs'),
+ util = require('util');
+var assert = require('assert');
+
+var config;
+var configFilename = 'config.json';
+
+if (fs.existsSync(configFilename)) {
+ config = JSON.parse(fs.readFileSync(configFilename));
+} else {
+ config = {
+ host : "localhost:8091",
+ bucket : "default",
+ operationTimeout : 20000,
+ connectionTimeout : 20000
+ };
+}
+
+function Harness(callback) {
+ this.client = new couchbase.Connection(config, callback);
+ this.keySerial = 0;
+}
+
+Harness.prototype.newClient = function(callback) {
+ return new couchbase.Connection(config, callback);
+};
+
+Harness.prototype.genKey = function(prefix) {
+ if (!prefix) {
+ prefix = "generic";
+ }
+
+ var ret = "JSCBC-test-" + prefix + this.keySerial;
+ this.keySerial++;
+ return ret;
+};
+
+Harness.prototype.genMultiKeys = function(count, prefix) {
+ var ret = {};
+ for (var i = 0; i < count; i++) {
+ var key = this.genKey(prefix);
+ ret[key] = { value: "value_for_" + key };
+ }
+ return ret;
+};
+
+Harness.prototype.okCallback = function(target) {
+ // Get the stack
+ var stack = new Error().stack;
+
+ return function(err, meta) {
+ if (err) {
+ console.dir(arguments);
+ console.log("Got error (created @):" + stack);
+ assert(!err, "Got unrecognized error: " + util.inspect(err));
+ }
+ assert(typeof meta === "object", "Meta is missing");
+ target(meta);
+ };
+};
+
+Harness.prototype.setGet = function(key, value, callback) {
+ var o = this;
+ o.client.set(key, value, o.okCallback(function(result) {
+ o.client.get(key, o.okCallback(function(result) {
+ callback(result.value);
+ }));
+ }));
+};
+
+module.exports = new Harness();
View
48 tests/00-args.t.js
@@ -1,48 +0,0 @@
-var setup = require('./setup'),
- assert = require('assert');
-
-
-process.on('uncaughtException', function(err) {
- console.log("Got an error!!!!");
-});
-process.on('error', function(err) {
- console.log("ffs..");
-});
-
-setup.plan(7)
-
-setup(function(err, cb) {
- assert(!err, "setup failure");
-
- cb.on("error", function (message) {
- console.log("ERROR: [" + message + "]");
- process.exit(1);
- });
-
- // things that should work
- assert.doesNotThrow(function() {
- cb.get("has callback", setup.end)
- });
-
- assert.doesNotThrow(function() {
- cb.set("has callback", "value", null, setup.end)
- });
-
- assert.doesNotThrow(function() {
- // falsy values for CAS and exp
- [null, undefined, 0, false].forEach(function(fv) {
- cb.set("has falsy meta", "value", {cas : fv, exp : fv}, setup.end)
- })
- });
-
- // things that should error
- assert.throws(function() {
- cb.get("needs callback")
- });
-
- assert.throws(function() {
- cb.set("needs callback")
- });
-
- setup.end();
-})
View
26 tests/01-set-big.js
@@ -1,26 +0,0 @@
-var setup = require('./setup');
-var assert = require('assert');
-var util = require("util");
-
-setup.plan(1);
-
-setup(function(err, cb) {
- assert(!err, "setup failure");
-
- cb.on("error", function (message) {
- console.log("ERROR: [" + message + "]");
- process.exit(1);
- });
-
- // test cas updates
- var testkey = "01-set-big.js"
- var object = "";
- for (var ii = 0; ii < 8192; ++ii) {
- object += "012345678\n";
- }
-
- cb.set(testkey, object, function (err, firstmeta) {
- assert(!err, "Failed to store object");
- setup.end();
- });
-})
View
42 tests/01-set.js
@@ -1,42 +0,0 @@
-var assert = require('assert');
-var harness = require('./harness.js');
-harness.plan(2);
-
-var t1 = function() {
- var H = new harness.Harness();
- var cb = H.client;
-
- var key = H.genKey("set1");
- cb.set(key, "bar", H.okCallback(function(firstmeta){
- // nothing broke
- cb.set(key, "baz", H.okCallback(function(secondmeta){
- assert.notDeepEqual(firstmeta.cas, secondmeta.cas, "CAS should change");
- cb.set(key, "bam", firstmeta, function(err, meta){
- assert(err, "Key should fail with stale CAS");
- cb.get(key, H.docCallback(function(doc){
- assert.equal(doc, "baz");
- cb.set(key, "grr", secondmeta, H.okCallback(function(meta){
- cb.get(key, H.docCallback(function(doc){
- assert.equal("grr", doc);
- harness.end(0);
- }))
- }))
- }))
- })
- }))
- }))
-}();
-
-var t2 = function() {
- var H = new harness.Harness();
- var cb = H.client;
- var key = H.genKey("set2");
- cb.set(key, JSON.stringify({foo: "bar"}), H.okCallback(function(){
- cb.set(key, JSON.stringify({foo: "baz"}), H.okCallback(function(){
- cb.get(key, H.docCallback(function(doc){
- assert.equal(JSON.stringify({foo: "baz"}), doc);
- harness.end(0);
- }))
- }));
- }));
-}();
View
112 tests/02-format.js
@@ -1,112 +0,0 @@
-var harness = require('./harness.js');
-var assert = require('assert');
-var couchbase = require('../lib/couchbase.js');
-
-harness.plan(10);
-var H = new harness.Harness();
-
-var t1 = function() {
- var key = H.genKey("test2-02get");
- H.setGet(key, {foo: "bar"}, function(doc) {
- assert.equal("bar", doc.foo,"JSON values should be converted back to objects");
- harness.end(0);
- });
-}();
-
-var t2 = function() {
- var key = H.genKey("test3-02get");
- var value = [1, "2", true, null, false, {}, []];
- H.setGet(key, value, function(doc){
- assert.deepEqual(value, doc, "JSON objects should match");
- harness.end(0);
- });
-}();
-
-var t3 = function() {
- var key = H.genKey("test4-02get");
- var value = [''];
- H.setGet(key, value, function(doc){
- assert.deepEqual(value, doc, "JSON with Unicode characters should round trip");
- harness.end(0);
- });
-}();
-
-
-// 2 tests here
-var t4 = function() {
- var value = [1,2,3,4,5,6];
- var key = H.genKey("test_raw");
- var cb = H.client;
-
- cb.set(key, value, H.okCallback(function(){
- cb.get(key, { format: 'raw' }, H.docCallback(function(doc){
- assert.equal(doc, JSON.stringify(value));
- harness.end(0);
- }));
-
- cb.get(key, { format: 'auto' }, H.docCallback(function(doc){
- assert.deepEqual(doc, value);
- harness.end(0);
- }));
- }))
-}();
-
-
-// 2 more here
-var t5 = function() {
- var value = "hello";
- var key = H.genKey("test-json-strings");
- var cb = H.client;
- cb.set(key, value, { format: 'json' }, H.okCallback(function(){
- cb.get(key, H.docCallback(function(doc){
- assert.equal(doc, value);
- harness.end(0);
- }));
- cb.get(key, { format: 'raw' }, H.docCallback(function(doc){
- assert.equal(doc, '"hello"');
- harness.end(0);
- }))
- }))
-}();
-
-var testUnencodable = function() {
- var value = [1,2,3,4];
- var key = H.genKey("test-utf8-inconvertible");
- var cb = H.client;
- cb.set(key, value, { format: 'raw' }, function(err, meta){
- assert(err);
- harness.end(0);
- })
-}();
-
-var testRawFormat = function() {
- var cb = H.client;
- var buf = new Buffer([0, 1, 2]);
- // \x00, \x01, \x02
- var key = H.genKey("test-raw-format");
-
- cb.set(key, buf, H.okCallback(function(){
- cb.get(key, H.okCallback(function(meta){
- var doc = meta.value;
- assert(Buffer.isBuffer(doc));
- assert.deepEqual(buf, doc);
- assert.equal(meta.flags, couchbase.format.raw);
- harness.end(0);
- }))
- }))
-}();
-
-var testFlagOverride = function() {
- var value = {val:"value"};
- var cb = H.client;
- var key = H.genKey("test-flags-override");
-
- // Note that we must specify the format as the flags no longer is carrying it
- cb.set(key, value, {flags: 14}, H.okCallback(function(){
- cb.get(key, {format: couchbase.format.json}, H.okCallback(function(result){
- assert.deepEqual(result.value, value);
- assert.equal(result.flags, 14);
- harness.end(0);
- }));
- }));
-}();
View
39 tests/02-get.js
@@ -1,39 +0,0 @@
-var harness = require('./harness.js'),
- assert = require('assert');
-
-harness.plan(2); // exit at fourth call to setup.end()
-
-var H = harness.create();
-var c = H.client;
-
-var t1 = function() {
- var key = H.genKey("test1-02get");
- var value = "{bar}";
-
- c.set(key, value, H.okCallback(function(meta){
- // Ensure we can set a simple key.
- c.get(key, H.okCallback(function(meta){
- assert.equal(meta.value, value);
-
- // Change the value and set again, with CAS
- var value2 = "{bam}";
- c.set(key, value2, H.okCallback(function(meta){
- c.get(key, H.okCallback(function(meta2) {
- assert.deepEqual(meta2.cas, meta.cas);
- assert.equal(meta2.value, value2);
- harness.end();
- }))
- }))
- }))
- }))
-}();
-
-
-var t5 = function() {
- var key = H.genKey("test5-02get");
- var value = '';
- H.setGet(key, value, function(doc){
- assert.equal(doc, value, "Unicode");
- harness.end(0);
- })
-}();
View
76 tests/03-multiget.js
@@ -1,76 +0,0 @@
-var harness = require('./harness.js'),
- assert = require('assert'),
- couchbase = require('../lib/couchbase.js');
-
-var H = new harness.Harness();
-var c = H.client;
-
-harness.plan(2);
-
-
-var t1 = function() {
- var calledTimes = 0;
- var keys = [];
- var values = {};
-
- for (var i = 0; i < 10; i++) {
- var k = H.genKey("test-multiget-" + i);
- var v = {value: "value" + i};
- keys.push(k);
- values[k] = v;
- }
-
- function doGets() {
- c.get(keys[0], H.docCallback(function(doc){
- assert.equal(doc, values[keys[0]].value);
- }));
-
- c.getMulti(keys, null, H.okCallback(function(meta){
- assert.equal(keys.length, Object.keys(meta).length);
- Object.keys(meta).forEach(function(k){
- assert(values[k] !== undefined);
- assert(meta[k] !== undefined);
- assert(meta[k].value === values[k].value);
- });
- harness.end(0);
- }));
- }
-
- var setHandler = H.okCallback(function(meta) {
- calledTimes++;
- if (calledTimes > 9) {
- calledTimes = 0;
- doGets();
- }
- });
-
- // Finally, put it all together
- c.setMulti(values, { spooled: false }, setHandler);
-
-}();
-
-var testNoSuchKeyErrorSpooled = function() {
- var H = new harness.Harness();
- var c = H.client;
-
- var badKey = H.genKey("test-multiget-error");
- var goodKey = H.genKey("test-multiget-spooled");
- var goodValue = 'foo';
-
- c.set(goodKey, goodValue, function(err, meta) {
- assert.ifError(err);
- var keys = [badKey, goodKey];
-
- c.getMulti(keys, null, function(err, meta) {
- assert.strictEqual(err.code, couchbase.errors.checkResults);
- var goodResult = meta[goodKey];
- assert.equal(goodResult.value, goodValue);
-
- var badResult = meta[badKey];
- assert.strictEqual(badResult.error.code, couchbase.errors.keyNotFound);
-
- harness.end(0);
- });
- });
-}();
-
View
62 tests/04-remove.js
@@ -1,62 +0,0 @@
-var harness = require('./harness.js');
-var assert = require('assert');
-var couchnode = require('../lib/couchbase.js');
-
-var H = new harness.Harness();
-var c = H.client;
-
-harness.plan(4);
-
-var simpleRemove = function () {
- var key = H.genKey();
- c.set(key, "a value", H.okCallback(function(meta){
- c.get(key, H.okCallback(function(meta){
- c.remove(key, H.okCallback(function(meta) {
- c.get(key, function(err, meta) {
- assert.equal(err.code, couchnode.errors.keyNotFound);
- harness.end(0);
- });
- }));
- }))
- }))
-}();
-
-var removeWithCas = function() {
- var key = H.genKey();
- var value = "Value";
- c.set(key, value, H.okCallback(function(meta1){
- c.set(key, "new value", H.okCallback(function(meta2){
- c.remove(key, { cas: meta1.cas }, function(err, meta){
- assert(err, "Remove fails with bad CAS");
- c.remove(key, {cas: meta2.cas}, H.okCallback(function(meta){
- harness.end(0);
- }));
- })
- }))
- }))
-}();
-
-var removeNonExistent = function() {
- var key = H.genKey();
- var value = "some value";
- c.set(key, value, H.okCallback(function(meta) {
- c.remove(key, H.okCallback(function(meta){
- c.remove(key, function(err, meta) {
- assert(err, "Can't remove key twice");
- harness.end(0);
- });
- }));
- }));
-}();
-
-var removeMulti = function() {
- var kv = H.genMultiKeys(10, "removeMulti");
-
- c.setMulti(kv, {spooled: true}, H.okCallback(function(results){
- c.getMulti(Object.keys(kv), {spooled: true}, H.okCallback(function(results){
- c.removeMulti(results, {spooled: true}, H.okCallback(function(results){
- harness.end(0);
- }));
- }));
- }));
-}();
View
30 tests/05-replace.js
@@ -1,30 +0,0 @@
-var harness = require('./harness.js');
-var assert = require('assert');
-
-var H = new harness.Harness();
-var cb = H.client;
-harness.plan(1);
-
-var t1 = function() {
- var testkey = H.genKey("replace");
- cb.remove(testkey, function(){
- // try to replace a missing key, should fail
- cb.replace(testkey, "bar", function(err, meta) {
- assert(err, "Can't replace object that is already removed");
-
- cb.set(testkey, "bar", function (err, meta) {
- assert(!err, "Failed to store object");
-
- cb.replace(testkey, "bazz", function (err, meta) {
- assert(!err, "Failed to replace object");
-
- cb.get(testkey, function (err, doc) {
- assert(!err, "Failed to get object");
- assert.equal("bazz", doc.value, "Replace didn't work")
- harness.end(0);
- })
- });
- });
- });
- });
-}();
View
19 tests/06-add.js
@@ -1,19 +0,0 @@
-var harness = require('./harness.js'),
- assert = require('assert');
-
-var H = new harness.Harness();
-var cb = H.client;
-
-harness.plan(1);
-var t1 = function() {
- var testkey = H.genKey("add");
- cb.remove(testkey, function(){
- cb.add(testkey, "bar", H.okCallback(function() {
- // try to add existing key, should fail
- cb.add(testkey, "baz", function (err, meta) {
- assert(err, "Can't add object at empty key");
- harness.end(0);
- });
- }));
- });
-}();
View
39 tests/07-shutdown.js
@@ -1,39 +0,0 @@
-var harness = require('./harness.js');
-var assert = require('assert');
-harness.plan(3);
-
-var testShutdown = function() {
- var H = new harness.Harness();
- var cb = H.client;
- var key = H.genKey("shutdown-1");
- H.setGet(key, "foo", function(doc){
- cb.shutdown();
- harness.end(0);
- })
-}();
-
-// Test shutdown twice..
-var testIssue37 = function() {
- var H = new harness.Harness();
- var cb = H.client;
- cb.set("key", "value", H.okCallback(function(meta){
- cb.shutdown();
- cb.get("key", function(err, meta){});
- cb.shutdown();
- harness.end(0);
- }));
-}();
-
-var testIssue38 = function() {
- var H = new harness.Harness();
- var cb = H.client;
- cb.set("key", "value", function(err, meta) {
- cb.shutdown();
- setTimeout(function() {
- cb.get("key", function(err, meta){
- assert(err, "Operation fails after shutdown");
- harness.end(0);
- });
- }, 10)
- });
-}();
View
38 tests/08-designdoc.js
@@ -1,38 +0,0 @@
-var harness = require('./harness.js');
-var util = require('util');
-var assert = require('assert');
-
-harness.plan(1);
-
-
-var ddoc = {
- "views": {
- "test-view": {
- "map": "function(doc,meta){emit(meta.id)}"
- }
- }
-};
-
-var t1 = function() {
- var H = new harness.Harness();
- var cb = H.client;
- var docname = "dev_ddoc-test";
-
- // We don't know the state of the server so just
- // do an unconditional delete
- cb.removeDesignDoc(docname, function() {
- // Ok, the design document should be done
- cb.setDesignDoc(docname, ddoc, function(err, data) {
- var util=require("util");
- assert(!err, "error creating design document");
- cb.getDesignDoc(docname, function(err, data) {
- assert(!err, "error getting design document");
- cb.removeDesignDoc(docname, function(err, data) {
- assert(!err, "Failed deleting design document");
- cb.shutdown();
- harness.end(0);
- });
- });
- });
- });
-}();
View
113 tests/08-page.js
@@ -1,113 +0,0 @@
-var util = require("util");
-var assert = require("assert");
-var async = require("async");
-var u = require("underscore");
-var harness = require('./harness.js');
-
-var H = new harness.Harness();
-var cb = H.client;
-
-harness.plan(1);
-
-var t1 = function() {
- var docname = "querytest";
- var ddoc1 = {
- "views": {
- "simple": {
- "map": "function(doc,meta){doc.type==10 ? emit( Number( meta.id.slice(6, meta.id.length))) : null }"
- },
- "compound": {
- "map": "function(doc,meta){doc.type==10 ? emit([doc.name, Number(meta.id.slice(6, meta.id.length))]) : null}",
- "reduce" : "_count"
- }
- }
- };
-
- // Popolate sample set of documents. documents are of the format
- // id : { "name" : <"alpha" | "beta" | "kappa" | "pi" | "epsilon"> }
- function TestPopulate(callback) {
- var values = ["alpha", "beta", "kappa", "pi", "epsilon"]
- var valueof = function(i) {
- return "{ \"type\": 10, \"name\": \""+values[i%values.length]+ "\" }"
- }
- var multikv = {}
- for (var i=0; i< 10000; i++) {
- multikv["query-"+i.toString()] = { value: valueof(i) };
- }
- cb.setMulti(multikv, {spooled:true}, function(){
- callback(null, 1);
- });
- }
-
- // Populate design-document with two views by name "simple" and "compound"
- function TestDD(callback) {
- cb.setDesignDoc(docname, ddoc1, function() {
- callback(null, 2)
- })
- }
-
- function TestPaginate(callback) {
- var pages = [];
- var q = cb.view(docname, "simple", {
- limit: 140,
- stale: false
- });
- q.firstPage(function(err, results, p) {
- assert(!err, "TestPaginate firstpage() failed")
- nextpages(results, p);
- });
-
- function nextpages(results, p) {
- pages.push( results );
- if (p.hasNext()) {
- p.next( function(err, results) {
- assert(!err, "TestPaginate next() failed")
- nextpages(results, p)
- });
- } else {
- assert( pages.length === 72, "TestPaginate failed" );
- var last = pages.pop();
- assert( last.length === 60, "TestPaginate failed" );
-
- p.prev( function(err, results) {
- assert(!err, "TestPaginate prev() failed");
- prevpages(results, p);
- });
- }
- };
-
- function prevpages(results, p) {
- var page = pages.pop();
- if (results.length > 0 ) {
- assert( u.isEqual(results, page) );
- p.prev( function(err, results) {
- assert(!err, "TestPaginate prev() failed")
- prevpages(results, p)
- });
- } else {
- p.next( function(err, results) {
- assert(!err, "TestPaginate next() failed")
- assert(results.length===140, "TestPaginate 1 next() failed")
- var l = results.pop();
- assert(l.id==="query-279", "TestPaginate 1 next() failed")
- callback(null, 4);
- });
- }
- };
- };
-
- function Shutdown(callback) {
- cb.shutdown();
- harness.end(0);
- callback(null, 5);
- }
-
- async.series([
- TestPopulate,
- TestDD,
- TestPaginate,
- Shutdown
- ])
-}()
-
-
View
273 tests/08-query.js
@@ -1,273 +0,0 @@
-var util = require("util");
-var assert = require("assert");
-var async = require("async");
-var u = require("underscore");
-var harness = require('./harness.js');
-
-var H = new harness.Harness();
-var cb = H.client;
-
-harness.plan(1);
-
-var t1 = function() {
- var docname = "querytest";
- var ddoc1 = {
- "views": {
- "simple": {
- "map": "function(doc,meta){doc.type==10 ? emit( Number( meta.id.slice(6, meta.id.length))) : null }"
- },
- "compound": {
- "map": "function(doc,meta){doc.type==10 ? emit([doc.name, Number(meta.id.slice(6, meta.id.length))]) : null}",
- "reduce" : "_count"
- }
- }
- };
-
- // Popolate sample set of documents. documents are of the format
- // id : { "name" : <"alpha" | "beta" | "kappa" | "pi" | "epsilon"> }
- function TestPopulate(callback) {
- var values = ["alpha", "beta", "kappa", "pi", "epsilon"]
- var valueof = function(i) {
- return "{ \"type\": 10, \"name\": \""+values[i%values.length]+ "\" }"
- }
- var multikv = {}
- for (var i=0; i< 10000; i++) {
- multikv["query-"+i.toString()] = { value: valueof(i) };
- }
- cb.setMulti(multikv, {spooled:true}, function(){
- callback(null, 1);
- });
- }
-
- // Populate design-document with two views by name "simple" and "compound"
- function TestDD(callback) {
- cb.setDesignDoc(docname, ddoc1, function() {
- callback(null, 2)
- })
- }
-
- // Test `startkey`, `endkey` and `inclusive_end`
- function TestRange(callback) {
- var q = cb.view(docname, "simple", {
- startkey : 1,
- endkey : 5,
- stale: false,
- inclusive_end: false,
- });
- q.query(function(err, results) {
- var sum = u.reduce(
- u.pluck(results, 'key'),
- function(acc, n){ return acc + n; }, 0
- );
- assert(!err, "TestRange query failed")
- assert(sum===10, "TestRange without inclusive_end does not add up");
-
- // Along with it use `limit` parameter
- q.query({limit: 3}, function(err, results) {
- assert(!err, "TestRange query with limit failed")
- assert(results[0].key === 1, "TestRange first key is not 1");
- assert(results.length === 3, "TestRange lenght is not 3");
-
- // Along with it use `skip` parameter
- q.query({skip: 2}, function(err, results) {
- assert(!err, "TestRange query with skip failed")
- assert(results[0].key === 3, "TestRange first key is not 3");
- assert(results.length === 2, "TestRange lenght is not 2");
- callback(null, 3);
- });
- });
- })
- }
-
- // Range query in descending order.
- function TestRangeD(callback) {
- var q = cb.view(docname, "simple", {
- endkey : 3,
- startkey : 10,
- stale: false,
- descending