From 960baaaaeb17faba13f97d842fc13c47db610dbc Mon Sep 17 00:00:00 2001 From: Yi DENG Date: Wed, 6 Mar 2019 16:36:05 +0800 Subject: [PATCH 1/4] Test case: fabricClient. #49 Signed-off-by: Yi DENG --- src/util/fabric.js | 98 ++++++++++++++++++++-------------------- test/util/fabric.test.js | 33 +++++++++----- 2 files changed, 70 insertions(+), 61 deletions(-) diff --git a/src/util/fabric.js b/src/util/fabric.js index e74fe2d..373d0a3 100644 --- a/src/util/fabric.js +++ b/src/util/fabric.js @@ -14,54 +14,54 @@ const logger = require('electron-log'); class FabricClient { constructor() { - const fabricClient = new FabricClientSDK(); - this.fabric_client = fabricClient; + this.fabricClient = new FabricClientSDK(); } // 抽出空挡,插入配置文件,以便集成测试 _getConfig(configDb) { - const self = this; return new Promise((resolve, reject) => { configDb.find({}, (err, resultList) => { if (err) { logger.info('the operation of find documents failed!'); reject('error'); } - logger.info('success get config!'); - const output = { - result: resultList, - obj: self, - }; - resolve(output); - logger.info('result:', resultList); + logger.info('success get config!', ' result:', resultList); + resolve(resultList); }); }); } _config(input) { - const obj = input.obj; + const config = input[0]; + const self = this; + const fabricClient = this.fabricClient; return new Promise((resolve) => { logger.info('input:', input.result); - const config = input.result[0]; if (config.tlsPeerPath === '' || config.tlsOrdererPath === '') { logger.info('+++++++++++++++++'); - obj.flag = false; + self.flag = false; + self.peer = fabricClient.newPeer(config.peerGrpcUrl); + self.order = fabricClient.newOrderer(config.ordererUrl); } else { logger.info('------------------'); - obj.peerCert = fs.readFileSync(config.tlsPeerPath); - obj.orderersCert = fs.readFileSync(config.tlsOrdererPath); - obj.flag = true; + self.peerCert = fs.readFileSync(config.tlsPeerPath); + self.orderersCert = fs.readFileSync(config.tlsOrdererPath); + self.flag = true; + self.peer = fabricClient.newPeer(config.peerGrpcUrl, + { pem: Buffer.from(this.peerCert).toString(), 'ssl-target-name-override': this.config.peerSSLTarget }); + self.order = fabricClient.newOrderer(config.ordererUrl, + { pem: Buffer.from(this.orderersCert).toString(), 'ssl-target-name-override': this.config.ordererSSLTarget }); } logger.info('config:', config); const storePath = path.join(__dirname, '../../', config.path); logger.info(`Store path:${storePath}`); - obj.config = config; - obj.store_path = storePath; - obj.channels = {}; + self.config = config; + self.store_path = storePath; + self.channels = {}; - resolve(obj); + resolve(); }); } @@ -70,22 +70,26 @@ class FabricClient { * @returns {Promise} * */ - _enrollUser(self) { + _enrollUser() { + const self = this; const usrName = self.config.mspid; - // logger.info('start to load member user.'); + logger.info('start to load member user.', ' store_path: ', self.store_path); return FabricClientSDK.newDefaultKeyValueStore({ path: self.store_path, }).then((stateStore) => { + logger.info('get stateStore: ', stateStore); + // assign the store to the fabric client - self.fabric_client.setStateStore(stateStore); + self.fabricClient.setStateStore(stateStore); const cryptoSuite = FabricClientSDK.newCryptoSuite(); // use the same location for the state store (where the users' certificate are kept) // and the crypto store (where the users' keys are kept) const cryptoStore = FabricClientSDK.newCryptoKeyStore({ path: self.store_path }); cryptoSuite.setCryptoKeyStore(cryptoStore); - self.fabric_client.setCryptoSuite(cryptoSuite); + self.fabricClient.setCryptoSuite(cryptoSuite); - return self.fabric_client.getUserContext(usrName, true); + logger.info('almost done'); + return self.fabricClient.getUserContext(usrName, true); }); } @@ -99,21 +103,14 @@ class FabricClient { let channel = this.channels[channelName]; if (!channel) { logger.info('start create channel'); - channel = this.fabric_client.newChannel(channelName); - + channel = this.fabricClient.newChannel(channelName); if (this.flag) { logger.info('-----------'); - this.peer = this.fabric_client.newPeer(this.config.peerGrpcUrl, - { pem: Buffer.from(this.peerCert).toString(), 'ssl-target-name-override': this.config.peerSSLTarget }); channel.addPeer(this.peer); - this.order = this.fabric_client.newOrderer(this.config.ordererUrl, - { pem: Buffer.from(this.orderersCert).toString(), 'ssl-target-name-override': this.config.ordererSSLTarget }); channel.addOrderer(this.order); } else { logger.info('+++++++++++++++++'); - this.peer = this.fabric_client.newPeer(this.config.peerGrpcUrl); channel.addPeer(this.peer); - this.order = this.fabric_client.newOrderer(this.config.ordererUrl); channel.addOrderer(this.order); } this.channels[channelName] = channel; @@ -195,7 +192,7 @@ class FabricClient { return Promise.reject(err); } let txID; - const fabricClient = this.fabric_client; + const fabricClient = this.fabricClient; const self = this; return this._enrollUser(this).then((user) => { if (user && user.isEnrolled()) { @@ -212,7 +209,7 @@ class FabricClient { tempTargets.push(self.peer); for (let i = 0; i < peerList.length; i++) { const peerCert = fs.readFileSync(certList[i]); - const peer = self.fabric_client.newPeer((peerList[i]), + const peer = self.fabricClient.newPeer((peerList[i]), { pem: Buffer.from(peerCert).toString(), 'ssl-target-name-override': sslTargetList[i] }); tempTargets.push(peer); } @@ -342,7 +339,7 @@ class FabricClient { * @param chaincodeVersion */ installCc(chaincodePath, chaincodeName, chaincodeVersion) { - logger.info(`${chaincodePath}, ${chaincodeName}, ${chaincodeVersion}`); + logger.info(`installing chaincode: ${chaincodePath}, ${chaincodeName}, ${chaincodeVersion}`); const request = { targets: [this.peer], // peerAddress @@ -350,7 +347,8 @@ class FabricClient { chaincodeId: chaincodeName, chaincodeVersion, }; - return this.fabric_client.installChaincode(request) + logger.info('installChaincode request param: ', request); + return this.fabricClient.installChaincode(request) .then((results) => { const proposalResponses = results[0]; if (proposalResponses && proposalResponses[0].response && @@ -393,7 +391,7 @@ class FabricClient { } logger.info('args: ', args, '&& endors-policy:', endorspolicy); - const txID = this.fabric_client.newTransactionID(); + const txID = this.fabricClient.newTransactionID(); let endorspolicyObj; let argsObj; @@ -497,7 +495,7 @@ class FabricClient { importCer(keyPath, certPath) { // -------------------- admin start --------- logger.info('start to create admin user.'); - return this.fabric_client.createUser({ + return this.fabricClient.createUser({ username: this.config.mspid, mspid: this.config.mspid, cryptoContent: { @@ -533,7 +531,7 @@ class FabricClient { logger.error(err); return Promise.reject('fail'); } - return this.fabric_client.queryInstalledChaincodes(this.peer) + return this.fabricClient.queryInstalledChaincodes(this.peer) .then((response) => { if (response) { logger.info('Successfully get response from fabric client'); @@ -597,7 +595,7 @@ class FabricClient { return Promise.reject('fail'); } const self = this; - return self.fabric_client.queryChannels(self.peer) + return self.fabricClient.queryChannels(self.peer) .then((response) => { if (response) { logger.info('Successfully get response from fabric client'); @@ -661,10 +659,10 @@ class FabricClient { return Promise.reject('fail'); } - const tempTxId = self.fabric_client.newTransactionID(); + const tempTxId = self.fabricClient.newTransactionID(); const envelopeBytes = fs.readFileSync(path.join(__dirname, '../../resources/key/tx/' + channelName + '.tx')); - const tempConfig = self.fabric_client.extractChannelConfig(envelopeBytes); - const signature = self.fabric_client.signChannelConfig(tempConfig); + const tempConfig = self.fabricClient.extractChannelConfig(envelopeBytes); + const signature = self.fabricClient.signChannelConfig(tempConfig); const stringSignature = signature.toBuffer().toString('hex'); const tempSignatures = []; tempSignatures.push(stringSignature); @@ -675,7 +673,7 @@ class FabricClient { orderer: self.order, txId: tempTxId, }; - return self.fabric_client.createChannel(request); + return self.fabricClient.createChannel(request); }) .then((result) => { logger.info(' response ::%j', result); @@ -707,7 +705,7 @@ class FabricClient { } const self = this; - const tempTxId = self.fabric_client.newTransactionID(); // 根据用户的证书构建新的事务ID,并自动生成nonce值。 + const tempTxId = self.fabricClient.newTransactionID(); // 根据用户的证书构建新的事务ID,并自动生成nonce值。 const request = { txId: tempTxId, }; @@ -719,7 +717,7 @@ class FabricClient { const tempTargets = []; tempTargets.push(self.peer); const genesisBlock = block; - const _tempTxId = self.fabric_client.newTransactionID(); + const _tempTxId = self.fabricClient.newTransactionID(); const _request = { targets: tempTargets, block: genesisBlock, @@ -768,7 +766,7 @@ class FabricClient { * @param opts 对象 */ newPeer(url, opts) { - return this.fabric_client.newPeer(url, opts); + return this.fabricClient.newPeer(url, opts); } } @@ -780,8 +778,8 @@ export function getFabricClientSingletonHelper(dbConfig) { logger.info('instantiating fabric client.'); __fabricClient = new FabricClient(); return __fabricClient._getConfig(dbConfig) - .then(__fabricClient._config) - .then(__fabricClient._enrollUser) + .then(input => __fabricClient._config(input)) + .then(() => __fabricClient._enrollUser()) .then(() => Promise.resolve(__fabricClient)); } return Promise.resolve(__fabricClient); diff --git a/test/util/fabric.test.js b/test/util/fabric.test.js index 5119ab2..d05c7e0 100644 --- a/test/util/fabric.test.js +++ b/test/util/fabric.test.js @@ -57,12 +57,10 @@ describe('Fabric Client Basic', () => { const clientPromise = getFabricClientSingletonHelper(configDbForTest); return clientPromise.then((client) => { logger.info('OK. Got client. client.channel: ', client.channels); - client.queryCc('fabcar', 'queryAllCars', null, 'mychannel') + return client.queryCc('fabcar', 'queryAllCars', null, 'mychannel') .then((result) => { logger.info('query result: ', result); - expect(result) - .not - .toBeNull(); + expect(result).not.toBeNull(); }) .catch((err) => { logger.error(err); @@ -74,6 +72,7 @@ describe('Fabric Client Basic', () => { describe('Fabric Client Advanced', () => { describe('invoke chaincode', () => { + // FIXME: invoke 后测试进程无法正常结束,可能存在连接或其他调用未断开。待查因解决 it('invoke for one peer', () => getFabricClientSingletonHelper(configDbForTest) .then(client => client.invokeCc('fabcar', 'changeCarOwner', @@ -84,9 +83,7 @@ describe('Fabric Client Advanced', () => { []) .then((result) => { logger.info('invoke result: ', result); - expect(result) - .not - .toBeNull(); + expect(result).not.toBeNull(); return Promise.resolve(); })) .catch((err) => { @@ -100,18 +97,32 @@ describe('Fabric Client Advanced', () => { }); }); - it('install chaincode', () => { - - }); + describe('put chaincode into system', () => { + it('install chaincode', () => getFabricClientSingletonHelper(configDbForTest) + .then(client => + // FIXME: 需处理GOPATH依赖的问题 + + client.installCc('fabcar', 'yetAnotherfabcar', '2.0') + .then((result) => { + logger.info('install chaincode result: ', result); + expect(result).not.toBeNull(); + }), + ) + .catch((err) => { + logger.info('install chaincode error: ', err); + throw err; + })); it('instantiate chaincode', () => { }); - it('upgrade chaincode', () => { + it('upgrade chaincode', () => { + }); }); + it('query block info', () => { }); From f54da2abba901fb9bab74e14cfd44db758c0675b Mon Sep 17 00:00:00 2001 From: Yi DENG Date: Thu, 7 Mar 2019 20:27:45 +0800 Subject: [PATCH 2/4] Test case: fabricClient: instantiate and upgrade chaincode. #49 Signed-off-by: Yi DENG --- test/util/fabric.test.js | 50 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/test/util/fabric.test.js b/test/util/fabric.test.js index d05c7e0..5fdea7d 100644 --- a/test/util/fabric.test.js +++ b/test/util/fabric.test.js @@ -97,7 +97,7 @@ describe('Fabric Client Advanced', () => { }); }); - describe('put chaincode into system', () => { + describe('manage chaincode', () => { it('install chaincode', () => getFabricClientSingletonHelper(configDbForTest) .then(client => // FIXME: 需处理GOPATH依赖的问题 @@ -113,12 +113,52 @@ describe('Fabric Client Advanced', () => { throw err; })); - it('instantiate chaincode', () => { - - }); + it('instantiate chaincode', () => { + const ccName = 'instFabcar'; + return getFabricClientSingletonHelper(configDbForTest) + .then(client => client.installCc('fabcar', ccName, '1.0') + .then((result) => { + expect(result) + .not + .toBeNull(); + return Promise.resolve(client); + })) + .then((client) => { + jest.setTimeout(100000); + return client.instantiateOrUpgradeCc(true, 'mychannel', ccName, '1.0', null, null) + .then((result) => { + logger.info('instantiateOrUpgradeCc result: ', result); + expect(result) + .not + .toBeNull(); + jest.setTimeout(30000); + }); + }) + .catch((err) => { + logger.info('instantiate chaincode error: ', err); + throw err; + }); + }); it('upgrade chaincode', () => { - + jest.setTimeout(120000); + const ccName = 'upgradeFabcar'; + return getFabricClientSingletonHelper(configDbForTest) + .then(client => client.installCc('fabcar', ccName, '1.0') + .then(() => client.instantiateOrUpgradeCc(true, 'mychannel', ccName, '1.0', null, null)) + // 等待链码实例化容器启动,否则升级链码会失败 + .then(() => new Promise(resolve => setTimeout(resolve, 10000))) + .then(() => client.installCc('fabcar', ccName, '2.0')) + .then(() => client.instantiateOrUpgradeCc(false, 'mychannel', ccName, '2.0', null, null) + .then((result) => { + logger.info('UpgradeCc result: ', result); + expect(result).not.toBeNull(); + jest.setTimeout(30000); + }))) + .catch((err) => { + logger.info('instantiate chaincode error: ', err); + throw err; + }); }); }); From d77cc074f6e5608daaea618dfbb0586a3b21cd08 Mon Sep 17 00:00:00 2001 From: Yi DENG Date: Fri, 8 Mar 2019 09:57:24 +0800 Subject: [PATCH 3/4] Improve fabricClient test: query block. #49 Signed-off-by: Yi DENG --- src/util/fabric.js | 8 +++++++- test/util/fabric.test.js | 14 +++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/util/fabric.js b/src/util/fabric.js index 373d0a3..8cfb478 100644 --- a/src/util/fabric.js +++ b/src/util/fabric.js @@ -443,7 +443,7 @@ class FabricClient { return Promise.resolve('success'); }, (err) => { logger.info('Failed instantiating chaincode.', err.stack); - return Promise.resolve('fail'); + return Promise.reject('fail'); }) .catch((err) => { logger.error(`Fail to instantiate chaincode. Error message: ${err.stack}` ? err.stack : err); @@ -768,6 +768,12 @@ class FabricClient { newPeer(url, opts) { return this.fabricClient.newPeer(url, opts); } + + // 关闭连接 + close() { + this.peer.close(); + this.order.close(); + } } diff --git a/test/util/fabric.test.js b/test/util/fabric.test.js index 5fdea7d..6e083dd 100644 --- a/test/util/fabric.test.js +++ b/test/util/fabric.test.js @@ -163,9 +163,17 @@ describe('Fabric Client Advanced', () => { }); - it('query block info', () => { - - }); + it('query block info', () => getFabricClientSingletonHelper(configDbForTest) + .then(client => client.queryBlock(0, 'mychannel') + .then((result) => { + logger.info('query block result: ', result); + expect(result) + .not + .toBeNull(); + })) + .catch((err) => { + throw err; + })); it('create channel', () => { From 9cc3f41a20e2bbe56786cdfb430175ab597f999a Mon Sep 17 00:00:00 2001 From: Yi DENG Date: Fri, 8 Mar 2019 11:28:50 +0800 Subject: [PATCH 4/4] Improve fabricClient test: manage channel. #49 Signed-off-by: Yi DENG --- test/util/fabric.test.js | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/test/util/fabric.test.js b/test/util/fabric.test.js index 6e083dd..8b05f8f 100644 --- a/test/util/fabric.test.js +++ b/test/util/fabric.test.js @@ -175,12 +175,37 @@ describe('Fabric Client Advanced', () => { throw err; })); - it('create channel', () => { - - }); - - it('join peer to channel', () => { + describe('manage channel', () => { + it('create channel', () => + // FIXME: 创建通道,目前依赖contenct类中,复制configtx.yaml文件到指定目录下,需考虑如何测试这一步 + getFabricClientSingletonHelper(configDbForTest) + .then(client => client.createChannel('createtestchannel', 'OneOrgChannel') + .then((result) => { + logger.info('createChannel result: ', result); + expect(result).not.toBeNull(); + })) + .catch((err) => { + throw err; + }), + ); + it('join peer to channel', () => { + const chanName = 'jointestchannel'; + return getFabricClientSingletonHelper(configDbForTest) + .then(client => client.createChannel(chanName, 'OneOrgChannel') + .then((result) => { + logger.info('createChannel result: ', result); + expect(result).not.toBeNull(); + }) + .then(() => client.joinChannel(chanName) + .then((result) => { + logger.info('joinChannel result: ', result); + expect(result).not.toBeNull(); + }))) + .catch((err) => { + throw err; + }); + }); }); });