Repository: basho/riak-nodejs-client
Pull request #98 (2015-09-21 22:49:24)

READY: Implement Get/Set Bucket Type Properties
CLIENTS-595


Patch:
diff --git a/Gruntfile.js b/Gruntfile.js
index f4ad51a..7c8cc85 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -76,9 +76,11 @@ module.exports = function(grunt) {
 
   grunt.registerTask('lint', 'jshint');
   grunt.registerTask('unit', function (testSuite) {
-    testSuite = testSuite.trim();
-    if (testSuite !== '') {
-      grunt.config.set('mochaTest.unit.src', ['test/unit/' + testSuite + '/*.js']);
+    if (testSuite) {
+        testSuite = testSuite.trim();
+        if (testSuite !== '') {
+            grunt.config.set('mochaTest.unit.src', ['test/unit/' + testSuite + '/*.js']);
+        }
     }
     grunt.task.run(['jshint', 'mochaTest:unit']);
   });
diff --git a/lib/commands/commandbase.js b/lib/commands/commandbase.js
index 09bcd62..9a6bc9c 100644
--- a/lib/commands/commandbase.js
+++ b/lib/commands/commandbase.js
@@ -44,17 +44,14 @@ function CommandBase(pbRequestName, pbResponseName, callback) {
     var requestCode = ProtoBufFactory.getCodeFor(pbRequestName);
     this.expectedCode = ProtoBufFactory.getCodeFor(pbResponseName);
     this.pbBuilder = ProtoBufFactory.getProtoFor(pbRequestName);
-   
+
     var schema = Joi.func().required();
     var self = this;
     Joi.validate(callback, schema, function(err, option) {
-       
        if (err) {
            throw 'callback is required and must be a function.';
        }
-       
        self.callback = callback;
-        
     });
    
     this.header = new Buffer(5);
@@ -65,7 +62,6 @@ function CommandBase(pbRequestName, pbResponseName, callback) {
     // This is to facilitate debugging what pb messages this Command represents
     this.PbRequestName = pbRequestName;
     this.PbResponseName = pbResponseName;
-
 }
 
 /**
diff --git a/lib/commands/kv/fetchbucketprops.js b/lib/commands/kv/fetchbucketprops.js
index c805115..c15e431 100644
--- a/lib/commands/kv/fetchbucketprops.js
+++ b/lib/commands/kv/fetchbucketprops.js
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-var CommandBase = require('../commandbase');
+var FetchPropsBase = require('./fetchpropsbase');
 var inherits = require('util').inherits;
 var Joi = require('joi');
 
@@ -23,7 +23,6 @@ var Joi = require('joi');
  * @module KV
  */
 
-
 /**
  * Command used to fetch a bucket's properties from Riak.
  *
@@ -44,122 +43,26 @@ var Joi = require('joi');
  * @param {Function} callback The callback to be executed when the operation completes.
  * @param {String} callback.err An error message. Will ne null if no error.
  * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
- * @extends CommandBase
+ * @extends FetchPropsBase
  */
 function FetchBucketProps(options, callback) {
-
-    CommandBase.call(this, 'RpbGetBucketReq','RpbGetBucketResp', callback);
+    FetchPropsBase.call(this, 'RpbGetBucketReq','RpbGetBucketResp', callback);
     var self = this;
     Joi.validate(options, schema, function(err, options) {
-
         if (err) {
             throw err;
         }
-
         self.options = options;
     });
-
-    this.remainingTries = 1;
-
 }
 
-inherits(FetchBucketProps, CommandBase);
+inherits(FetchBucketProps, FetchPropsBase);
 
 FetchBucketProps.prototype.constructPbRequest = function() {
-
     var protobuf = this.getPbReqBuilder();
-
     protobuf.setType(new Buffer(this.options.bucketType));
     protobuf.setBucket(new Buffer(this.options.bucket));
-
     return protobuf;
-
-};
-
-FetchBucketProps.prototype.onSuccess = function(rpbGetBucketResp) {
-
-    var rpbBucketProps = rpbGetBucketResp.getProps();
-
-    var bucketProps  = {
-
-        nVal : rpbBucketProps.getNVal(),
-        allowMult : rpbBucketProps.getAllowMult(),
-        lastWriteWins: rpbBucketProps.getLastWriteWins(),
-        hasPrecommit : rpbBucketProps.getHasPrecommit(),
-        hasPostcommit: rpbBucketProps.getHasPostcommit(),
-        oldVClock : rpbBucketProps.getOldVclock(),
-        youngVClock: rpbBucketProps.getYoungVclock(),
-        bigVClock : rpbBucketProps.getBigVclock(),
-        smallVClock: rpbBucketProps.getSmallVclock(),
-        pr: rpbBucketProps.getPr(),
-        r: rpbBucketProps.getR(),
-        w: rpbBucketProps.getW(),
-        pw: rpbBucketProps.getPw(),
-        dw: rpbBucketProps.getDw(),
-        rw: rpbBucketProps.getRw(),
-        basicQuorum: rpbBucketProps.getBasicQuorum(),
-        notFoundOk: rpbBucketProps.getNotfoundOk(),
-        search: rpbBucketProps.getSearch(),
-        consistent: rpbBucketProps.getConsistent(),
-        repl: rpbBucketProps.getRepl()
-    };
-
-    var backend;
-    if ((backend = rpbBucketProps.getBackend()) !== null) {
-        bucketProps.backend = backend.toString('utf8');
-    }
-
-    var searchIndex;
-    if ((searchIndex = rpbBucketProps.getSearchIndex()) !== null) {
-        bucketProps.searchIndex = searchIndex.toString('utf8');
-    }
-
-    var dataType;
-    if ((dataType = rpbBucketProps.getDatatype()) !== null) {
-        bucketProps.dataType = dataType.toString('utf8');
-    }
-
-    if (rpbBucketProps.getHasPrecommit()) {
-        bucketProps.precommit = this._parseHooks(rpbBucketProps.getPrecommit());
-    } else {
-        bucketProps.precommit = [];
-    }
-
-    if (rpbBucketProps.getHasPostcommit()) {
-        bucketProps.postcommit = this._parseHooks(rpbBucketProps.getPostcommit());
-    } else {
-        bucketProps.postcommit = [];
-    }
-
-    var chashKeyFun;
-    if ((chashKeyFun = rpbBucketProps.getChashKeyfun()) !== null) {
-        bucketProps.chashKeyfun = { mod: chashKeyFun.module.toString('utf8'),
-            fun: chashKeyFun.function.toString('utf8') };
-    }
-
-    var linkfun;
-    if ((linkfun = rpbBucketProps.getLinkfun()) !== null) {
-        bucketProps.linkFun = { mod: linkfun.module.toString('utf8'),
-            fun: linkfun.function.toString('utf8') };
-    }
-
-    this._callback(null, bucketProps);
-    return true;
-
-};
-
-FetchBucketProps.prototype._parseHooks = function(rpbCommitHooks) {
-    var hooks = new Array(rpbCommitHooks.length);
-    for (var i = 0; i < rpbCommitHooks.length; i++) {
-        if (rpbCommitHooks[i].name) {
-            hooks[i] = { name: rpbCommitHooks[i].name.toString('utf8') };
-        } else {
-            hooks[i] = { mod: rpbCommitHooks[i].modfun.module.toString('utf8'),
-                fun: rpbCommitHooks[i].modfun.function.toString('utf8') };
-        }
-    }
-    return hooks;
-
 };
 
 var schema = Joi.object().keys({
@@ -168,7 +71,7 @@ var schema = Joi.object().keys({
 });
 
 /**
- * A builder for constructing GetBucketProps instances
+ * A builder for constructing FetchBucketProps instances
  *
  * Rather than having to manually construct the __options__ and instantiating
  * a FetchBucketProps directly, this builder may be used.
@@ -182,53 +85,34 @@ var schema = Joi.object().keys({
  * @class FetchBucketProps.Builder
  * @constructor
  */
-function Builder() {}
+function Builder() {
+    FetchPropsBase.Builder.call(this);
+}
+
+inherits(Builder, FetchPropsBase.Builder);
 
-Builder.prototype = {
-    /**
-     * Set the bucket.
-     * @method withBucket
-     * @param {String} bucket the bucket in Riak
-     * @chainable
-     */
-    withBucket : function(bucket) {
-        this.bucket = bucket;
-        return this;
-    },
-    /**
-     * Set the bucket type.
-     * If not supplied, 'default' is used.
-     * @method withBucketType
-     * @param {String} bucketType the bucket type in riak
-     * @chainable
-     */
-    withBucketType : function(bucketType) {
-        this.bucketType = bucketType;
-        return this;
-    },
-    /**
-     * Set the callback to be executed when the operation completes.
-     * @method withCallback
-     * @param {Function} callback The callback to be executed when the operation completes.
-     * @param {String} callback.err An error message. Will ne null if no error.
-     * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
-     * @chainable
-     */
-    withCallback : function(callback) {
-        this.callback = callback;
-        return this;
-    },
-    /**
-     * Construct a FetchBucketProps instance.
-     * @method build
-     * @return {FetchBucketProps}
-     */
-    build : function() {
-        var cb = this.callback;
-        delete this.callback;
-        return new FetchBucketProps(this, cb);
-    }
+/**
+ * Set the bucket.
+ * @method withBucket
+ * @param {String} bucket the bucket in Riak
+ * @chainable
+ */
+Builder.prototype.withBucket = function(bucket) {
+    this.bucket = bucket;
+    return this;
+};
+
+/**
+    * Construct a FetchBucketProps instance.
+    * @method build
+    * @return {FetchBucketProps}
+    */
+Builder.prototype.build = function() {
+    var cb = this.callback;
+    delete this.callback;
+    return new FetchBucketProps(this, cb);
 };
 
 module.exports = FetchBucketProps;
 module.exports.Builder = Builder;
+
diff --git a/lib/commands/kv/fetchbuckettypeprops.js b/lib/commands/kv/fetchbuckettypeprops.js
new file mode 100644
index 0000000..839c488
--- /dev/null
+++ b/lib/commands/kv/fetchbuckettypeprops.js
@@ -0,0 +1,103 @@
+/*
+ * 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 FetchPropsBase = require('./fetchpropsbase');
+var inherits = require('util').inherits;
+var Joi = require('joi');
+
+/**
+ * Provides the FetchBucketTypeProps class, its builder, and its response.
+ * @module KV
+ */
+
+/**
+ * Command used to fetch a bucket's properties from Riak.
+ *
+ * As a convenience, a builder class is provided:
+ *
+ *     var fetch = new FetchBucketTypeProps.Builder()
+ *         .withBucketType('my_type')
+ *         .withCallback(myCallback)
+ *         .build();
+ *
+ * See {{#crossLink "FetchBucketTypeProps.Builder"}}FetchBucketTypeProps.Builder{{/crossLink}}
+ * @class FetchBucketTypeProps
+ * @constructor
+ * @param {Object} options The options for this command
+ * @param {String} [options.bucketType=default] The bucket type in riak.
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will ne null if no error.
+ * @param {Object} callback.response The response from Riak. This is an oject with all the bucket type properties.
+ * @extends FetchPropsBase
+ */
+function FetchBucketTypeProps(options, callback) {
+    FetchPropsBase.call(this, 'RpbGetBucketTypeReq','RpbGetBucketResp', callback);
+    var self = this;
+    Joi.validate(options, schema, function(err, options) {
+        if (err) {
+            throw err;
+        }
+        self.options = options;
+    });
+    this.remainingTries = 1;
+}
+
+inherits(FetchBucketTypeProps, FetchPropsBase);
+
+FetchBucketTypeProps.prototype.constructPbRequest = function() {
+    var protobuf = this.getPbReqBuilder();
+    protobuf.setType(new Buffer(this.options.bucketType));
+    return protobuf;
+};
+
+var schema = Joi.object().keys({
+   bucketType: Joi.string().default('default')
+});
+
+/**
+ * A builder for constructing FetchBucketTypeProps instances
+ *
+ * Rather than having to manually construct the __options__ and instantiating
+ * a FetchBucketTypeProps directly, this builder may be used.
+ *
+ *     var fetch = new FetchBucketTypeProps.Builder()
+ *         .withBucketType('my_type')
+ *         .withCallback(myCallback)
+ *         .build();
+ *
+ * @class FetchBucketTypeProps.Builder
+ * @constructor
+ */
+function Builder() {
+    FetchPropsBase.Builder.call(this);
+}
+
+inherits(Builder, FetchPropsBase.Builder);
+
+/**
+ * Construct a FetchBucketTypeProps instance.
+ * @method build
+ * @return {FetchBucketTypeProps}
+ */
+Builder.prototype.build = function() {
+    var cb = this.callback;
+    delete this.callback;
+    return new FetchBucketTypeProps(this, cb);
+};
+
+module.exports = FetchBucketTypeProps;
+module.exports.Builder = Builder;
+
diff --git a/lib/commands/kv/fetchpropsbase.js b/lib/commands/kv/fetchpropsbase.js
new file mode 100644
index 0000000..3e2af9c
--- /dev/null
+++ b/lib/commands/kv/fetchpropsbase.js
@@ -0,0 +1,155 @@
+/*
+ * 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 CommandBase = require('../commandbase');
+var inherits = require('util').inherits;
+
+/**
+ * Base class for FetchBucketProps and FetchBucketTypeProps classes.
+ * @module KV
+ */
+
+/**
+ * @class FetchPropsBase
+ * @constructor
+ * @param {String} pbRequestName name of the Riak protocol buffer this command will send
+ * @param {String} pbResponseName name of the Riak protocol buffer this command will receive
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will ne null if no error.
+ * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
+ * @extends CommandBase
+ */
+function FetchPropsBase(pbRequestName, pbResponseName, callback) {
+    CommandBase.call(this, pbRequestName, pbResponseName, callback);
+}
+
+inherits(FetchPropsBase, CommandBase);
+
+FetchPropsBase.prototype.onSuccess = function(rpbGetBucketResp) {
+
+    var rpbBucketProps = rpbGetBucketResp.getProps();
+
+    var bucketProps  = {
+
+        nVal : rpbBucketProps.getNVal(),
+        allowMult : rpbBucketProps.getAllowMult(),
+        lastWriteWins: rpbBucketProps.getLastWriteWins(),
+        hasPrecommit : rpbBucketProps.getHasPrecommit(),
+        hasPostcommit: rpbBucketProps.getHasPostcommit(),
+        oldVClock : rpbBucketProps.getOldVclock(),
+        youngVClock: rpbBucketProps.getYoungVclock(),
+        bigVClock : rpbBucketProps.getBigVclock(),
+        smallVClock: rpbBucketProps.getSmallVclock(),
+        pr: rpbBucketProps.getPr(),
+        r: rpbBucketProps.getR(),
+        w: rpbBucketProps.getW(),
+        pw: rpbBucketProps.getPw(),
+        dw: rpbBucketProps.getDw(),
+        rw: rpbBucketProps.getRw(),
+        basicQuorum: rpbBucketProps.getBasicQuorum(),
+        notFoundOk: rpbBucketProps.getNotfoundOk(),
+        search: rpbBucketProps.getSearch(),
+        consistent: rpbBucketProps.getConsistent(),
+        repl: rpbBucketProps.getRepl()
+    };
+
+    var backend;
+    if ((backend = rpbBucketProps.getBackend()) !== null) {
+        bucketProps.backend = backend.toString('utf8');
+    }
+
+    var searchIndex;
+    if ((searchIndex = rpbBucketProps.getSearchIndex()) !== null) {
+        bucketProps.searchIndex = searchIndex.toString('utf8');
+    }
+
+    var dataType;
+    if ((dataType = rpbBucketProps.getDatatype()) !== null) {
+        bucketProps.dataType = dataType.toString('utf8');
+    }
+
+    if (rpbBucketProps.getHasPrecommit()) {
+        bucketProps.precommit = this._parseHooks(rpbBucketProps.getPrecommit());
+    } else {
+        bucketProps.precommit = [];
+    }
+
+    if (rpbBucketProps.getHasPostcommit()) {
+        bucketProps.postcommit = this._parseHooks(rpbBucketProps.getPostcommit());
+    } else {
+        bucketProps.postcommit = [];
+    }
+
+    var chashKeyFun;
+    if ((chashKeyFun = rpbBucketProps.getChashKeyfun()) !== null) {
+        bucketProps.chashKeyfun = { mod: chashKeyFun.module.toString('utf8'),
+            fun: chashKeyFun.function.toString('utf8') };
+    }
+
+    var linkfun;
+    if ((linkfun = rpbBucketProps.getLinkfun()) !== null) {
+        bucketProps.linkFun = { mod: linkfun.module.toString('utf8'),
+            fun: linkfun.function.toString('utf8') };
+    }
+
+    this._callback(null, bucketProps);
+    return true;
+
+};
+
+FetchPropsBase.prototype._parseHooks = function(rpbCommitHooks) {
+    var hooks = new Array(rpbCommitHooks.length);
+    for (var i = 0; i < rpbCommitHooks.length; i++) {
+        if (rpbCommitHooks[i].name) {
+            hooks[i] = { name: rpbCommitHooks[i].name.toString('utf8') };
+        } else {
+            hooks[i] = { mod: rpbCommitHooks[i].modfun.module.toString('utf8'),
+                fun: rpbCommitHooks[i].modfun.function.toString('utf8') };
+        }
+    }
+    return hooks;
+};
+
+function Builder() {}
+
+/**
+ * Set the bucket type.
+ * If not supplied, 'default' is used.
+ * @method withBucketType
+ * @param {String} bucketType the bucket type in riak
+ * @chainable
+ */
+Builder.prototype.withBucketType = function(bucketType) {
+    this.bucketType = bucketType;
+    return this;
+};
+
+/**
+ * Set the callback to be executed when the operation completes.
+ * @method withCallback
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will ne null if no error.
+ * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
+ * @chainable
+ */
+Builder.prototype.withCallback = function(callback) {
+    this.callback = callback;
+    return this;
+};
+
+module.exports = FetchPropsBase;
+module.exports.Builder = Builder;
+
diff --git a/lib/commands/kv/storebucketprops.js b/lib/commands/kv/storebucketprops.js
index b48eb3a..fe9249d 100644
--- a/lib/commands/kv/storebucketprops.js
+++ b/lib/commands/kv/storebucketprops.js
@@ -14,25 +14,24 @@
  * limitations under the License.
  */
 
-var CommandBase = require('../commandbase');
-var RpbBucketProps = require('../../protobuf/riakprotobuf').getProtoFor('RpbBucketProps');
-var RpbCommitHook = require('../../protobuf/riakprotobuf').getProtoFor('RpbCommitHook');
-var RpbModFun = require('../../protobuf/riakprotobuf').getProtoFor('RpbModFun');
+var rpb = require('../../protobuf/riakprotobuf');
 var inherits = require('util').inherits;
 var Joi = require('joi');
 
+var StorePropsBase = require('./storepropsbase');
+
 /**
  * Provides the StoreBucketProps class, its builder, and its response.
  * @module KV
  */
 
-
 /**
  * Command used to set the properties on a bucket in Riak.
  *
  * As a convenience, a builder class is provided:
  *
  *     var storeProps = new StoreBucketProps.Builder()
+ *                  .withBucket('my-bucket')
  *                  .withAllowMult(true)
  *                  .build();
  *
@@ -43,156 +42,33 @@ var Joi = require('joi');
  * @param {Object} options The properties to store
  * @param {String} options.bucket The bucket in riak.
  * @param {String} [options.bucketType] The bucket type in riak. If not supplied 'default is used'
- * @param {Number} [options.r] The R value.
- * @param {Number} [options.pr] The PR value.
- * @param {Number} [options.w] The W value.
- * @param {Number} [options.dw] The DW value.
- * @param {Number} [options.pw] The PW value.
- * @param {Number} [options.rw] The RW value.
- * @param {Boolean} [options.notFoundOk] If true a vnode returning notfound for a key increments the r tally.
- * @param {Boolean} [options.basicQuorum] Controls whether a read request should return early in some fail cases.
- * @param {Number} [options.nVal] The number of replicas.
- * @param {Boolean} [options.allowMult] Whether to allow sibling objects to be created.
- * @param {Boolean} [options.lastWriteWins] Whether to ignore vector clocks when writing.
- * @param {Number} [options.oldVClock] An epoch time value.
- * @param {Number} [options.youngVClock] An epoch time value.
- * @param {Number} [options.bigVClock] An epoch time value.
- * @param {Number} [options.smallVClock] An epoch time value.
- * @param {Sring} [options.backend] The name of the backend to use.
- * @param {Boolean} [options.search] Enable the pre-commit hook for Legacy Riak search.
- * @param {String} [options.indexName] The name of the search index to use.
- * @param {Object} [options.chashKeyfun] An object representing the Erlang func to use.
- * @param {Object[]} [options.precommit] Array of precommit hooks
- * @param {Object[]} [options.postcommit] Array of postcommit hooks
- * @param {Function} callback The callback to be executed when the operation completes.
- * @param {String} callback.err An error message. Will be null if no error.
- * @param {Boolean} callback.response the response from Riak. This will be true.
- * @extends CommandBase
+ * @extends StorePropsBase
  */
 function StoreBucketProps(options, callback) {
-    CommandBase.call(this, 'RpbSetBucketReq', 'RpbSetBucketResp', callback);
-
+    StorePropsBase.call(this, options, 'RpbSetBucketReq', 'RpbSetBucketResp', callback);
     var self = this;
-    Joi.validate(options, schema, function(err, options) {
-
+    Joi.validate(options, schema, { allowUnknown: true }, function(err, options) {
         if (err) {
             throw err;
         }
-
         self.options = options;
     });
-
-    this.remainingTries = 1;
-
 }
 
-inherits(StoreBucketProps, CommandBase);
+inherits(StoreBucketProps, StorePropsBase);
 
 StoreBucketProps.prototype.constructPbRequest = function() {
-
-    var protobuf = this.getPbReqBuilder();
-
+    var protobuf = StoreBucketProps.super_.prototype.constructPbRequest.call(this); 
     protobuf.setBucket(new Buffer(this.options.bucket));
     protobuf.setType(new Buffer(this.options.bucketType));
-
-    var props = new RpbBucketProps();
-
-    props.setNVal(this.options.nVal > 0 ? this.options.nVal : null );
-    props.setOldVclock(this.options.oldVClock >= 0 ? this.options.oldVClock : null);
-    props.setYoungVclock(this.options.youngVClock >= 0 ? this.options.youngVClock : null);
-    props.setBigVclock(this.options.bigVClock >= 0 ? this.options.bigVClock : null);
-    props.setSmallVclock(this.options.smallVClock >= 0 ? this.options.smallVClock : null);
-    props.setR(this.options.r >= 0 ? this.options.r : null);
-    props.setPr(this.options.pr >= 0 ? this.options.pr : null);
-    props.setW(this.options.w >= 0 ? this.options.w : null);
-    props.setPw(this.options.pw >= 0 ? this.options.pw : null);
-    props.setDw(this.options.dw >= 0 ? this.options.dw : null);
-    props.setRw(this.options.rw >= 0 ? this.options.rw : null);
-
-    props.setBasicQuorum(typeof this.options.basicQuorum === 'boolean' ? this.options.basicQuorum : null);
-    props.setNotfoundOk(typeof this.options.notFoundOk === 'boolean' ? this.options.notFoundOk : null);
-    props.setSearch(typeof this.options.search === 'boolean' ? this.options.search : null);
-    props.setAllowMult(typeof this.options.allowMult === 'boolean' ? this.options.allowMult : null);
-    props.setLastWriteWins(typeof this.options.lastWriteWins === 'boolean' ? this.options.lastWriteWins : null);
-
-    props.setBackend(this.options.backend ? new Buffer(this.options.backend) : null);
-    props.setSearchIndex(this.options.searchIndex ? new Buffer(this.options.searchIndex) : null);
-
-    if (this.options.precommit) {
-        props.setPrecommit(this._convertHooks(this.options.precommit));
-    }
-
-    if (this.options.postcommit) {
-        props.setPostcommit(this._convertHooks(this.options.postcommit));
-    }
-
-    if (this.options.chashKeyfun) {
-        var modfun = new RpbModFun();
-        modfun.module = new Buffer(this.options.chashKeyfun.mod);
-        modfun.function = new Buffer(this.options.chashKeyfun.fun);
-        props.setChashKeyfun(modfun);
-    }
-
-    protobuf.setProps(props);
-
     return protobuf;
-
-};
-
-StoreBucketProps.prototype._convertHooks = function(hooks) {
-    var rpbHooks = new Array(hooks.length);
-    for (var i = 0; i < hooks.length; i++) {
-        var hook = new RpbCommitHook();
-        if (this.options.precommit[i].name) {
-            hook.name = new Buffer(this.options.precommit[i].name);
-        } else {
-            var modfun = new RpbModFun();
-            modfun.module = new Buffer(this.options.precommit[i].mod);
-            modfun.function = new Buffer(this.options.precommit[i].fun);
-            hook.modfun = modfun;
-        }
-        rpbHooks[i] = hook;
-    }
-    return rpbHooks;
-};
-
-StoreBucketProps.prototype.onSuccess = function(rpbSetBucketResp) {
-
-    // There is not response from riak except a code. rpbSetBucketResp
-    // will be null upon success.
-    this._callback(null, true);
-    return true;
-
 };
 
 var schema = Joi.object().keys({
     bucket: Joi.string().required(),
-    bucketType: Joi.string().default('default'),
-    r: Joi.number().optional(),
-    pr: Joi.number().optional(),
-    w: Joi.number().optional(),
-    dw: Joi.number().optional(),
-    pw: Joi.number().optional(),
-    rw: Joi.number().optional(),
-    notFoundOk: Joi.boolean().optional(),
-    nVal: Joi.number().optional(),
-    allowMult: Joi.boolean().optional(),
-    lastWriteWins : Joi.boolean().optional(),
-    precommit : Joi.array().optional(),
-    postcommit : Joi.array().optional(),
-    oldVClock : Joi.number().optional(),
-    youngVClock : Joi.number().optional(),
-    bigVClock : Joi.number().optional(),
-    smallVClock : Joi.number().optional(),
-    backend : Joi.string().optional(),
-    basicQuorum : Joi.boolean().optional(),
-    search : Joi.boolean().optional(),
-    searchIndex : Joi.string().optional(),
-    chashKeyfun : Joi.object().optional()
-
+    bucketType: Joi.string().default('default')
 });
 
-
 /**
  * A builder for constructing StoreBucketProps instances
  *
@@ -207,294 +83,33 @@ var schema = Joi.object().keys({
  * @constructor
  */
 function Builder() {
-
+    StorePropsBase.Builder.call(this);
     this.precommit = [];
     this.postcommit = [];
 }
 
-Builder.prototype = {
-    /**
-     * Set the bucket.
-     * @method withBucket
-     * @param {String} bucket the bucket in Riak
-     * @chainable
-     */
-    withBucket : function(bucket) {
-        this.bucket = bucket;
-        return this;
-    },
-    /**
-     * Set the bucket type.
-     * If not supplied, 'default' is used.
-     * @method withBucketType
-     * @param {String} bucketType the bucket type in riak
-     * @chainable
-     */
-    withBucketType : function(bucketType) {
-        this.bucketType = bucketType;
-        return this;
-    },
-    /**
-    * Set the nVal.
-    * @method withNVal
-    * @param {Number} nVal the number of replicas.
-    * @chainable
-    */
-    withNVal : function(nVal) {
-        this.nVal = nVal;
-        return this;
-    },
-    /**
-    * Set the allow_multi value.
-    *
-    * @method withAllowMult
-    * @param {Boolean} allowMult whether to allow sibling objects to be created.
-    * @chainable
-    */
-    withAllowMult : function(allowMult) {
-        this.allowMult = allowMult;
-        return this;
-    },
-    /**
-    * Set the last_write_wins value. Unless you really know what you're
-    * doing, you probably do not want to set this to true.
-    * @method withLastWriteWins
-    * @param {Boolean} lastWriteWins whether to ignore vector clocks when writing.
-    * @chainable
-    */
-    withLastWriteWins : function(lastWriteWins) {
-        this.lastWriteWins = lastWriteWins;
-        return this;
-    },
-    /**
-    * Add a pre-commit hook.
-    *
-    * @method addPrecommitHook
-    * @param {Object} precommitHook the hook to add.
-    * @chainable
-    */
-    addPrecommitHook : function(precommitHook) {
-        this.precommit.push(precommitHook);
-        return this;
-    },
-    /**
-    * Add a pre-commit hook.
-    *
-    * @method addPostcommitHook
-    * @param {Object} postcommitHook the hook to add.
-    * @chainable
-    */
-    addPostcommitHook : function(postcommitHook) {
-        this.postcommit.push(postcommitHook);
-        return this;
-    },
-    /**
-     * Set the old VClock value
-     * @method withOldVClock
-     * @param {Number} oldVClock an epoch time value
-     * @chainable
-     */
-    withOldVClock : function(oldVClock) {
-        this.oldVClock = oldVClock;
-        return this;
-    },
-    /**
-     * Set the young VClock value
-     * @method withYoungVClock
-     * @param {Number} youngVClock an epoch time value
-     * @chainable
-     */
-    withYoungVClock : function(youngVClock) {
-        this.youngVClock = youngVClock;
-        return this;
-    },
-    /**
-     * Set the big VClock value.
-     * @method withBigVClock
-     * @param {Number} bigVClock an epoch time value
-     * @chainable
-     */
-    withBigVClock : function(bigVClock) {
-        this.bigVClock = bigVClock;
-        return this;
-    },
-    /**
-     * Set the small VClock value.
-     * @method withSmallVClock
-     * @param {Number} smallVClock an epoch time value.
-     * @chainable
-     */
-    withSmallVClock : function(smallVClock) {
-        this.smallVClock = smallVClock;
-        return this;
-    },
-    /**
-    * Set the backend used by this bucket.
-    * Only applies when using
-    * riak_kv_multi_backend in Riak.
-    * @method withBackend
-    * @param {Sring} backend the name of the backend to use.
-    * @chainable
-    */
-    withBackend : function(backend) {
-        this.backend = backend;
-        return this;
-    },
-    /**
-     * Set the R value.
-     * If not asSet the bucket default is used.
-     * @method withR
-     * @param {Number} r the R value.
-     * @chainable
-     */
-    withR : function(r) {
-        this.r = r;
-        return this;
-    },
-    /**
-    * Set the PR value.
-    * If not asSet the bucket default is used.
-    * @method withPr
-    * @param {Number} pr the PR value.
-    * @chainable
-    */
-    withPr : function(pr) {
-        this.pr = pr;
-        return this;
-    },
-    /**
-    * Set the W value.
-    * How many replicas to write to before returning a successful response.
-    * If not set the bucket default is used.
-    * @method withW
-    * @param {number} w the W value.
-    * @chainable
-    */
-    withW : function(w) {
-        this.w = w ;
-        return this;
-    },
-    /**
-     * Set the DW value.
-     * How many replicas to commit to durable storage before returning a successful response.
-     * If not set the bucket default is used.
-     * @method withDw
-     * @param {number} dw the DW value.
-     * @chainable
-     */
-    withDw : function(dw) {
-        this.dw = dw;
-        return this;
-    },
-    /**
-     * Set the PW value.
-     * How many primary nodes must be up when the write is attempted.
-     * If not set the bucket default is used.
-     * @method withPw
-     * @param {number} pw the PW value.
-     * @chainable
-     */
-    withPw : function(pw) {
-        this.pw = pw;
-        return this;
-    },
-    /**
-     * Set the RW value.
-     * Quorum for both operations (get and put) involved in deleting an object .
-     * @method withRw
-     * @param {number} rw the RW value.
-     * @chainable
-     */
-    withRw : function(rw) {
-        this.rw = rw;
-        return this;
-    },
-    /**
-    * Set the basic_quorum value.
-    * The parameter controls whether a read request should return early in
-    * some fail cases.
-    * E.g. If a quorum of nodes has already
-    * returned notfound/error, don't wait around for the rest.
-    * @method withBasicQuorum
-    * @param {Boolean} useBasicQuorum the basic_quorum value.
-    * @chainable
-    */
-    withBasicQuorum : function(useBasicQuorum) {
-        this.basicQuorum = useBasicQuorum;
-        return this;
-    },
-    /**
-    * Set the not_found_ok value.
-    * If true a vnode returning notfound for a key increments the r tally.
-    * False is higher consistency, true is higher availability.
-    * @method withNotFoundOk
-    * @param {Boolean} notFoundOk the not_found_ok value.
-    * @chainable
-    */
-    withNotFoundOk : function(notFoundOk) {
-        this.notFoundOk = notFoundOk;
-        return this;
-    },
-    /**
-    * Enable Legacy Riak Search. Setting this to true causes the search
-    * pre-commit hook to be added.
-    *
-    * Note this is only for legacy Riak (&lt; v2.0) Search support.
-    * @method withLegacySearchEnabled
-    * @param {Boolean} search enable add/remove (true/false) the pre-commit hook for Legacy
-    * Riak Search.
-    * @chainable
-    */
-    withSearch : function(search) {
-        this.search = search;
-        return this;
-    },
-    /**
-    * Associate a Search Index.
-    * This only applies if Yokozuna is enabled in
-    * Riak v2.0.
-    * @method withSearchIndex
-    * @param {String} indexName The name of the search index to use.
-    * @chainable
-    */
-    withSearchIndex : function(indexName) {
-        this.searchIndex = indexName;
-        return this;
-    },
-    /**
-     * Set the chash_keyfun value.
-     *
-     * @method withChashkeyFunction
-     * @param {Object} func a object representing the Erlang func to use.
-     * @chainable
-     */
-    withChashkeyFunction : function(func) {
-        this.chashKeyfun = func;
-        return this;
-    },
-    /**
-     * Set the callback to be executed when the operation completes.
-     * @method withCallback
-     * @param {Function} callback The callback to be executed when the operation completes.
-     * @param {String} callback.err An error message. Will be null if no error.
-     * @param {Boolean} callback.response the response from Riak. This will be true.
-     * @chainable
-     */
-    withCallback : function(callback) {
-        this.callback = callback;
-        return this;
-    },
-    /**
-     * Construct a StoreBucketProps instance.
-     * @method build
-     * @return {StoreBucketProps}
-     */
-    build : function() {
-        var cb = this.callback;
-        delete this.callback;
-        return new StoreBucketProps(this, cb);
-    }
+inherits(Builder, StorePropsBase.Builder);
+
+/**
+ * Set the bucket.
+ * @method withBucket
+ * @param {String} bucket the bucket in Riak
+ * @chainable
+ */
+Builder.prototype.withBucket = function(bucket) {
+    this.bucket = bucket;
+    return this;
+};
 
+/**
+ * Construct a StoreBucketProps instance.
+ * @method build
+ * @return {StoreBucketProps}
+ */
+Builder.prototype.build = function() {
+    var cb = this.callback;
+    delete this.callback;
+    return new StoreBucketProps(this, cb);
 };
 
 module.exports = StoreBucketProps;
diff --git a/lib/commands/kv/storebuckettypeprops.js b/lib/commands/kv/storebuckettypeprops.js
new file mode 100644
index 0000000..d8fc6e7
--- /dev/null
+++ b/lib/commands/kv/storebuckettypeprops.js
@@ -0,0 +1,102 @@
+/*
+ * 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 rpb = require('../../protobuf/riakprotobuf');
+var inherits = require('util').inherits;
+var Joi = require('joi');
+
+var StorePropsBase = require('./storepropsbase');
+
+/**
+ * Provides the StoreBucketTypeProps class, its builder, and its response.
+ * @module KV
+ */
+
+/**
+ * Command used to set the properties on a bucket type in Riak.
+ *
+ * As a convenience, a builder class is provided:
+ *
+ *     var storeProps = new StoreBucketTypeProps.Builder()
+ *                  .withBucketType('my-type')
+ *                  .withAllowMult(true)
+ *                  .build();
+ *
+ * See {{#crossLink "StoreBucketTypeProps.Builder"}}StoreBucketTypeProps.Builder{{/crossLink}}
+ *
+ * @class StoreBucketTypeProps
+ * @constructor
+ * @param {Object} options The properties to store
+ * @param {String} [options.bucketType] The bucket type in riak. If not supplied 'default is used'
+ * @extends StorePropsBase
+ */
+function StoreBucketTypeProps(options, callback) {
+    StorePropsBase.call(this, options, 'RpbSetBucketTypeReq', 'RpbSetBucketResp', callback);
+    var self = this;
+    Joi.validate(options, schema, { allowUnknown: true }, function(err, options) {
+        if (err) {
+            throw err;
+        }
+        self.options = options;
+    });
+}
+
+inherits(StoreBucketTypeProps, StorePropsBase);
+
+StoreBucketTypeProps.prototype.constructPbRequest = function() {
+    var protobuf = StoreBucketTypeProps.super_.prototype.constructPbRequest.call(this); 
+    protobuf.setType(new Buffer(this.options.bucketType));
+    return protobuf;
+};
+
+/**
+ * A builder for constructing StoreBucketTypeProps instances
+ *
+ * Rather than having to manually construct the __options__ and instantiating
+ * a StoreBucketTypeProps directly, this builder may be used.
+ *
+ *     var storeProps = new StoreBucketTypeProps.Builder()
+ *                  .withAllowMult(true)
+ *                  .build();
+ *
+ * @class StoreBucketTypeProps.Builder
+ * @constructor
+ */
+function Builder() {
+    StorePropsBase.Builder.call(this);
+    this.precommit = [];
+    this.postcommit = [];
+}
+
+inherits(Builder, StorePropsBase.Builder);
+
+var schema = Joi.object().keys({
+    bucketType: Joi.string().default('default')
+});
+
+/**
+ * Construct a StoreBucketTypeProps instance.
+ * @method build
+ * @return {StoreBucketTypeProps}
+ */
+Builder.prototype.build = function() {
+    var cb = this.callback;
+    delete this.callback;
+    return new StoreBucketTypeProps(this, cb);
+};
+
+module.exports = StoreBucketTypeProps;
+module.exports.Builder = Builder;
diff --git a/lib/commands/kv/storepropsbase.js b/lib/commands/kv/storepropsbase.js
new file mode 100644
index 0000000..bdb6fc8
--- /dev/null
+++ b/lib/commands/kv/storepropsbase.js
@@ -0,0 +1,466 @@
+/*
+ * 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 rpb = require('../../protobuf/riakprotobuf');
+var inherits = require('util').inherits;
+var Joi = require('joi');
+
+var CommandBase = require('../commandbase');
+
+var RpbBucketProps = rpb.getProtoFor('RpbBucketProps');
+var RpbCommitHook = rpb.getProtoFor('RpbCommitHook');
+var RpbModFun = rpb.getProtoFor('RpbModFun');
+
+/**
+ * Base class for StoreBucketProps and StoreBucketTypeProps classes.
+ * @module KV
+ */
+
+/**
+ * @class StorePropsBase
+ * @constructor
+ * @param {Object} options The properties to store
+ * @param {Number} [options.r] The R value.
+ * @param {Number} [options.pr] The PR value.
+ * @param {Number} [options.w] The W value.
+ * @param {Number} [options.dw] The DW value.
+ * @param {Number} [options.pw] The PW value.
+ * @param {Number} [options.rw] The RW value.
+ * @param {Boolean} [options.notFoundOk] If true a vnode returning notfound for a key increments the r tally.
+ * @param {Boolean} [options.basicQuorum] Controls whether a read request should return early in some fail cases.
+ * @param {Number} [options.nVal] The number of replicas.
+ * @param {Boolean} [options.allowMult] Whether to allow sibling objects to be created.
+ * @param {Boolean} [options.lastWriteWins] Whether to ignore vector clocks when writing.
+ * @param {Number} [options.oldVClock] An epoch time value.
+ * @param {Number} [options.youngVClock] An epoch time value.
+ * @param {Number} [options.bigVClock] An epoch time value.
+ * @param {Number} [options.smallVClock] An epoch time value.
+ * @param {Sring} [options.backend] The name of the backend to use.
+ * @param {Boolean} [options.search] Enable the pre-commit hook for Legacy Riak search.
+ * @param {String} [options.indexName] The name of the search index to use.
+ * @param {Object} [options.chashKeyfun] An object representing the Erlang func to use.
+ * @param {Object[]} [options.precommit] Array of precommit hooks
+ * @param {Object[]} [options.postcommit] Array of postcommit hooks
+ * @param {String} pbRequestName name of the Riak protocol buffer this command will send
+ * @param {String} pbResponseName name of the Riak protocol buffer this command will receive
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will be null if no error.
+ * @param {Boolean} callback.response the response from Riak. This will be true.
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will ne null if no error.
+ * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
+ * @extends CommandBase
+ */
+function StorePropsBase(options, pbRequestName, pbResponseName, callback) {
+    CommandBase.call(this, pbRequestName, pbResponseName, callback);
+    var self = this;
+    Joi.validate(options, schema, function(err, options) {
+        if (err) {
+            throw err;
+        }
+        self.options = options;
+    });
+}
+
+inherits(StorePropsBase, CommandBase);
+
+StorePropsBase.prototype.constructPbRequest = function() {
+
+    var protobuf = this.getPbReqBuilder();
+
+    var props = new RpbBucketProps();
+
+    props.setNVal(this.options.nVal > 0 ? this.options.nVal : null );
+    props.setOldVclock(this.options.oldVClock >= 0 ? this.options.oldVClock : null);
+    props.setYoungVclock(this.options.youngVClock >= 0 ? this.options.youngVClock : null);
+    props.setBigVclock(this.options.bigVClock >= 0 ? this.options.bigVClock : null);
+    props.setSmallVclock(this.options.smallVClock >= 0 ? this.options.smallVClock : null);
+    props.setR(this.options.r >= 0 ? this.options.r : null);
+    props.setPr(this.options.pr >= 0 ? this.options.pr : null);
+    props.setW(this.options.w >= 0 ? this.options.w : null);
+    props.setPw(this.options.pw >= 0 ? this.options.pw : null);
+    props.setDw(this.options.dw >= 0 ? this.options.dw : null);
+    props.setRw(this.options.rw >= 0 ? this.options.rw : null);
+
+    props.setBasicQuorum(typeof this.options.basicQuorum === 'boolean' ? this.options.basicQuorum : null);
+    props.setNotfoundOk(typeof this.options.notFoundOk === 'boolean' ? this.options.notFoundOk : null);
+    props.setSearch(typeof this.options.search === 'boolean' ? this.options.search : null);
+    props.setAllowMult(typeof this.options.allowMult === 'boolean' ? this.options.allowMult : null);
+    props.setLastWriteWins(typeof this.options.lastWriteWins === 'boolean' ? this.options.lastWriteWins : null);
+
+    props.setBackend(this.options.backend ? new Buffer(this.options.backend) : null);
+    props.setSearchIndex(this.options.searchIndex ? new Buffer(this.options.searchIndex) : null);
+
+    if (this.options.precommit) {
+        props.setPrecommit(this._convertHooks(this.options.precommit));
+    }
+
+    if (this.options.postcommit) {
+        props.setPostcommit(this._convertHooks(this.options.postcommit));
+    }
+
+    if (this.options.chashKeyfun) {
+        var modfun = new RpbModFun();
+        modfun.module = new Buffer(this.options.chashKeyfun.mod);
+        modfun.function = new Buffer(this.options.chashKeyfun.fun);
+        props.setChashKeyfun(modfun);
+    }
+
+    protobuf.setProps(props);
+
+    return protobuf;
+};
+
+StorePropsBase.prototype._convertHooks = function(hooks) {
+    var rpbHooks = new Array(hooks.length);
+    for (var i = 0; i < hooks.length; i++) {
+        var hook = new RpbCommitHook();
+        if (this.options.precommit[i].name) {
+            hook.name = new Buffer(this.options.precommit[i].name);
+        } else {
+            var modfun = new RpbModFun();
+            modfun.module = new Buffer(this.options.precommit[i].mod);
+            modfun.function = new Buffer(this.options.precommit[i].fun);
+            hook.modfun = modfun;
+        }
+        rpbHooks[i] = hook;
+    }
+    return rpbHooks;
+};
+
+StorePropsBase.prototype.onSuccess = function(rpbSetBucketResp) {
+    // There is not response from riak except a code. rpbSetBucketResp
+    // will be null upon success.
+    this._callback(null, true);
+    return true;
+};
+
+var schema = Joi.object().keys({
+    // dervied classes validate these
+    bucket: Joi.string().optional(),
+    bucketType: Joi.string().optional(),
+    // StorePropsBase validates the rest
+    r: Joi.number().optional(),
+    pr: Joi.number().optional(),
+    w: Joi.number().optional(),
+    dw: Joi.number().optional(),
+    pw: Joi.number().optional(),
+    rw: Joi.number().optional(),
+    notFoundOk: Joi.boolean().optional(),
+    nVal: Joi.number().optional(),
+    allowMult: Joi.boolean().optional(),
+    lastWriteWins : Joi.boolean().optional(),
+    precommit : Joi.array().optional(),
+    postcommit : Joi.array().optional(),
+    oldVClock : Joi.number().optional(),
+    youngVClock : Joi.number().optional(),
+    bigVClock : Joi.number().optional(),
+    smallVClock : Joi.number().optional(),
+    backend : Joi.string().optional(),
+    basicQuorum : Joi.boolean().optional(),
+    search : Joi.boolean().optional(),
+    searchIndex : Joi.string().optional(),
+    chashKeyfun : Joi.object().optional()
+});
+
+function Builder() {}
+
+/**
+ * Set the bucket type.
+ * If not supplied, 'default' is used.
+ * @method withBucketType
+ * @param {String} bucketType the bucket type in riak
+ * @chainable
+ */
+Builder.prototype.withBucketType = function(bucketType) {
+    this.bucketType = bucketType;
+    return this;
+};
+
+/**
+ * Set the nVal.
+ * @method withNVal
+ * @param {Number} nVal the number of replicas.
+ * @chainable
+ */
+Builder.prototype.withNVal = function(nVal) {
+    this.nVal = nVal;
+    return this;
+};
+
+/**
+ * Set the allow_multi value.
+ *
+ * @method withAllowMult
+ * @param {Boolean} allowMult whether to allow sibling objects to be created.
+ * @chainable
+ */
+Builder.prototype.withAllowMult = function(allowMult) {
+    this.allowMult = allowMult;
+    return this;
+};
+
+/**
+ * Set the last_write_wins value. Unless you really know what you're
+ * doing, you probably do not want to set this to true.
+ * @method withLastWriteWins
+ * @param {Boolean} lastWriteWins whether to ignore vector clocks when writing.
+ * @chainable
+ */
+Builder.prototype.withLastWriteWins = function(lastWriteWins) {
+    this.lastWriteWins = lastWriteWins;
+    return this;
+};
+
+/**
+ * Add a pre-commit hook.
+ *
+ * @method addPrecommitHook
+ * @param {Object} precommitHook the hook to add.
+ * @chainable
+ */
+Builder.prototype.addPrecommitHook = function(precommitHook) {
+    this.precommit.push(precommitHook);
+    return this;
+};
+
+/**
+ * Add a pre-commit hook.
+ *
+ * @method addPostcommitHook
+ * @param {Object} postcommitHook the hook to add.
+ * @chainable
+ */
+Builder.prototype.addPostcommitHook = function(postcommitHook) {
+    this.postcommit.push(postcommitHook);
+    return this;
+};
+
+/**
+ * Set the old VClock value
+ * @method withOldVClock
+ * @param {Number} oldVClock an epoch time value
+ * @chainable
+ */
+Builder.prototype.withOldVClock = function(oldVClock) {
+    this.oldVClock = oldVClock;
+    return this;
+};
+
+/**
+ * Set the young VClock value
+ * @method withYoungVClock
+ * @param {Number} youngVClock an epoch time value
+ * @chainable
+ */
+Builder.prototype.withYoungVClock = function(youngVClock) {
+    this.youngVClock = youngVClock;
+    return this;
+};
+
+/**
+ * Set the big VClock value.
+ * @method withBigVClock
+ * @param {Number} bigVClock an epoch time value
+ * @chainable
+ */
+Builder.prototype.withBigVClock = function(bigVClock) {
+    this.bigVClock = bigVClock;
+    return this;
+};
+
+/**
+ * Set the small VClock value.
+ * @method withSmallVClock
+ * @param {Number} smallVClock an epoch time value.
+ * @chainable
+ */
+Builder.prototype.withSmallVClock = function(smallVClock) {
+    this.smallVClock = smallVClock;
+    return this;
+};
+
+/**
+ * Set the backend used by this bucket.
+ * Only applies when using
+ * riak_kv_multi_backend in Riak.
+ * @method withBackend
+ * @param {Sring} backend the name of the backend to use.
+ * @chainable
+ */
+Builder.prototype.withBackend = function(backend) {
+    this.backend = backend;
+    return this;
+};
+
+/**
+ * Set the R value.
+ * If not asSet the bucket default is used.
+ * @method withR
+ * @param {Number} r the R value.
+ * @chainable
+ */
+Builder.prototype.withR = function(r) {
+    this.r = r;
+    return this;
+};
+
+/**
+* Set the PR value.
+* If not asSet the bucket default is used.
+* @method withPr
+* @param {Number} pr the PR value.
+* @chainable
+*/
+Builder.prototype.withPr = function(pr) {
+    this.pr = pr;
+    return this;
+};
+
+/**
+ * Set the W value.
+ * How many replicas to write to before returning a successful response.
+ * If not set the bucket default is used.
+ * @method withW
+ * @param {number} w the W value.
+ * @chainable
+ */
+Builder.prototype.withW = function(w) {
+    this.w = w ;
+    return this;
+};
+
+/**
+ * Set the DW value.
+ * How many replicas to commit to durable storage before returning a successful response.
+ * If not set the bucket default is used.
+ * @method withDw
+ * @param {number} dw the DW value.
+ * @chainable
+ */
+Builder.prototype.withDw = function(dw) {
+    this.dw = dw;
+    return this;
+};
+
+/**
+ * Set the PW value.
+ * How many primary nodes must be up when the write is attempted.
+ * If not set the bucket default is used.
+ * @method withPw
+ * @param {number} pw the PW value.
+ * @chainable
+ */
+Builder.prototype.withPw = function(pw) {
+    this.pw = pw;
+    return this;
+};
+
+/**
+ * Set the RW value.
+ * Quorum for both operations (get and put) involved in deleting an object .
+ * @method withRw
+ * @param {number} rw the RW value.
+ * @chainable
+ */
+Builder.prototype.withRw = function(rw) {
+    this.rw = rw;
+    return this;
+};
+
+/**
+ * Set the basic_quorum value.
+ * The parameter controls whether a read request should return early in
+ * some fail cases.
+ * E.g. If a quorum of nodes has already
+ * returned notfound/error, don't wait around for the rest.
+ * @method withBasicQuorum
+ * @param {Boolean} useBasicQuorum the basic_quorum value.
+ * @chainable
+ */
+Builder.prototype.withBasicQuorum = function(useBasicQuorum) {
+    this.basicQuorum = useBasicQuorum;
+    return this;
+};
+
+/**
+ * Set the not_found_ok value.
+ * If true a vnode returning notfound for a key increments the r tally.
+ * False is higher consistency, true is higher availability.
+ * @method withNotFoundOk
+ * @param {Boolean} notFoundOk the not_found_ok value.
+ * @chainable
+ */
+Builder.prototype.withNotFoundOk = function(notFoundOk) {
+    this.notFoundOk = notFoundOk;
+    return this;
+};
+
+/**
+ * Enable Legacy Riak Search. Setting this to true causes the search
+ * pre-commit hook to be added.
+ *
+ * Note this is only for legacy Riak (&lt; v2.0) Search support.
+ * @method withLegacySearchEnabled
+ * @param {Boolean} search enable add/remove (true/false) the pre-commit hook for Legacy
+ * Riak Search.
+ * @chainable
+ */
+Builder.prototype.withSearch = function(search) {
+    this.search = search;
+    return this;
+};
+
+/**
+ * Associate a Search Index.
+ * This only applies if Yokozuna is enabled in
+ * Riak v2.0.
+ * @method withSearchIndex
+ * @param {String} indexName The name of the search index to use.
+ * @chainable
+ */
+Builder.prototype.withSearchIndex = function(indexName) {
+    this.searchIndex = indexName;
+    return this;
+};
+
+/**
+ * Set the chash_keyfun value.
+ *
+ * @method withChashkeyFunction
+ * @param {Object} func a object representing the Erlang func to use.
+ * @chainable
+ */
+Builder.prototype.withChashkeyFunction = function(func) {
+    this.chashKeyfun = func;
+    return this;
+};
+
+/**
+ * Set the callback to be executed when the operation completes.
+ * @method withCallback
+ * @param {Function} callback The callback to be executed when the operation completes.
+ * @param {String} callback.err An error message. Will ne null if no error.
+ * @param {Object} callback.response The response from Riak. This is an oject with all the bucket properties.
+ * @chainable
+ */
+Builder.prototype.withCallback = function(callback) {
+    this.callback = callback;
+    return this;
+};
+
+module.exports = StorePropsBase;
+module.exports.Builder = Builder;


Test patch:
diff --git a/test/integration/kv/fetchandsetbuckettypeprops.js b/test/integration/kv/fetchandsetbuckettypeprops.js
new file mode 100644
index 0000000..5b7305b
--- /dev/null
+++ b/test/integration/kv/fetchandsetbuckettypeprops.js
@@ -0,0 +1,110 @@
+/*
+ * 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 StoreBucketTypeProps = require('../../../lib/commands/kv/storebuckettypeprops');
+var FetchBucketTypeProps = require('../../../lib/commands/kv/fetchbuckettypeprops');
+var RiakNode = require('../../../lib/core/riaknode');
+var RiakCluster = require('../../../lib/core/riakcluster');
+var assert = require('assert');
+
+var bucketName = Test.bucketName + '_sp';
+
+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) {
+        var sc = function (state) {
+            if (state === RiakCluster.State.SHUTDOWN) {
+                done();
+            }
+        };
+        cluster.on('stateChange', sc);
+        cluster.stop();
+    });
+    
+    describe('StoreBucketTypeProps', function() {
+        it('Should NOT store props for the default bucket type', function(done) {
+            var callback = function(err, resp) {
+                assert(err, err);
+                done();
+            };
+            var store = new StoreBucketTypeProps.Builder()
+                    .withAllowMult(true)
+                    .withCallback(callback)
+                    .build();
+            cluster.execute(store);
+        });
+    
+        it('Should store bucket props for a non-default bucket type', function(done) {
+            var cb2 = function(err, resp) {
+                assert(!err, err);
+                done();
+            };
+            var cb1 = function(err, resp) {
+                assert(!err, err);
+                var store = new StoreBucketTypeProps.Builder()
+                        .withBucketType(Test.bucketType)
+                        .withAllowMult(true)
+                        .withCallback(cb2)
+                        .build();
+                cluster.execute(store);
+            };
+            var store = new StoreBucketTypeProps.Builder()
+                    .withBucketType(Test.bucketType)
+                    .withAllowMult(false)
+                    .withCallback(cb1)
+                    .build();
+            cluster.execute(store);
+        });
+    });
+    
+    describe('FetchBucketTypeProps', function() {
+        it('Should fetch props for the default bucket type', function(done) {
+            var callback = function(err, resp) {
+                assert(!err, err);
+                assert(resp.nVal);
+                done();
+            };
+            var fetch = new FetchBucketTypeProps.Builder()
+                .withCallback(callback)
+                .build();
+            cluster.execute(fetch);
+        });
+        
+        it('Should fetch props for a non-default bucket type', function(done) {
+            var callback = function(err, resp) {
+                assert(!err, err);
+                assert(resp.nVal);
+                done();
+            };
+            var fetch = new FetchBucketTypeProps.Builder()
+                .withBucketType(Test.bucketType)
+                .withCallback(callback)
+                .build();
+            cluster.execute(fetch);
+        });
+    });
+});
diff --git a/test/integration/testparams.js b/test/integration/testparams.js
index 788ced3..ab5b188 100644
--- a/test/integration/testparams.js
+++ b/test/integration/testparams.js
@@ -33,9 +33,11 @@ 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;
+if (process.env.RIAK_HOST) {
+    riakHost = String(process.env.RIAK_HOST);
+}
+if (process.env.RIAK_PORT) {
+    riakPort = Number(process.env.RIAK_PORT);
 }
 
 module.exports.nodeAddresses = [ riakHost + ':' + riakPort ];
diff --git a/test/unit/kv/fetchbucketprops.js b/test/unit/kv/fetchbucketprops.js
index 920d07c..f55ca0c 100644
--- a/test/unit/kv/fetchbucketprops.js
+++ b/test/unit/kv/fetchbucketprops.js
@@ -23,27 +23,38 @@ var RpbCommitHook = rpb.getProtoFor('RpbCommitHook');
 var RpbModFun = rpb.getProtoFor('RpbModFun');
 var assert = require('assert');
 
-
 describe('FetchBucketProps', function() {
     describe('Build', function() {
         it('should build a RpbGetBucketProps correctly', function(done) {
-            
-            var fetchProps = new FetchBucketProps.Builder()
-                    .withBucketType('bucket_type')
-                    .withBucket('bucket_name')
-                    .withCallback(function(){})
-                    .build();
-            
+            var bucketType = 'bucket_type';
+            var bucketName = 'bucket_name';
+
+            var opts = {
+                bucketType: bucketType,
+                bucket: bucketName,
+            };
+            var cb = function (err, rslt) {};
+            var fetchProps = new FetchBucketProps(opts, cb);
+
             var protobuf = fetchProps.constructPbRequest();
-            
-            assert.equal(protobuf.getType().toString('utf8'), 'bucket_type');
-            assert.equal(protobuf.getBucket().toString('utf8'), 'bucket_name');
+            assert.equal(protobuf.getType().toString('utf8'), bucketType);
+            assert.equal(protobuf.getBucket().toString('utf8'), bucketName);
+
+            var fetchPropsBuilder = new FetchBucketProps.Builder();
+
+            fetchPropsBuilder.withBucketType(bucketType);
+            fetchPropsBuilder.withBucket(bucketName);
+            fetchPropsBuilder.withCallback(cb);
+
+            fetchProps = fetchPropsBuilder.build();
+
+            protobuf = fetchProps.constructPbRequest();
+            assert.equal(protobuf.getType().toString('utf8'), bucketType);
+            assert.equal(protobuf.getBucket().toString('utf8'), bucketName);
             done();
         });
         
         it('should take a RpbGetBucketResp and call the users callback with the response', function(done) {
-            
-            
             var props = new RpbBucketProps();
             
             props.setNVal(3);
@@ -85,7 +96,6 @@ describe('FetchBucketProps', function() {
             protobuf.setProps(props);
             
             var callback = function(err, response) {
-                
                 assert.equal(response.nVal, 3);
                 assert.equal(response.allowMult, true);
                 assert.equal(response.lastWriteWins, true);
@@ -109,19 +119,14 @@ describe('FetchBucketProps', function() {
                 assert.equal(response.backend, 'backend');
                 assert.equal(response.searchIndex, 'index');
                 assert.equal(response.dataType, 'dataType');
-                
                 assert.equal(response.precommit[0].mod, 'module_name');
                 assert.equal(response.precommit[0].fun, 'function_name');
                 assert.equal(response.postcommit[0].mod, 'module_name');
                 assert.equal(response.postcommit[0].fun, 'function_name');
                 assert.equal(response.chashKeyfun.mod, 'module_name');
                 assert.equal(response.chashKeyfun.fun, 'function_name');
-                
                 assert.equal(response.linkFun.mod, 'module_name');
                 assert.equal(response.linkFun.fun, 'function_name');
-                
-              
-              
                 done();
             };
             
@@ -130,9 +135,7 @@ describe('FetchBucketProps', function() {
                     .withBucket('bucket_name')
                     .withCallback(callback)
                     .build();
-            
             fetchProps.onSuccess(protobuf);
-            
         });
         
         it ('should take a RpbErrorResp and call the users callback with the error message', function(done) {
@@ -151,11 +154,7 @@ describe('FetchBucketProps', function() {
                .withBucket('bucket_name')
                .withCallback(callback)
                .build();
-       
             fetchCommand.onRiakError(rpbErrorResp);
-           
-           
        });
-        
     });
 });
diff --git a/test/unit/kv/fetchbuckettypeprops.js b/test/unit/kv/fetchbuckettypeprops.js
new file mode 100644
index 0000000..ff2804d
--- /dev/null
+++ b/test/unit/kv/fetchbuckettypeprops.js
@@ -0,0 +1,154 @@
+/*
+ * 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 rpb = require('../../../lib/protobuf/riakprotobuf');
+var FetchBucketTypeProps = require('../../../lib/commands/kv/fetchbuckettypeprops');
+var RpbGetBucketTypeReq = rpb.getProtoFor('RpbGetBucketTypeReq');
+var RpbGetBucketResp = rpb.getProtoFor('RpbGetBucketResp');
+var RpbBucketProps = rpb.getProtoFor('RpbBucketProps');
+var RpbErrorResp = rpb.getProtoFor('RpbErrorResp');
+var RpbCommitHook = rpb.getProtoFor('RpbCommitHook');
+var RpbModFun = rpb.getProtoFor('RpbModFun');
+var assert = require('assert');
+
+describe('FetchBucketTypeProps', function() {
+    describe('Build', function() {
+        it('should build a RpbGetBucketTypeProps correctly', function(done) {
+            var bucketType = 'bucket_type';
+
+            var opts = {
+                bucketType: bucketType,
+            };
+            var cb = function (err, rslt) {};
+            var fetchProps = new FetchBucketTypeProps(opts, cb);
+
+            var protobuf = fetchProps.constructPbRequest();
+            assert.equal(protobuf.getType().toString('utf8'), bucketType);
+
+            var fetchPropsBuilder = new FetchBucketTypeProps.Builder();
+
+            fetchPropsBuilder.withBucketType(bucketType);
+            fetchPropsBuilder.withCallback(cb);
+
+            fetchProps = fetchPropsBuilder.build();
+
+            protobuf = fetchProps.constructPbRequest();
+            assert.equal(protobuf.getType().toString('utf8'), bucketType);
+            done();
+        });
+
+        it('should take a RpbGetBucketResp and call the users callback with the response', function(done) {
+            var props = new RpbBucketProps();
+
+            props.setNVal(3);
+            props.setAllowMult(true);
+            props.setLastWriteWins(true);
+            props.setHasPrecommit(true);
+            props.setHasPostcommit(true);
+            props.setOldVclock(86400);
+            props.setYoungVclock(20);
+            props.setBigVclock(50);
+            props.setSmallVclock(50);
+            props.setR(1);
+            props.setPr(2);
+            props.setW(3);
+            props.setPw(4);
+            props.setDw(5);
+            props.setRw(6);
+            props.setBasicQuorum(true);
+            props.setNotfoundOk(true);
+            props.setSearch(true);
+            props.setConsistent(true);
+            props.setRepl(1);
+            props.setBackend(new Buffer('backend'));
+            props.setSearchIndex(new Buffer('index'));
+            props.setDatatype(new Buffer('dataType'));
+            
+            var hook = new RpbCommitHook();
+            var modfun = new RpbModFun();
+            modfun.module = new Buffer('module_name');
+            modfun.function = new Buffer('function_name');
+            hook.modfun = modfun;
+            
+            props.precommit.push(hook);
+            props.postcommit.push(hook);
+            props.setChashKeyfun(modfun);
+            props.setLinkfun(modfun);
+            
+            var protobuf = new RpbGetBucketResp();
+            protobuf.setProps(props);
+            
+            var callback = function(err, response) {
+                assert.equal(response.nVal, 3);
+                assert.equal(response.allowMult, true);
+                assert.equal(response.lastWriteWins, true);
+                assert.equal(response.hasPrecommit, true);
+                assert.equal(response.hasPostcommit, true);
+                assert.equal(response.oldVClock, 86400);
+                assert.equal(response.youngVClock, 20);
+                assert.equal(response.bigVClock, 50);
+                assert.equal(response.smallVClock, 50);
+                assert.equal(response.r, 1);
+                assert.equal(response.pr, 2);
+                assert.equal(response.w, 3);
+                assert.equal(response.pw, 4);
+                assert.equal(response.dw, 5);
+                assert.equal(response.rw, 6);
+                assert.equal(response.basicQuorum, true);
+                assert.equal(response.notFoundOk, true);
+                assert.equal(response.search, true);
+                assert.equal(response.consistent, true);
+                assert.equal(response.repl, 1);
+                assert.equal(response.backend, 'backend');
+                assert.equal(response.searchIndex, 'index');
+                assert.equal(response.dataType, 'dataType');
+                assert.equal(response.precommit[0].mod, 'module_name');
+                assert.equal(response.precommit[0].fun, 'function_name');
+                assert.equal(response.postcommit[0].mod, 'module_name');
+                assert.equal(response.postcommit[0].fun, 'function_name');
+                assert.equal(response.chashKeyfun.mod, 'module_name');
+                assert.equal(response.chashKeyfun.fun, 'function_name');
+                assert.equal(response.linkFun.mod, 'module_name');
+                assert.equal(response.linkFun.fun, 'function_name');
+                done();
+            };
+            
+            var fetchProps = new FetchBucketTypeProps.Builder()
+                    .withBucketType('bucket_type')
+                    .withCallback(callback)
+                    .build();
+            fetchProps.onSuccess(protobuf);
+        });
+        
+        it ('should take a RpbErrorResp and call the users callback with the error message', function(done) {
+           var rpbErrorResp = new RpbErrorResp();
+           rpbErrorResp.setErrmsg(new Buffer('this is an error'));
+           
+           var callback = function(err, response) {
+               if (err) {
+                   assert.equal(err,'this is an error');
+                   done();
+               }
+           };
+           
+           var fetchCommand = new FetchBucketTypeProps.Builder()
+               .withBucketType('bucket_type')
+               .withCallback(callback)
+               .build();
+            fetchCommand.onRiakError(rpbErrorResp);
+       });
+    });
+});
diff --git a/test/unit/kv/storebuckettypeprops.js b/test/unit/kv/storebuckettypeprops.js
new file mode 100644
index 0000000..289cc1d
--- /dev/null
+++ b/test/unit/kv/storebuckettypeprops.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 rpb = require('../../../lib/protobuf/riakprotobuf');
+var StoreBucketTypeProps = require('../../../lib/commands/kv/storebuckettypeprops');
+var RpbErrorResp = rpb.getProtoFor('RpbErrorResp');
+var RpbCommitHook = rpb.getProtoFor('RpbCommitHook');
+var RpbModFun = rpb.getProtoFor('RpbModFun');
+var assert = require('assert');
+
+describe('StoreBucketTypeProps', function() {
+    describe('Build', function() {
+        it('should build a RpbSetBucketTypeProps correctly', function(done) {
+            var hook = { mod: 'module_name', fun: 'function_name' };
+            var storeProps = new StoreBucketTypeProps.Builder()
+                .withBucketType('bucket_type')
+                .withNVal(3)
+                .withAllowMult(true)
+                .withLastWriteWins(true)
+                .withOldVClock(86400)
+                .withYoungVClock(20)
+                .withBigVClock(50)
+                .withSmallVClock(51)
+                .withR(1)
+                .withPr(2)
+                .withW(3)
+                .withPw(4)
+                .withDw(5)
+                .withRw(6)
+                .withBasicQuorum(false)
+                .withNotFoundOk(true)
+                .withSearch(true)
+                .withBackend('backend')
+                .withSearchIndex('indexName')
+                .addPrecommitHook(hook)
+                .addPostcommitHook(hook)
+                .withChashkeyFunction(hook)
+                .withCallback(function(){})
+                .build();
+        
+            var protobuf = storeProps.constructPbRequest();
+            var props = protobuf.getProps();
+            
+            assert.equal(protobuf.type.toString('utf8'), 'bucket_type');
+            assert.equal(props.getNVal(), 3);
+            assert.equal(props.getAllowMult(), true);
+            assert.equal(props.getLastWriteWins(), true);
+            assert.equal(props.getOldVclock(), 86400);
+            assert.equal(props.getYoungVclock(), 20);
+            assert.equal(props.getBigVclock(), 50);
+            assert.equal(props.getSmallVclock(), 51);
+            assert.equal(props.r, 1);
+            assert.equal(props.pr, 2);
+            assert.equal(props.w, 3);
+            assert.equal(props.pw, 4);
+            assert.equal(props.dw, 5);
+            assert.equal(props.rw, 6);
+            assert.equal(props.getBasicQuorum(), false);
+            assert.equal(props.getNotfoundOk(), true);
+            assert.equal(props.getSearch(), true);
+            assert.equal(props.getBackend().toString('utf8'), 'backend');
+            assert.equal(props.getSearchIndex().toString('utf8'), 'indexName');
+            
+            assert.equal(props.precommit.length, 1);
+            assert.equal(props.precommit[0].modfun.module.toString('utf8'), 'module_name');
+            assert.equal(props.precommit[0].modfun.function.toString('utf8'), 'function_name');
+            
+            assert.equal(props.postcommit.length, 1);
+            assert.equal(props.postcommit[0].modfun.module.toString('utf8'), 'module_name');
+            assert.equal(props.postcommit[0].modfun.function.toString('utf8'), 'function_name');
+            
+            assert.equal(props.getChashKeyfun().module.toString('utf8'), 'module_name');
+            assert.equal(props.getChashKeyfun().function.toString('utf8'), 'function_name');
+            done();
+        });
+        
+        it('should take a RpbSetBucketResp and call the users callback with the response', function(done) {
+            // RpbSetBucketResp has no body. Riak just sends back the code so we supply null
+            // to the command on success and a simple boolean true is sent to the user callback
+            var callback = function(err, response) {
+                assert.equal(response, true);
+                done();
+            };
+            var storeProps = new StoreBucketTypeProps.Builder()
+                .withBucketType('bucket_type')
+                .withCallback(callback)
+                .build();
+            storeProps.onSuccess(null);
+        });
+        
+        it ('should take a RpbErrorResp and call the users callback with the error message', function(done) {
+           var rpbErrorResp = new RpbErrorResp();
+           rpbErrorResp.setErrmsg(new Buffer('this is an error'));
+           var callback = function(err, response) {
+               if (err) {
+                   assert.equal(err,'this is an error');
+                   done();
+               }
+           };
+           var storeProps = new StoreBucketTypeProps.Builder()
+                .withBucketType('bucket_type')
+                .withCallback(callback)
+                .build();
+            storeProps.onRiakError(rpbErrorResp);
+        });
+    });
+});