diff --git a/build/tasks/eslint.js b/build/tasks/eslint.js index a13d832f7a..3a3a5957c4 100644 --- a/build/tasks/eslint.js +++ b/build/tasks/eslint.js @@ -12,16 +12,16 @@ gulp.task('lint', () => { 'fabric-network/**/*.js', 'fabric-client/**/*.js', 'fabric-ca-client/lib/*.js', - '!fabric-client/coverage/**', - '!fabric-ca-client/coverage/**', + '!coverage/**', + '!docs/**', '!fabric-network/coverage/**', - '!test/typescript/*.js', - '!node_modules/**', '!fabric-network/node_modules/**', + '!fabric-client/coverage/**', '!fabric-client/node_modules/**', + '!fabric-ca-client/coverage/**', '!fabric-ca-client/node_modules/**', - '!docs/**', - '!coverage/**', + '!node_modules/**', + '!test/typescript/*.js', '!tmp/**', ]).pipe(eslint()) .pipe(eslint.format()) diff --git a/fabric-ca-client/lib/FabricCAClient.js b/fabric-ca-client/lib/FabricCAClient.js index 066d04f925..d9e188eadf 100644 --- a/fabric-ca-client/lib/FabricCAClient.js +++ b/fabric-ca-client/lib/FabricCAClient.js @@ -314,7 +314,7 @@ const FabricCAClient = class { const payload = responseBody.join(''); if (!payload) { - reject(new Error( + return reject(new Error( util.format('fabric-ca request %s failed with HTTP status code %s', api_method, JSON.parse(data).statusCode))); } //response should be JSON @@ -329,7 +329,7 @@ const FabricCAClient = class { } } catch (err) { - reject(new Error( + return reject(new Error( util.format('Could not parse %s response [%s] as JSON due to error [%s]', api_method, payload, err))); } }); @@ -453,7 +453,7 @@ const FabricCAClient = class { const payload = responseBody.join(''); if (!payload) { - reject(new Error( + return reject(new Error( util.format('Enrollment failed with HTTP status code', JSON.parse(data).statusCode))); } //response should be JSON @@ -472,7 +472,7 @@ const FabricCAClient = class { } } catch (err) { - reject(new Error( + return reject(new Error( util.format('Could not parse enrollment response [%s] as JSON due to error [%s]', payload, err))); } }); diff --git a/fabric-client/lib/CertificateAuthority.js b/fabric-client/lib/CertificateAuthority.js index f69186c53b..bcb535296a 100644 --- a/fabric-client/lib/CertificateAuthority.js +++ b/fabric-client/lib/CertificateAuthority.js @@ -1,14 +1,22 @@ /* - Copyright 2017, 2018 IBM All Rights Reserved. - - SPDX-License-Identifier: Apache-2.0 + * 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 utils = require('./utils.js'); -var logger = utils.getLogger('CertificateAuthority.js'); +const utils = require('./utils.js'); +const logger = utils.getLogger('CertificateAuthority.js'); /** * The CertificateAuthority class represents a Certificate Authority configuration @@ -21,7 +29,7 @@ var logger = utils.getLogger('CertificateAuthority.js'); * * @class */ -var CertificateAuthority = class { +const CertificateAuthority = class { /** * Construct a CertificateAuthority object diff --git a/fabric-client/lib/Policy.js b/fabric-client/lib/Policy.js index 7065f101a5..5e29d74b3f 100644 --- a/fabric-client/lib/Policy.js +++ b/fabric-client/lib/Policy.js @@ -1,19 +1,26 @@ /* - Copyright 2017, 2018 IBM All Rights Reserved. - - SPDX-License-Identifier: Apache-2.0 - -*/ + * 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 grpc = require('grpc'); -var util = require('util'); +const grpc = require('grpc'); +const util = require('util'); -var _mspPrProto = grpc.load(__dirname + '/protos/msp/msp_principal.proto').common; -var _policiesProto = grpc.load(__dirname + '/protos/common/policies.proto').common; +const _mspPrProto = grpc.load(__dirname + '/protos/msp/msp_principal.proto').common; +const _policiesProto = grpc.load(__dirname + '/protos/common/policies.proto').common; -var IDENTITY_TYPE = { +const IDENTITY_TYPE = { Role: 'role', OrganizationUnit: 'organization-unit', Identity: 'identity' @@ -51,7 +58,7 @@ var IDENTITY_TYPE = { * Governs the constructions of endorsement policies to be passed into the calls to instantiate chaincodes * @class */ -var EndorsementPolicy = class { +const EndorsementPolicy = class { /** * Constructs an endorsement policy envelope. If the optional "policy" object is not present, a default * policy of "a signature by any member from any of the organizations corresponding to the array of member @@ -65,17 +72,17 @@ var EndorsementPolicy = class { static buildPolicy(msps, policy) { const principals = []; const envelope = new _policiesProto.SignaturePolicyEnvelope(); - if (typeof policy === 'undefined' || policy === null) { + if (!policy) { // no policy was passed in, construct a 'Signed By any member of an organization by mspid' policy // construct a list of msp principals to select from using the 'n out of' operator - var signedBys = []; - var index = 0; - for (let name in msps) { + const signedBys = []; + let index = 0; + for (const name in msps) { if (msps.hasOwnProperty(name)) { - let onePrn = new _mspPrProto.MSPPrincipal(); + const onePrn = new _mspPrProto.MSPPrincipal(); onePrn.setPrincipalClassification(_mspPrProto.MSPPrincipal.Classification.ROLE); - let memberRole = new _mspPrProto.MSPRole(); + const memberRole = new _mspPrProto.MSPRole(); memberRole.setRole(_mspPrProto.MSPRole.MSPRoleType.MEMBER); memberRole.setMspIdentifier(name); @@ -83,7 +90,7 @@ var EndorsementPolicy = class { principals.push(onePrn); - var signedBy = new _policiesProto.SignaturePolicy(); + const signedBy = new _policiesProto.SignaturePolicy(); signedBy.set('signed_by', index++); signedBys.push(signedBy); } @@ -94,11 +101,11 @@ var EndorsementPolicy = class { } // construct 'one of any' policy - var oneOfAny = new _policiesProto.SignaturePolicy.NOutOf(); + const oneOfAny = new _policiesProto.SignaturePolicy.NOutOf(); oneOfAny.setN(1); oneOfAny.setRules(signedBys); - var noutof = new _policiesProto.SignaturePolicy(); + const noutof = new _policiesProto.SignaturePolicy(); noutof.set('n_out_of', oneOfAny); envelope.setVersion(0); @@ -111,11 +118,11 @@ var EndorsementPolicy = class { checkPolicy(policy); policy.identities.forEach((identity) => { - let newPrincipal = buildPrincipal(identity); + const newPrincipal = buildPrincipal(identity); principals.push(newPrincipal); }); - var thePolicy = new parsePolicy(policy.policy); + const thePolicy = parsePolicy(policy.policy); envelope.setVersion(0); envelope.setRule(thePolicy); @@ -144,11 +151,11 @@ function buildPrincipal(identity) { throw new Error(util.format('Invalid role name found: must be one of "peer", "member" or "admin", but found "%s"', roleName)); } - let mspid = identity[principalType].mspId; + const mspid = identity[principalType].mspId; if (typeof mspid !== 'string' || !mspid) { throw new Error(util.format('Invalid mspid found: "%j"', mspid)); } - newRole.setMspIdentifier(identity[principalType].mspId); + newRole.setMspIdentifier(mspid); newPrincipal.setPrincipal(newRole.toBuffer()); } else { @@ -159,8 +166,8 @@ function buildPrincipal(identity) { } function getIdentityType(obj) { - var invalidTypes = []; - for (let key in obj) { + const invalidTypes = []; + for (const key in obj) { if (obj.hasOwnProperty(key)) { if (key === IDENTITY_TYPE.Role || key === IDENTITY_TYPE.OrganizationUnit || key === IDENTITY_TYPE.Identity) { return key; @@ -179,8 +186,8 @@ function getIdentityType(obj) { } function getPolicyType(spec) { - var invalidTypes = []; - for (var key in spec) { + const invalidTypes = []; + for (const key in spec) { if (spec.hasOwnProperty(key)) { // each policy spec has exactly one property of one of these two forms: 'n-of' or 'signed-by' if (key === 'signed-by' || key.match(/^\d+-of$/)) { @@ -195,27 +202,27 @@ function getPolicyType(spec) { } function parsePolicy(spec) { - var type = getPolicyType(spec); + const type = getPolicyType(spec); if (type === 'signed-by') { - let signedBy = new _policiesProto.SignaturePolicy(); + const signedBy = new _policiesProto.SignaturePolicy(); signedBy.set('signed_by', spec[type]); return signedBy; } else { - let n = type.match(/^(\d+)-of$/)[1]; - let array = spec[type]; + const n = type.match(/^(\d+)-of$/)[1]; + const array = spec[type]; - let nOutOf = new _policiesProto.SignaturePolicy.NOutOf(); + const nOutOf = new _policiesProto.SignaturePolicy.NOutOf(); nOutOf.setN(parseInt(n)); - let subs = []; + const subs = []; array.forEach((sub) => { - var subPolicy = parsePolicy(sub); + const subPolicy = parsePolicy(sub); subs.push(subPolicy); }); nOutOf.setRules(subs); - let nOf = new _policiesProto.SignaturePolicy(); + const nOf = new _policiesProto.SignaturePolicy(); nOf.set('n_out_of', nOutOf); return nOf; @@ -231,8 +238,8 @@ function buildSignaturePolicy(spec) { } else { let n = type.match(/^(\d+)-of$/)[1]; n = parseInt(n); - let ruleArray = spec[type]; - let rules = []; + const ruleArray = spec[type]; + const rules = []; ruleArray.forEach(rule => { rules.push(buildSignaturePolicy(rule)); }); @@ -250,13 +257,13 @@ function checkPolicy(policy){ if (!policy) { throw new Error('Missing Required Param "policy"'); } - if (typeof policy.identities === 'undefined' || policy.identities === null || policy.identities === '' || policy.identities === {}) { + if (!policy.identities || policy.identities === '' || Object.keys(policy.identities).length === 0 ) { throw new Error('Invalid policy, missing the "identities" property'); } else if (!Array.isArray(policy.identities)) { throw new Error('Invalid policy, the "identities" property must be an array'); } - if (typeof policy.policy === 'undefined' || policy.policy === null || policy.policy === '' || policy.policy === {}) { + if (!policy.policy || policy.policy === '' || Object.keys(policy.policy).length === 0) { throw new Error('Invalid policy, missing the "policy" property'); } } diff --git a/fabric-client/test/BlockDecoder.js b/fabric-client/test/BlockDecoder.js index 19870e78fe..fc20d707ed 100644 --- a/fabric-client/test/BlockDecoder.js +++ b/fabric-client/test/BlockDecoder.js @@ -1,15 +1,169 @@ /* - Copyright 2018 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. + */ - SPDX-License-Identifier: Apache-2.0 - -*/ +'use strict'; const rewire = require('rewire'); const BlockDecoderRewire = rewire('../lib/BlockDecoder'); require('chai').should(); describe('BlockDecoder', () => { + + describe('#BlockDecoder.decode', () => { + + }); + + describe('#BlockDecoder.decodeBlock', () => { + + }); + + describe('#BlockDecoder.decodeTransaction', () => { + + }); + + describe('#decodeBlockHeader', () => { + + }); + + describe('#decodeBlockData', () => { + + }); + + describe('#decodeBlockMetaData', () => { + + }); + + describe('#decodeTransactionFilter', () => { + + }); + + describe('#decodeLastConfigSequenceNumber', () => { + + }); + + describe('#decodeMetadataSignatures', () => { + + }); + + describe('#decodeMetadataValueSignatures', () => { + + }); + + describe('#decodeBlockDataEnvelope', () => { + + }); + + describe('#decodeEndorserTransaction', () => { + + }); + + describe('#decodeConfigEnvelope', () => { + + }); + + describe('#decodeConfig', () => { + + }); + + describe('#decodeConfigUpdateEnvelope', () => { + + }); + + describe('#decodeConfigUpdate', () => { + + }); + + describe('#decodeConfigGroups', () => { + + }); + + describe('#decodeConfigGroup', () => { + + }); + + describe('#decodeConfigValues', () => { + + }); + + describe('#decodeConfigValue', () => { + + }); + + describe('#decodeConfigPolicies', () => { + + }); + + describe('#decodeConfigPolicy', () => { + + }); + + describe('#decodeImplicitMetaPolicy', () => { + + }); + + describe('#decodeSignaturePolicyEnvelope', () => { + + }); + + describe('#decodeSignaturePolicy', () => { + + }); + + describe('#decodeMSPPrincipal', () => { + + }); + + describe('#decodeConfigSignature', () => { + + }); + + describe('#decodeSignatureHeader', () => { + + }); + + describe('#decodeIdentity', () => { + + }); + + describe('#decodeFabricMSPConfig', () => { + + }); + + describe('#decodeFabricOUIdentifier', () => { + + }); + + describe('#toPEMcerts', () => { + + }); + + describe('#decodeSigningIdentityInfo', () => { + + }); + + describe('#decodeKeyInfo', () => { + + }); + + describe('#decodeHeader', () => { + + }); + + describe('#decodeChannelHeader', () => { + + }); + describe('timeStampToDate()', () => { const timeStampToDate = BlockDecoderRewire.__get__('timeStampToDate'); @@ -28,4 +182,81 @@ describe('BlockDecoder', () => { res.should.have.string(now.getMilliseconds().toString()); }); }); + + describe('#decodeChaincodeActionPayload', () => { + + }); + + describe('#decodeChaincodeProposalPayload', () => { + + }); + + describe('#decodeChaincodeProposalPayloadInput', () => { + + }); + + describe('#chaincodeTypeToString', () => { + + }); + + describe('#decodeChaincodeSpec', () => { + + }); + + describe('#decodeChaincodeInput', () => { + + }); + + describe('#decodeChaincodeEndorsedAction', () => { + + }); + + describe('#decodeEndorsement', () => { + + }); + + describe('#decodeProposalResponsePayload', () => { + + }); + + describe('#decodeChaincodeAction', () => { + + }); + + describe('#decodeChaincodeEvents', () => { + + }); + + describe('#decodeChaincodeID', () => { + + }); + + describe('#decodeReadWriteSets', () => { + + }); + + describe('#decodeKVRWSet', () => { + + }); + + describe('#decodeKVRead', () => { + + }); + + describe('#decodeRangeQueryInfo', () => { + + }); + + describe('#decodeKVWrite', () => { + + }); + + describe('#decodeResponse', () => { + + }); + + describe('#decodeVersion', () => { + + }); + }); \ No newline at end of file diff --git a/fabric-client/test/Policy.js b/fabric-client/test/Policy.js new file mode 100644 index 0000000000..a54dfeceeb --- /dev/null +++ b/fabric-client/test/Policy.js @@ -0,0 +1,504 @@ +/* + * 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'; + +const rewire = require('rewire'); +const { checkPolicy, buildSignaturePolicy, buildPrincipal } = require('../lib/Policy'); + +const chai = require('chai'); +const should = chai.should(); +const sinon = require('sinon'); + +describe('Policy', () => { + + describe('#EndorsementPolicy.buildPolicy', () => { + + let PolicyRewire; + const setVersionStub = sinon.stub(); + const setRuleStub = sinon.stub(); + const setIdentitiesStub = sinon.stub(); + const toBufferStub = sinon.stub().returns({test: 'response'}); + + const MockSignaturePolicyEnvelope = sinon.stub(); + MockSignaturePolicyEnvelope.prototype.setVersion = setVersionStub; + MockSignaturePolicyEnvelope.prototype.setRule = setRuleStub; + MockSignaturePolicyEnvelope.prototype.setIdentities = setIdentitiesStub; + MockSignaturePolicyEnvelope.prototype.toBuffer = toBufferStub; + + const setRoleStub = sinon.stub(); + const setMspIdentifierStub = sinon.stub(); + const MockRole = sinon.stub(); + MockRole.prototype.setRole = setRoleStub; + MockRole.prototype.setMspIdentifier = setMspIdentifierStub; + + const MockNOutOfStub = sinon.stub(); + MockNOutOfStub.prototype.setN = sinon.stub(); + MockNOutOfStub.prototype.setRules = sinon.stub(); + + const MockSignaturePolicy = sinon.stub(); + MockSignaturePolicy.prototype.getName = sinon.stub().returns('MockSignaturePolicy'); + const setStub = sinon.stub(); + MockSignaturePolicy.prototype.set = setStub; + MockSignaturePolicy.NOutOf = MockNOutOfStub; + + const MockPolicyProto = sinon.stub(); + MockPolicyProto.SignaturePolicyEnvelope = MockSignaturePolicyEnvelope; + MockPolicyProto.SignaturePolicy = MockSignaturePolicy; + MockPolicyProto.Role = MockRole; + + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + 'signed-by': 0 + } + }; + + beforeEach(() =>{ + PolicyRewire = rewire('../lib/Policy'); + PolicyRewire.__set__('_policiesProto', MockPolicyProto); + }); + + afterEach(() => { + setVersionStub.resetHistory(); + setRuleStub.resetHistory(); + setIdentitiesStub.resetHistory(); + toBufferStub.resetHistory(); + }); + + it('should throw if no policy provided and no valid msps', () => { + (() => { + PolicyRewire.buildPolicy([], undefined); + }).should.throw(/Verifying MSPs not found in the channel object/); + }); + + it('should create and set a one of any policy if no policy provided', () => { + PolicyRewire.buildPolicy(['geoff'], undefined); + + // Set SignaturePolicy + sinon.assert.calledTwice(setStub); + const firstCall = setStub.getCall(0).args; + const secondCall = setStub.getCall(1).args; + firstCall[0].should.be.equal('signed_by'); + firstCall[1].should.be.equal(0); + + secondCall[0].should.be.equal('n_out_of'); + + // Set version + sinon.assert.calledOnce(setVersionStub); + sinon.assert.calledWith(setVersionStub, 0); + + // Set rule with that created + sinon.assert.calledOnce(setRuleStub); + let args = setRuleStub.getCall(0).args; + args[0].getName().should.be.equal('MockSignaturePolicy'); + + // Set identities Array + sinon.assert.calledOnce(setIdentitiesStub); + args = setIdentitiesStub.getCall(0).args; + args[0][0].principal_classification.should.be.equal(0); + + // Sent to buffer + sinon.assert.calledOnce(toBufferStub); + }); + + it('should use the policy if provided', () => { + PolicyRewire.buildPolicy([], policy); + + // Set version + sinon.assert.calledOnce(setVersionStub); + sinon.assert.calledWith(setVersionStub, 0); + + // Set rule + sinon.assert.calledOnce(setRuleStub); + let args = setRuleStub.getCall(0).args; + args[0].getName().should.be.equal('MockSignaturePolicy'); + + // Set identities Array + sinon.assert.calledOnce(setIdentitiesStub); + args = setIdentitiesStub.getCall(0).args; + args[0][0].principal_classification.should.be.equal(0); + + + // Sent to buffer + sinon.assert.calledOnce(toBufferStub); + }); + + }); + + describe('#buildPrincipal', () => { + + let PolicyRewire; + + const MockMSPPrincipal = sinon.stub(); + MockMSPPrincipal.prototype.setPrincipalClassification = sinon.stub(); + MockMSPPrincipal.prototype.setPrincipal = sinon.stub(); + MockMSPPrincipal.Classification = sinon.stub(); + MockMSPPrincipal.Classification.ROLE = sinon.stub(); + MockMSPPrincipal.Classification.ROLE.returns('asd'); + + const MockPeerRole = sinon.stub().returns('PEER'); + const MockMemberRole = sinon.stub().returns('MEMBER'); + const MockAdminRole = sinon.stub().returns('ADMIN'); + + const MockMSPRoleType = sinon.stub(); + MockMSPRoleType.PEER = MockPeerRole; + MockMSPRoleType.MEMBER = MockMemberRole; + MockMSPRoleType.ADMIN = MockAdminRole; + + const setRoleStub = sinon.stub(); + const setMspIdentifierStub = sinon.stub(); + const toBufferStub = sinon.stub(); + const MockMSPRole = sinon.stub(); + MockMSPRole.prototype.setRole = setRoleStub; + MockMSPRole.prototype.setMspIdentifier = setMspIdentifierStub; + MockMSPRole.prototype.toBuffer = toBufferStub; + MockMSPRole.MSPRoleType = MockMSPRoleType; + + const MockMspProto = sinon.stub(); + MockMspProto.MSPRole = MockMSPRole; + MockMspProto.MSPPrincipal = MockMSPPrincipal; + + beforeEach(() =>{ + PolicyRewire = rewire('../lib/Policy'); + PolicyRewire.__set__('_mspPrProto', MockMspProto); + }); + + afterEach(() =>{ + MockMSPRole.resetHistory(); + setRoleStub.resetHistory(); + }); + + it('should throw if the identity type is unknown', () => { + (() => { + buildPrincipal({ 'role': 'penguin' }); + }).should.throw(/Invalid role name found/); + }); + + it('should throw if the identity type is unimplemented', () => { + (() => { + buildPrincipal({ 'organization-unit': 'my organization-unit' }); + }).should.throw(/NOT IMPLEMENTED/); + }); + + it('should throw if invalid role name passed', () => { + (() => { + buildPrincipal({ 'role': {name: 'penguin', mspId: 20 }}); + }).should.throw(/Invalid role name found/); + }); + + it('should throw if invalid mspid passed', () => { + (() => { + buildPrincipal({ 'role': {name: 'peer', mspId: 20 }}); + }).should.throw(/Invalid mspid found/); + }); + + it('should throw if no mspid passed', () => { + (() => { + buildPrincipal({ 'role': {name: 'peer', mspId: null }}); + }).should.throw(/Invalid mspid found/); + }); + + it('should set the role to peer if peer role', () =>{ + + const buildPrincipal = PolicyRewire.__get__('buildPrincipal'); + buildPrincipal({ 'role': {name: 'peer', mspId: 'my_mspId' }}); + + sinon.assert.calledOnce(setRoleStub); + sinon.assert.calledWith(setRoleStub, MockPeerRole); + }); + + it('should set the role to member if member role', () =>{ + + const buildPrincipal = PolicyRewire.__get__('buildPrincipal'); + buildPrincipal({ 'role': {name: 'member', mspId: 'my_mspId' }}); + + sinon.assert.calledOnce(setRoleStub); + sinon.assert.calledWith(setRoleStub, MockMemberRole); + }); + + it('should set the role to admin if admin role', () =>{ + + const buildPrincipal = PolicyRewire.__get__('buildPrincipal'); + buildPrincipal({ 'role': {name: 'admin', mspId: 'my_mspId' }}); + + sinon.assert.calledOnce(setRoleStub); + sinon.assert.calledWith(setRoleStub, MockAdminRole); + }); + }); + + describe('#getIdentityType', () => { + const RewirePolicy = rewire('../lib/Policy'); + const getIdentityType = RewirePolicy.__get__('getIdentityType'); + + it('should throw no identity type', () => { + (() => { + getIdentityType({}); + }).should.throw(/Invalid identity type found/); + }); + + it('should throw if an invalid identity type', () => { + (() => { + getIdentityType({ 'invalid': true }); + }).should.throw(/Invalid identity type found: must be one of role, organization-unit or identity, but found invalid/); + }); + + it('should return role type', () => { + const result = getIdentityType({ 'role': 'my role' }); + result.should.equal('role'); + }); + + it('should return organisation type', () => { + const result = getIdentityType({ 'organization-unit': 'my organization-unit' }); + result.should.equal('organization-unit'); + }); + + it('should return identity type', () => { + const result = getIdentityType({ 'identity': 'my identity' }); + result.should.equal('identity'); + }); + }); + + describe('#getPolicyType', () => { + const RewirePolicy = rewire('../lib/Policy'); + const getPolicy = RewirePolicy.__get__('getPolicyType'); + + it('should throw if invalid type found', () => { + (() => { + getPolicy({ 'two-of': true }); + }).should.throw(/Invalid policy type found/); + }); + + it('should throw if invalid type found', () => { + (() => { + getPolicy({ 'geoff': true }); + }).should.throw(/Invalid policy type found/); + }); + + it('should return "signed-by" if that is the policy type', () => { + const myType = getPolicy({ 'signed-by': true }); + myType.should.be.equal('signed-by'); + }); + + it('should return "n-of" if that is the policy type', () => { + const myType = getPolicy({ '3-of': true }); + myType.should.be.equal('3-of'); + }); + }); + + describe('#parsePolicy', () => { + const RewirePolicy = rewire('../lib/Policy'); + const parsePolicy = RewirePolicy.__get__('parsePolicy'); + + it('should return a signiture policy with the type "signedby" set if that policy type', () => { + + const policy = { + 'signed-by': 0 + }; + + const result = parsePolicy(policy); + + result.Type.should.equal('signed_by'); + result.signed_by.should.equal(0); + should.not.exist(result.n_out_of); + }); + + it('should return a signiture policy with the type "n_out_of" set if that policy type', () => { + + const policy = { + '1-of': [ + { + 'signed-by': 0 + } + ] + }; + + const result = parsePolicy(policy); + + result.Type.should.equal('n_out_of'); + result.signed_by.should.equal(0); + result.n_out_of.n.should.equal(1); + result.n_out_of.rules[0].Type.should.equal('signed_by'); + result.n_out_of.rules[0].signed_by.should.equal(0); + + }); + + }); + + describe('#buildSignaturePolicy', () => { + + it('should return signed by if that policy type', () => { + const policy = { + 'signed-by': 0 + }; + + const result = buildSignaturePolicy(policy); + result.should.deep.equal({ signed_by: 0 }); + }); + + it('should recursively build if n-of detected', () => { + const policy = { + '1-of': [ + { + 'signed-by': 0 + } + ] + }; + + const expected = { + n_out_of: { + n: 1, + rules: [ + { + signed_by: 0 + } + ] + } + }; + + const result = buildSignaturePolicy(policy); + result.should.deep.equal(expected); + }); + }); + + describe('#checkPolicy', () => { + + it('should throw if missing a passed parameter', () => { + (() => { + checkPolicy(); + }).should.throw(/Missing Required Param "policy"/); + }); + + it('should throw if passed parameter is null', () => { + (() => { + checkPolicy(null); + }).should.throw(/Missing Required Param "policy"/); + }); + + it('should throw if passed parameter is undefined', () => { + (() => { + checkPolicy(undefined); + }).should.throw(/Missing Required Param "policy"/); + }); + + it('should throw if passed parameter policy.identities is missing', () => { + (() => { + checkPolicy({ name: 'nothing' }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.identities is null', () => { + (() => { + checkPolicy({ identities: null }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.identities is undefined', () => { + (() => { + checkPolicy({ identities: undefined }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.identities is an empty string', () => { + (() => { + checkPolicy({ identities: '' }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.identities is an empty object', () => { + (() => { + checkPolicy({ identities: {} }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.identities is not an array', () => { + (() => { + checkPolicy({ identities: { name: 'something' } }); + }).should.throw(/Invalid policy, the "identities" property must be an array/); + }); + + it('should throw if passed parameter policy.policy is missing', () => { + (() => { + checkPolicy({ identities: true }); + }).should.throw(/Invalid policy, missing the "identities" property/); + }); + + it('should throw if passed parameter policy.policy is null', () => { + (() => { + const identities = [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + }]; + checkPolicy({ identities: identities, policy: null }); + }).should.throw(/Invalid policy, missing the "policy" property/); + }); + + it('should throw if passed parameter policy.policy is undefined', () => { + (() => { + const identities = [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + }]; + checkPolicy({ identities: identities, policy: undefined }); + }).should.throw(/Invalid policy, missing the "policy" property/); + }); + + it('should throw if passed parameter policy.policy is an empty object', () => { + (() => { + const identities = [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + }]; + checkPolicy({ identities: identities, policy: {} }); + }).should.throw(/Invalid policy, missing the "policy" property/); + }); + + it('should not throw if passed a valid policy', () => { + (() => { + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + '1-of': [ + { + 'signed-by': 0 + } + ] + } + }; + + checkPolicy(policy); + }).should.not.throw(); + }); + + }); + +}); \ No newline at end of file diff --git a/fabric-client/test/TransactionID.js b/fabric-client/test/TransactionID.js index 394d3eadfe..cb36305904 100644 --- a/fabric-client/test/TransactionID.js +++ b/fabric-client/test/TransactionID.js @@ -25,7 +25,7 @@ const Utils = require('../lib/utils'); require('chai').should(); const sinon = require('sinon'); -describe.only('TransactionID', () => { +describe('TransactionID', () => { let revert; let bufferSpy; diff --git a/test/unit/channel.js b/test/unit/channel.js index b25c6704a0..1d9995ea7f 100644 --- a/test/unit/channel.js +++ b/test/unit/channel.js @@ -541,7 +541,7 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: {}}); + c._buildEndorsementPolicy({identities: {name: 'something'}}); }, /Invalid policy, the "identities" property must be an array/, 'Checking policy spec: identities must be an array' @@ -549,7 +549,13 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: []}); + const identities = [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + }]; + c._buildEndorsementPolicy({identities: identities}); }, /Invalid policy, missing the "policy" property/, 'Checking policy spec: must have "policy"' @@ -557,7 +563,23 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: [{dummy: 'value', dummer: 'value'}], policy: {}}); + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + '1-of': [ + { + 'signed-by': 0 + } + ] + } + }; + c._buildEndorsementPolicy({identities: [{dummy: 'value', dummer: 'value'}], policy: policy}); }, /Invalid identity type found: must be one of role, organization-unit or identity, but found dummy,dummer/, 'Checking policy spec: each identity must be "role", "organization-unit" or "identity"' @@ -565,7 +587,23 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: [{role: 'value'}], policy: {}}); + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + '1-of': [ + { + 'signed-by': 0 + } + ] + } + }; + c._buildEndorsementPolicy({identities: [{role: 'value'}], policy: policy}); }, /Invalid role name found: must be one of "peer", "member" or "admin", but found/, 'Checking policy spec: value identity type "role" must have valid "name" value' @@ -573,7 +611,23 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: [{'organization-unit': 'value'}], policy: {}}); + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + '1-of': [ + { + 'signed-by': 0 + } + ] + } + }; + c._buildEndorsementPolicy({identities: [{'organization-unit': 'value'}], policy: policy}); }, /NOT IMPLEMENTED/, 'Checking policy spec: value identity type "organization-unit"' @@ -581,7 +635,23 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', (t) => { t.throws( () => { - c._buildEndorsementPolicy({identities: [{identity: 'value'}], policy: {}}); + const policy = { + identities: [{ + role: { + name: 'member', + mspId: 'Org1MSP' + } + } + ], + policy: { + '1-of': [ + { + 'signed-by': 0 + } + ] + } + }; + c._buildEndorsementPolicy({identities: [{identity: 'value'}], policy: policy}); }, /NOT IMPLEMENTED/, 'Checking policy spec: value identity type "identity"' diff --git a/test/unit/policy.js b/test/unit/policy.js deleted file mode 100644 index 37f02bcde9..0000000000 --- a/test/unit/policy.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright 2018 Zhao Chaoyi, All Rights Reserved. - - SPDX-License-Identifier: Apache-2.0 - -*/ - -const tape = require('tape'); -const tapePromise = require('tape-promise').default; -const test = tapePromise(tape); -const { checkPolicy } = require('fabric-client/lib/Policy'); - -test('Test Policy.checkPolicy()', async (t) => { - let policy; - - t.throws(()=> { - checkPolicy(policy); - }, - /Missing Required Param "policy"/, - 'checkPolicy should throw error if missing param "policy"'); - - policy = { - policy: {} - }; - t.throws(()=> { - checkPolicy(policy); - }, - /Invalid policy, missing the "identities" property/, - 'checkPolicy should throw error if missing property "identities"'); - - policy = { - policy: {}, - identities: {}, - }; - t.throws(()=> { - checkPolicy(policy); - }, - /Invalid policy, the "identities" property must be an array/, - 'checkPolicy should throw error if property "identities" is not an array'); - - policy = { - identities: [], - }; - t.throws(()=> { - checkPolicy(policy); - }, - /Invalid policy, missing the "policy" property/, - 'checkPolicy should throw error if missing property "policy"'); - - policy = { - identities: [{ - role: { - name: 'member', - mspId: 'Org1MSP' - } - } - ], - policy: { - '1-of': [ - { - 'signed-by': 0 - } - ] - } - }; - t.doesNotThrow(()=>{ - checkPolicy(policy); - }, 'checkPolicy should not throw error for a valid policy'); -});