Repository: basho/riak-nodejs-client
Pull request #30 (2015-03-31 00:13:01)

Jira/bar/clients 292
All commands have integration tests! 


Patch:
diff --git a/lib/commands/crdt/fetchcounter.js b/lib/commands/crdt/fetchcounter.js
index 0acf59b..65a3747 100644
--- a/lib/commands/crdt/fetchcounter.js
+++ b/lib/commands/crdt/fetchcounter.js
@@ -91,14 +91,14 @@ FetchCounter.prototype.constructPbRequest = function() {
 
 FetchCounter.prototype.onSuccess = function(dtFetchResp) {
   
+    var value = null;
     if (dtFetchResp.getValue()) {
         // sint64 is weird. You either get the zigzag encoding, or
         // you can get the actual number via the bytebuffer.
-        var value = dtFetchResp.value.counter_value.toNumber();
-        this._callback(null, value);
-    } else {
-        this._callback(null, null);
-    }
+        value = dtFetchResp.value.counter_value.toNumber();
+        
+    } 
+    this._callback(null, { counterValue: value });
     
     return true;
 };
diff --git a/lib/commands/crdt/fetchmap.js b/lib/commands/crdt/fetchmap.js
index 8be6cf3..f3987c8 100644
--- a/lib/commands/crdt/fetchmap.js
+++ b/lib/commands/crdt/fetchmap.js
@@ -91,7 +91,7 @@ FetchMap.prototype.constructPbRequest = function() {
 };
 
 FetchMap.prototype.onSuccess = function(dtFetchResp) {
-    var response = null;
+    var response;
     // on "not found" dtFetchResp.value will be null
     if (dtFetchResp.getValue()) {
         if (dtFetchResp.getType() !== DtFetchResp.DataType.MAP) {
@@ -100,6 +100,8 @@ FetchMap.prototype.onSuccess = function(dtFetchResp) {
             response = { context: dtFetchResp.getContext().toBuffer(),
                 map: FetchMap.parsePbResponse(dtFetchResp.value.map_value, this.options.setsAsBuffers) };
         }
+    } else {
+        response = { context: null, map: null };
     }
     this._callback(null, response);
     return true;
diff --git a/lib/commands/crdt/fetchset.js b/lib/commands/crdt/fetchset.js
index b7126fc..484b9c4 100644
--- a/lib/commands/crdt/fetchset.js
+++ b/lib/commands/crdt/fetchset.js
@@ -93,12 +93,13 @@ FetchSet.prototype.constructPbRequest = function() {
 
 FetchSet.prototype.onSuccess = function(dtFetchResp) {
     
-    var response = null;
+    var response;
     // on a "not found" the value is null
-    if (dtFetchResp.getValue())
-    {
+    var valuesToReturn = null;
+    var context = null;
+    if (dtFetchResp.getValue()) {
         var valueBuffers = dtFetchResp.getValue().getSetValue();
-        var valuesToReturn = new Array(valueBuffers.length);
+        valuesToReturn = new Array(valueBuffers.length);
         var valueCount = valueBuffers.length;
         for (var i = 0; i < valueCount; i++) {
             if (this.options.setsAsBuffers) {
@@ -107,12 +108,15 @@ FetchSet.prototype.onSuccess = function(dtFetchResp) {
                 valuesToReturn[i] = valueBuffers[i].toString('utf8');
             }
         }
-        response = {
-            // treat context as opaque, don't string-ify
-            context: dtFetchResp.getContext() ? dtFetchResp.getContext().toBuffer() : null,
-            values: valuesToReturn
-        };
+        
+        context = dtFetchResp.getContext() ? dtFetchResp.getContext().toBuffer() : null;
+        
+    } else {
+        valuesToReturn = [];
     }
+    
+    response = { context: context, values: valuesToReturn };
+    
     this._callback(null, response);
     return true;
 };
diff --git a/lib/commands/crdt/updatecounter.js b/lib/commands/crdt/updatecounter.js
index 80da2f7..4f246dc 100644
--- a/lib/commands/crdt/updatecounter.js
+++ b/lib/commands/crdt/updatecounter.js
@@ -49,7 +49,7 @@ var CounterOp = require('../../protobuf/riakprotobuf').getProtoFor('CounterOp');
  * @param {Number} [options.w] the W value to use.
  * @param {Number} [options.dw] the DW value to use.
  * @param {Number} [options.pw] the PW value to use.
- * @param {Boolean} [options.returnBody] return the counter.
+ * @param {Boolean} [options.returnBody=true] return the counter.
  * @param {Number} [options.timeout] set a timeout for this command.
  * @param {Function} callback the callback to be executed when the operation completes.
  * @param {String} callback.err An error message
diff --git a/lib/commands/crdt/updatemap.js b/lib/commands/crdt/updatemap.js
index d2f0908..5058bfa 100644
--- a/lib/commands/crdt/updatemap.js
+++ b/lib/commands/crdt/updatemap.js
@@ -66,7 +66,7 @@ var FetchMap = require('./fetchmap');
  * @param {Number} [options.w] the W value to use.
  * @param {Number} [options.dw] the DW value to use.
  * @param {Number} [options.pw] the PW value to use.
- * @param {Boolean} [options.returnBody=false] return the map.
+ * @param {Boolean} [options.returnBody=true] return the map.
  * @param {Boolean} [options.setsAsBuffers=false] return sets as arrays of Buffers rather than strings.
  * @param {Number} [options.timeout] set a timeout for this command.
  * @param {Function} callback the callback to be executed when the operation completes.
@@ -196,13 +196,13 @@ UpdateMap.prototype._populate = function(mapOp, pbMapOp) {
         update.setCounterOp(counterOp);
         pbMapOp.updates.push(update);
     }
-    var j,v;
+    var j, v, setOp;
     for (i = 0; i < mapOp.sets.adds.length; i++) {
         update = new MapUpdate();
         field = new MapField();
         field.setName(new Buffer(mapOp.sets.adds[i].key));
         field.setType(MapField.MapFieldType.SET);
-        var setOp = new SetOp();
+        setOp = new SetOp();
         for (j = 0; j < mapOp.sets.adds[i].add.length; j++) {
             v = mapOp.sets.adds[i].add[j];
             if (typeof v === 'string') {
@@ -219,7 +219,7 @@ UpdateMap.prototype._populate = function(mapOp, pbMapOp) {
         field = new MapField();
         field.setName(new Buffer(mapOp.sets.removes[i].key));
         field.setType(MapField.MapFieldType.SET);
-        var setOp = new SetOp();
+        setOp = new SetOp();
         for (j = 0; j < mapOp.sets.removes[i].remove.length; j++) {
             v = mapOp.sets.removes[i].remove[j];
             if (typeof v === 'string') {
@@ -275,7 +275,7 @@ var schema = Joi.object().keys({
     w: Joi.number().default(null).optional(),
     dw: Joi.number().default(null).optional(),
     pw: Joi.number().default(null).optional(),
-    returnBody: Joi.boolean().default(false).optional(),
+    returnBody: Joi.boolean().default(true).optional(),
     setsAsBuffers: Joi.boolean().default(false).optional(),
     timeout: Joi.number().default(null).optional(),
     context: Joi.binary().default(null).optional()    
@@ -692,4 +692,4 @@ MapOperation.prototype = {
 
 module.exports = UpdateMap;
 module.exports.MapOperation = MapOperation;
-module.exports.Builder = Builder;
\ No newline at end of file
+module.exports.Builder = Builder;
diff --git a/lib/commands/crdt/updateset.js b/lib/commands/crdt/updateset.js
index a6d167b..d8d3b0b 100644
--- a/lib/commands/crdt/updateset.js
+++ b/lib/commands/crdt/updateset.js
@@ -55,7 +55,7 @@ var SetOp = Rpb.getProtoFor('SetOp');
  * @param {Number} [options.w] the W value to use.
  * @param {Number} [options.dw] the DW value to use.
  * @param {Number} [options.pw] the PW value to use.
- * @param {Boolean} [options.returnBody] return the set.
+ * @param {Boolean} [options.returnBody=true] return the set.
  * @param {Number} [options.timeout] set a timeout for this command.
  * @param {Function} callback the callback to be executed when the operation completes.
  * @param {String} callback.err An error message
diff --git a/lib/commands/kv/fetchvalue.js b/lib/commands/kv/fetchvalue.js
index d6ab7cb..8f57450 100644
--- a/lib/commands/kv/fetchvalue.js
+++ b/lib/commands/kv/fetchvalue.js
@@ -16,7 +16,6 @@
 
 
 var RiakObject = require('./riakobject');
-var KvResponseBase = require('./kvresponsebase');
 var CommandBase = require('../commandbase');
 var inherits = require('util').inherits;
 var Joi = require('joi');
@@ -90,31 +89,15 @@ FetchValue.prototype.constructPbRequest = function() {
     protobuf.setType(new Buffer(this.options.bucketType));
     protobuf.setKey(new Buffer(this.options.key));
 
-    if (this.options.hasOwnProperty('r')) {
-        protobuf.setR(this.options.r);
-    }
-    if (this.options.hasOwnProperty('pr')) {
-        protobuf.setPr(this.options.pr);
-    }
-    if (this.options.hasOwnProperty('notFoundOk')) {
-        protobuf.setNotfoundOk(this.options.notFoundOk);
-    }
-    if (this.options.hasOwnProperty('useBasicQuorum')) {
-        protobuf.setBasicQuorum(this.options.useBasicQuorum);
-    }
-    if (this.options.hasOwnProperty('returnDeletedVClock')) {
-        protobuf.setDeletedvclock(this.options.returnDeletedVClock);
-    }
-    if (this.options.hasOwnProperty('headOnly')) {
-        protobuf.setHead(this.options.headOnly);
-    }
-    if (this.options.hasOwnProperty('ifNotModified')) {
-        protobuf.setIfModified(this.options.ifNotModified);
-    }
-    if (this.options.hasOwnProperty('timeout')) {
-        protobuf.setTimeout(this.options.timeout);
-    }
-
+    protobuf.setR(this.options.r);
+    protobuf.setPr(this.options.pr);
+    protobuf.setNotfoundOk(this.options.notFoundOk);
+    protobuf.setBasicQuorum(this.options.useBasicQuorum);
+    protobuf.setDeletedvclock(this.options.returnDeletedVClock);
+    protobuf.setHead(this.options.headOnly);
+    protobuf.setIfModified(this.options.ifNotModified);
+    protobuf.setTimeout(this.options.timeout);
+    
     return protobuf;
 
 };
@@ -124,13 +107,12 @@ FetchValue.prototype.onSuccess = function(rpbGetResp) {
     // If the response is null ... it means not found. Riak only sends 
     // a message code and zero bytes when that's the case. 
     // Because that makes sense!
-    if (rpbGetResp === null) {
-        this._callback(null, new Response(true, false, []));
-    } else {
+    var response;
+    if (rpbGetResp) {
 
         var pbContentArray = rpbGetResp.getContent();
         var vclock = rpbGetResp.getVclock().toBuffer();
-
+        var unchanged = rpbGetResp.getUnchanged();
         // To unify the behavior of having just a tombstone vs. siblings
         // that include a tombstone, we create an empty object and mark
         // it deleted
@@ -143,7 +125,9 @@ FetchValue.prototype.onSuccess = function(rpbGetResp) {
             riakObject.key = this.key;
             riakObject.bucket = this.bucket;
             riakObject.bucketType = this.bucketType;
-            this._callback(null, new Response(false, false, [riakObject]));
+
+            response = { isNotFound : false, isUnchanged : unchanged, vclock: vclock, values : [riakObject] }; 
+
         } else {
 
             var values = new Array(pbContentArray.length);
@@ -155,18 +139,22 @@ FetchValue.prototype.onSuccess = function(rpbGetResp) {
                 riakObject.bucket = this.options.bucket;
                 riakObject.bucketType = this.options.bucketType;
                 riakObject.key = this.options.key;
-                
+
                 values[i] = riakObject;
             }
-            if (this.options.conflictResolver) {
-                this._callback(null, new Response(false, false, [this.options.conflictResolver(values)]));
-            } else {
-                this._callback(null, new Response(false, false, values));
 
+            if (this.options.conflictResolver) {
+                values = [this.options.conflictResolver(values)];
             }
+            
+            response = { isNotFound: false, isUnchanged: unchanged, vclock: vclock, values: values };                        
         }
+    } else {
+        response = { isNotFound: true, isUnchanged: false, vclock: null, values: [] };
     }
-
+    
+    this._callback(null, response);
+    
     return true;
 };
     
@@ -174,17 +162,17 @@ var schema = Joi.object().keys({
    bucket: Joi.string().required(),
    bucketType: Joi.string().default('default'),
    key: Joi.string().required(),
-   r: Joi.number().optional(),
-   pr: Joi.number().optional(),
-   notFoundOk: Joi.boolean().optional(),
-   useBasicQuorum: Joi.boolean().optional(),
-   returnDeletedVClock: Joi.boolean().default(false),
-   headOnly: Joi.boolean().default(false),
-   ifNotModified: Joi.binary().default(null),
-   timeout: Joi.number().default(null),
-   callback: Joi.func().strip().optional(),
-   conflictResolver: Joi.func().optional(),
-   convertToJs: Joi.boolean().default(false)
+   r: Joi.number().default(null).optional(),
+   pr: Joi.number().default(null).optional(),
+   notFoundOk: Joi.boolean().default(false).optional(),
+   useBasicQuorum: Joi.boolean().default(false).optional(),
+   returnDeletedVClock: Joi.boolean().default(false).optional(),
+   headOnly: Joi.boolean().default(false).optional(),
+   ifNotModified: Joi.binary().default(null).optional(),
+   timeout: Joi.number().default(null).optional(),
+   conflictResolver: Joi.func().default(null).optional(),
+   convertToJs: Joi.boolean().default(false).optional(),
+   callback: Joi.func().strip().optional()
 });
 
 /**
@@ -378,45 +366,5 @@ Builder.prototype = {
         
 };
 
-/**
- * The response from a FetchValue command.
- * @namespace FetchValue
- * @class Response
- * @constructor
- * @param {Boolean} notFound if the response was not found.
- * @param {Boolean} unchanged if the response was unchanged.
- * @param {RiakObject[]} riakobjects array of RiakObjects from Riak.
- * @extends KvResponseBase
- */
-function Response(notFound, unchanged, riakobjects) {
-    
-    KvResponseBase.call(this, riakobjects);
-    this.notFound = notFound;
-    this.unchanged = unchanged;
-}
-
-inherits(Response, KvResponseBase);
-
-/**
- * Determine if a value was present in Riak.
- * @return {Boolean} true if there was no value in riak. 
- */
-Response.prototype.isNotFound = function() {
-    return this.notFound;
-};
-
-/**
-* Determine if the value is unchanged.
-* 
-* If the fetch request included a vclock via withIfNotModified()
-* this indicates if the value in Riak has been modified. 
-*
-* @return {Boolean} true if the vector clock for the object in Riak matched the supplied vector clock, false otherwise.
-*/
-Response.prototype.isUnchanged = function() {
-    return this.unchanged;
-};
-
-
 module.exports = FetchValue;
 module.exports.Builder = Builder;
diff --git a/lib/commands/kv/kvresponsebase.js b/lib/commands/kv/kvresponsebase.js
deleted file mode 100644
index f27803a..0000000
--- a/lib/commands/kv/kvresponsebase.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2015 Basho Technologies, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Base class for KV responses from Riak
- * @class KvResponseBase
- * @constructor
- * @param {RiakObject[]} riakobjects an array of RiakObjects from Riak.
- */
-function KvResponseBase(riakobjects) {
-
-    this.riakObjects = riakobjects;
-}
-
-/**
- * Get the objects returned from Riak.
- * If siblings were present and no conflict resolver was provided all
- * siblings are returned. 
- * @method getRiakObjects
- * @returns {RiakObject[]} an array containing the returned objects.
- */
-KvResponseBase.prototype.getRiakObjects = function() {
-    return this.riakObjects;
-};
-
-module.exports = KvResponseBase;
diff --git a/lib/commands/kv/listbuckets.js b/lib/commands/kv/listbuckets.js
index 478403f..d20417e 100644
--- a/lib/commands/kv/listbuckets.js
+++ b/lib/commands/kv/listbuckets.js
@@ -93,11 +93,11 @@ ListBuckets.prototype.onSuccess = function(rpbListBucketsResp) {
     }
         
     if (this.options.stream) {
-        this._callback(null, bucketsToSend, rpbListBucketsResp.done);
+        this._callback(null, { buckets: bucketsToSend, done: rpbListBucketsResp.done });
     } else {
         Array.prototype.push.apply(this.buckets, bucketsToSend);
         if (rpbListBucketsResp.done) {
-            this._callback(null, this.buckets, rpbListBucketsResp.done);
+            this._callback(null, { buckets: this.buckets, done: rpbListBucketsResp.done});
         }
     }
     
diff --git a/lib/commands/kv/listkeys.js b/lib/commands/kv/listkeys.js
index a224efb..2a1345c 100644
--- a/lib/commands/kv/listkeys.js
+++ b/lib/commands/kv/listkeys.js
@@ -88,17 +88,21 @@ ListKeys.prototype.onSuccess = function(rpbListKeysResp) {
     
     var keysToSend = new Array(rpbListKeysResp.keys.length);
     if (rpbListKeysResp.keys.length) {
-            for (var i = 0; i < rpbListKeysResp.keys.length; i++) {
+        for (var i = 0; i < rpbListKeysResp.keys.length; i++) {
             keysToSend[i] = rpbListKeysResp.keys[i].toString('utf8');
         }
     }
         
     if (this.options.stream) {
-        this._callback(null, keysToSend, rpbListKeysResp.done);
+        this._callback(null, { bucketType: this.options.bucketType, 
+            bucket: this.options.bucket, 
+            keys: keysToSend, done: rpbListKeysResp.done});
     } else {
         Array.prototype.push.apply(this.keys, keysToSend);
         if (rpbListKeysResp.done) {
-            this._callback(null, this.keys, rpbListKeysResp.done);
+            this._callback(null, {  bucketType: this.options.bucketType, 
+                bucket: this.options.bucket, keys: this.keys, 
+                done: rpbListKeysResp.done });
         }
     }
     
diff --git a/lib/commands/kv/riakobject.js b/lib/commands/kv/riakobject.js
index aef0248..b14877d 100644
--- a/lib/commands/kv/riakobject.js
+++ b/lib/commands/kv/riakobject.js
@@ -276,8 +276,8 @@ module.exports.createFromRpbContent = function(rpbContent, convertToJs) {
     // ReturnHead will only retun metadata
     if (convertToJs && value) {
         ro.value = JSON.parse(value.toString('utf8'));
-    } else {
-        ro.value = value;
+    } else if (value) {
+        ro.value = value.toBuffer();
     }
     
     if (rpbContent.getContentType()) {
diff --git a/lib/commands/kv/secondaryindexquery.js b/lib/commands/kv/secondaryindexquery.js
index eff8d9e..932a93f 100644
--- a/lib/commands/kv/secondaryindexquery.js
+++ b/lib/commands/kv/secondaryindexquery.js
@@ -56,9 +56,10 @@ var RiakObject = require('./riakobject');
  * @param {Boolean} [options.paginationSort=false] true to sort a non-paginated query.
  * @param {Function} callback the callback to be executed by the command.
  * @param {String} callback.err  An error message
- * @param {Object[]} callback.response object keys returned by the query, and optionally the index keys.
- * @param {Boolean} callback.done if you have received all the results.
- * @param {Buffer} callback.continuation if a continuation was returned
+ * @param {Object} callback.response
+ * @param {Object[]} callback.response.values object keys returned by the query, and optionally the index keys.
+ * @param {Boolean} callback.response.done if you have received all the results.
+ * @param {Buffer} callback.response.continuation if a continuation was returned
  * @extends CommandBase
  */
 function SecondaryIndexQuery(options, callback) {
@@ -164,11 +165,11 @@ SecondaryIndexQuery.prototype.onSuccess = function(rpbIndexResp) {
     var continuation = rpbIndexResp.continuation;
     
     if (this.options.stream) {
-        this._callback(null, resultsToReturn, rpbIndexResp.done, continuation );
+        this._callback(null, { values: resultsToReturn, done: rpbIndexResp.done, continuation: continuation });
     } else {
         Array.prototype.push.apply(this.responses, resultsToReturn);
         if (rpbIndexResp.done) {
-            this._callback(null, this.responses, true, continuation);
+            this._callback(null, { values: this.responses, done : true, continuation: continuation });
         }
     }
     
diff --git a/lib/commands/kv/storevalue.js b/lib/commands/kv/storevalue.js
index f2cc17f..00aceb8 100644
--- a/lib/commands/kv/storevalue.js
+++ b/lib/commands/kv/storevalue.js
@@ -15,7 +15,6 @@
  */
 
 var RiakObject = require('./riakobject');
-var KvResponseBase = require('./kvresponsebase');
 var CommandBase = require('../commandbase');
 var inherits = require('util').inherits;
 var Joi = require('joi');
@@ -68,7 +67,11 @@ function StoreValue(options, callback) {
         }
     
         self.options = options;
-    
+        
+        if (!options.bucket && ((options.value instanceof RiakObject) && !options.value.bucket)) {
+            throw 'Must supply bucket directly or via a RiakObject';
+        }
+        
     });
     
     this.remainingTries = 1;
@@ -80,68 +83,44 @@ StoreValue.prototype.constructPbRequest = function() {
     
     var protobuf = this.getPbReqBuilder();
     
-    protobuf.setBucket(new Buffer(this.options.bucket));
-    protobuf.setType(new Buffer(this.options.bucketType));
-    
-    if (this.options.hasOwnProperty('key')) {
-        protobuf.setKey(new Buffer(this.options.key));
-    } 
-    
-    if (this.options.hasOwnProperty('vclock')) {
-        protobuf.setVclock(this.options.vclock);
-    }
-    
-    if (this.options.hasOwnProperty('w')) {
-        protobuf.setW(this.options.w);
-    }
-    
-    if (this.options.hasOwnProperty('dw')) {
-        protobuf.setDw(this.options.dw);
-    }
-    
-    if (this.options.hasOwnProperty('pw')) {
-        protobuf.setPw(this.options.pw);
-    }
+    // RiakObject values take precidence 
+    var value = this.options.value;
     
-    if (this.options.hasOwnProperty('returnBody')) {
-        protobuf.setReturnBody(this.options.returnBody);
-    }
+    if (value instanceof RiakObject) {
     
-    if (this.options.hasOwnProperty('returnHead')) {
-        protobuf.setReturnHead(this.options.returnHead);
+        if (value.hasOwnProperty('vclock')) {
+            this.options.vclock = value.vclock;
+        }
+        if (value.hasOwnProperty('bucket')) {
+            this.options.bucket = value.bucket;
+        }
+        if (value.hasOwnProperty('bucketType')) {
+            this.options.bucketType = value.bucketType;
+        }
+        if (value.hasOwnProperty('key')) {
+            this.options.key = value.key;
+        }
+    } else {
+        value = new RiakObject().setValue(this.options.value);
     }
     
-    if (this.options.hasOwnProperty('timeout')) {
-        protobuf.setTimeout(this.options.timeout);
+    protobuf.setBucket(new Buffer(this.options.bucket));
+    protobuf.setType(new Buffer(this.options.bucketType));
+    if (this.options.key) {
+        protobuf.setKey(new Buffer(this.options.key));
     }
+    protobuf.setVclock(this.options.vclock);
+    protobuf.setW(this.options.w);
+    protobuf.setDw(this.options.dw);
+    protobuf.setPw(this.options.pw);
+    protobuf.setReturnBody(this.options.returnBody);
+    protobuf.setReturnHead(this.options.returnHead);
+    protobuf.setTimeout(this.options.timeout);
+    protobuf.setIfNotModified(this.options.ifNotModified);
+    protobuf.setIfNoneMatch(this.options.ifNoneMatch);
     
-    if (this.options.hasOwnProperty('ifNotModified')) {
-        protobuf.setIfNotModified(this.options.ifNotModified);
-    }
     
-    if (this.options.hasOwnProperty('ifNoneMatch')) {
-        protobuf.setIfNoneMatch(this.options.ifNoneMatch);
-    }
     
-    // RiakObject values take precidence 
-    var value = this.options.value;
-        
-    if (value.hasOwnProperty('vclock')) {
-        protobuf.setVclock(value.vclock);
-    }
-    if (value.hasOwnProperty('bucket')) {
-        protobuf.setBucket(new Buffer(value.bucket));
-    }
-    if (value.hasOwnProperty('bucketType')) {
-        protobuf.setType(new Buffer(value.bucketType));
-    }
-    if (value.hasOwnProperty('key')) {
-        protobuf.setKey(new Buffer(value.key));
-    }
-    
-    if (!(value instanceof RiakObject)) {
-        value = new RiakObject().setValue(this.options.value);
-    }
     var rpbContent = RiakObject.populateRpbContentFromRiakObject(value);
     
     protobuf.setContent(rpbContent);
@@ -154,21 +133,22 @@ StoreValue.prototype.onSuccess = function(rpbPutResp) {
     
     // unless returnHead or returnMeta were specified, or if no key was supplied
     // Riak doesn't return any data 
+    var response = {};
     if (rpbPutResp) {
                 
-        var responseKey;
+        var responseKey = null;
 
         if (rpbPutResp.getKey()) {
             responseKey = rpbPutResp.getKey().toString('utf8');
         } 
 
         var values;
-        
+        var vclock = null;
         if (rpbPutResp.getContent().length) {
             var pbContentArray = rpbPutResp.getContent();
 
             values = new Array(pbContentArray.length);
-            var vclock = rpbPutResp.getVclock().toBuffer();
+            vclock = rpbPutResp.getVclock().toBuffer();
             for (var i = 0; i < pbContentArray.length; i++) {
                 var riakObject = RiakObject.createFromRpbContent(pbContentArray[i], this.options.convertToJs);
                 riakObject.vclock = vclock;
@@ -178,35 +158,43 @@ StoreValue.prototype.onSuccess = function(rpbPutResp) {
                 
                 values[i] = riakObject;
             }
+            
+            if (this.options.conflictResolver) {
+                values = [this.options.conflictResolver(values)];
+            }
+            
         } else {
             values =[];
         }
 
-        this._callback(null, new Response(values, responseKey));
+        response = { generatedKey: responseKey, vclock: vclock, values: values };
+
     } else {
-        this._callback(null, new Response([]));
+        response = { generatedKey: null, vclock: null, values: [] };
     }
     
+    this._callback(null, response);
+    
     return true;    
 };
 
 var schema = Joi.object().keys({
-    bucket: Joi.string().required(),
+    bucket: Joi.string().optional(),
     bucketType: Joi.string().default('default'),
-    key: Joi.string().optional(),
+    key: Joi.string().default(null).optional(),
     callback: Joi.func().strip().optional(),
     value: Joi.any().required(),
-    w: Joi.number().optional(),
-    dw: Joi.number().optional(),
-    pw: Joi.number().optional(),
-    returnBody: Joi.boolean().optional(),
-    returnHead: Joi.boolean().optional(),
-    timeout: Joi.number().optional(),
-    ifNotModified: Joi.boolean().optional(),
-    ifNoneMatch: Joi.boolean().optional(),
-    vclock: Joi.binary().optional(),
-    convertToJs: Joi.boolean().optional(),
-    conflictResolver: Joi.func().optional()
+    w: Joi.number().default(null).optional(),
+    dw: Joi.number().default(null).optional(),
+    pw: Joi.number().default(null).optional(),
+    returnBody: Joi.boolean().default(false).optional(),
+    returnHead: Joi.boolean().default(false).optional(),
+    timeout: Joi.number().default(null).optional(),
+    ifNotModified: Joi.boolean().default(false).optional(),
+    ifNoneMatch: Joi.boolean().default(false).optional(),
+    vclock: Joi.binary().default(null).optional(),
+    convertToJs: Joi.boolean().default(false).optional(),
+    conflictResolver: Joi.func().default(null).optional()
 });
 
 
@@ -432,43 +420,6 @@ Builder.prototype = {
     
 };
 
-/**
- * The response from a StoreValue command.
- * @namespace StoreValue
- * @class Response
- * @constructor
- * @param {RiakObject[]} riakobjects array of values and their meta
- * @param {String} [generatedKey] key generated by Riak
- * @extends KvResponsBase
- */
-function Response(riakobjects, generatedKey) {
-    KvResponseBase.call(this, riakobjects);
-    
-    this.generatedKey = generatedKey;
-}
-
-inherits(Response, KvResponseBase);
-
-/**
- * Check to see if this response contains a key generated by Riak.
- * This is also injected into the RiakObject.
- * @method hasGeneratedKey
- * @return {Boolean} true if a generated key exists.
- */
-Response.prototype.hasGeneratedKey = function() {
-    return this.generatedKey !== undefined;
-};
-
-/**
- * Get the generated key.
- * @methos getGeneratedKey
- * @return {String} the key generated by riak, or undefined if none exists.
- */
-Response.prototype.getGeneratedKey = function() {
-    return this.generatedKey;
-};
-
-
 
 module.exports = StoreValue;
 module.exports.Builder = Builder;
diff --git a/lib/commands/mapreduce/mapreduce.js b/lib/commands/mapreduce/mapreduce.js
index f977d24..627866a 100644
--- a/lib/commands/mapreduce/mapreduce.js
+++ b/lib/commands/mapreduce/mapreduce.js
@@ -118,10 +118,11 @@ MapReduce.prototype.onSuccess = function(rpbMapRedResp) {
     
     if (!this.stream) {
         if (done) {
-            this._callback(null, this.response, done);
+            this.response.done = true;
+            this._callback(null, this.response);
         }
     } else {
-        this._callback(null, { phase : phase, response: responseArray}, done);
+        this._callback(null, { phase : phase, response: responseArray, done: done});
     }
     
     return done;
diff --git a/lib/commands/mr.js b/lib/commands/mr.js
index ec950e7..9b2040b 100644
--- a/lib/commands/mr.js
+++ b/lib/commands/mr.js
@@ -17,6 +17,6 @@
 function MR() { }
 
 // MR exports
-module.exports = MR
+module.exports = MR;
 module.exports.MapReduce = require('./mapreduce/mapreduce');
 
diff --git a/lib/commands/yz.js b/lib/commands/yz.js
index ab4b26b..c39b519 100644
--- a/lib/commands/yz.js
+++ b/lib/commands/yz.js
@@ -17,7 +17,7 @@
 function YZ() { }
 
 // YZ exports
-module.exports = YZ
+module.exports = YZ;
 module.exports.DeleteIndex = require('./yokozuna/deleteindex');
 module.exports.FetchIndex = require('./yokozuna/fetchindex');
 module.exports.FetchSchema = require('./yokozuna/fetchschema');
diff --git a/lib/core/riakcluster.js b/lib/core/riakcluster.js
index d4ecb93..3c5d1c2 100644
--- a/lib/core/riakcluster.js
+++ b/lib/core/riakcluster.js
@@ -241,7 +241,7 @@ RiakCluster.prototype._onRetryCommand = function(command, lastNode) {
 
 RiakCluster.prototype._stateCheck = function(allowedStates) {
     if (allowedStates.indexOf(this.state) === -1) {
-        throw 'Illegal State; required: ' + allowedStates + 'current: ' + this.state; 
+        throw 'RiakCluster: Illegal State; required: ' + allowedStates + ' current: ' + this.state; 
     }
 };
 
diff --git a/lib/core/riaknode.js b/lib/core/riaknode.js
index 1660231..2fdd07d 100644
--- a/lib/core/riaknode.js
+++ b/lib/core/riaknode.js
@@ -304,7 +304,7 @@ RiakNode.prototype._connectionClosed = function(conn) {
 
 RiakNode.prototype._stateCheck = function(allowedStates) {
     if (allowedStates.indexOf(this.state) === -1) {
-        throw "Illegal State; required: " + allowedStates + "current: " + this.state; 
+        throw "RiakNode: Illegal State; required: " + allowedStates + " current: " + this.state; 
     }
 };
 


Test patch:
diff --git a/test/integration/crdt/updateandfetchcounter.js b/test/integration/crdt/updateandfetchcounter.js
new file mode 100644
index 0000000..0410c97
--- /dev/null
+++ b/test/integration/crdt/updateandfetchcounter.js
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var UpdateCounter = require('../../../lib/commands/crdt/updatecounter');
+var FetchCounter = require('../../../lib/commands/crdt/fetchcounter');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Update and Fetch Counter - Integration', function() {
+   
+    var cluster;
+    this.timeout(10000);
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            done();
+        };
+        
+        // This ... tests updating a new counter
+        var update = new UpdateCounter.Builder()
+                .withBucketType(Test.counterBucketType)
+                .withBucket(Test.bucketName)
+                .withKey('counter_1')
+                .withIncrement(10)
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(update);
+        
+    });
+    
+    after(function(done) {
+        Test.cleanBucket(cluster, Test.counterBucketType, Test.bucketName, function() {
+            cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+            cluster.stop();
+        });
+    });
+    
+    it('Should fetch a counter', function(done) {
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.counterValue, 10);
+            done();
+        };
+        
+        var fetch = new FetchCounter.Builder()
+            .withKey('counter_1')
+            .withBucketType(Test.counterBucketType)
+            .withBucket(Test.bucketName)
+            .withCallback(callback)
+            .build();
+    
+        cluster.execute(fetch);
+        
+    });
+    
+    it('Should update a counter', function(done) {
+       
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.counterValue, 20);
+            done();
+        };
+        
+        var update = new UpdateCounter.Builder()
+                .withKey('counter_1')
+                .withBucketType(Test.counterBucketType)
+                .withBucket(Test.bucketName)
+                .withIncrement(10)
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(update);
+        
+    });
+    
+    it('Should generate a key if one isn\'t supplied', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.counterValue, 10);
+            assert(resp.generatedKey);
+            done();
+        };
+        
+        var update = new UpdateCounter.Builder()
+                .withBucketType(Test.counterBucketType)
+                .withBucket(Test.bucketName)
+                .withIncrement(10)
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(update);
+        
+    });
+    
+    
+    
+});
\ No newline at end of file
diff --git a/test/integration/crdt/updateandfetchmap.js b/test/integration/crdt/updateandfetchmap.js
new file mode 100644
index 0000000..63788a0
--- /dev/null
+++ b/test/integration/crdt/updateandfetchmap.js
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var UpdateMap = require('../../../lib/commands/crdt/updatemap');
+var FetchMap = require('../../../lib/commands/crdt/fetchmap');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Update and Fetch Map - Integration', function() {
+    
+    var cluster;
+    this.timeout(10000);
+    var context;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp.context);
+            context = resp.context;
+            done();
+        };
+
+        var mapOp = new UpdateMap.MapOperation();
+           
+        mapOp.incrementCounter('counter_1', 50)
+            .addToSet('set_1', 'value_1')
+            .setRegister('register_1', new Buffer('register_value_1'))
+            .setFlag('flag_1', true);
+
+        mapOp.map('map_2').incrementCounter('counter_1', 50)
+            .addToSet('set_1', 'value_1')
+            .setRegister('register_1', new Buffer('register_value_1'))
+            .setFlag('flag_1', true)
+            .map('map_3');
+
+
+        var update = new UpdateMap.Builder()
+            .withBucketType(Test.mapBucketType)
+            .withBucket(Test.bucketName)
+            .withKey('map_1')
+            .withMapOperation(mapOp)
+            .withCallback(callback)
+            .withReturnBody(true)
+            .withTimeout(20000)
+            .build();
+
+        cluster.execute(update);
+
+    });
+    
+    after(function(done) {
+        Test.cleanBucket(cluster, Test.mapBucketType, Test.bucketName, function() {
+            cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+            cluster.stop();
+        });
+    });
+    
+    it('Should fetch a map', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp.context);
+            assert(resp.map);
+            assert.equal(resp.map.counters.counter_1, 50);
+            assert.equal(resp.map.sets.set_1[0], 'value_1');
+            assert.equal(resp.map.registers.register_1.toString('utf8'), 'register_value_1');
+            assert.equal(resp.map.flags.flag_1, true);
+            done();
+        };
+        
+        var fetch = new FetchMap.Builder()
+				.withBucketType(Test.mapBucketType)
+                .withBucket(Test.bucketName)
+                .withKey('map_1')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(fetch);
+
+        
+    });
+    
+    it('Should remove stuff from a map', function(done) {
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp.context);
+            assert(resp.map);
+            assert(!resp.map.counters.counter_1);
+            assert.equal(resp.map.sets.set_1[0], 'value_1');
+            assert.equal(resp.map.registers.register_1.toString('utf8'), 'register_value_1');
+            assert.equal(resp.map.flags.flag_1, true);
+            done();
+        };
+        
+        var mapOp = new UpdateMap.MapOperation().removeCounter('counter_1');
+        
+        var update = new UpdateMap.Builder()
+            .withBucketType(Test.mapBucketType)
+            .withBucket(Test.bucketName)
+            .withKey('map_1')
+            .withContext(context)
+            .withMapOperation(mapOp)
+            .withCallback(callback)
+            .withTimeout(20000)
+            .build();
+    
+        cluster.execute(update);
+        
+        
+    });
+    
+});
diff --git a/test/integration/crdt/updateandfetchset.js b/test/integration/crdt/updateandfetchset.js
new file mode 100644
index 0000000..51bf9de
--- /dev/null
+++ b/test/integration/crdt/updateandfetchset.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var UpdateSet = require('../../../lib/commands/crdt/updateset');
+var FetchSet = require('../../../lib/commands/crdt/fetchset');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Update and Fetch Set - Integration', function() {
+    
+    var cluster;
+    this.timeout(10000);
+    var context;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 2);
+            assert(resp.context);
+            context = resp.context;
+            done();
+        };
+        
+        // This ... tests updating a new set
+        var update = new UpdateSet.Builder()
+                .withBucketType(Test.setBucketType)
+                .withBucket(Test.bucketName)
+                .withKey('set_1')
+                .withAdditions(['this', 'that'])
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(update);
+        
+    });
+    
+    after(function(done) {
+        Test.cleanBucket(cluster, Test.setBucketType, Test.bucketName, function() {
+            cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+            cluster.stop();
+        });
+    });
+    
+    
+    it('Should fetch a set', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 2);
+            assert(resp.context);
+            done();
+        };
+        
+        var fetch = new FetchSet.Builder()
+                .withBucketType(Test.setBucketType)
+                .withBucket(Test.bucketName)
+                .withKey('set_1')
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+        
+    });
+    
+    it('Should remove from a set', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 1);
+            done();
+        };
+        
+        // This ... tests updating a new set
+        var update = new UpdateSet.Builder()
+                .withBucketType(Test.setBucketType)
+                .withBucket(Test.bucketName)
+                .withKey('set_1')
+                .withRemovals(['this'])
+                .withContext(context)
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(update);
+        
+    });
+
+});
diff --git a/test/integration/kv/fetchandsetbucketprops.js b/test/integration/kv/fetchandsetbucketprops.js
new file mode 100644
index 0000000..6dc5017
--- /dev/null
+++ b/test/integration/kv/fetchandsetbucketprops.js
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreProps = require('../../../lib/commands/kv/storebucketprops');
+var FetchProps = require('../../../lib/commands/kv/fetchbucketprops');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Store and Fetch Bucket props - Integration', function() {
+   
+   this.timeout(10000);
+   
+    var cluster;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        done();
+    });
+    
+    after(function(done) {
+        
+        cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+        cluster.stop();
+            
+    });
+    
+    describe('StoreBucketProps', function() {
+        
+        it('Should store props for a bucket in the default type', function(done) {
+            var callback = function(err, resp) {
+                assert(!err, err);
+                done();
+            };
+
+            var store = new StoreProps.Builder()
+                    .withBucket(Test.bucketName + '_sp')
+                    .withAllowMult(true)
+                    .withCallback(callback)
+                    .build();
+
+            cluster.execute(store);
+
+        });
+    
+    
+        it('Should store bucket props for a bucket in a non-default type', function(done) {
+
+            var callback = function(err, resp) {
+                assert(!err, err);
+                done();
+            };
+
+            var store = new StoreProps.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(Test.bucketName + '_sp')
+                    .withAllowMult(false)
+                    .withCallback(callback)
+                    .build();
+
+            cluster.execute(store);
+
+        });
+    });
+    
+    describe('FetchBucketProps', function() {
+        it('Should fetch props for a bucket in the default Type', function(done) {
+            
+            var callback = function(err, resp) {
+                assert(!err, err);
+                assert(resp.nVal);
+                done();
+            };
+            
+            var fetch = new FetchProps.Builder()
+                .withBucket(Test.bucketName + '_sp')
+                .withCallback(callback)
+                .build();
+        
+            cluster.execute(fetch);
+        });
+        
+        it('Should fetch props for a bucket in a non-default Type', function(done) {
+            
+            var callback = function(err, resp) {
+                assert(!err, err);
+                assert(resp.nVal);
+                done();
+            };
+            
+            var fetch = new FetchProps.Builder()
+                .withBucketType(Test.bucketType)
+                .withCallback(callback)
+                .withBucket(Test.bucketName + '_sp')
+                .build();
+        
+            cluster.execute(fetch);
+        });
+    });
+        
+});
+
diff --git a/test/integration/kv/fetchvalue.js b/test/integration/kv/fetchvalue.js
new file mode 100644
index 0000000..96115e8
--- /dev/null
+++ b/test/integration/kv/fetchvalue.js
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+var FetchValue = require('../../../lib/commands/kv/fetchvalue');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('FetchValue - Integration', function() {
+   
+    var cluster;
+    this.timeout(10000);
+    
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var count = 0;
+        var cb = function(err, resp) {
+            assert(!err, err);
+            count++;
+            if (count === 5) {
+                done();
+            }
+            
+        };
+        
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName)
+               .withKey('my_key1')
+               .withContent('this is a value in Riak')
+               .withCallback(cb)
+               .build();
+       
+        cluster.execute(store);
+
+        var myObject = { field1: 'field1_value', field2: 'field2_value', field3: 7 };
+
+        store = new StoreValue.Builder()
+                .withBucket(Test.bucketName)
+                .withKey('my_key2')
+                .withContent(myObject)
+                .withCallback(cb)
+                .build();
+
+        cluster.execute(store);
+
+        var i;
+        for (i = 0; i < 2; i++) {
+            store = new StoreValue.Builder()
+                .withBucket(Test.bucketName)
+                .withBucketType(Test.bucketType)
+                .withKey('my_key2')
+                .withContent('this is a value in Riak')
+                .withCallback(cb)
+                .build();
+            
+            cluster.execute(store);
+               
+       }
+
+        store = new StoreValue.Builder()
+                .withBucket(Test.bucketName)
+                .withBucketType(Test.bucketType)
+                .withKey('my_key1')
+                .withContent('this is a value in Riak')
+                .withCallback(cb)
+                .build();
+
+        cluster.execute(store);
+
+        
+        
+    });
+    
+    after(function(done) {
+        Test.cleanBucket(cluster, 'default', Test.bucketName, function() { 
+            Test.cleanBucket(cluster, Test.bucketType, Test.bucketName, function() {
+                cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+                cluster.stop();
+            });
+        });
+        
+   });
+
+    it('Should fetch a value from Riak (default type)', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 1);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+            assert.equal(resp.isNotFound, false);
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withKey('my_key1')
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+        
+    });
+    
+    it('Should fetch a value in a non-default bucket-type from Riak', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 1);
+            assert.equal(resp.isNotFound, false);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withBucketType(Test.bucketType)
+                .withKey('my_key1')
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+        
+    });
+    
+    it('Should convert value from JSON if specified', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 1);
+            var value = resp.values[0].getValue();
+            assert.equal(value.field1, 'field1_value' );
+            assert.equal(value.field2, 'field2_value' );
+            assert.equal(value.field3, 7 );
+
+            assert.equal(resp.isNotFound, false);
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withKey('my_key2')
+                .withConvertValueToJs(true)
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+        
+    });
+    
+    it('Should report not-found when value doesn\'t exist', function(done) {
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 0);
+            assert.equal(resp.isNotFound, true);
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withKey('no_key')
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+    });
+    
+    
+    
+    
+    
+    it('Should return siblings if no conflict resolver', function(done) {
+       
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 2);
+            assert.equal(resp.isNotFound, false);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+            assert.equal(resp.values[1].getValue().toString('utf8'), 'this is a value in Riak');
+
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withBucketType(Test.bucketType)
+                .withKey('my_key2')
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(fetch);
+        
+        
+    });
+    
+    it('Should resolve siblings if conflict resolver provided', function(done) {
+       
+        var cf = function(objects) {
+          
+            assert.equal(objects.length, 2);
+            return objects[0];
+            
+        };
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.values.length, 1);
+            assert.equal(resp.isNotFound, false);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+
+            done();
+        };
+        
+        var fetch = new FetchValue.Builder()
+                .withBucket(Test.bucketName)
+                .withBucketType(Test.bucketType)
+                .withKey('my_key2')
+                .withCallback(callback)
+                .withConflictResolver(cf)
+                .build();
+        
+        cluster.execute(fetch);
+        
+        
+    });
+
+});
diff --git a/test/integration/kv/listbuckets.js b/test/integration/kv/listbuckets.js
new file mode 100644
index 0000000..4108164
--- /dev/null
+++ b/test/integration/kv/listbuckets.js
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var ListBuckets = require('../../../lib/commands/kv/listbuckets');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+
+
+describe('ListBuckets - Integration', function() {
+   
+    this.timeout(60000);
+   
+    var cluster;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var count = 0;
+        var cb = function(err, resp) {
+            assert(!err, err);
+            count++;
+            if (count === 10) {
+                done();
+            }
+        };
+        
+        for (var i = 0; i < 5; i++) {
+            
+            // Will create buckets
+            var bucket = Test.bucketName + '_lb' + i;
+            var store = new StoreValue.Builder()
+                    .withBucket(bucket)
+                    .withContent('value')
+                    .withCallback(cb)
+                    .build();
+            
+            cluster.execute(store);
+            
+            store = new StoreValue.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(bucket)
+                    .withContent('value')
+                    .withCallback(cb)
+                    .build();
+            
+            cluster.execute(store);
+        }
+    });
+    
+    after(function(done) {
+       
+       
+        var num = 0;
+        var type = 'default';
+        var nukeBucket = function() {
+            
+            num++;
+            
+            if (num === 6) {
+                if(type === 'default') {
+                    type = Test.bucketType;
+                    num = 1;
+                    Test.cleanBucket(cluster, type, Test.bucketName + '_lb' + (num - 1), nukeBucket);
+                } else {
+                    cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+                    cluster.stop();
+                }
+            } else {
+                Test.cleanBucket(cluster, type, Test.bucketName + '_lb' + (num - 1), nukeBucket);
+            }
+        };
+    
+        nukeBucket();
+        
+    });
+    
+    it('should list buckets in the default type', function(done) {
+       
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            if (!resp.done) {
+                assert(resp.buckets.length);
+            } else {
+                done();
+            }
+        };
+       
+        var list = new ListBuckets.Builder()
+                .withCallback(callback)
+                .build();
+        
+        cluster.execute(list);
+        
+    });
+        
+    it('should list buckets in a non-default type', function(done) {
+       
+        
+        var callback = function(err, resp) {
+            assert(!err, err);
+            if (!resp.done) {
+                assert(resp.buckets.length);
+            } else {
+                done();
+            }
+        };
+       
+        var list = new ListBuckets.Builder()
+                .withCallback(callback)
+                .withBucketType(Test.bucketType)
+                .build();
+        
+        cluster.execute(list);
+        
+    });
+    
+});
\ No newline at end of file
diff --git a/test/integration/kv/secondaryindexquery.js b/test/integration/kv/secondaryindexquery.js
new file mode 100644
index 0000000..9bd7661
--- /dev/null
+++ b/test/integration/kv/secondaryindexquery.js
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+var RiakObject = require('../../../lib/commands/kv/riakobject');
+var SecondaryIndexQuery = require('../../../lib/commands/kv/secondaryindexquery');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Secondary Index Query - Integration', function() {
+   
+    var cluster;
+    this.timeout(10000);
+    
+    before(function(done) {
+       
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var count = 0;
+        var storeCb = function(err, response) {
+
+            count++;
+            if (count === 100) {
+                done();
+            }
+        };
+    
+    
+        for (var i = 0; i < 25; i++) {
+            var ro = new RiakObject();
+            ro.addToIndex('id_int', i);
+            ro.setValue('this is a value');
+            var store = new StoreValue.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(Test.bucketName)
+                    .withContent(ro)
+                    .withKey('key' + i)
+                    .withCallback(storeCb)
+                    .build();
+
+            cluster.execute(store);
+            
+            ro = new RiakObject();
+            ro.addToIndex('email_bin', 'email' + i);
+            ro.setValue('this is a value');
+            store = new StoreValue.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(Test.bucketName)
+                    .withContent(ro)
+                    .withKey('key_' + i)
+                    .withCallback(storeCb)
+                    .build();
+
+            cluster.execute(store);
+            
+            ro = new RiakObject();
+            ro.addToIndex('id_int', i);
+            ro.setValue('this is a value');
+            store = new StoreValue.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(Test.bucketName)
+                    .withContent(ro)
+                    .withKey('key' + i)
+                    .withCallback(storeCb)
+                    .build();
+
+            cluster.execute(store);
+            
+            ro = new RiakObject();
+            ro.addToIndex('email_bin', 'email' + i);
+            ro.setValue('this is a value');
+            store = new StoreValue.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withBucket(Test.bucketName)
+                    .withContent(ro)
+                    .withKey('key_' + i)
+                    .withCallback(storeCb)
+                    .build();
+
+            cluster.execute(store);
+            
+        }
+
+    });
+    
+    after(function(done) {
+        Test.cleanBucket(cluster, 'default', Test.bucketName, function() { 
+            Test.cleanBucket(cluster, Test.bucketType, Test.bucketName, function() {
+                cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done(); } });
+                cluster.stop();
+            });
+        });
+        
+   });
+   
+   it('Should perform a _int query against the default type', function(done) {
+      
+        var count = 0;
+        var callback = function(err, response) {
+            assert(!err, err);
+            count += response.values.length;
+            if (response.done) {
+                assert.equal(count, 25);
+                done();
+            }
+        };
+        
+        var siq = new SecondaryIndexQuery.Builder()
+					.withBucket(Test.bucketName)
+                    .withBucketType(Test.bucketType)
+					.withIndexName('id_int')
+					.withRange(0,10000)
+					.withCallback(callback)
+					.withReturnKeyAndIndex(true)
+					.build();
+
+		cluster.execute(siq);
+       
+   });
+   
+   it('Should perform a _int query against a non-default type', function(done) {
+      
+        var count = 0;
+        var callback = function(err, response) {
+            assert(!err, err);
+            count += response.values.length;
+            if (response.done) {
+                assert.equal(count, 25);
+                done();
+            }
+        };
+        
+        var siq = new SecondaryIndexQuery.Builder()
+					.withBucket(Test.bucketName)
+                    .withBucketType(Test.bucketType)
+					.withIndexName('id_int')
+					.withRange(0,10000)
+					.withCallback(callback)
+					.withReturnKeyAndIndex(true)
+					.build();
+
+		cluster.execute(siq);
+       
+   });
+   
+   it('Should perform a _bin query against the default type', function(done) {
+      
+        var count = 0;
+        var callback = function(err, response) {
+            assert(!err, err);
+            count += response.values.length;
+            if (response.done) {
+                assert.equal(count, 25);
+                done();
+            }
+        };
+        
+        var siq = new SecondaryIndexQuery.Builder()
+					.withBucket(Test.bucketName)
+                    .withBucketType(Test.bucketType)
+					.withIndexName('email_bin')
+					.withRange('a','z')
+					.withCallback(callback)
+					.withReturnKeyAndIndex(true)
+					.build();
+
+		cluster.execute(siq);
+       
+   });
+   
+   it('Should perform a _bin query against a non-default type', function(done) {
+      
+        var count = 0;
+        var callback = function(err, response) {
+            assert(!err, err);
+            count += response.values.length;
+            if (response.done) {
+                assert.equal(count, 25);
+                done();
+            }
+        };
+        
+        var siq = new SecondaryIndexQuery.Builder()
+					.withBucket(Test.bucketName)
+                    .withBucketType(Test.bucketType)
+					.withIndexName('email_bin')
+					.withRange('a','z')
+					.withCallback(callback)
+					.withReturnKeyAndIndex(true)
+					.build();
+
+		cluster.execute(siq);
+       
+   });
+   
+   it('Should set a coninuation on a paginated query', function(done) {
+      
+       var count = 0;
+        var callback = function(err, response) {
+            assert(!err, err);
+            count += response.values.length;
+            if (response.done) {
+                assert.equal(count, 10);
+                assert(response.continuation);
+                done();
+            }
+        };
+        
+        var siq = new SecondaryIndexQuery.Builder()
+					.withBucket(Test.bucketName)
+                    .withBucketType(Test.bucketType)
+					.withIndexName('email_bin')
+					.withRange('a','z')
+                    .withMaxResults(10)
+					.withCallback(callback)
+					.withReturnKeyAndIndex(true)
+					.build();
+
+		cluster.execute(siq);
+       
+   });
+    
+});
+
diff --git a/test/integration/kv/storevalue.js b/test/integration/kv/storevalue.js
new file mode 100644
index 0000000..642b945
--- /dev/null
+++ b/test/integration/kv/storevalue.js
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+
+
+describe('StoreValue - Integration', function() {
+   
+    this.timeout(10000);
+   
+    var cluster;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        done();
+    });
+   
+    it('Should store a (String) value in Riak (default type) and return it', function(done) {
+            
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.generatedKey, null);
+            assert(resp.vclock);
+            assert.equal(resp.values.length, 1);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+            done();
+            
+        };
+      
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName + '_sv')
+               .withKey('my_key1')
+               .withContent('this is a value in Riak')
+               .withCallback(callback)
+               .withReturnBody(true)
+               .build();
+       
+       cluster.execute(store);
+       
+   });
+   
+   it('Should store a JS object as JSON in Riak (default type) and return it', function(done) {
+       
+       var myObject = { field1: 'field1_value', field2: 'field2_value', field3: 7 };
+       
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.generatedKey, null);
+            assert(resp.vclock);
+            assert.equal(resp.values.length, 1);
+            
+            var returnedObj = resp.values[0].getValue();
+            
+            assert.equal(returnedObj.field1, 'field1_value');
+            assert.equal(returnedObj.field2, 'field2_value');
+            assert.equal(returnedObj.field3, 7);
+            done();
+            
+        };
+        
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName + '_sv')
+               .withKey('my_key2')
+               .withContent(myObject)
+               .withCallback(callback)
+               .withReturnBody(true, true)
+               .build();
+       
+       cluster.execute(store);
+       
+   });
+   
+   it('Should store a buffer in Riak (default type) and return it', function(done) {
+       
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.generatedKey, null);
+            assert(resp.vclock);
+            assert.equal(resp.values.length, 1);
+            
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'some content');
+            done();
+            
+        };
+        
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName + '_sv')
+               .withKey('my_key3')
+               .withContent(new Buffer('some content'))
+               .withCallback(callback)
+               .withReturnBody(true)
+               .build();
+       
+       cluster.execute(store);
+       
+   });
+   
+   it('Should store an object in a non-default bucket-type and return it', function(done) {
+      
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.generatedKey, null);
+            assert(resp.vclock);
+            assert.equal(resp.values.length, 1);
+            assert.equal(resp.values[0].getValue().toString('utf8'), 'this is a value in Riak');
+            done();
+            
+        };
+      
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName + '_sv')
+               .withBucketType(Test.bucketType)
+               .withKey('my_key1')
+               .withContent('this is a value in Riak')
+               .withCallback(callback)
+               .withReturnBody(true)
+               .build();
+       
+       cluster.execute(store);
+       
+   });
+   
+   it('Should store an object and not return it (returnBody=false)', function(done) {
+      
+       var callback = function(err, resp) {
+            assert(!err, err);
+            assert.equal(resp.generatedKey, null);
+            assert(!resp.vclock);
+            assert.equal(resp.values.length, 0);
+            done();
+            
+        };
+      
+        var store = new StoreValue.Builder()
+               .withBucket(Test.bucketName + '_sv')
+               .withKey('my_key4')
+               .withContent('this is a value in Riak')
+               .withCallback(callback)
+               .build();
+       
+       cluster.execute(store);
+       
+   });
+   
+   it('Should store a value and generate a key, returning it', function(done) {
+      
+        var callback = function(err, resp) {
+             assert(!err, err);
+             assert(resp.generatedKey);
+             done();
+
+         };
+
+         var store = new StoreValue.Builder()
+                .withBucket(Test.bucketName + '_sv')
+                .withContent('this is a value in Riak')
+                .withCallback(callback)
+                .build();
+       
+        cluster.execute(store);
+       
+   });
+   
+   after(function(done) {
+        Test.cleanBucket(cluster, 'default', Test.bucketName + '_sv', function() { 
+            Test.cleanBucket(cluster, Test.bucketType, Test.bucketName + '_sv', function() {
+                cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+                cluster.stop();
+            });
+        });
+        
+   });
+   
+});
+
diff --git a/test/integration/mapreduce/mapreduce.js b/test/integration/mapreduce/mapreduce.js
new file mode 100644
index 0000000..6f69f84
--- /dev/null
+++ b/test/integration/mapreduce/mapreduce.js
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreProps = require('../../../lib/commands/kv/storebucketprops');
+var MapReduce = require('../../../lib/commands/mapreduce/mapreduce');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('MapReduce - Integration', function() {
+   
+    var cluster;
+    this.timeout(30000);
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        var stuffToStore = [
+
+            "Alice was beginning to get very tired of sitting by her sister on the " +
+                                "bank, and of having nothing to do: once or twice she had peeped into the " +
+                                "book her sister was reading, but it had no pictures or conversations in " +
+                                "it, 'and what is the use of a book,' thought Alice 'without pictures or " +
+                                "conversation?'",
+            "So she was considering in her own mind (as well as she could, for the " +
+                                "hot day made her feel very sleepy and stupid), whether the pleasure " +
+                                "of making a daisy-chain would be worth the trouble of getting up and " +
+                                "picking the daisies, when suddenly a White Rabbit with pink eyes ran " +
+                                "close by her.",
+
+            "The rabbit-hole went straight on like a tunnel for some way, and then " +
+                                "dipped suddenly down, so suddenly that Alice had not a moment to think " +
+                                "about stopping herself before she found herself falling down a very deep " +
+                                "well."
+
+
+        ];
+        
+        var count = 0;
+        var storeCb = function(err, resp) {
+            if (count < 3) {
+                var store = new StoreValue.Builder()
+                    .withBucket(Test.bucketName + '_mr')
+                    .withKey('p' + count)
+                    .withContent(stuffToStore[count])
+                    .withCallback(storeCb)	
+                    .build();
+
+                count++;
+                cluster.execute(store);
+            } else {
+                done();
+            }
+        };
+
+        storeCb();
+    });
+
+    
+    after(function(done) {
+       Test.cleanBucket(cluster, 'default', Test.bucketName + '_mr', function() {
+            cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+            cluster.stop();
+        }); 
+    });
+    
+    it('Should Map and Reduce', function(done) {
+       
+        var callback = function(err, resp) {
+          
+            assert(!err, err);
+            if (resp.done) {
+                done();
+            } else {
+                assert(resp.response.length > 0);
+            }
+            
+        };
+       
+        var query = "{\"inputs\":[[\"mr_bucket\",\"p0\"]," +
+            "[\"mr_bucket\",\"p1\"]," +
+            "[\"mr_bucket\",\"p2\"]]," +
+            "\"query\":[{\"map\":{\"language\":\"javascript\",\"source\":\"" +
+            "function(v) {var m = v.values[0].data.toLowerCase().match(/\\w*/g); var r = [];" +
+            "for(var i in m) {if(m[i] != '') {var o = {};o[m[i]] = 1;r.push(o);}}return r;}" +
+            "\"}},{\"reduce\":{\"language\":\"javascript\",\"source\":\"" +
+            "function(v) {var r = {};for(var i in v) {for(var w in v[i]) {if(w in r) r[w] += v[i][w];" +
+            "else r[w] = v[i][w];}}return [r];}\"}}]}";
+	
+		var mr = new MapReduce(query, callback);
+		cluster.execute(mr);
+        
+        
+    });
+
+
+});
\ No newline at end of file
diff --git a/test/integration/riakconnection.js b/test/integration/riakconnection.js
index 72ab5bd..a9f7ace 100644
--- a/test/integration/riakconnection.js
+++ b/test/integration/riakconnection.js
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+var Test = require('./testparams');
 var RiakConnection = require('../../lib/core/riakconnection');
 var assert = require('assert');
 var fs = require('fs');
