From 681394eb99db55dc3b4262fb1ea601c427cb674f Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Mon, 8 Apr 2019 14:03:47 +0200 Subject: [PATCH 1/3] [DDW-614] add unit tests for wallet recovery mnemonics generation and validation --- ...nemonics-generation-and-validation.feature | 9 ++++++++ features/tests/unit/steps/mnemonics-steps.js | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 features/mnemonics-generation-and-validation.feature create mode 100644 features/tests/unit/steps/mnemonics-steps.js diff --git a/features/mnemonics-generation-and-validation.feature b/features/mnemonics-generation-and-validation.feature new file mode 100644 index 0000000000..7046a3d2dc --- /dev/null +++ b/features/mnemonics-generation-and-validation.feature @@ -0,0 +1,9 @@ +@unit @slow +Feature: Mnemonics generation and validation + + As a developer I want to be sure our mnemonic + (12-word recovery phrase) is correctly generated/validated + + Scenario: All generated wallet recovery mnemonics are valid + Given I generate 10000 wallet recovery mnemonics + Then all generated wallet recovery mnemonics should be valid diff --git a/features/tests/unit/steps/mnemonics-steps.js b/features/tests/unit/steps/mnemonics-steps.js new file mode 100644 index 0000000000..d64764056b --- /dev/null +++ b/features/tests/unit/steps/mnemonics-steps.js @@ -0,0 +1,22 @@ +import { Given, When, Then } from 'cucumber'; +import { expect } from 'chai'; +import { range } from 'lodash'; +import { generateAccountMnemonics } from '../../../../source/renderer/app/api/utils/mnemonics'; +import { isValidMnemonic } from '../../../../source/common/crypto/decrypt'; +import { WALLET_RECOVERY_PHRASE_WORD_COUNT } from '../../../../source/renderer/app/config/cryptoConfig'; + +Given('I generate {int} wallet recovery mnemonics', function( + numberOfMnemonics +) { + this.context.mnemonics = range(numberOfMnemonics).map(() => + generateAccountMnemonics().join(' ') + ); +}); + +Then('all generated wallet recovery mnemonics should be valid', function() { + for (const mnemonic of this.context.mnemonics) { + if (!isValidMnemonic(mnemonic, WALLET_RECOVERY_PHRASE_WORD_COUNT)) { + throw new Error(`"${mnemonic}" is not valid`); + } + } +}); From 13b5ebd19b2aa297c1aa1eb76c880cfc0e8ec33c Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Mon, 8 Apr 2019 14:31:21 +0200 Subject: [PATCH 2/3] [DDW-614] add unbound mnemonics test case --- ...nemonics-generation-and-validation.feature | 6 ++++- features/tests/unit/steps/mnemonics-steps.js | 22 ++++++++++++++++++- package.json | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/features/mnemonics-generation-and-validation.feature b/features/mnemonics-generation-and-validation.feature index 7046a3d2dc..83d56cd2f8 100644 --- a/features/mnemonics-generation-and-validation.feature +++ b/features/mnemonics-generation-and-validation.feature @@ -1,9 +1,13 @@ -@unit @slow Feature: Mnemonics generation and validation As a developer I want to be sure our mnemonic (12-word recovery phrase) is correctly generated/validated + @unit @slow Scenario: All generated wallet recovery mnemonics are valid Given I generate 10000 wallet recovery mnemonics Then all generated wallet recovery mnemonics should be valid + + @unbound @mnemonics + Scenario: Unbound manual test run gives no invalid mnemeonics + Given I generate and validate an unbound number of wallet recovery mnemonics diff --git a/features/tests/unit/steps/mnemonics-steps.js b/features/tests/unit/steps/mnemonics-steps.js index d64764056b..7b9ce92033 100644 --- a/features/tests/unit/steps/mnemonics-steps.js +++ b/features/tests/unit/steps/mnemonics-steps.js @@ -5,6 +5,9 @@ import { generateAccountMnemonics } from '../../../../source/renderer/app/api/ut import { isValidMnemonic } from '../../../../source/common/crypto/decrypt'; import { WALLET_RECOVERY_PHRASE_WORD_COUNT } from '../../../../source/renderer/app/config/cryptoConfig'; +const isValidWalletRecoveryPhrase = mnemonic => + isValidMnemonic(mnemonic, WALLET_RECOVERY_PHRASE_WORD_COUNT); + Given('I generate {int} wallet recovery mnemonics', function( numberOfMnemonics ) { @@ -15,8 +18,25 @@ Given('I generate {int} wallet recovery mnemonics', function( Then('all generated wallet recovery mnemonics should be valid', function() { for (const mnemonic of this.context.mnemonics) { - if (!isValidMnemonic(mnemonic, WALLET_RECOVERY_PHRASE_WORD_COUNT)) { + if (!isValidWalletRecoveryPhrase(mnemonic)) { throw new Error(`"${mnemonic}" is not valid`); } } }); + +Given( + 'I generate and validate an unbound number of wallet recovery mnemonics', + function() { + let numberOfTestsExecuted = 0; + while (true) { + const mnemonic = generateAccountMnemonics().join(' '); + if (!isValidWalletRecoveryPhrase(mnemonic)) { + throw new Error(`"${mnemonic}" is not valid`); + } + numberOfTestsExecuted++; + process.stdout.clearLine(); + process.stdout.cursorTo(0); + process.stdout.write(numberOfTestsExecuted + ' mnemonics validated.'); + } + } +); diff --git a/package.json b/package.json index 7ff1ea303d..e779e895ff 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "test": "NODE_ENV=test yarn build && yarn test:unit && yarn test:ui", "test:unit": "yarn cucumber --require 'features/tests/unit/**/*.js' --tags '@unit and not @skip'", "test:unit:watch": "nodemon --watch source --watch features --exec \"yarn test:unit --tags '@unit and @watch'\"", + "test:unit:unbound": "yarn cucumber --require 'features/tests/unit/**/*.js' --tags '@unbound and not @skip'", "test:ui": "yarn cucumber --require 'features/tests/ui/**/*.js' --tags '@ui and not @skip'", "test:ui:watch": "gulp test:ui:watch", "cucumber": "cross-env NODE_ENV=test cucumber-js --require-module @babel/register -f node_modules/cucumber-pretty --format-options '{\"snippetInterface\": \"async-await\"}'", From ac38deb32d91ec096e765dfc87951147d83f986e Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Mon, 8 Apr 2019 18:04:14 +0200 Subject: [PATCH 3/3] [DDW-614] add changelog and updates testing readme --- CHANGELOG.md | 1 + features/README.md | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e4ead768..50b8860984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Changelog ### Chores +- Added unit tests for mnemonic generation and validation ([PR 1379](https://github.com/input-output-hk/daedalus/pull/1379)) - Simplified the test setup ([PR 1378](https://github.com/input-output-hk/daedalus/pull/1378)) - Updated PR template ([PR 1376](https://github.com/input-output-hk/daedalus/pull/1376)) - Implemented new About Us dialog design with a close button ([PR 1369](https://github.com/input-output-hk/daedalus/pull/1369) diff --git a/features/README.md b/features/README.md index e7ae1a4944..cbf47c4b1c 100644 --- a/features/README.md +++ b/features/README.md @@ -20,6 +20,16 @@ Make sure Daedalus is properly installed (see above). $ yarn test:unit ``` +## Unbound tests + +Unbound tests run as long as you keep them running +(never end except if an error occurs). + +Example: +`yarn test:unit:unbound --tags @mnemonics` +generates and validates mnemonics as long as you keep it +running (the number of executions is updated in the terminal) + # Run UI tests 1. Make sure Daedalus is properly installed (see above).