diff --git a/fabric-client/lib/impl/CouchDBKeyValueStore.js b/fabric-client/lib/impl/CouchDBKeyValueStore.js
index e934285b88..ab45bebb11 100644
--- a/fabric-client/lib/impl/CouchDBKeyValueStore.js
+++ b/fabric-client/lib/impl/CouchDBKeyValueStore.js
@@ -19,6 +19,7 @@
var api = require('../api.js');
var fs = require('fs-extra');
var path = require('path');
+var util = require('util');
var utils = require('../utils');
var nano = require('nano');
@@ -35,37 +36,23 @@ var CouchDBKeyValueStore = class extends api.KeyValueStore {
/**
* constructor
*
- * @description options contains a path property which represents a CouchDB client instance.
- * The following code snippet shows how to create a nano minimalistic client for CouchDB. For more
- * information see github dscape / nano.
- *
var nano = require('nano');
- * var couchDBClient = nano(couchdb_IP_Address + ':' + couchdb_Port);
- *
- *
The following code snippet shows how to create a Cloudant CouchDB client.
- * Username and password map to the IBM Bluemix service credentials VCAP_SERVICES environment variables username and password.
- * To obtain an instance of Cloudant, see the IBM Bluemix Catalog --> Services --> Data & Analytics at
- * Cloudant NoSQL DB.
- * var Cloudant = require('cloudant');
- * var cloudantClient = Cloudant({account: username, password: password});
- *
- *
- * @param {Object} options Contains two properties:
- * path - The CouchDB database client instance.
+ * @param {Object} options Contains the properties:
+ * url - The CouchDB instance url.
* name - Optional. Identifies the name of the database if different from the default of 'member_db'.
*/
constructor(options) {
logger.debug('constructor, options: ' + options);
- if (!options || !options.path) {
- throw new Error('Must provide the CouchDB database client instance to store membership data.');
+ if (!options || !options.url) {
+ throw new Error('Must provide the CouchDB database url to store membership data.');
}
// Create the keyValStore instance
super();
var self = this;
- // path is the database client instance
- this._path = options.path;
+ // url is the database instance url
+ this._url = options.url;
// Name of the database, optional
if (!options.name) {
this._name = 'member_db';
@@ -73,34 +60,37 @@ var CouchDBKeyValueStore = class extends api.KeyValueStore {
this._name = options.name;
}
- logger.debug('options.path - ' + options.path);
+ logger.debug('options.url - ' + options.url);
logger.debug('options.name - ' + options.name);
return new Promise(function(resolve, reject) {
// Initialize the CouchDB database client
- var dbClient = self._path;
+ var dbClient = nano(self._url);
// Check if the database already exists. If not, create it.
dbClient.db.get(self._name, function(err, body) {
// Check for error
if (err) {
// Database doesn't exist
if (err.error == 'not_found') {
- logger.info('No member_db found, creating member_db');
+ logger.info(util.format('No %s found, creating %s', self._name, self._name));
+
+ dbClient.db.create(self._name, function(err, body) {
+ if (err) {
+ return reject(new Error(util.format('Failed to create %s database due to error: %s', self._name, err.stack ? err.stack : err)));
+ }
- dbClient.db.create(self._name, function() {
- logger.info('Created member_db database');
+ logger.info(util.format('Created %s database', self._name));
// Specify it as the database to use
self._database = dbClient.use(self._name);
resolve(self);
});
} else {
// Other error
- logger.error('ERROR: ' + err);
- reject(new Error('Error creating member_db database to store membership data.'));
+ return reject(new Error(util.format('Error creating %s database to store membership data: %s', self._name, err.stack ? err.stack : err)));
}
} else {
// Database exists
- logger.info('member_db already exists');
+ logger.info(util.format('%s already exists', self._name));
// Specify it as the database to use
self._database = dbClient.use(self._name);
resolve(self);
diff --git a/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js b/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js
index 44a36776c4..c6d5704bbb 100644
--- a/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js
+++ b/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js
@@ -49,27 +49,41 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite {
* constructor
*
* @param {number} keySize Key size for the ECDSA algorithm, can only be 256 or 384
- * @param {string} kvsPath A path to a directory used by the built-in key store to save private keys
+ * @param {string} KVSImplClass Optional. The built-in key store saves private keys. The key store may be backed by different
+ * {@link KeyValueStore} implementations. If specified, the value of the argument must point to a module implementing the
+ * KeyValueStore interface.
+ * @param {object} opts Implementation-specific options object for the {@link KeyValueStore} class to instantiate an instance
*/
- constructor(keySize, kvsPath) {
+ constructor(keySize, KVSImplClass, opts) {
if (keySize !== 256 && keySize !== 384) {
throw new Error('Illegal key size: ' + keySize + ' - this crypto suite only supports key sizes 256 or 384');
}
super();
- if (typeof kvsPath === 'undefined' || kvsPath === null) {
- this._storePath = null;
+ var superClass;
+
+ if (typeof KVSImplClass !== 'function') {
+ superClass = require(utils.getConfigSetting('key-value-store'));
} else {
- if (typeof kvsPath !== 'string') {
- throw new Error('The "kvsPath" parameter for this constructor, if specified, must be a string specifying a file system path');
- }
+ superClass = KVSImplClass;
+ }
- this._storePath = kvsPath;
+ if (KVSImplClass && typeof opts === 'undefined') {
+ // the function is called with only one argument for the 'opts'
+ opts = KVSImplClass;
+ } else if (typeof KVSImplClass === 'undefined' && typeof opts === 'undefined') {
+ opts = {
+ path: CryptoSuite_ECDSA_AES.getDefaultKeyStorePath()
+ };
}
this._keySize = keySize;
this._store = null;
+ this._storeConfig = {
+ superClass: superClass,
+ opts: opts
+ };
this._initialize();
}
@@ -226,16 +240,15 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite {
var self = this;
return new Promise((resolve, reject) => {
if (self._store === null) {
- var storePath = self._storePath ? self._storePath : CryptoSuite_ECDSA_AES.getDefaultKeyStorePath();
- logger.info('This class requires a CryptoKeyStore to save keys, using the store at %s', self._storePath);
+ logger.info(util.format('This class requires a CryptoKeyStore to save keys, using the store: %j', self._storeConfig));
- CKS({
- path: storePath
- })
+ CKS(self._storeConfig.superClass, self._storeConfig.opts)
.then((ks) => {
logger.debug('_getKeyStore returning ks');
self._store = ks;
return resolve(self._store);
+ }).catch((err) => {
+ reject(err);
});
} else {
logger.debug('_getKeyStore resolving store');
diff --git a/package.json b/package.json
index 86e092213e..c110ca119d 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"intercept-stdout": "^0.1.2",
"jsrsasign": "6.2.2",
"log4js": "^0.6.38",
+ "mock-couch": "https://github.com/jimthematrix/mock-couch.git",
"nano": "^6.2.0",
"require-dir": "^0.3.0",
"rewire": "^2.5.2",
diff --git a/test/fixtures/couchdb.json b/test/fixtures/couchdb.json
index cd37ca64e4..76f2ee7c6d 100644
--- a/test/fixtures/couchdb.json
+++ b/test/fixtures/couchdb.json
@@ -1,5 +1,5 @@
{
"couchdb-ip-addr" : "http://localhost",
"couchdb-port" : "5984",
- "key-value-store" : "./impl/CouchDBKeyValueStore.js"
+ "key-value-store" : "fabric-client/lib/impl/CouchDBKeyValueStore.js"
}
diff --git a/test/integration/couchdb-fabricca-tests.js b/test/integration/couchdb-fabricca-tests.js
index d0e027e3fe..b26c5cea67 100644
--- a/test/integration/couchdb-fabricca-tests.js
+++ b/test/integration/couchdb-fabricca-tests.js
@@ -28,10 +28,14 @@ var couchdbUtil = require('./couchdb-util.js');
// Use the CouchDB specific config file
hfc.addConfigFile('test/fixtures/couchdb.json');
-var dbClient = couchdbUtil.getCouchDBClient();
+
var keyValueStore = hfc.getConfigSetting('key-value-store');
console.log('Key Value Store = ' + keyValueStore);
+var couchdbIPAddr = hfc.getConfigSetting('couchdb-ip-addr', 'notfound');
+var couchdbPort = hfc.getConfigSetting('couchdb-port', 'notfound');
+var keyValStorePath = couchdbIPAddr + ':' + couchdbPort;
+
// This test first checks to see if a user has already been enrolled. If so,
// the test terminates. If the user is not yet enrolled, the test uses the
// FabricCAClientImpl to enroll a user, and saves the enrollment materials into the
@@ -49,11 +53,11 @@ test('Use FabricCAServices with a CouchDB KeyValueStore', function(t) {
var dbname = 'member_db';
var member;
- couchdbUtil.destroy(dbname, dbClient)
+ couchdbUtil.destroy(dbname, keyValStorePath)
.then( function(status) {
t.comment('Cleanup of existing ' + dbname + ' returned '+status);
t.comment('Initilize the CouchDB KeyValueStore');
- utils.newKeyValueStore({name: dbname, path: dbClient})
+ utils.newKeyValueStore({name: dbname, url: keyValStorePath})
.then(
function(kvs) {
t.comment('Setting client keyValueStore to: ' +kvs);
@@ -88,7 +92,7 @@ test('Use FabricCAServices with a CouchDB KeyValueStore', function(t) {
});
},
function(err) {
- t.fail('Failed to initilize the Fabric CA service: ' + err);
+ t.fail('Failed to initilize the Fabric CA service: ' + err.stack ? err.stack : err);
t.end();
}
)
diff --git a/test/integration/couchdb-util.js b/test/integration/couchdb-util.js
index 7adc2e9344..d067a84543 100644
--- a/test/integration/couchdb-util.js
+++ b/test/integration/couchdb-util.js
@@ -25,18 +25,8 @@ module.exports.getCloudantClient = function(configFile) {
return Cloudant({account: username, password: password});
};
-module.exports.getCouchDBClient = function(configFile) {
- var couchdbIPAddr = hfc.getConfigSetting('couchdb-ip-addr', 'notfound');
- var couchdbPort = hfc.getConfigSetting('couchdb-port', 'notfound');
-
- // Record the CouchDB KeyValueStorePath set by couchdb.json
- var keyValStorePath = couchdbIPAddr + ':' + couchdbPort;
- console.log('CouchDBClient IP address:port = ' + keyValStorePath);
- return nano(keyValStorePath);
-};
-
-module.exports.destroy = function(name, path) {
- this._path = path;
+module.exports.destroy = function(name, url) {
+ this._url = url;
this._name = name;
// Name of the database, optional
if (!name) {
@@ -44,7 +34,7 @@ module.exports.destroy = function(name, path) {
}
var self = this;
return new Promise(function(resolve, reject) {
- var dbClient = self._path;
+ var dbClient = nano(self._url);
dbClient.db.destroy(self._name, function(err, body) {
if (err) {
resolve(false);
diff --git a/test/unit/chain.js b/test/unit/chain.js
index b5c53822a9..74212e967c 100644
--- a/test/unit/chain.js
+++ b/test/unit/chain.js
@@ -257,6 +257,7 @@ test('\n\n ** Chain - method tests **\n\n', function (t) {
test_chain.initializeChain().then(
function (response) {
t.fail('Chain tests: orderer should have been required');
+ t.end();
},
function (error) {
if(!error) {
@@ -265,13 +266,15 @@ test('\n\n ** Chain - method tests **\n\n', function (t) {
else {
t.equals(error.toString(),'Error: no primary orderer defined','Chain tests: orederer is required when initializing');
}
+
+ var test_chain2 = new Chain('someTestChain2', {_userContext : {} });
+ test_chain2.addOrderer(new Orderer('grpc://somehost.com:1234'));
+ return test_chain2.initializeChain();
}
- );
- var test_chain2 = new Chain('someTestChain2', {_userContext : {} });
- test_chain2.addOrderer(new Orderer('grpc://somehost.com:1234'));
- test_chain2.initializeChain().then(
+ ).then(
function (response) {
t.fail('Chain tests: transaction should have been required');
+ t.end();
},
function (error) {
if(!error) {
@@ -280,20 +283,24 @@ test('\n\n ** Chain - method tests **\n\n', function (t) {
else {
t.equals(error.toString(),'Error: Initial transaction id is not defined','Chain tests: transaction id is required when initializing');
}
+
+ var client3 = new Client();
+ var test_chain3 = new Chain('someTestChain3', client3);
+ test_chain3.addOrderer(new Orderer('grpc://somehost.com:1234'));
+ return test_chain3.initializeChain();
}
- );
- var client3 = new Client();
- var test_chain3 = new Chain('someTestChain3', client3);
- test_chain3.addOrderer(new Orderer('grpc://somehost.com:1234'));
- test_chain3.initializeChain().then(function(response){
- t.fail('Chain tests: no user defined should, throw error, response '+response);
- },function(error){
- if (error && error.message && error.message === 'no user defined')
- t.pass('Chain tests: no user defined, should throw error');
- else t.fail('Chain tests: no user defined, should have thrown error "no user defined"');
- });
+ ).then(
+ function(response){
+ t.fail('Chain tests: no user defined should, throw error, response '+response);
+ t.end();
+ },function(error){
+ if (error && error.message && error.message === 'no user defined')
+ t.pass('Chain tests: no user defined, should throw error');
+ else t.fail('Chain tests: no user defined, should have thrown error "no user defined"');
- t.end();
+ t.end();
+ }
+ );
});
test('\n\n ** Chain query tests', function(t) {
@@ -471,11 +478,12 @@ test('\n\n** Chain packageChaincode tests **\n\n', function(t) {
var checkPath = path.join(destDir, 'src', 'github.com', 'example_cc');
t.equal(fs.existsSync(checkPath), true, 'The tar.gz file produced by Chain.packageChaincode() has the "src/github.com/example_cc" folder');
});
+
+ t.end();
}).catch((err) => {
t.fail(err.stack ? err.stack : err);
+ t.end();
});
-
- t.end();
});
test('\n\n ** Chain sendInstallProposal() tests **\n\n', function (t) {
@@ -602,19 +610,17 @@ test('\n\n ** Chain sendInstallProposal() tests **\n\n', function (t) {
});
Promise.all([p1, p1a, p3, p4, p6, p7])
- .then(
+ .then(
function (data) {
t.end();
}
- ).catch(
+ ).catch(
function (err) {
t.fail('Chain sendInstallProposal() tests, Promise.all: ');
console.log(err.stack ? err.stack : err);
t.end();
}
- );
-
- t.end();
+ );
});
test('\n\n ** Chain sendDeploymentProposal() tests **\n\n', function (t) {
@@ -771,18 +777,16 @@ test('\n\n ** Chain sendDeploymentProposal() tests **\n\n', function (t) {
});
Promise.all([p1, p1a, p2, p3, p4, p6, p7])
- .then(
+ .then(
function (data) {
t.end();
}
- ).catch(
+ ).catch(
function (err) {
t.fail('Chain sendDeploymentProposal() tests, Promise.all: '+err.stack ? err.stack : err);
t.end();
}
- );
-
- t.end();
+ );
});
test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) {
@@ -902,18 +906,16 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) {
});
Promise.all([p1, p2, p3, p4, p5, p6, p7])
- .then(
+ .then(
function (data) {
t.end();
}
- ).catch(
+ ).catch(
function (err) {
t.fail('Chain sendTransactionProposal() tests, Promise.all: '+err.stack ? err.stack : err);
t.end();
}
- );
-
- t.end();
+ );
});
test('\n\n ** Client queryByChaincode() tests **\n\n', function (t) {
@@ -1033,19 +1035,17 @@ test('\n\n ** Client queryByChaincode() tests **\n\n', function (t) {
});
Promise.all([p1, p2, p3, p4, p5, p6, p7])
- .then(
+ .then(
function (data) {
t.end();
}
- ).catch(
+ ).catch(
function (err) {
t.fail('Client queryByChaincode() tests, Promise.all: ');
console.log(err.stack ? err.stack : err);
t.end();
}
- );
-
- t.end();
+ );
});
test('\n\n ** Chain sendTransaction() tests **\n\n', function (t) {
@@ -1107,18 +1107,16 @@ test('\n\n ** Chain sendTransaction() tests **\n\n', function (t) {
});
Promise.all([p1, p2, p3, p4])
- .then(
+ .then(
function (data) {
t.end();
}
- ).catch(
+ ).catch(
function (err) {
t.fail('Chain sendTransaction() tests, Promise.all: '+err.stack ? err.stack : err);
t.end();
}
- );
-
- t.end();
+ );
});
//
@@ -1161,14 +1159,13 @@ test('\n\n** TEST ** orderer via chain setOrderer/getOrderer', function(t) {
var orderers = chain.getOrderers();
if(orderers !== null && orderers.length > 0 && orderers[1].getUrl() === 'grpc://localhost:5152') {
t.pass('Successfully retrieved the upated orderer URL from the chain');
- t.end();
}
else {
t.fail('Failed to retieve the updated orderer URL from the chain');
- t.end();
}
- }
- catch(err2) {
+
+ t.end();
+ } catch(err2) {
t.fail('Failed to update the order URL ' + err2);
t.end();
}
diff --git a/test/unit/client.js b/test/unit/client.js
index 53058d64f4..cf28419c0b 100644
--- a/test/unit/client.js
+++ b/test/unit/client.js
@@ -64,102 +64,100 @@ test('\n\n ** lib/Client.js **\n\n', function (t) {
if (response === null)
t.pass('Client tests: getUserContext successful null user name.');
else t.fail('Client tests: getUserContext failed null name check');
+
+ return client.saveUserToStateStore();
}, function(error){
t.fail('Client tests: Unexpected error, getUserContext null name check. ' + error);
- });
-
- client.saveUserToStateStore()
- .then(function(response){
+ t.end();
+ }).then(function(response){
t.fail('Client tests: got response, but should throw "Cannot save user to state store when userContext is null."');
+ t.end();
}, function(error){
if (error.message === 'Cannot save user to state store when userContext is null.')
t.pass('Client tests: Should throw "Cannot save user to state store when userContext is null."');
else t.fail('Client tests: Unexpected error message thrown, should throw "Cannot save user to state store when userContext is null." ' + error);
- });
- client.setUserContext(null)
- .then(function(response){
+ return client.setUserContext(null);
+ }).then(function(response){
t.fail('Client tests: got response, but should throw "Cannot save null userContext."');
+ t.end();
}, function(error){
if (error.message === 'Cannot save null userContext.')
t.pass('Client tests: Should throw "Cannot save null userContext."');
else t.fail('Client tests: Unexpected error message thrown, should throw "Cannot save null userContext." ' + error);
- });
- client.getUserContext('someUser')
- .then(function(response){
+ return client.getUserContext('someUser');
+ }).then(function(response){
if (response == null)
t.pass('Client tests: getUserContext with no context in memory or persisted returns null');
else t.fail('Client tests: getUserContext with no context in memory or persisted did not return null');
+
+ return client.setUserContext(new User('someUser'), true);
}, function(error){
t.fail('Client tests: getUserContext with no context in memory or persisted did not returned error. ' + error);
- });
-
- client.setUserContext(new User('someUser'), true)
- .then(function(response){
+ t.end();
+ }).then(function(response){
if (response && response.getName() === 'someUser') {
t.pass('Client tests: successfully setUserContext with skipPersistence.');
return response;
}
else t.fail('Client tests: failed name check after setUserContext with skipPersistence.');
+
+ return client.getUserContext('someUser');
}, function(error){
t.fail('Client tests: Unexpected error, failed setUserContext with skipPersistence. ' + error);
- })
- .then(function(response){
- client.getUserContext('someUser')
- .then(function(response){
- if (response && response.getName() === 'someUser')
- t.pass('Client tests: getUserContext not persisted/skipPersistence was successful.');
- else t.fail('Client tests: getUserContext not persisted/skipPersistence was not successful.');
- }, function(error){
- t.fail('Client tests: Unexpected error, getUserContext not persisted/skipPersistence. ' + error);
- });
- });
-
- client.setUserContext(new User('someUser'))
- .then(function(result){
+ t.end();
+ }).then(function(response){
+ if (response && response.getName() === 'someUser')
+ t.pass('Client tests: getUserContext not persisted/skipPersistence was successful.');
+ else t.fail('Client tests: getUserContext not persisted/skipPersistence was not successful.');
+
+ return client.setUserContext(new User('someUser'));
+ }, function(error){
+ t.fail('Client tests: Unexpected error, getUserContext not persisted/skipPersistence. ' + error);
+ t.end();
+ }).then(function(result){
t.fail('Client tests: setUserContext without skipPersistence and no stateStore should not return result.');
- },
- function(error){
+ t.end();
+ }, function(error){
if (error.message === 'Cannot save user to state store when stateStore is null.')
t.pass('Client tests: Should throw "Cannot save user to state store when stateStore is null"');
else t.fail('Client tests: Unexpected error message thrown, should throw "Cannot save user to state store when stateStore is null." ' + error);
- });
-
- var chain = client.newChain('someChain');
- t.equals(chain.getName(), 'someChain', 'Checking chain names match');
- t.throws(
- function () {
- client.newChain('someChain');
- },
- /^Error: Chain someChain already exist/,
- 'Client tests: checking that chain already exists.');
-
- t.doesNotThrow(
- function() {
- client.getChain('someChain');
- },
- null,
- 'Client tests: getChain()');
- t.throws(
+ var chain = client.newChain('someChain');
+ t.equals(chain.getName(), 'someChain', 'Checking chain names match');
+ t.throws(
function () {
- client.getChain('someOtherChain');
+ client.newChain('someChain');
},
- /^Error: Chain not found for name someOtherChain./,
- 'Client tests: Should throw Error: Chain not found for name someOtherChain.');
+ /^Error: Chain someChain already exist/,
+ 'Client tests: checking that chain already exists.');
- t.throws(
- function() {
- client.setStateStore({});
- },
- /The "keyValueStore" parameter must be an object that implements the following methods, which are missing:/,
- 'Client tests: checking state store parameter implementing required functions');
+ t.doesNotThrow(
+ function() {
+ client.getChain('someChain');
+ },
+ null,
+ 'Client tests: getChain()');
+
+ t.throws(
+ function () {
+ client.getChain('someOtherChain');
+ },
+ /^Error: Chain not found for name someOtherChain./,
+ 'Client tests: Should throw Error: Chain not found for name someOtherChain.');
+
+ t.throws(
+ function() {
+ client.setStateStore({});
+ },
+ /The "keyValueStore" parameter must be an object that implements the following methods, which are missing:/,
+ 'Client tests: checking state store parameter implementing required functions');
- testutil.cleanupDir(chainKeyValStorePath);
+ testutil.cleanupDir(chainKeyValStorePath);
- Client.newDefaultKeyValueStore({ path: chainKeyValStorePath })
- .then (
+ return Client.newDefaultKeyValueStore({ path: chainKeyValStorePath });
+ }).then (
function (kvs) {
client.setStateStore(kvs);
@@ -170,26 +168,25 @@ test('\n\n ** lib/Client.js **\n\n', function (t) {
t.fail('Client setKeyValueStore test: Failed to create new directory: ' + chainKeyValStorePath);
var store = client.getStateStore();
- store.setValue('testKey', 'testValue')
- .then(
- function (result) {
- t.pass('Client getStateStore test: Successfully set value, result: ' + result);
-
- var exists = testutil.existsSync(chainKeyValStorePath, testKey);
- if (exists)
- t.pass('Client getStateStore test: Verified the file for key ' + testKey + ' does exist');
- else
- t.fail('Client getStateStore test: Failed to create file for key ' + testKey);
-
- t.end();
- }
- ).catch(
- function (reason) {
- t.fail('Client getStateStore test: Failed to set value, reason: ' + reason);
- t.end();
- }
- );
- });
+ return store.setValue('testKey', 'testValue');
+ }).then(
+ function (result) {
+ t.pass('Client getStateStore test: Successfully set value, result: ' + result);
+
+ var exists = testutil.existsSync(chainKeyValStorePath, testKey);
+ if (exists)
+ t.pass('Client getStateStore test: Verified the file for key ' + testKey + ' does exist');
+ else
+ t.fail('Client getStateStore test: Failed to create file for key ' + testKey);
+
+ t.end();
+ }
+ ).catch(
+ function (reason) {
+ t.fail('Client getStateStore test: Failed to set value, reason: ' + reason);
+ t.end();
+ }
+ );
});
/*
diff --git a/test/unit/couchdb-key-value-store.js b/test/unit/couchdb-key-value-store.js
new file mode 100644
index 0000000000..f4a004eb37
--- /dev/null
+++ b/test/unit/couchdb-key-value-store.js
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2017 IBM All Rights Reserved.
+ *
+ * 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.
+ */
+
+'use strict';
+
+var tape = require('tape');
+var _test = require('tape-promise');
+var test = _test(tape);
+var CouchdbMock = require('mock-couch');
+
+var CDBKVS = require('fabric-client/lib/impl/CouchDBKeyValueStore.js');
+
+test('\n\n** CouchDBKeyValueStore tests', (t) => {
+ t.throws(
+ () => {
+ new CDBKVS();
+ },
+ /Must provide the CouchDB database url to store membership data/,
+ 'Error checking in the constructor: missing opts'
+ );
+
+ t.throws(
+ () => {
+ new CDBKVS({dummy: 'value'});
+ },
+ /Must provide the CouchDB database url to store membership data/,
+ 'Error checking in the constructor: opts object missing required "url"'
+ );
+
+ var store;
+
+ new CDBKVS({url: 'http://dummyUrl'})
+ .then(() => {
+ t.fail('Should not have been able to successfully constructed a store from an invalid URL');
+ t.end();
+ }).catch((err) => {
+ if (err.message && err.message.indexOf('Error: getaddrinfo ENOTFOUND dummyurl') > 0) {
+ t.pass('Successfully rejected the construction request due to invalid URL');
+ } else {
+ t.fail('Store construction failed for unknown reason: ' + err.stack ? err.stack : err);
+ }
+
+ var couchdb = CouchdbMock.createServer();
+ couchdb.listen(5985);
+
+ // override t.end function so it'll always disconnect the event hub
+ t.end = ((context, mockdb, f) => {
+ return function() {
+ if (mockdb) {
+ console.log('Disconnecting the mock couchdb server');
+ mockdb.close();
+ }
+
+ f.apply(context, arguments);
+ };
+ })(t, couchdb, t.end);
+
+ return new CDBKVS({url: 'http://localhost:5985'});
+ }).then((st) => {
+ store = st;
+ t.pass('Successfully connected the key value store to couchdb at localhost:5985');
+
+ t.notEqual(store._database, undefined, 'Check "_database" value of the constructed store object');
+
+ return store.setValue('someKey', 'someValue');
+ }).then((value) => {
+ t.equal(value, 'someValue', 'Check result of setValue()');
+
+ return store.getValue('someKey');
+ }).then((value) => {
+ t.equal(value, 'someValue', 'Check result of getValue()');
+ t.end();
+ }).catch((err) => {
+ t.fail(err.stack ? err.stack : err);
+ t.end();
+ });
+});
\ No newline at end of file
diff --git a/test/unit/crypto-key-store.js b/test/unit/crypto-key-store.js
index a8e6413031..9d7d31f1aa 100644
--- a/test/unit/crypto-key-store.js
+++ b/test/unit/crypto-key-store.js
@@ -26,11 +26,14 @@ var fs = require('fs-extra');
var path = require('path');
var jsrsa = require('jsrsasign');
var KEYUTIL = jsrsa.KEYUTIL;
+var CouchdbMock = require('mock-couch');
+var nano = require('nano');
testutil.resetDefaults();
var ecdsaKey = require('fabric-client/lib/impl/ecdsa/key.js');
var CKS = require('fabric-client/lib/impl/CryptoKeyStore.js');
+var CouchDBKeyValueStore = require('fabric-client/lib/impl/CouchDBKeyValueStore.js');
var TEST_KEY_PRIVATE_PEM = '-----BEGIN PRIVATE KEY-----' +
'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgZYMvf3w5VkzzsTQY' +
@@ -52,6 +55,14 @@ var TEST_KEY_PRIVATE_CERT_PEM = '-----BEGIN CERTIFICATE-----' +
'BAHpeA==' +
'-----END CERTIFICATE-----';
+var dbname = 'test_keystore';
+var dbclient = nano('http://localhost:5985');
+
+var f1 = KEYUTIL.getKey(TEST_KEY_PRIVATE_PEM);
+var testPrivKey = new ecdsaKey(f1);
+var f2 = KEYUTIL.getKey(TEST_KEY_PRIVATE_CERT_PEM);
+var testPubKey = new ecdsaKey(f2);
+
test('\n\n** CryptoKeyStore tests **\n\n', function(t) {
t.throws(
() => {
@@ -69,11 +80,6 @@ test('\n\n** CryptoKeyStore tests **\n\n', function(t) {
'Test invalid constructor calls: missing "path" property in the "options" parameter'
);
- var f1 = KEYUTIL.getKey(TEST_KEY_PRIVATE_PEM);
- var testPrivKey = new ecdsaKey(f1);
- var f2 = KEYUTIL.getKey(TEST_KEY_PRIVATE_CERT_PEM);
- var testPubKey = new ecdsaKey(f2);
-
var store;
CKS({path: '/tmp/hfc-cks'})
.then((st) => {
@@ -106,9 +112,124 @@ test('\n\n** CryptoKeyStore tests **\n\n', function(t) {
}).then((recoveredKey) => {
t.notEqual(recoveredKey, null, 'Successfully read public key from store using SKI');
t.equal(recoveredKey.isPrivate(), false, 'Test if the recovered key is a public key');
+ t.end();
}).catch((err) => {
t.fail(err.stack ? err.stack : err);
+ t.end();
});
+});
+
+
+test('\n\n** CryptoKeyStore tests - couchdb based store tests - use configSetting **\n\n', function(t) {
+ utils.setConfigSetting('key-value-store', 'fabric-client/lib/impl/CouchDBKeyValueStore.js');
+
+ var couchdb = CouchdbMock.createServer();
+ couchdb.listen(5985);
+
+ // override t.end function so it'll always disconnect the event hub
+ t.end = ((context, mockdb, f) => {
+ return function() {
+ if (mockdb) {
+ console.log('Disconnecting the mock couchdb server');
+ mockdb.close();
+ }
+
+ f.apply(context, arguments);
+ };
+ })(t, couchdb, t.end);
- t.end();
-});
\ No newline at end of file
+ CKS({name: dbname, url: 'http://localhost:5985'})
+ .then((store) => {
+ return testKeyStore(store, t);
+ }).catch((err) => {
+ t.fail(err.stack ? err.stack : err);
+ t.end();
+ }).then(() => {
+ t.end();
+ });
+});
+
+test('\n\n** CryptoKeyStore tests - couchdb based store tests - use constructor argument **\n\n', function(t) {
+ var couchdb = CouchdbMock.createServer();
+ couchdb.listen(5985);
+
+ // override t.end function so it'll always disconnect the event hub
+ t.end = ((context, mockdb, f) => {
+ return function() {
+ if (mockdb) {
+ console.log('Disconnecting the mock couchdb server');
+ mockdb.close();
+ }
+
+ f.apply(context, arguments);
+ };
+ })(t, couchdb, t.end);
+
+ CKS(CouchDBKeyValueStore, {name: dbname, url: 'http://localhost:5985'})
+ .then((store) => {
+ return testKeyStore(store, t);
+ }).catch((err) => {
+ t.fail(err.stack ? err.stack : err);
+ t.end();
+ }).then(() => {
+ t.end();
+ });
+});
+
+function testKeyStore(store, t) {
+ var docRev;
+
+ return store.putKey(testPrivKey)
+ .then((keyPEM) => {
+ t.pass('Successfully saved private key in store based on couchdb');
+
+ return new Promise((resolve, reject) => {
+ dbclient.use(dbname).get(testPrivKey.getSKI() + '-priv', function(err, body) {
+ if (!err) {
+ t.pass('Successfully verified private key persisted in couchdb');
+ docRev = body._rev;
+ return resolve(store.getKey(testPrivKey.getSKI()));
+ } else {
+ t.fail('Failed to persist private key in couchdb. ' + err.stack ? err.stack : err);
+ t.end();
+ }
+ });
+ });
+ }).then((recoveredKey) => {
+ t.notEqual(recoveredKey, null, 'Successfully read private key from store using SKI');
+ t.equal(recoveredKey.isPrivate(), true, 'Test if the recovered key is a private key');
+
+ return store.putKey(testPubKey);
+ }).then((keyPEM) => {
+ return new Promise((resolve, reject) => {
+ dbclient.use(dbname).get(testPrivKey.getSKI() + '-pub', function(err, body) {
+ if (!err) {
+ t.pass('Successfully verified public key persisted in couchdb');
+ return resolve(store.getKey(testPubKey.getSKI()));
+ } else {
+ t.fail('Failed to persist public key in couchdb. ' + err.stack ? err.stack : err);
+ t.end();
+ }
+ });
+ });
+ }).then((recoveredKey) => {
+ t.notEqual(recoveredKey, null, 'Successfully read public key from store using SKI');
+ t.equal(recoveredKey.isPrivate(), true, 'Test if the recovered key is a private key');
+
+ // delete the private key entry and test if getKey() would return the public key
+ return new Promise((resolve, reject) => {
+ dbclient.use(dbname).destroy(testPrivKey.getSKI() + '-priv', docRev, function(err, body) {
+ if (!err) {
+ t.comment('Successfully deleted entry for private key');
+ return resolve(store.getKey(testPubKey.getSKI()));
+ } else {
+ t.fail('Failed to delete private key in couchdb. ' + err.stack ? err.stack : err);
+ t.end();
+ }
+ });
+ });
+ }).then((recoveredKey) => {
+ t.notEqual(recoveredKey, null, 'Successfully read public key from store using SKI');
+ t.equal(recoveredKey.isPrivate(), false, 'Test if the recovered key is a public key');
+ });
+}
diff --git a/test/unit/cryptosuite-ecdsa-aes.js b/test/unit/cryptosuite-ecdsa-aes.js
index 8f52200143..cb607688c3 100644
--- a/test/unit/cryptosuite-ecdsa-aes.js
+++ b/test/unit/cryptosuite-ecdsa-aes.js
@@ -25,13 +25,14 @@ var testutil = require('./util.js');
var utils = require('fabric-client/lib/utils.js');
var path = require('path');
var fs = require('fs-extra');
-
-testutil.resetDefaults();
+var util = require('util');
+var os = require('os');
var jsrsa = require('jsrsasign');
var KEYUTIL = jsrsa.KEYUTIL;
var ECDSA = jsrsa.ECDSA;
+var CouchDBKeyValueStore = require('fabric-client/lib/impl/CouchDBKeyValueStore.js');
var CryptoSuite_ECDSA_AES = require('fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js');
var ecdsaKey = require('fabric-client/lib/impl/ecdsa/key.js');
var api = require('fabric-client/lib/api.js');
@@ -132,20 +133,31 @@ const halfOrdersForCurve = {
var _client = new hfc();
test('\n\n** utils.getCryptoSuite tests **\n\n', (t) => {
- var cs = utils.getCryptoSuite({keysize: 384, algorithm: 'EC'}, keyValStorePath);
+ testutil.resetDefaults();
+
+ let config = { path: keyValStorePath };
+
+ let cs = utils.getCryptoSuite({keysize: 384, algorithm: 'EC'}, config);
t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES');
t.equal(cs._keySize, 384, 'Returned instance should have keysize of 384');
- t.equal(cs._storePath, keyValStorePath, 'Returned instance should have store path of ' + keyValStorePath);
+ t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config));
+ t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass');
- cs = utils.getCryptoSuite({keysize: 384, algorithm: 'EC'}, keyValStorePath);
+ cs = utils.getCryptoSuite({keysize: 384}, config);
t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Default test: should return an instance of CryptoSuite_ECDSA_AES');
t.equal(cs._keySize, 384, 'Returned instance should have keysize of 384');
- t.equal(cs._storePath, keyValStorePath, 'Returned instance should have store path of ' + keyValStorePath);
+ t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config));
+
+ cs = utils.getCryptoSuite({algorithm: 'EC'}, config);
+ t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES');
+ t.equal(cs._keySize, 256, 'Returned instance should have keysize of 256');
+ t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config));
- cs = utils.getCryptoSuite({algorithm: 'EC'}, keyValStorePath);
+ let defaultKVSPath = path.join(os.homedir(), '.hfc-key-store');
+ cs = utils.getCryptoSuite({algorithm: 'EC'});
t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES');
t.equal(cs._keySize, 256, 'Returned instance should have keysize of 256');
- t.equal(cs._storePath, keyValStorePath, 'Returned instance should have store path of ' + keyValStorePath);
+ t.equal(cs._storeConfig.opts.path, defaultKVSPath, util.format('Returned instance should have store config opts.path of %s', defaultKVSPath));
// each app instance is expected to use either HSM or software-based key management, as such this question
// is answered with a config setting rather than controlled on a case-by-case basis
@@ -159,57 +171,77 @@ test('\n\n** utils.getCryptoSuite tests **\n\n', (t) => {
);
utils.setConfigSetting('crypto-hsm', false);
- t.throws(
+ t.doesNotThrow(
() => {
cs = utils.getCryptoSuite({lib: '/usr/local/lib', slot: 0, pin: '1234' });
+ cs._getKeyStore()
+ .then((store) => {
+ t.fail('Should not have been able to get a valid key store because of invalid store config');
+ t.end();
+ }).catch((err) => {
+ t.pass('Successfully rejected _getKeyStore() due to invalid config');
+ t.end();
+ });
},
- /^Error: The "kvsPath" parameter for this constructor, if specified, must be a string specifying a file system path/,
- 'Should attempt to load the CryptoSuite_ECDSA_AES module and fail because of the invalid file store path'
+ null,
+ 'Load the CryptoSuite_ECDSA_AES module and pass in an invalid config object'
);
-
- t.end();
});
test('\n\n ** CryptoSuite_ECDSA_AES - constructor tests **\n\n', function (t) {
cleanupFileKeyValueStore(keyValStorePath);
- var keyValueStorePromise = utils.newKeyValueStore({ path: getRelativePath(keyValStorePath) });
-
- t.throws(
- function() {
- utils.getCryptoSuite(keyValueStorePromise);
- },
- /^Error: The "kvsPath" parameter for this constructor, if specified, must be a string specifying a file system path/,
- 'CryptoSuite_ECDSA_AES constructor tests: opts passed as a promise should throw error'
- );
var keyValueStore = null;
- var cs5;
- t.doesNotThrow(
- function () {
- cs5 = utils.getCryptoSuite(keyValStorePath);
- },
- null,
- 'CryptoSuite_ECDSA_AES constructor tests: pass in a string as kvs path'
- );
+ let cs;
- cs5._getKeyStore()
- .then((store) => {
+ cs = new CryptoSuite_ECDSA_AES(256, CouchDBKeyValueStore, { name: 'test_db', url: 'http://dummyUrl'});
+ cs._getKeyStore()
+ .then(() => {
+ t.fail('Should not have been able to get a valid key store because the url was invalid');
+ }).catch((err) => {
+ if (err.message.indexOf('Error creating test_db database to store membership data: Error: getaddrinfo ENOTFOUND dummyurl') >= 0) {
+ t.pass('Successfully rejected _getKeyStore() because the url was invalid');
+ } else {
+ t.fail(err);
+ }
+
+ t.doesNotThrow(
+ () => {
+ cs = utils.getCryptoSuite(keyValStorePath);
+ },
+ null,
+ 'CryptoSuite_ECDSA_AES constructor tests: pass in a string as kvs path'
+ );
+
+ return cs._getKeyStore();
+ }).then(() => {
+ t.fail('Should not have been able to obtain a proper key store due to invalid config');
+ }).catch(() => {
+ t.pass('Successfully rejected attempt to obtain a proper key store');
+
+ utils.setConfigSetting('key-value-store', 'fabric-client/lib/impl/FileKeyValueStore.js');
+
+ let cs1 = utils.getCryptoSuite({
+ path: keyValStorePath
+ });
+
+ return cs1._getKeyStore();
+ }).then((store) => {
t.notEqual(store, null, 'Crypto Key Store successfully initialized by CryptoSuite_ECDSA_AES');
t.equal(typeof store.getKey, 'function', 'Crypto key store much have the "getKey()" function');
t.equal(typeof store.putKey, 'function', 'Crypto key store much have the "putKey()" function');
- });
- var cs = new CryptoSuite_ECDSA_AES(256, keyValStorePath);
- cs._getKeyStore()
- .then((store) => {
+ let cs2 = new CryptoSuite_ECDSA_AES(256, {path: keyValStorePath});
+ return cs2._getKeyStore();
+ }).then((store) => {
t.notEqual(store, null, 'Crypto Key Store successfully initialized by CryptoSuite_ECDSA_AES');
t.equal(typeof store.getKey, 'function', 'Crypto key store much have the "getKey()" function');
t.equal(typeof store.putKey, 'function', 'Crypto key store much have the "putKey()" function');
+ t.end();
}).catch((err) => {
t.fail(err.stack ? err.stack : err);
+ t.end();
});
-
- t.end();
});
test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) {
@@ -405,59 +437,51 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) {
testVerify(TEST_LONG_MSG_SIGNATURE_SHA2_256, TEST_LONG_MSG, false);
// test importKey()
- cryptoUtils.importKey(TEST_CERT_PEM)
- .then((pubKey) => {
- t.equal(pubKey.isPrivate(), false, 'Test imported public key isPrivate()');
- t.equal(pubKey.getSKI(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef', 'Test imported public key SKI');
-
- // verify that the pub key has been saved in the key store by the proper key
- t.equal(
- fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef-pub')),
- true,
- 'Check that the imported public key has been saved in the key store');
- }).catch((err) => {
- t.fail(err.stack ? err.stack : err);
- });
-
- cryptoUtils.importKey(TEST_KEY_PRIVATE_PEM)
- .then((privKey) => {
- t.equal(privKey.isPrivate(), true, 'Test imported private key isPrivate');
- t.equal(privKey.getSKI(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a', 'Test imported private key SKI');
- t.end();
-
- // verify that the imported private key has been saved in the key store by the proper key
- t.equal(
- fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')),
- true,
- 'Check that the imported private key has been saved in the key store');
-
- // verify that the imported key can properly sign messages
- var testSig = cryptoUtils.sign(privKey, cryptoUtils.hash(TEST_MSG));
- t.equal(
- cryptoUtils.verify(privKey.getPublicKey(), testSig, TEST_MSG),
- true,
- 'Check that the imported private key can properly sign messages');
-
- // manufacture an error condition where the private key does not exist for the SKI, and only the public key does
- return cryptoUtils.importKey(TEST_KEY_PRIVATE_CERT_PEM);
- }).then((pubKey) => {
- fs.removeSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv'));
-
- var poorUser = new User('admin2', _client);
- poorUser.fromString(JSON.stringify(TEST_USER_ENROLLMENT))
- .then(() => {
- t.fail('Failed to catch missing private key expected from a user enrollment object');
- }).catch((err) => {
- t.pass('Successfully caught missing private key expected from a user enrollment object');
- });
- }).catch((err) => {
- t.fail(err.stack ? err.stack : err);
- });
+ return cryptoUtils.importKey(TEST_CERT_PEM);
+ }).then((pubKey) => {
+ t.equal(pubKey.isPrivate(), false, 'Test imported public key isPrivate()');
+ t.equal(pubKey.getSKI(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef', 'Test imported public key SKI');
+
+ // verify that the pub key has been saved in the key store by the proper key
+ t.equal(
+ fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef-pub')),
+ true,
+ 'Check that the imported public key has been saved in the key store');
+
+ return cryptoUtils.importKey(TEST_KEY_PRIVATE_PEM);
+ }).then((privKey) => {
+ t.equal(privKey.isPrivate(), true, 'Test imported private key isPrivate');
+ t.equal(privKey.getSKI(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a', 'Test imported private key SKI');
+ t.end();
+ // verify that the imported private key has been saved in the key store by the proper key
+ t.equal(
+ fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')),
+ true,
+ 'Check that the imported private key has been saved in the key store');
+
+ // verify that the imported key can properly sign messages
+ var testSig = cryptoUtils.sign(privKey, cryptoUtils.hash(TEST_MSG));
+ t.equal(
+ cryptoUtils.verify(privKey.getPublicKey(), testSig, TEST_MSG),
+ true,
+ 'Check that the imported private key can properly sign messages');
+
+ // manufacture an error condition where the private key does not exist for the SKI, and only the public key does
+ return cryptoUtils.importKey(TEST_KEY_PRIVATE_CERT_PEM);
+ }).then((pubKey) => {
+ fs.removeSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv'));
+
+ var poorUser = new User('admin2', _client);
+ return poorUser.fromString(JSON.stringify(TEST_USER_ENROLLMENT));
+ }).then(() => {
+ t.fail('Failed to catch missing private key expected from a user enrollment object');
t.end();
- })
- .catch(function (err) {
- t.fail('Unexpected error: ' + err.stack ? err.stack : err);
+ },(err) => {
+ t.pass('Successfully caught missing private key expected from a user enrollment object');
+ t.end();
+ }).catch((err) => {
+ t.fail(err.stack ? err.stack : err);
t.end();
});
});
diff --git a/test/unit/fabric-ca-client.js b/test/unit/fabric-ca-client.js
index 1af0808a0f..e7f01a5255 100644
--- a/test/unit/fabric-ca-client.js
+++ b/test/unit/fabric-ca-client.js
@@ -220,18 +220,20 @@ test('FabricCAClient: Test enroll with missing parameters', function (t) {
port: 7054
});
- //
- return client.enroll()
- .then(function (csr) {
- t.fail('Enrollment must fail when missing required parameters');
- })
- .catch(function (err) {
- if (err.message.startsWith('Missing required parameters')) {
- t.pass('Enrollment should fail when missing required parameters');
- } else {
- t.fail('Enrollment should have failed with \'Missing required parameters\'');
- }
- });
+ client.enroll()
+ .then(function (csr) {
+ t.fail('Enrollment must fail when missing required parameters');
+ t.end();
+ })
+ .catch(function (err) {
+ if (err.message.startsWith('Missing required parameters')) {
+ t.pass('Enrollment should fail when missing required parameters');
+ } else {
+ t.fail('Enrollment should have failed with \'Missing required parameters\'');
+ }
+
+ t.end();
+ });
});
/**
@@ -245,15 +247,18 @@ test('FabricCAClient: Test register with missing parameters', function (t) {
port: 7054
});
- return client.register()
- .then(function (token) {
- t.fail('Register must fail when missing required parameters');
- })
- .catch(function (err) {
- if (err.message.startsWith('Missing required parameters')) {
- t.pass('Register should fail when missing required parameters');
- } else {
- t.fail('Register should have failed with \'Missing required parameters\'');
- }
- });
+ client.register()
+ .then(function (token) {
+ t.fail('Register must fail when missing required parameters');
+ t.end();
+ })
+ .catch(function (err) {
+ if (err.message.startsWith('Missing required parameters')) {
+ t.pass('Register should fail when missing required parameters');
+ } else {
+ t.fail('Register should have failed with \'Missing required parameters\'');
+ }
+
+ t.end();
+ });
});
\ No newline at end of file
diff --git a/test/unit/file-key-value-store.js b/test/unit/file-key-value-store.js
index 40140fc21a..edd66164db 100644
--- a/test/unit/file-key-value-store.js
+++ b/test/unit/file-key-value-store.js
@@ -141,13 +141,15 @@ test('\n\n ** FileKeyValueStore - constructor setValue getValue test store1 **\n
t.fail('FileKeyValueStore read and write test store1: get value ' + val + ' does not equal testValue of ' + testValue);
else
t.pass('FileKeyValueStore read and write test store1: Successfully retrieved value');
+
+ t.end();
}
).catch (
- function(err) {
- t.fail('FileKeyValueStore store1 setValue test store1, caught err: ' + err);
- }
- );
- t.end();
+ function(err) {
+ t.fail('FileKeyValueStore store1 setValue test store1, caught err: ' + err);
+ t.end();
+ }
+ );
});
test('\n\n ** FileKeyValueStore - constructor setValue getValue test store2 **\n\n', function (t) {
@@ -245,18 +247,14 @@ test('\n\n** FileKeyValueStore error check tests **\n\n', function (t) {
} else {
t.fail('FileKeyValueStore error check tests: Delete store & getValue test. getValue successfully retrieved value: ' + val);
}
+
+ cleanupFileKeyValueStore(keyValStorePath4);
+ return new FileKeyValueStore({ path: getRelativePath(keyValStorePath4) });
},
function (reason) {
t.fail('FileKeyValueStore error check tests: Delete store & getValue test. getValue caught unexpected error: ' + reason);
- })
- .catch(
- function (err) {
- t.fail('Failed with unexpected error: ' + err.stack ? err.stack : err);
- t.end();
- });
-
- cleanupFileKeyValueStore(keyValStorePath4);
- var promise4 = new FileKeyValueStore({ path: getRelativePath(keyValStorePath4) })
+ }
+ )
.then(
function (store) {
store4 = store;
diff --git a/test/unit/identity.js b/test/unit/identity.js
index b0598a7f1d..9bb748ee8f 100644
--- a/test/unit/identity.js
+++ b/test/unit/identity.js
@@ -233,9 +233,9 @@ test('\n\n ** Identity class tests **\n\n', function (t) {
var sig = signingID.sign(TEST_MSG);
t.equal(cryptoUtils.verify(pubKey, sig, TEST_MSG), true, 'Test SigningIdentity sign() method');
t.equal(signingID.verify(TEST_MSG, sig), true, 'Test Identity verify() method');
+ t.end();
}).catch((err) => {
t.fail(err.stack ? err.stack : err);
+ t.end();
});
-
- t.end();
});
\ No newline at end of file
diff --git a/test/unit/user.js b/test/unit/user.js
index e40e253416..43977a1928 100644
--- a/test/unit/user.js
+++ b/test/unit/user.js
@@ -118,19 +118,14 @@ test('\n\n ** User - constructor set get tests **\n\n', function (t) {
cryptoUtils.generateKey()
.then(function (key) {
// the private key and cert don't match, but it's ok, the code doesn't check
- member2.setEnrollment(key, TEST_CERT_PEM)
- .then(() => {
- var id = member2.getIdentity();
+ return member2.setEnrollment(key, TEST_CERT_PEM);
+ }).then(() => {
+ var id = member2.getIdentity();
- t.equal(id._publicKey._key.pubKeyHex, '0452a75e1ee105da7ab3d389fda69d8a04f5cf65b305b49cec7cdbdeb91a585cf87bef5a96aa9683d96bbabfe60d8cc6f5db9d0bc8c58d56bb28887ed81c6005ac', 'User class setEnrollment() test');
- t.end();
- });
-
- // TODO: test SigningIdentity
+ t.equal(id._publicKey._key.pubKeyHex, '0452a75e1ee105da7ab3d389fda69d8a04f5cf65b305b49cec7cdbdeb91a585cf87bef5a96aa9683d96bbabfe60d8cc6f5db9d0bc8c58d56bb28887ed81c6005ac', 'User class setEnrollment() test');
t.end();
}).catch((err) => {
t.fail(err.stack ? err.stack : err);
+ t.end();
});
-
- t.end();
});
\ No newline at end of file