From 2cb4ab936d00e16aae143e199e9308d9cb94655c Mon Sep 17 00:00:00 2001 From: James Kasten Date: Thu, 29 Jan 2015 20:07:29 -0800 Subject: [PATCH] generator to list to conform to API --- letsencrypt/client/auth_handler.py | 6 +- letsencrypt/client/tests/auth_handler_test.py | 84 ++++++++++++++++--- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/letsencrypt/client/auth_handler.py b/letsencrypt/client/auth_handler.py index 7ede54c94..7c72980ed 100644 --- a/letsencrypt/client/auth_handler.py +++ b/letsencrypt/client/auth_handler.py @@ -208,9 +208,11 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes """ logging.info("Cleaning up challenges for %s", domain) # These are indexed challenges... give just the challenges to the auth - self.dv_auth.cleanup(ichall.chall for ichall in self.dv_c[domain]) + # Chose to make these lists instead of a generator to make it easier to + # work with... + self.dv_auth.cleanup([ichall.chall for ichall in self.dv_c[domain]]) self.client_auth.cleanup( - ichall.chall for ichall in self.client_c[domain]) + [ichall.chall for ichall in self.client_c[domain]]) def _cleanup_state(self, delete_list): """Cleanup state after an authorization is received. diff --git a/letsencrypt/client/tests/auth_handler_test.py b/letsencrypt/client/tests/auth_handler_test.py index b80c3c61d..33dfb6907 100644 --- a/letsencrypt/client/tests/auth_handler_test.py +++ b/letsencrypt/client/tests/auth_handler_test.py @@ -1,4 +1,5 @@ """Tests for letsencrypt.client.auth_handler.""" +import logging import unittest import mock @@ -35,6 +36,11 @@ class SatisfyChallengesTest(unittest.TestCase): self.handler = AuthHandler( self.mock_dv_auth, self.mock_client_auth, None) + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + def test_name1_dvsni1(self): dom = "0" challenge = [acme_util.CHALLENGES["dvsni"]] @@ -54,7 +60,7 @@ class SatisfyChallengesTest(unittest.TestCase): def test_name5_dvsni5(self): challenge = [acme_util.CHALLENGES["dvsni"]] - for i in range(5): + for i in xrange(5): self.handler.add_chall_msg( str(i), acme_util.get_chall_msg(str(i), "nonce%d" % i, challenge), @@ -67,7 +73,7 @@ class SatisfyChallengesTest(unittest.TestCase): self.assertEqual(len(self.handler.client_c), 5) # Each message contains 1 auth, 0 client - for i in range(5): + for i in xrange(5): dom = str(i) self.assertEqual(len(self.handler.responses[dom]), 1) self.assertEqual(self.handler.responses[dom][0], "DvsniChall%d" % i) @@ -140,7 +146,7 @@ class SatisfyChallengesTest(unittest.TestCase): def test_name5_all(self, mock_chall_path): challenges = acme_util.get_challenges() combos = acme_util.gen_combos(challenges) - for i in range(5): + for i in xrange(5): self.handler.add_chall_msg( str(i), acme_util.get_chall_msg( @@ -153,7 +159,7 @@ class SatisfyChallengesTest(unittest.TestCase): self.handler._satisfy_challenges() # pylint: disable=protected-access self.assertEqual(len(self.handler.responses), 5) - for i in range(5): + for i in xrange(5): self.assertEqual( len(self.handler.responses[str(i)]), len(challenges)) self.assertEqual(len(self.handler.dv_c), 5) @@ -188,7 +194,7 @@ class SatisfyChallengesTest(unittest.TestCase): acme_util.get_challenges()] # Combos doesn't matter since I am overriding the gen_path function - for i in range(5): + for i in xrange(5): dom = str(i) paths.append(gen_path(chosen_chall[i], challenge_list[i])) self.handler.add_chall_msg( @@ -205,7 +211,7 @@ class SatisfyChallengesTest(unittest.TestCase): self.assertEqual(len(self.handler.dv_c), 5) self.assertEqual(len(self.handler.client_c), 5) - for i in range(5): + for i in xrange(5): dom = str(i) resp = self._get_exp_response(i, paths[i], challenge_list[i]) self.assertEqual(self.handler.responses[dom], resp) @@ -229,6 +235,49 @@ class SatisfyChallengesTest(unittest.TestCase): self.assertEqual( type(self.handler.client_c["4"][0].chall).__name__, "RecTokenChall") + @mock.patch("letsencrypt.client.auth_handler.gen_challenge_path") + def test_perform_exception_cleanup(self, mock_chall_path): + """3 Challenge messages... fail perform... clean up.""" + # pylint: disable=protected-access + self.mock_dv_auth.perform.side_effect = errors.LetsEncryptDvsniError + + challenges = acme_util.get_challenges() + combos = acme_util.gen_combos(challenges) + + for i in xrange(3): + self.handler.add_chall_msg( + str(i), + acme_util.get_chall_msg( + str(i), "nonce%d" % i, challenges, combos), + "dummy_key") + + path = gen_path(["dvsni", "proofOfPossession"], challenges) + mock_chall_path.return_value = path + + # This may change in the future... but for now catch the error + self.assertRaises(errors.LetsEncryptAuthHandlerError, + self.handler._satisfy_challenges) + + # Verify cleanup is actually run correctly + self.assertEqual(self.mock_dv_auth.cleanup.call_count, 3) + self.assertEqual(self.mock_client_auth.cleanup.call_count, 3) + + # Check DV cleanup + mock_cleanup_args = self.mock_dv_auth.cleanup.call_args_list + for i in xrange(3): + # Assert length of arg list was 1 + arg_chall_list = mock_cleanup_args[i][0][0] + self.assertEqual(len(arg_chall_list), 1) + self.assertEqual(type(arg_chall_list[0]).__name__, "DvsniChall") + + # Check Auth cleanup + mock_cleanup_args = self.mock_client_auth.cleanup.call_args_list + for i in xrange(3): + arg_chall_list = mock_cleanup_args[i][0][0] + self.assertEqual(len(arg_chall_list), 1) + self.assertEqual(type(arg_chall_list[0]).__name__, "PopChall") + + def _get_exp_response(self, domain, path, challenges): # pylint: disable=no-self-use exp_resp = ["null"] * len(challenges) for i in path: @@ -259,7 +308,7 @@ class GetAuthorizationsTest(unittest.TestCase): def test_solved3_at_once(self): # Set 3 DVSNI challenges challenge = [acme_util.CHALLENGES["dvsni"]] - for i in range(3): + for i in xrange(3): self.handler.add_chall_msg( str(i), acme_util.get_chall_msg(str(i), "nonce%d" % i, challenge), @@ -277,7 +326,7 @@ class GetAuthorizationsTest(unittest.TestCase): self._test_finished() def _sat_solved_at_once(self): - for i in range(3): + for i in xrange(3): dom = str(i) self.handler.responses[dom] = ["DvsniChall%d" % i] self.handler.paths[dom] = [0] @@ -314,7 +363,7 @@ class GetAuthorizationsTest(unittest.TestCase): challs = [] challs.append(acme_util.get_challenges()) challs.append(acme_util.get_dv_challenges()) - for i in range(2): + for i in xrange(2): dom = str(i) self.handler.add_chall_msg( dom, @@ -388,7 +437,7 @@ class PathSatisfiedTest(unittest.TestCase): self.handler.paths[dom[4]] = [] self.handler.responses[dom[4]] = ["respond... sure"] - for i in range(5): + for i in xrange(5): self.assertTrue(self.handler._path_satisfied(dom[i])) def test_not_satisfied(self): @@ -405,16 +454,25 @@ class PathSatisfiedTest(unittest.TestCase): self.handler.paths[dom[3]] = [0] self.handler.responses[dom[3]] = ["null"] - for i in range(4): + for i in xrange(4): self.assertFalse(self.handler._path_satisfied(dom[i])) -def gen_auth_resp(chall_list): # pylint: disable=missing-docstring +def gen_auth_resp(chall_list): + """Generate a dummy authorization response.""" return ["%s%s" % (type(chall).__name__, chall.domain) for chall in chall_list] -def gen_path(str_list, challenges): # pylint: disable=missing-docstring +def gen_path(str_list, challenges): + """Generate a path for challenge messages + + :param list str_list: list of str, challenge message types + :param dict challenges: ACME challenge messages + + :return: list of int + + """ path = [] for i, chall in enumerate(challenges): for str_chall in str_list: