diff --git a/sdk/node/src/hfc.ts b/sdk/node/src/hfc.ts index 1a420e669ec..12d84b03435 100644 --- a/sdk/node/src/hfc.ts +++ b/sdk/node/src/hfc.ts @@ -454,6 +454,18 @@ export class Chain { * @returns {Peer} Returns a new peer. */ addPeer(url:string, pem?:string):Peer { + + //check to see if the peer is already part of the chain + this.peers.forEach(function(peer){ + if (peer.getUrl()===url) + { + var error = new Error(); + error.name = "DuplicatePeer"; + error.message = "Peer with URL " + url + " is already a member of the chain"; + throw error; + } + }) + let peer = new Peer(url, this, pem); this.peers.push(peer); return peer; diff --git a/sdk/node/test/unit/chain-tests.js b/sdk/node/test/unit/chain-tests.js index 8d42972c2b5..5912a2651e3 100644 --- a/sdk/node/test/unit/chain-tests.js +++ b/sdk/node/test/unit/chain-tests.js @@ -54,7 +54,7 @@ chain.addPeer("grpc://localhost:7051"); // or network mode (code package built and sent to the peer). // -var mode = process.env['DEPLOY_MODE']; +var mode = process.env['DEPLOY_MODE']; console.log("$DEPLOY_MODE: " + mode); if (mode === 'dev') { chain.setDevMode(true); @@ -104,7 +104,7 @@ var deltaAB = "1"; function getUser(name, cb) { chain.getUser(name, function (err, user) { if (err) return cb(err); - if (user.isEnrolled()) return cb(null,user); + if (user.isEnrolled()) return cb(null, user); // User is not enrolled yet, so perform both registration and enrollment // The chain registrar is already set inside 'Set chain registrar' test var registrationRequest = { @@ -201,6 +201,92 @@ test('Add valid peer URLs to the chain', function (t) { }); +// +// Test adding multiple peers to the chain +// +test('Add multiple peers to the chain', function (t) { + + t.plan(1); + + var chain_multiple = hfc.newChain("chain_multiple"); + + var peers = [ + "grpc://localhost:7051", + "grpc://localhost:7052", + "grpc://localhost:7053", + "grpc://localhost:7054" + ]; + + peers.forEach(function (peer) { + + try { + chain_multiple.addPeer(peer); + } + catch (err) { + t.fail("Failed to add multiple peers to the chain"); + } + + }) + + //check to see we have the correct number of peers + if (chain_multiple.getPeers().length == peers.length) { + t.pass("Successfully added multiple peers to the chain(" + peers.length + + " expected | " + chain_multiple.getPeers().length + " found)"); + + } + else { + t.fail("Failed to add multiple peers to the chain(" + peers.length + + " expected | " + chain_multiple.getPeers().length + " found)"); + } +}); + +// +// Test adding duplicate peers to the chain +// +test('Catch duplicate peer added to chain', function (t) { + + t.plan(2); + + var chain_duplicate = hfc.newChain("chain_duplicate"); + + var peers = [ + "grpc://localhost:7051", + "grpc://localhost:7052", + "grpc://localhost:7053", + "grpc://localhost:7051" + ]; + + //we have one duplicate to set the expected value + var expected = peers.length - 1; + + peers.forEach(function (peer) { + + try { + chain_duplicate.addPeer(peer); + } + catch (err) { + if (err.name != "DuplicatePeer"){ + t.fail("Unexpected error " + err.toString()); + } + else { + t.pass("Expected error message 'DuplicatePeer' thrown"); + } + } + + }) + + //check to see we have the correct number of peers + if (chain_duplicate.getPeers().length == expected) { + t.pass("Duplicate peer not added to the chain(" + expected + + " expected | " + chain_duplicate.getPeers().length + " found)"); + + } + else { + t.fail("Failed to detect duplicate peer (" + expected + + " expected | " + chain_duplicate.getPeers().length + " found)"); + } +}); + // // Set Invalid security level and hash algorithm. // @@ -363,35 +449,35 @@ test('Register and enroll a new user', function (t) { // the missing parameter. // -test('Deploy with missing chaincodeName or chaincodePath', function(t) { - t.plan(1); - - // Construct the deploy request with a missing chaincodeName/chaincodePath - var deployRequest = { - // Function to trigger - fcn: "init", - // Arguments to the initializing function - args: ["a", initA, "b", initB] - }; - - // Trigger the deploy transaction - var deployTx = test_user_Member1.deploy(deployRequest); - - // Print the deploy results - deployTx.on('complete', function(results) { - // Deploy request completed successfully - console.log(util.format("deploy results: %j",results)); - // Set the testChaincodeID for subsequent tests - testChaincodeID = results.chaincodeID; - console.log("testChaincodeID:" + testChaincodeID); - t.fail(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results)); - // Exit the test script after a failure - process.exit(1); - }); - deployTx.on('error', function(err) { - // Deploy request failed - t.pass(util.format("Failed to deploy chaincode: request=%j, error=%j",deployRequest,err)); - }); +test('Deploy with missing chaincodeName or chaincodePath', function (t) { + t.plan(1); + + // Construct the deploy request with a missing chaincodeName/chaincodePath + var deployRequest = { + // Function to trigger + fcn: "init", + // Arguments to the initializing function + args: ["a", initA, "b", initB] + }; + + // Trigger the deploy transaction + var deployTx = test_user_Member1.deploy(deployRequest); + + // Print the deploy results + deployTx.on('complete', function (results) { + // Deploy request completed successfully + console.log(util.format("deploy results: %j", results)); + // Set the testChaincodeID for subsequent tests + testChaincodeID = results.chaincodeID; + console.log("testChaincodeID:" + testChaincodeID); + t.fail(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results)); + // Exit the test script after a failure + process.exit(1); + }); + deployTx.on('error', function (err) { + // Deploy request failed + t.pass(util.format("Failed to deploy chaincode: request=%j, error=%j", deployRequest, err)); + }); }); // @@ -400,43 +486,43 @@ test('Deploy with missing chaincodeName or chaincodePath', function(t) { // a local directory in the user's $GOPATH. // -test('Deploy a chaincode by enrolled user', function(t) { - t.plan(1); - - // Construct the deploy request - var deployRequest = { - // Function to trigger - fcn: "init", - // Arguments to the initializing function - args: ["a", initA, "b", initB] - }; - - if (mode === 'dev') { - // Name required for deploy in development mode - deployRequest.chaincodeName = testChaincodeName; - } else { - // Path (under $GOPATH) required for deploy in network mode - deployRequest.chaincodePath = testChaincodePath; - } - - // Trigger the deploy transaction - var deployTx = test_user_Member1.deploy(deployRequest); - - // Print the deploy results - deployTx.on('complete', function(results) { - // Deploy request completed successfully - console.log(util.format("deploy results: %j",results)); - // Set the testChaincodeID for subsequent tests - testChaincodeID = results.chaincodeID; - console.log("testChaincodeID:" + testChaincodeID); - t.pass(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results)); - }); - deployTx.on('error', function(err) { - // Deploy request failed - t.fail(util.format("Failed to deploy chaincode: request=%j, error=%j",deployRequest,err)); - // Exit the test script after a failure - process.exit(1); - }); +test('Deploy a chaincode by enrolled user', function (t) { + t.plan(1); + + // Construct the deploy request + var deployRequest = { + // Function to trigger + fcn: "init", + // Arguments to the initializing function + args: ["a", initA, "b", initB] + }; + + if (mode === 'dev') { + // Name required for deploy in development mode + deployRequest.chaincodeName = testChaincodeName; + } else { + // Path (under $GOPATH) required for deploy in network mode + deployRequest.chaincodePath = testChaincodePath; + } + + // Trigger the deploy transaction + var deployTx = test_user_Member1.deploy(deployRequest); + + // Print the deploy results + deployTx.on('complete', function (results) { + // Deploy request completed successfully + console.log(util.format("deploy results: %j", results)); + // Set the testChaincodeID for subsequent tests + testChaincodeID = results.chaincodeID; + console.log("testChaincodeID:" + testChaincodeID); + t.pass(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results)); + }); + deployTx.on('error', function (err) { + // Deploy request failed + t.fail(util.format("Failed to deploy chaincode: request=%j, error=%j", deployRequest, err)); + // Exit the test script after a failure + process.exit(1); + }); }); // @@ -538,10 +624,10 @@ test('Query existing chaincode state by enrolled user with batch size of 100', f t.pass(util.format("Successfully queried existing chaincode state: request=%j, response=%j, value=%s", queryRequest, results, results.result.toString())); }); queryTx.on('error', function (err) { - // Query failed - t.fail(util.format("Failed to query existing chaincode state: request=%j, error=%j", queryRequest, err)); - // Exit the test script after a failure - process.exit(1); + // Query failed + t.fail(util.format("Failed to query existing chaincode state: request=%j, error=%j", queryRequest, err)); + // Exit the test script after a failure + process.exit(1); }); }); @@ -576,7 +662,7 @@ test('Query non-existing chaincode state by enrolled user', function (t) { }); queryTx.on('error', function (err) { // Query failed - t.pass(util.format("Failed to query non-existing chaincode state: request=%j, error=%j",queryRequest,err)); + t.pass(util.format("Failed to query non-existing chaincode state: request=%j, error=%j", queryRequest, err)); }); }); @@ -611,7 +697,7 @@ test('Query non-existing chaincode function by enrolled user', function (t) { }); queryTx.on('error', function (err) { // Query failed - t.pass(util.format("Failed to query non-existing chaincode function: request=%j, error=%j",queryRequest,err)); + t.pass(util.format("Failed to query non-existing chaincode function: request=%j, error=%j", queryRequest, err)); }); }); @@ -638,7 +724,7 @@ test('Invoke with missing chaincodeID', function (t) { // Print the invoke results invokeTx.on('submitted', function (results) { // Invoke transaction submitted successfully - t.fail(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest,results)); + t.fail(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest, results)); // Exit the test script after a failure process.exit(1); }); @@ -672,7 +758,7 @@ test('Invoke a chaincode by enrolled user', function (t) { // Print the invoke results invokeTx.on('submitted', function (results) { // Invoke transaction submitted successfully - t.pass(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest,results)); + t.pass(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest, results)); }); invokeTx.on('error', function (err) { // Invoke transaction submission failed