From: Andres Weber Date: Thu, 1 Nov 2018 05:50:55 +0000 (-0400) Subject: Simplified TestCase runner, removed mocking, split off interactive logic that caused... X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=904374abab00b5928e76ac8d18a1e61217ea4804;p=redacted-XKCD-password-generator.git Simplified TestCase runner, removed mocking, split off interactive logic that caused bug. Added initialize_interactive_run method to isolate number setting logic. --- diff --git a/tests/test_xkcdpass.py b/tests/test_xkcdpass.py index cc90008..7a5ae55 100644 --- a/tests/test_xkcdpass.py +++ b/tests/test_xkcdpass.py @@ -1,6 +1,6 @@ """ Unit test for `xkcd_password` module. """ -import subprocess +from subprocess import PIPE, Popen import argparse import io import re @@ -83,12 +83,8 @@ class XkcdPasswordTests(unittest.TestCase): testing=True ) - self.assertTrue( - observed_random_result_1 in ( - expected_random_result_1_py2, expected_random_result_1_py3)) - self.assertTrue( - observed_random_result_2 in ( - expected_random_result_2_py2, expected_random_result_2_py3)) + self.assertIn(observed_random_result_1, (expected_random_result_1_py2, expected_random_result_1_py3)) + self.assertIn(observed_random_result_2, (expected_random_result_2_py2, expected_random_result_2_py3)) class TestEmitPasswords(unittest.TestCase): @@ -157,18 +153,16 @@ class TestEntropyInformation(unittest.TestCase): """ Test cases for function `emit_passwords`. """ @staticmethod - def run_xkcdpass_process(): - test = subprocess.Popen( - ["xkcdpass", "-V", "-i"], stdout=subprocess.PIPE, stdin=subprocess.PIPE) - return test.communicate()[0] + def run_xkcdpass_process(*args): + process = Popen(["xkcdpass", "-V", "-i"], stdout=PIPE, stdin=PIPE) + return process.communicate('\n'.join(args))[0] - @mock.patch('__builtin__.input', side_effect=['4', 'y']) - def test_entropy_printout_valid_input(self, mock): - values = self.run_xkcdpass_process() - self.assertIn( - 'A 4 word password from this list will have roughly 51', values) + def test_entropy_printout_valid_input(self): + values = self.run_xkcdpass_process('4', 'y') + self.assertIn('A 4 word password from this list will have roughly 51', values) if __name__ == '__main__': - suites = [unittest.TestLoader().loadTestsFromTestCase(test_case) for test_case in [XkcdPasswordTests, TestEmitPasswords, TestEntropyInformation]] + test_cases = [XkcdPasswordTests, TestEmitPasswords, TestEntropyInformation] + suites = [unittest.TestLoader().loadTestsFromTestCase(test_case) for test_case in test_cases] unittest.TextTestRunner(verbosity=2).run(unittest.TestSuite(suites)) diff --git a/xkcdpass/xkcd_password.py b/xkcdpass/xkcd_password.py index fe4d8a8..f958e41 100755 --- a/xkcdpass/xkcd_password.py +++ b/xkcdpass/xkcd_password.py @@ -328,45 +328,46 @@ def generate_xkcdpassword(wordlist, # useful if driving the logic from other code if not interactive: return gen_passwd() - + # else, interactive session - # define input validators + else: + # define input validators + def accepted_validator(answer): + return answer.lower().strip() in ["y", "yes"] + + # generate passwords until the user accepts + accepted = False + + while not accepted: + passwd = gen_passwd() + print("Generated: " + passwd) + accepted = try_input("Accept? [yN] ", accepted_validator) + print('accepted', accepted) + return passwd + + +def initialize_interactive_run(options): def n_words_validator(answer): - """ - Validate custom number of words input - """ - - if isinstance(answer, str) and len(answer) == 0: - return numwords - try: - number = int(answer) - if number < 1: - raise ValueError - return number - except ValueError: - sys.stderr.write("Please enter a positive integer\n") - sys.exit(1) - - def accepted_validator(answer): - return answer.lower().strip() in ["y", "yes"] - - if not acrostic: - n_words_prompt = ("Enter number of words (default {0}):" - " ".format(numwords)) - - numwords = try_input(n_words_prompt, n_words_validator) + """ + Validate custom number of words input + """ + + if isinstance(answer, str) and len(answer) == 0: + return options.numwords + try: + number = int(answer) + if number < 1: + raise ValueError + return number + except ValueError: + sys.stderr.write("Please enter a positive integer\n") + sys.exit(1) + + if not options.acrostic: + n_words_prompt = ("Enter number of words (default {0}):\n".format(options.numwords)) + options.numwords = try_input(n_words_prompt, n_words_validator) else: - numwords = len(acrostic) - - # generate passwords until the user accepts - accepted = False - - while not accepted: - passwd = gen_passwd() - print("Generated: " + passwd) - accepted = try_input("Accept? [yN] ", accepted_validator) - - return passwd + options.numwords = len(options.acrostic) def emit_passwords(wordlist, options): @@ -489,6 +490,9 @@ def main(argv=None): max_length=options.max_length, valid_chars=options.valid_chars) + if options.interactive: + initialize_interactive_run(options) + if options.verbose: verbose_reports(my_wordlist, options)