From 03befea55cfeb58e045f0aeed3b3e609e5e9333e Mon Sep 17 00:00:00 2001 From: Diego Garcia Date: Thu, 19 Oct 2017 17:29:14 +0200 Subject: [PATCH] Improve general comprehension - Better variable naming - Add comments - Improve descriptions - Get constants from core - Add new test for unconfirmed states --- test/functional/http/post/3.votes.js | 193 +++++++++++++++------------ 1 file changed, 110 insertions(+), 83 deletions(-) diff --git a/test/functional/http/post/3.votes.js b/test/functional/http/post/3.votes.js index 96f419293e2..728466bb4cf 100644 --- a/test/functional/http/post/3.votes.js +++ b/test/functional/http/post/3.votes.js @@ -16,28 +16,28 @@ describe('POST /api/transactions (type 3) votes', function () { var badTransactionsEnforcement = []; var goodTransactionsEnforcement = []; - var account = node.randomAccount(); + var delegateAccount = node.randomAccount(); var accountNoFunds = node.randomAccount(); var accountMinimalFunds = node.randomAccount(); var accountDuplicate = node.randomAccount(); - var account33 = node.randomAccount(); - var delegates33 = []; - - var account101 = node.randomAccount(); - var delegates101 = []; + // Creating two scenarios with two isolated set of accounts + var accountMaxVotesPerTransaction = node.randomAccount(); + var delegatesMaxVotesPerTransaction = []; + var accountMaxVotesPerAccount = node.randomAccount(); + var delegatesMaxVotesPerAccount = []; var transaction; before(function () { - // Crediting accounts and registering delegates + // Crediting all the accounts and registering delegates for the two scenarios var promises = []; - promises.push(creditAccountPromise(account.address, 1000 * node.normalizer)); + promises.push(creditAccountPromise(delegateAccount.address, 1000 * node.normalizer)); promises.push(creditAccountPromise(accountMinimalFunds.address, constants.fees.vote)); promises.push(creditAccountPromise(node.eAccount.address, 1000 * node.normalizer)); - promises.push(creditAccountPromise(account33.address, 1000 * node.normalizer)); - promises.push(creditAccountPromise(account101.address, 1000 * node.normalizer)); - promises.push(creditAccountPromise(accountDuplicate.address, constants.fees.vote * 2)); + promises.push(creditAccountPromise(accountMaxVotesPerTransaction.address, 1000 * node.normalizer)); + promises.push(creditAccountPromise(accountMaxVotesPerAccount.address, 1000 * node.normalizer)); + promises.push(creditAccountPromise(accountDuplicate.address, constants.fees.vote * 4)); return node.Promise.all(promises).then(function (results) { results.forEach(function (res) { @@ -46,14 +46,14 @@ describe('POST /api/transactions (type 3) votes', function () { }); }) .then(function (res) { - var promisesCredits33 = []; - for (var i = 0; i < 33; i++) { - var accounts33 = node.randomAccount(); - delegates33.push(accounts33); - promisesCredits33.push(creditAccountPromise(accounts33.address, constants.fees.delegate)); + var promisesCreditsMaxVotesPerTransaction = []; + for (var i = 0; i < constants.maxVotesPerTransaction; i++) { + var tempAccount = node.randomAccount(); + delegatesMaxVotesPerTransaction.push(tempAccount); + promisesCreditsMaxVotesPerTransaction.push(creditAccountPromise(tempAccount.address, constants.fees.delegate)); }; - return node.Promise.all(promisesCredits33).then(function (results) { + return node.Promise.all(promisesCreditsMaxVotesPerTransaction).then(function (results) { results.forEach(function (res) { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').that.is.not.empty; @@ -61,14 +61,14 @@ describe('POST /api/transactions (type 3) votes', function () { }); }) .then(function (res) { - var promisesCredits101 = []; - for (var i = 0; i < 101; i++) { - var accounts101 = node.randomAccount(); - delegates101.push(accounts101); - promisesCredits101.push(creditAccountPromise(accounts101.address, constants.fees.delegate)); + var promisesCreditsMaxVotesPerAccount = []; + for (var i = 0; i < constants.activeDelegates; i++) { + var tempAccount = node.randomAccount(); + delegatesMaxVotesPerAccount.push(tempAccount); + promisesCreditsMaxVotesPerAccount.push(creditAccountPromise(tempAccount.address, constants.fees.delegate)); }; - return node.Promise.all(promisesCredits101).then(function (results) { + return node.Promise.all(promisesCreditsMaxVotesPerAccount).then(function (results) { results.forEach(function (res) { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').that.is.not.empty; @@ -79,12 +79,18 @@ describe('POST /api/transactions (type 3) votes', function () { return waitForBlocksPromise(7); }) .then(function (res) { - var promisesDelegates33 = []; - for (var i = 0; i < 33; i++) { - promisesDelegates33.push(registerDelegatePromise(delegates33[i])); + return registerDelegatePromise(delegateAccount).then(function (result) { + node.expect(result).to.have.property('success').to.be.ok; + node.expect(result).to.have.property('transactionId').that.is.not.empty; + }); + }) + .then(function (res) { + var promisesDelegatesMaxVotesPerTransaction = []; + for (var i = 0; i < constants.maxVotesPerTransaction; i++) { + promisesDelegatesMaxVotesPerTransaction.push(registerDelegatePromise(delegatesMaxVotesPerTransaction[i])); }; - return node.Promise.all(promisesDelegates33).then(function (results) { + return node.Promise.all(promisesDelegatesMaxVotesPerTransaction).then(function (results) { results.forEach(function (res) { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').that.is.not.empty; @@ -92,12 +98,12 @@ describe('POST /api/transactions (type 3) votes', function () { }); }) .then(function (res) { - var promisesDelegates101 = []; - for (var i = 0; i < 101; i++) { - promisesDelegates101.push(registerDelegatePromise(delegates101[i])); + var promisesDelegatesMaxVotesPerAccount = []; + for (var i = 0; i < constants.activeDelegates; i++) { + promisesDelegatesMaxVotesPerAccount.push(registerDelegatePromise(delegatesMaxVotesPerAccount[i])); }; - return node.Promise.all(promisesDelegates101).then(function (results) { + return node.Promise.all(promisesDelegatesMaxVotesPerAccount).then(function (results) { results.forEach(function (res) { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').that.is.not.empty; @@ -111,23 +117,23 @@ describe('POST /api/transactions (type 3) votes', function () { describe('schema validations', function () { - shared.invalidAssets(account, 'votes', badTransactions); + shared.invalidAssets(delegateAccount, 'votes', badTransactions); }); describe('transactions processing', function () { - it('upvoting with manipulated vote should fail', function () { - transaction = node.lisk.vote.createVote(account.password, ['++' + node.eAccount.publicKey]); + it('voting with invalid vote format should fail', function () { + transaction = node.lisk.vote.createVote(delegateAccount.password, ['++' + node.eAccount.publicKey.slice(0, -1)]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; - node.expect(res).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote length'); + node.expect(res).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote format'); badTransactions.push(transaction); }); }); - it('downvoting with manipulated vote should fail', function () { - transaction = node.lisk.vote.createVote(account.password, ['--' + node.eAccount.publicKey]); + it('voting with invalid vote length should fail', function () { + transaction = node.lisk.vote.createVote(delegateAccount.password, ['--' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -136,8 +142,8 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('using invalid vote operator should fail', function () { - transaction = node.lisk.vote.createVote(account.password, ['x' + node.eAccount.publicKey]); + it('using invalid vote operator \'x\' should fail', function () { + transaction = node.lisk.vote.createVote(delegateAccount.password, ['x' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -147,7 +153,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('using no vote operator should fail', function () { - transaction = node.lisk.vote.createVote(account.password, [node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, [node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -157,7 +163,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('using a null publicKey inside votes should fail', function () { - transaction = node.lisk.vote.createVote(account.password, [null]); + transaction = node.lisk.vote.createVote(delegateAccount.password, [null]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -188,7 +194,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('downvoting not voted delegate should fail', function () { - transaction = node.lisk.vote.createVote(account.password, ['-' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['-' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -198,7 +204,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('upvoting with valid params should be ok', function () { - transaction = node.lisk.vote.createVote(account.password, ['+' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['+' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.ok; @@ -208,7 +214,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('self upvoting with valid params should be ok', function () { - transaction = node.lisk.vote.createVote(node.eAccount.password, ['+' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['+' + delegateAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.ok; @@ -217,8 +223,8 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('upvoting 33 delegates at once should be ok', function () { - transaction = node.lisk.vote.createVote(account33.password, delegates33.map(function (delegate) { + it('upvoting ' + constants.maxVotesPerTransaction + ' delegates (maximum votes per transaction) at once should be ok', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerTransaction.password, delegatesMaxVotesPerTransaction.map(function (delegate) { return '+' + delegate.publicKey; })); @@ -229,8 +235,8 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('upvoting 34 delegates at once should fail', function () { - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(0, 34).map(function (delegate) { + it('upvoting ' + (constants.maxVotesPerTransaction + 1) + ' delegates (maximum votes per transaction + 1) at once should fail', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(0, constants.maxVotesPerTransaction + 1).map(function (delegate) { return '+' + delegate.publicKey; })); @@ -241,17 +247,16 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('upvoting 101 delegates separately should be ok', function () { - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(0, 33).map(function (delegate) { - return '+' + delegate.publicKey; - })); + it('upvoting ' + (constants.activeDelegates + 1) + ' delegates (number of actived delegates + 1) separately should be ok but just 101 votes confirmed', function () { + // This transaction will be accepted but not confirmed due to we reach the maximum allowed votes + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, ['+' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').to.equal(transaction.id); - goodTransactions.push(transaction); + badTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(33, 66).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(0, 33).map(function (delegate) { return '+' + delegate.publicKey; })); @@ -260,7 +265,7 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(66, 99).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(33, 66).map(function (delegate) { return '+' + delegate.publicKey; })); @@ -269,7 +274,7 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(99, 102).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(66, 99).map(function (delegate) { return '+' + delegate.publicKey; })); @@ -277,6 +282,16 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('success').to.be.ok; node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); + + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(99, 102).map(function (delegate) { + return '+' + delegate.publicKey; + })); + + return sendTransactionPromise(transaction).then(function (res) { + node.expect(res).to.have.property('success').to.be.ok; + node.expect(res).to.have.property('transactionId').to.equal(transaction.id); + goodTransactions.push(transaction); + }); }); }); }); @@ -286,7 +301,7 @@ describe('POST /api/transactions (type 3) votes', function () { describe('unconfirmed state', function () { - it('upvoting with valid params and duplicate submission should be ok but just last transaction will be confirmed', function () { + it('upvoting with valid params and duplicate submission should be ok but just first transaction to arrive will be confirmed', function () { transaction = node.lisk.vote.createVote(accountDuplicate.password, ['+' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { @@ -314,7 +329,7 @@ describe('POST /api/transactions (type 3) votes', function () { describe('validation', function () { it('upvoting same delegate twice should fail', function () { - transaction = node.lisk.vote.createVote(account.password, ['+' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['+' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; @@ -324,7 +339,7 @@ describe('POST /api/transactions (type 3) votes', function () { }); it('downvoting voted delegate should be ok', function () { - transaction = node.lisk.vote.createVote(account.password, ['-' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['-' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.ok; @@ -333,18 +348,8 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('self upvoting twice should fail', function () { - transaction = node.lisk.vote.createVote(node.eAccount.password, ['+' + node.eAccount.publicKey]); - - return sendTransactionPromise(transaction).then(function (res) { - node.expect(res).to.have.property('success').to.be.not.ok; - node.expect(res).to.have.property('message').to.equal('Failed to add vote, account has already voted for this delegate'); - badTransactions.push(transaction); - }); - }); - it('self downvoting should be ok', function () { - transaction = node.lisk.vote.createVote(node.eAccount.password, ['-' + node.eAccount.publicKey]); + transaction = node.lisk.vote.createVote(delegateAccount.password, ['-' + delegateAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.ok; @@ -353,18 +358,18 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('exceeding maximum of 101 votes should fail', function () { - transaction = node.lisk.vote.createVote(account101.password, ['+' + node.eAccount.publicKey]); + it('exceeding maximum of ' + constants.activeDelegates + ' votes (number of actived delegates + 1) should fail', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, ['+' + node.eAccount.publicKey]); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; - node.expect(res).to.have.property('message').to.equal('Maximum number of 101 votes exceeded (1 too many)'); + node.expect(res).to.have.property('message').to.equal('Maximum number of ' + constants.activeDelegates + ' votes exceeded (1 too many)'); badTransactions.push(transaction); }); }); - it('downvoting 33 delegates at once should be ok', function () { - transaction = node.lisk.vote.createVote(account33.password, delegates33.map(function (delegate) { + it('downvoting ' + constants.maxVotesPerTransaction + ' delegates (maximum votes per transaction) at once should be ok', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerTransaction.password, delegatesMaxVotesPerTransaction.map(function (delegate) { return '-' + delegate.publicKey; })); @@ -375,20 +380,20 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); - it('downvoting 34 delegates at once should fail', function () { - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(0, 34).map(function (delegate) { + it('downvoting ' + (constants.maxVotesPerTransaction + 1) + ' delegates (maximum votes per transaction + 1) at once should fail', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(0, 34).map(function (delegate) { return '-' + delegate.publicKey; })); return sendTransactionPromise(transaction).then(function (res) { node.expect(res).to.have.property('success').to.be.not.ok; - node.expect(res).to.have.property('message').to.equal('Invalid transaction body - Failed to validate vote schema: Array is too long (34), maximum 33'); + node.expect(res).to.have.property('message').to.equal('Invalid transaction body - Failed to validate vote schema: Array is too long ('+ (constants.maxVotesPerTransaction + 1) + '), maximum ' + constants.maxVotesPerTransaction); badTransactions.push(transaction); }); }); - it('downvoting 101 delegates separately should be ok', function () { - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(0, 33).map(function (delegate) { + it('downvoting ' + constants.activeDelegates + ' delegates (number of actived delegates) separately should be ok', function () { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(0, 33).map(function (delegate) { return '-' + delegate.publicKey; })); @@ -397,7 +402,7 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(33, 66).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(33, 66).map(function (delegate) { return '-' + delegate.publicKey; })); @@ -406,7 +411,7 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(66, 99).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(66, 99).map(function (delegate) { return '-' + delegate.publicKey; })); @@ -415,7 +420,7 @@ describe('POST /api/transactions (type 3) votes', function () { node.expect(res).to.have.property('transactionId').to.equal(transaction.id); goodTransactions.push(transaction); - transaction = node.lisk.vote.createVote(account101.password, delegates101.slice(99, 102).map(function (delegate) { + transaction = node.lisk.vote.createVote(accountMaxVotesPerAccount.password, delegatesMaxVotesPerAccount.slice(99, 102).map(function (delegate) { return '-' + delegate.publicKey; })); @@ -430,6 +435,28 @@ describe('POST /api/transactions (type 3) votes', function () { }); }); + describe('unconfirmed state after validation', function () { + + it('downvoting with valid params and duplicate submission should be ok but just first transaction to arrive will be confirmed', function () { + transaction = node.lisk.vote.createVote(accountDuplicate.password, ['-' + node.eAccount.publicKey]); + + return sendTransactionPromise(transaction).then(function (res) { + node.expect(res).to.have.property('success').to.be.ok; + node.expect(res).to.have.property('transactionId').to.equal(transaction.id); + badTransactionsEnforcement.push(transaction); + + // Transaction with same info but different ID (due to timeOffSet parameter) + transaction = node.lisk.vote.createVote(accountDuplicate.password, ['-' + node.eAccount.publicKey], null, 1); + + return sendTransactionPromise(transaction).then(function (res) { + node.expect(res).to.have.property('success').to.be.ok; + node.expect(res).to.have.property('transactionId').to.equal(transaction.id); + goodTransactionsEnforcement.push(transaction); + }); + }); + }); + }); + describe('confirm validation', function () { shared.confirmationPhase(goodTransactionsEnforcement, badTransactionsEnforcement);