@@ -34,8 +35,8 @@ describe('RiakConnection - Integration', function() {
         it('should emit on connection success', function(done) {
 
             var conn = new RiakConnection({
-                remoteAddress : 'riak-test',
-                remotePort : 10017,
+                remoteAddress : Test.riakHost,
+                remotePort : Test.riakPort,
                 connectionTimeout : 30000,
                 auth: {
                     // Use the following when the private key and public cert
@@ -72,8 +73,8 @@ describe('RiakConnection - Integration', function() {
         it('should emit on connection success', function(done) {
 
             var conn = new RiakConnection({
-                remoteAddress : 'riak-test',
-                remotePort : 10017,
+                remoteAddress : Test.riakHost,
+                remotePort : Test.riakPort,
                 connectionTimeout : 5000,
                 auth: {
                     user: 'riakpass',
@@ -105,10 +106,11 @@ describe('RiakConnection - Integration', function() {
         this.timeout(5000);
         
         it('should emit on connection success', function(done) {
-            var conn = new RiakConnection({ remoteAddress : "127.0.0.1",
-                                            remotePort : 1337,
-                                            connectionTimeout : 30000
-                                          });
+            var conn = new RiakConnection({
+                remoteAddress : "127.0.0.1",
+                remotePort : 1337,
+                connectionTimeout : 30000
+            });
             var errTimeout = setTimeout(function () {
                 assert(false, 'Event never fired');
                 done();
diff --git a/test/integration/testparams.js b/test/integration/testparams.js
new file mode 100644
index 0000000..943c9aa
--- /dev/null
+++ b/test/integration/testparams.js
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var ListKeys = require('../../lib/commands/kv/listkeys');
+var DeleteValue = require('../../lib/commands/kv/deletevalue');
+var assert = require('assert');
+var logger = require('winston');
+/*
+ * To increase logging verbosity: */
+
+logger.remove(logger.transports.Console);
+logger.add(logger.transports.Console, {
+    level : 'debug',
+    colorize: true,
+    timestamp: true
+});
+// */
+
+
+module.exports.bucketName = 'riak_index_tests';
+
+/**
+* Bucket type
+* 
+* you must create the type 'plain' to use this:
+*
+* riak-admin bucket-type create plain '{"props":{}}'
+* riak-admin bucket-type activate plain
+*/
+module.exports.bucketType = 'leveldb_type';
+
+var riakHost = 'riak-test';
+var riakPort = 10017;
+if (process.env.RIAK_HOST && process.env.RIAK_PORT) {
+    riakHost = process.env.RIAK_HOST;
+    riakPort = process.env.RIAK_PORT;
+}
+module.exports.nodeAddresses = [ riakHost + ':' + riakPort ];
+module.exports.riakHost = riakHost;
+module.exports.riakPort = riakPort;
+/**
+ * 
+ * CRDTs - need to create these types 
+ */
+module.exports.counterBucketType = 'counters';
+module.exports.setBucketType = 'sets';
+module.exports.mapBucketType = 'maps';
+
+
+module.exports.cleanBucket = function(cluster, type, bucket, callback) {
+  
+    // Note this also acts as the integration test for ListKeys and 
+    // DeleteValue
+    logger.debug('Clearing bucket: %s:%s', type, bucket);
+    var numKeys = 0;
+    var count = 0;
+    var lkCallback = function(err, resp) {
+        assert(!err, err);
+        
+        numKeys += resp.keys.length;
+
+        if (numKeys > 0) {
+            logger.debug('\tkey count to delete %s', numKeys);
+        } else {
+            logger.debug('DONE clearing bucket: %s:%s', type, bucket);
+            callback();
+        }
+        
+        var dCallback = function(err, resp) {
+            assert(!err, err);
+            count++;
+            if (count === numKeys) {
+                logger.debug('DONE clearing bucket: %s:%s', type, bucket);
+                callback();
+            }
+        };
+        
+        for (var i = 0; i < resp.keys.length; i++) {
+            
+            var del = new DeleteValue.Builder()
+                    .withBucket(resp.bucket)
+                    .withBucketType(resp.bucketType)
+                    .withKey(resp.keys[i])
+                    .withCallback(dCallback)
+                    .build();
+            
+            cluster.execute(del);
+        }
+        
+    };
+    
+    var list = new ListKeys.Builder()
+            .withBucket(bucket)
+            .withBucketType(type)
+            .withCallback(lkCallback)
+            .withStreaming(false)
+            .build();
+    
+    cluster.execute(list);
+    
+};
+
diff --git a/test/integration/yokozuna/search.js b/test/integration/yokozuna/search.js
new file mode 100644
index 0000000..f671a8e
--- /dev/null
+++ b/test/integration/yokozuna/search.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreIndex = require('../../../lib/commands/yokozuna/storeindex');
+var FetchIndex = require('../../../lib/commands/yokozuna/fetchindex');
+var DeleteIndex = require('../../../lib/commands/yokozuna/deleteindex');
+var Search = require('../../../lib/commands/yokozuna/search');
+var StoreProps = require('../../../lib/commands/kv/storebucketprops');
+var StoreValue = require('../../../lib/commands/kv/storevalue');
+
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Search - Integration', function() {
+   
+    var cluster;
+    this.timeout(30000);
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        
+        var callback = function(err, resp) {
+          
+            assert(!err, err);
+            assert(resp);
+        };
+    
+        var store = new StoreIndex.Builder()
+				.withIndexName('myIndex')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(store);
+
+
+        var prepSearch = function() {
+          
+            var stuffToStore = [
+
+                "{ \"content_s\":\"Alice was beginning to get very tired of sitting by her sister on the " +
+                                    "bank, and of having nothing to do: once or twice she had peeped into the " +
+                                    "book her sister was reading, but it had no pictures or conversations in " +
+                                    "it, 'and what is the use of a book,' thought Alice 'without pictures or " +
+                                    "conversation?'\"}",
+                "{ \"content_s\":\"So she was considering in her own mind (as well as she could, for the " +
+                                    "hot day made her feel very sleepy and stupid), whether the pleasure " +
+                                    "of making a daisy-chain would be worth the trouble of getting up and " +
+                                    "picking the daisies, when suddenly a White Rabbit with pink eyes ran " +
+                                    "close by her.\", \"multi_ss\":[\"this\",\"that\"]}",
+
+                "{ \"content_s\":\"The rabbit-hole went straight on like a tunnel for some way, and then " +
+                                    "dipped suddenly down, so suddenly that Alice had not a moment to think " +
+                                    "about stopping herself before she found herself falling down a very deep " +
+                                    "well.\"}"
+
+
+            ];
+        
+            var count = 0;
+            var storeCb = function(err, resp) {
+                if (count < 3) {
+                    var store = new StoreValue.Builder()
+                        .withBucket(Test.bucketName + '_search')
+                        .withKey('p' + count)
+                        .withContent(stuffToStore[count])
+                        .withCallback(storeCb)	
+                        .build();
+
+                    count++;
+                    cluster.execute(store);
+                } else {
+                    done();
+                }
+            };
+            
+            storeCb();
+
+
+        };
+
+        var setOnBucket = function() {
+            
+            var store = new StoreProps.Builder()
+				.withBucket(Test.bucketName + '_search')
+				.withSearchIndex('myIndex')
+				.withCallback(function(err, resp) { assert(!err, err); prepSearch(); })
+				.build();
+
+            cluster.execute(store);
+            
+        };
+
+        var count = 0;
+        fmCallback = function(err, resp) {
+            count++;
+            if(err && err === 'notfound') {
+                if (count < 6) {
+                    setTimeout(fetchme, 2000 * count);
+                } else {
+                    assert(!err, err);
+                }
+            } else {
+                assert(resp);
+                setOnBucket();
+            }
+        };
+
+        var fetchme = function() {
+            var fetch = new FetchIndex.Builder()
+				.withIndexName('myIndex')
+				.withCallback(fmCallback)
+				.build();
+
+            cluster.execute(fetch);
+        };
+        
+        fetchme();
+    
+    });
+    
+    after(function(done) {
+        
+        var bpCallback = function(err, resp) {
+            assert(!err, err);
+            Test.cleanBucket(cluster, 'default', Test.bucketName + '_search', function() {
+                cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+                cluster.stop();
+            });
+            
+        };
+        
+        var store = new StoreProps.Builder()
+				.withBucket(Test.bucketName + '_search')
+				.withSearchIndex('_dont_index_')
+				.withCallback(bpCallback)
+				.build();
+
+        cluster.execute(store);
+        
+        
+    });
+        
+   
+    it('Should perform a search', function(done) {
+       
+        var count = 0;
+        var callback = function(err, resp) {
+            assert(!err, err);
+            count++;
+            if(resp.numFound === 0) {
+                if(count < 6) {
+                    setTimeout(searchme, 2000 * count);
+                } else {
+                    assert.fail('Search failed; ' + resp);
+                }
+            } else {
+               done();
+            }
+        };
+        
+        
+        var searchme = function() {
+            var search = new Search.Builder()
+                .withIndexName('myIndex')
+                .withQuery('multi_ss:t*')
+                .withCallback(callback)
+                .build();
+            
+            cluster.execute(search);
+        };
+        
+        searchme();
+        
+    });
+   
+    
+    
+});
\ No newline at end of file
diff --git a/test/integration/yokozuna/storeandfetchschema.js b/test/integration/yokozuna/storeandfetchschema.js
new file mode 100644
index 0000000..654164c
--- /dev/null
+++ b/test/integration/yokozuna/storeandfetchschema.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreSchema = require('../../../lib/commands/yokozuna/storeschema');
+var FetchSchema = require('../../../lib/commands/yokozuna/fetchschema');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Update and Fetch Yokozuna schema - Integration', function() {
+   
+    var cluster;
+    this.timeout(10000);
+    var defaultSchema;
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp.content);
+            defaultSchema = resp.content;
+            done();
+        };
+        
+        var fetch = new FetchSchema.Builder()
+				.withSchemaName('_yz_default')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(fetch);
+
+        
+    });
+    
+    after(function(done) {
+       cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+       cluster.stop(); 
+    });
+    
+    it('Should store a schema', function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp);
+            done();
+        };
+       
+        var store = new StoreSchema.Builder()
+					.withSchemaName('mySchema')
+					.withSchema(defaultSchema)
+					.withCallback(callback)
+					.build();
+
+	cluster.execute(store);	
+        
+    });
+    
+    it('Should fetch a schema', function(done) {
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp);
+            done();
+        };
+        
+        var fetch = new FetchSchema.Builder()
+				.withSchemaName('mySchema')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(fetch);
+        
+    });
+    
+});
\ No newline at end of file
diff --git a/test/integration/yokozuna/storefetchdeleteindex.js b/test/integration/yokozuna/storefetchdeleteindex.js
new file mode 100644
index 0000000..fcc4b0d
--- /dev/null
+++ b/test/integration/yokozuna/storefetchdeleteindex.js
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 Basho Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Test = require('../testparams');
+var StoreIndex = require('../../../lib/commands/yokozuna/storeindex');
+var FetchIndex = require('../../../lib/commands/yokozuna/fetchindex');
+var DeleteIndex = require('../../../lib/commands/yokozuna/deleteindex');
+
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+describe('Update and Fetch Yokozuna index - Integration', function() {
+   
+    var cluster;
+    this.timeout(30000);
+    
+    before(function(done) {
+        var nodes = RiakNode.buildNodes(Test.nodeAddresses);
+        cluster = new RiakCluster({ nodes: nodes});
+        cluster.start();
+        
+        
+        var callback = function(err, resp) {
+          
+            assert(!err, err);
+            assert(resp);
+            done();
+            
+        };
+    
+        var store = new StoreIndex.Builder()
+				.withIndexName('myIndex')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(store);
+
+    
+    });
+    
+    after(function(done) {
+       
+        var callback = function(err, resp) {
+            assert(!err, err);
+            assert(resp);
+            cluster.on('stateChange', function(state) { if (state === RiakCluster.State.SHUTDOWN) { done();} });
+            cluster.stop();
+        };
+        
+        var del = new DeleteIndex.Builder()
+				.withIndexName('myIndex')
+				.withCallback(callback)
+				.build();
+
+        cluster.execute(del);
+
+        
+    });
+    
+    
+    it('Should fetch an index', function(done) {
+       
+        var count = 0;
+        var callback = function(err, resp) {
+            count++;
+            if(err && err === 'notfound') {
+                if (count < 6) {
+                    setTimeout(fetchme, 2000 * count);
+                } else {
+                    assert(!err, err);
+                }
+            } else {
+                assert(resp);
+                done();
+            }
+        };
+
+        var fetchme = function() {
+            var fetch = new FetchIndex.Builder()
+				.withIndexName('myIndex')
+				.withCallback(callback)
+				.build();
+
+            cluster.execute(fetch);
+        };
+        
+        fetchme();
+        
+    });
+    
+});
\ No newline at end of file
diff --git a/test/unit/crdt/fetchcounter.js b/test/unit/crdt/fetchcounter.js
index c5ad504..fdfedd5 100644
--- a/test/unit/crdt/fetchcounter.js
+++ b/test/unit/crdt/fetchcounter.js
@@ -61,7 +61,7 @@ describe('FetchCounter', function() {
             
             var callback = function(err, response) {
                 if (response) {
-                    assert.equal(response, 42);
+                    assert.equal(response.counterValue, 42);
                     done();
                 }
             };
diff --git a/test/unit/crdt/fetchmap.js b/test/unit/crdt/fetchmap.js
index a11997f..be31b9f 100644
--- a/test/unit/crdt/fetchmap.js
+++ b/test/unit/crdt/fetchmap.js
@@ -83,16 +83,16 @@ describe('FetchMap', function() {
                 mapEntry.set_value.push.apply(mapEntry.set_value, [ByteBuffer.fromUTF8('value_1'), ByteBuffer.fromUTF8('value_2')]);
                 mapEntries.push(mapEntry);
                 
-                var mapEntry = new MapEntry();
-                var mapField = new MapField();
+                mapEntry = new MapEntry();
+                mapField = new MapField();
                 mapField.setType(MapField.MapFieldType.REGISTER);
                 mapField.setName(new Buffer('register_1'));
                 mapEntry.setField(mapField);
                 mapEntry.setRegisterValue(ByteBuffer.fromUTF8('1234'));
                 mapEntries.push(mapEntry);
                 
-                var mapEntry = new MapEntry();
-                var mapField = new MapField();
+                mapEntry = new MapEntry();
+                mapField = new MapField();
                 mapField.setType(MapField.MapFieldType.FLAG);
                 mapField.setName(new Buffer('flag_1'));
                 mapEntry.setField(mapField);
@@ -121,15 +121,15 @@ describe('FetchMap', function() {
                 assert.equal(resp.context.toString('utf8'), '1234');
                 
                 var verifyMap = function(map) {
-                    assert.equal(map.counters['counter_1'], 50);
-                    assert.equal(map.sets['set_1'][0], 'value_1');
-                    assert.equal(map.sets['set_1'][1], 'value_2');
-                    assert.equal(map.registers['register_1'].toString('utf8'), '1234');
-                    assert.equal(map.flags['flag_1'], true);
+                    assert.equal(map.counters.counter_1, 50);
+                    assert.equal(map.sets.set_1[0], 'value_1');
+                    assert.equal(map.sets.set_1[1], 'value_2');
+                    assert.equal(map.registers.register_1.toString('utf8'), '1234');
+                    assert.equal(map.flags.flag_1, true);
                 };
             
                 verifyMap(resp.map);
-                verifyMap(resp.map.maps['map_1']);
+                verifyMap(resp.map.maps.map_1);
                 done();
             
             };
@@ -150,4 +150,4 @@ describe('FetchMap', function() {
     
     
     
-});
\ No newline at end of file
+});
diff --git a/test/unit/crdt/updatemap.js b/test/unit/crdt/updatemap.js
index e44f7c8..77a1fbe 100644
--- a/test/unit/crdt/updatemap.js
+++ b/test/unit/crdt/updatemap.js
@@ -225,16 +225,16 @@ describe('UpdateMap', function() {
                 mapEntry.set_value.push.apply(mapEntry.set_value, [ByteBuffer.fromUTF8('value_1'), ByteBuffer.fromUTF8('value_2')]);
                 mapEntries.push(mapEntry);
                 
-                var mapEntry = new MapEntry();
-                var mapField = new MapField();
+                mapEntry = new MapEntry();
+                mapField = new MapField();
                 mapField.setType(MapField.MapFieldType.REGISTER);
                 mapField.setName(new Buffer('register_1'));
                 mapEntry.setField(mapField);
                 mapEntry.setRegisterValue(ByteBuffer.fromUTF8('1234'));
                 mapEntries.push(mapEntry);
                 
-                var mapEntry = new MapEntry();
-                var mapField = new MapField();
+                mapEntry = new MapEntry();
+                mapField = new MapField();
                 mapField.setType(MapField.MapFieldType.FLAG);
                 mapField.setName(new Buffer('flag_1'));
                 mapEntry.setField(mapField);
@@ -262,15 +262,15 @@ describe('UpdateMap', function() {
                 assert.equal(resp.context.toString('utf8'), '1234');
                 
                 var verifyMap = function(map) {
-                    assert.equal(map.counters['counter_1'], 50);
-                    assert.equal(map.sets['set_1'][0], 'value_1');
-                    assert.equal(map.sets['set_1'][1], 'value_2');
-                    assert.equal(map.registers['register_1'].toString('utf8'), '1234');
-                    assert.equal(map.flags['flag_1'], true);
+                    assert.equal(map.counters.counter_1, 50);
+                    assert.equal(map.sets.set_1[0], 'value_1');
+                    assert.equal(map.sets.set_1[1], 'value_2');
+                    assert.equal(map.registers.register_1.toString('utf8'), '1234');
+                    assert.equal(map.flags.flag_1, true);
                 };
             
                 verifyMap(resp.map);
-                verifyMap(resp.map.maps['map_1']);
+                verifyMap(resp.map.maps.map_1);
                 done();
             
             };
diff --git a/test/unit/crdt/updateset.js b/test/unit/crdt/updateset.js
index fad5870..a0dcbce 100644
--- a/test/unit/crdt/updateset.js
+++ b/test/unit/crdt/updateset.js
@@ -113,7 +113,7 @@ describe('UpdateSet', function() {
 
     describe('with body, without key, as buffers', function() {
         it('calls back with successful results', function(done) {
-            var resp = new DtUpdateResp;
+            var resp = new DtUpdateResp();
             resp.setContext(new Buffer("asdf"));
             resp.setSetValue([hampenBuffer, snabbfotadBuffer]);
 
@@ -141,7 +141,7 @@ describe('UpdateSet', function() {
 
     describe('with body, without key, as strings', function() {
         it('calls back with successful results', function(done) {
-            var resp = new DtUpdateResp;
+            var resp = new DtUpdateResp();
             resp.setContext(new Buffer("asdf"));
             resp.setSetValue([hampenBuffer, snabbfotadBuffer]);
 
diff --git a/test/unit/fetchvalue.js b/test/unit/fetchvalue.js
index 0f6a26f..106c41c 100644
--- a/test/unit/fetchvalue.js
+++ b/test/unit/fetchvalue.js
@@ -81,8 +81,8 @@ describe('FetchValue', function() {
             
             var callback = function(err, response) {
                 if (response) {
-                    assert.equal(response.getRiakObjects().length, 1);
-                    var riakObject = response.getRiakObjects()[0];
+                    assert.equal(response.values.length, 1);
+                    var riakObject = response.values[0];
                     assert.equal(riakObject.getBucketType(), 'bucket_type');
                     assert.equal(riakObject.getBucket(), 'bucket_name');
                     assert.equal(riakObject.getKey(), 'key');
diff --git a/test/unit/listbuckets.js b/test/unit/listbuckets.js
index 99fad40..b4c3a87 100644
--- a/test/unit/listbuckets.js
+++ b/test/unit/listbuckets.js
@@ -42,10 +42,10 @@ describe('ListBuckets', function() {
         
         it('should take multiple RpbListBucketsResp and call the users callback with the response', function(done) {
            
-            var callback = function(err, buckets, complete){
-                
-                assert.equal(buckets.length, 100);
-                assert.equal(complete, true);
+            var callback = function(err, resp){
+                assert(!err, err);
+                assert.equal(resp.buckets.length, 100);
+                assert.equal(resp.done, true);
                 done();
             };
             
@@ -72,11 +72,11 @@ describe('ListBuckets', function() {
            
             var count = 0;
             var timesCalled = 0;
-            var callback = function(err, buckets, complete){
+            var callback = function(err, resp){
                 
                 timesCalled++;
-                count += buckets.length;
-                if (complete) {
+                count += resp.buckets.length;
+                if (resp.done) {
                     assert.equal(timesCalled, 20);
                     assert.equal(count, 100);
                     done();
diff --git a/test/unit/listkeys.js b/test/unit/listkeys.js
index 373bd6c..8c4e7ea 100644
--- a/test/unit/listkeys.js
+++ b/test/unit/listkeys.js
@@ -40,10 +40,10 @@ describe('ListKeys', function() {
         
         it('should take multiple RpbListKeysResp and call the users callback with the response', function(done) {
            
-            var callback = function(err, keys, complete){
+            var callback = function(err, resp){
                 
-                assert.equal(keys.length, 100);
-                assert.equal(complete, true);
+                assert.equal(resp.keys.length, 100);
+                assert.equal(resp.done, true);
                 done();
             };
             
@@ -71,11 +71,11 @@ describe('ListKeys', function() {
            
             var count = 0;
             var timesCalled = 0;
-            var callback = function(err, keys, complete){
+            var callback = function(err, resp){
                 
                 timesCalled++;
-                count += keys.length;
-                if (complete) {
+                count += resp.keys.length;
+                if (resp.done) {
                     assert.equal(timesCalled, 20);
                     assert.equal(count, 100);
                     done();
diff --git a/test/unit/mapreduce/mapreduce.js b/test/unit/mapreduce/mapreduce.js
index be5f793..9c63765 100644
--- a/test/unit/mapreduce/mapreduce.js
+++ b/test/unit/mapreduce/mapreduce.js
@@ -49,13 +49,13 @@ describe('MapReduce', function() {
             resp.response = new Buffer('[{ "the": 8}]');
             resp.done = true;
             
-            var callback = function(err, resp, complete) {
+            var callback = function(err, resp) {
                 assert(resp.phase_1);
                 // returned JSON is parsed and returned as JS
                 assert.equal(resp.phase_1.constructor, Array);
                 assert.equal(resp.phase_1.length, 1);
                 assert.equal(resp.phase_1[0].the, 8);
-                assert.equal(complete, true);
+                assert.equal(resp.done, true);
                 done();
             };
             
@@ -73,13 +73,13 @@ describe('MapReduce', function() {
             resp.response = new Buffer('[{ "the": 8}]');
             resp.done = true;
             
-            var callback = function(err, resp, complete) {
+            var callback = function(err, resp) {
                 assert.equal(resp.phase, 1);
                 // returned JSON is parsed and returned as JS
                 assert.equal(resp.response.constructor, Array);
                 assert.equal(resp.response.length, 1);
                 assert.equal(resp.response[0].the, 8);
-                assert.equal(complete, true);
+                assert.equal(resp.done, true);
                 done();
             };
             
diff --git a/test/unit/secondaryindexquery.js b/test/unit/secondaryindexquery.js
index 8fb1697..6bbf840 100644
--- a/test/unit/secondaryindexquery.js
+++ b/test/unit/secondaryindexquery.js
@@ -155,13 +155,13 @@ describe('SecondaryIndexQuery', function() {
         
         it('should take multiple RpbIndexResp with just object keys and call the users callback with the response', function(done) {
             
-            var callback = function(err, response, complete, continuation) {
+            var callback = function(err, response) {
                 
-                assert.equal(response.length, 100);
-                assert.equal(response[0].indexKey, null);
-                assert.equal(response[0].objectKey, 'object_key');
-                assert.equal(complete, true);
-                assert.equal(continuation.toString('utf8'), '1234');
+                assert.equal(response.values.length, 100);
+                assert.equal(response.values[0].indexKey, null);
+                assert.equal(response.values[0].objectKey, 'object_key');
+                assert.equal(response.done, true);
+                assert.equal(response.continuation.toString('utf8'), '1234');
                 done();
             };
             
@@ -188,13 +188,13 @@ describe('SecondaryIndexQuery', function() {
         
         it('should take multiple RpbIndexResp with term/key pairs and call the users callback with the response', function(done) {
             
-            var callback = function(err, response, complete, continuation) {
+            var callback = function(err, response) {
                 
-                assert.equal(response.length, 100);
-                assert.equal(response[0].indexKey, 'index_key');
-                assert.equal(response[0].objectKey, 'object_key');
-                assert.equal(complete, true);
-                assert.equal(continuation.toString('utf8'), '1234');
+                assert.equal(response.values.length, 100);
+                assert.equal(response.values[0].indexKey, 'index_key');
+                assert.equal(response.values[0].objectKey, 'object_key');
+                assert.equal(response.done, true);
+                assert.equal(response.continuation.toString('utf8'), '1234');
                 done();
             };
             
@@ -227,19 +227,19 @@ describe('SecondaryIndexQuery', function() {
             
             var count = 0;
             var timesCalled = 0;
-            var callback = function(err, response, complete, continuation) {
+            var callback = function(err, response) {
                 
                 timesCalled++;
-                count += response.length;
+                count += response.values.length;
                 
-                assert.equal(response[0].indexKey, null);
-                assert.equal(response[0].objectKey, 'object_key');
+                assert.equal(response.values[0].indexKey, null);
+                assert.equal(response.values[0].objectKey, 'object_key');
                 
                 
-                if (complete) {
+                if (response.done) {
                     assert.equal(timesCalled, 20);
                     assert.equal(count, 100);
-                    assert.equal(continuation.toString('utf8'), '1234');
+                    assert.equal(response.continuation.toString('utf8'), '1234');
                     done();
                 }
             };
@@ -269,18 +269,18 @@ describe('SecondaryIndexQuery', function() {
             
             var count = 0;
             var timesCalled = 0;
-            var callback = function(err, response, complete, continuation) {
+            var callback = function(err, response) {
                 timesCalled++;
-                count += response.length;
+                count += response.values.length;
                 
-                assert.equal(response[0].indexKey, 123);
-                assert.equal(response[0].objectKey, 'object_key');
+                assert.equal(response.values[0].indexKey, 123);
+                assert.equal(response.values[0].objectKey, 'object_key');
                 
                 
-                if (complete) {
+                if (response.done) {
                     assert.equal(timesCalled, 20);
                     assert.equal(count, 100);
-                    assert.equal(continuation.toString('utf8'), '1234');
+                    assert.equal(response.continuation.toString('utf8'), '1234');
                     done();
                 }
             };
diff --git a/test/unit/storevalue.js b/test/unit/storevalue.js
index effdd69..e24d623 100644
--- a/test/unit/storevalue.js
+++ b/test/unit/storevalue.js
@@ -77,6 +77,32 @@ describe('StoreValue', function() {
             
         });
         
+        it('Should take the key, bucket, type and vclock from a RiakObject', function(done) {
+           
+            var value = 'this is a value';
+            var riakObject = new RiakObject()
+                    .setKey('key')
+                    .setBucket('bucket_name')
+                    .setBucketType('bucket_type')
+                    .setVClock(new Buffer('1234'))
+                    .setValue('this is a value');
+            
+            var storeCommand = new StoreValue.Builder()
+                    .withContent(riakObject)
+                    .withCallback(function(){})
+                    .build();
+            
+            var protobuf = storeCommand.constructPbRequest();
+            
+            assert.equal(protobuf.getType().toString('utf8'), 'bucket_type');
+            assert.equal(protobuf.getBucket().toString('utf8'), 'bucket_name');
+            assert.equal(protobuf.getKey().toString('utf8'), 'key');
+            assert.equal(protobuf.getVclock().toString('utf8'), '1234');
+            assert.equal(protobuf.getContent().getValue().toString('utf8'), 'this is a value');
+            done();
+            
+        });
+        
         it('should take a RpbPutResp and call the users callback with the response', function(done) {
             
             var rpbContent = new RpbContent();
@@ -99,8 +125,8 @@ describe('StoreValue', function() {
             
             var callback = function(err, response) {
                 if (response) {
-                    assert.equal(response.getRiakObjects().length, 1);
-                    var riakObject = response.getRiakObjects()[0];
+                    assert.equal(response.values.length, 1);
+                    var riakObject = response.values[0];
                     assert.equal(riakObject.getBucketType(), 'bucket_type');
                     assert.equal(riakObject.getBucket(), 'bucket_name');
                     assert.equal(riakObject.getKey(), 'key');