From ed7977fb039d74455d088a4bb11cbf2eaf91373b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 28 Sep 2015 18:45:12 -0700 Subject: [PATCH] Added cli tests --- letsencrypt/tests/cli_test.py | 140 ++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 33 deletions(-) diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 2e9f3330c..31cef584b 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -16,6 +16,9 @@ from letsencrypt.tests import renewer_test from letsencrypt.tests import test_util +CSR = test_util.vector_path('csr.der') + + class CLITest(unittest.TestCase): """Tests for different commands.""" @@ -65,40 +68,111 @@ class CLITest(unittest.TestCase): for r in xrange(len(flags)))): self._call(['plugins'] + list(args)) - @mock.patch("letsencrypt.cli.sys") + def test_auth_bad_args(self): + ret, _, _, _ = self._call(['-d', 'foo.bar', 'auth', '--csr', CSR]) + self.assertEqual(ret, '--domains and --csr are mutually exclusive') + + ret, _, _, _ = self._call(['-a', 'bad_auth', 'auth']) + self.assertEqual(ret, 'Authenticator could not be determined') + + @mock.patch('letsencrypt.cli.zope.component.getUtility') + def test_auth_new_request_success(self, mock_get_utility): + cert_path = '/etc/letsencrypt/live/foo.bar' + mock_lineage = mock.MagicMock(cert=cert_path) + mock_client = mock.MagicMock() + mock_client.obtain_and_enroll_certificate.return_value = mock_lineage + self._auth_new_request_common(mock_client) + self.assertEqual( + mock_client.obtain_and_enroll_certificate.call_count, 1) + self.assertTrue( + cert_path in mock_get_utility().add_message.call_args[0][0]) + + def test_auth_new_request_failure(self): + mock_client = mock.MagicMock() + mock_client.obtain_and_enroll_certificate.return_value = False + self.assertRaises(errors.Error, + self._auth_new_request_common, mock_client) + + def _auth_new_request_common(self, mock_client): + with mock.patch('letsencrypt.cli._treat_as_renewal') as mock_renewal: + mock_renewal.return_value = None + with mock.patch('letsencrypt.cli._init_le_client') as mock_init: + mock_init.return_value = mock_client + self._call(['-d', 'foo.bar', '-a', + 'standalone', '-i', 'bad', 'auth']) + + @mock.patch('letsencrypt.cli.zope.component.getUtility') + @mock.patch('letsencrypt.cli._treat_as_renewal') + @mock.patch('letsencrypt.cli._init_le_client') + def test_auth_renewal(self, mock_init, mock_renewal, mock_get_utility): + cert_path = '/etc/letsencrypt/live/foo.bar' + mock_lineage = mock.MagicMock(cert=cert_path) + mock_cert = mock.MagicMock(body='body') + mock_key = mock.MagicMock(pem='pem_key') + mock_renewal.return_value = mock_lineage + mock_client = mock.MagicMock() + mock_client.obtain_certificate.return_value = (mock_cert, 'chain', + mock_key, 'csr') + mock_init.return_value = mock_client + with mock.patch('letsencrypt.cli.OpenSSL'): + with mock.patch('letsencrypt.cli.crypto_util'): + self._call(['-d', 'foo.bar', '-a', 'standalone', 'auth']) + mock_client.obtain_certificate.assert_called_once_with(['foo.bar']) + self.assertEqual(mock_lineage.save_successor.call_count, 1) + mock_lineage.update_all_links_to.assert_called_once_with( + mock_lineage.latest_common_version()) + self.assertTrue( + cert_path in mock_get_utility().add_message.call_args[0][0]) + + @mock.patch('letsencrypt.cli.zope.component.getUtility') + @mock.patch('letsencrypt.cli._init_le_client') + def test_auth_csr(self, mock_init, mock_get_utility): + cert_path = '/etc/letsencrypt/live/foo.bar' + mock_client = mock.MagicMock() + mock_client.obtain_certificate_from_csr.return_value = ('certr', + 'chain') + mock_init.return_value = mock_client + self._call(['-a', 'standalone', 'auth', '--csr', CSR, + '--cert-path', cert_path, '--chain-path', '/']) + mock_client.save_certificate.assert_called_once_with( + 'certr', 'chain', cert_path, '/') + self.assertTrue( + cert_path in mock_get_utility().add_message.call_args[0][0]) + + @mock.patch('letsencrypt.cli.sys') def test_handle_exception(self, mock_sys): # pylint: disable=protected-access from letsencrypt import cli mock_open = mock.mock_open() - with mock.patch("letsencrypt.cli.open", mock_open, create=True): - exception = Exception("detail") + with mock.patch('letsencrypt.cli.open', mock_open, create=True): + exception = Exception('detail') cli._handle_exception( Exception, exc_value=exception, trace=None, args=None) - mock_open().write.assert_called_once_with("".join( + mock_open().write.assert_called_once_with(''.join( traceback.format_exception_only(Exception, exception))) error_msg = mock_sys.exit.call_args_list[0][0][0] - self.assertTrue("unexpected error" in error_msg) + self.assertTrue('unexpected error' in error_msg) - with mock.patch("letsencrypt.cli.open", mock_open, create=True): + with mock.patch('letsencrypt.cli.open', mock_open, create=True): mock_open.side_effect = [KeyboardInterrupt] - error = errors.Error("detail") + error = errors.Error('detail') cli._handle_exception( errors.Error, exc_value=error, trace=None, args=None) # assert_any_call used because sys.exit doesn't exit in cli.py - mock_sys.exit.assert_any_call("".join( + mock_sys.exit.assert_any_call(''.join( traceback.format_exception_only(errors.Error, error))) args = mock.MagicMock(debug=False) cli._handle_exception( - Exception, exc_value=Exception("detail"), trace=None, args=args) + Exception, exc_value=Exception('detail'), trace=None, args=args) error_msg = mock_sys.exit.call_args_list[-1][0][0] - self.assertTrue("unexpected error" in error_msg) + self.assertTrue('unexpected error' in error_msg) - interrupt = KeyboardInterrupt("detail") + interrupt = KeyboardInterrupt('detail') cli._handle_exception( KeyboardInterrupt, exc_value=interrupt, trace=None, args=None) - mock_sys.exit.assert_called_with("".join( + mock_sys.exit.assert_called_with(''.join( traceback.format_exception_only(KeyboardInterrupt, interrupt))) @@ -108,13 +182,13 @@ class DetermineAccountTest(unittest.TestCase): def setUp(self): self.args = mock.MagicMock(account=None, email=None) self.config = configuration.NamespaceConfig(self.args) - self.accs = [mock.MagicMock(id="x"), mock.MagicMock(id="y")] + self.accs = [mock.MagicMock(id='x'), mock.MagicMock(id='y')] self.account_storage = account.AccountMemoryStorage() def _call(self): # pylint: disable=protected-access from letsencrypt.cli import _determine_account - with mock.patch("letsencrypt.cli.account.AccountFileStorage") as mock_storage: + with mock.patch('letsencrypt.cli.account.AccountFileStorage') as mock_storage: mock_storage.return_value = self.account_storage return _determine_account(self.args, self.config) @@ -131,7 +205,7 @@ class DetermineAccountTest(unittest.TestCase): self.assertEqual(self.accs[0].id, self.args.account) self.assertTrue(self.args.email is None) - @mock.patch("letsencrypt.client.display_ops.choose_account") + @mock.patch('letsencrypt.client.display_ops.choose_account') def test_multiple_accounts(self, mock_choose_accounts): for acc in self.accs: self.account_storage.save(acc) @@ -142,11 +216,11 @@ class DetermineAccountTest(unittest.TestCase): self.assertEqual(self.accs[1].id, self.args.account) self.assertTrue(self.args.email is None) - @mock.patch("letsencrypt.client.display_ops.get_email") + @mock.patch('letsencrypt.client.display_ops.get_email') def test_no_accounts_no_email(self, mock_get_email): - mock_get_email.return_value = "foo@bar.baz" + mock_get_email.return_value = 'foo@bar.baz' - with mock.patch("letsencrypt.cli.client") as client: + with mock.patch('letsencrypt.cli.client') as client: client.register.return_value = ( self.accs[0], mock.sentinel.acme) self.assertEqual((self.accs[0], mock.sentinel.acme), self._call()) @@ -154,15 +228,15 @@ class DetermineAccountTest(unittest.TestCase): self.config, self.account_storage, tos_cb=mock.ANY) self.assertEqual(self.accs[0].id, self.args.account) - self.assertEqual("foo@bar.baz", self.args.email) + self.assertEqual('foo@bar.baz', self.args.email) def test_no_accounts_email(self): - self.args.email = "other email" - with mock.patch("letsencrypt.cli.client") as client: + self.args.email = 'other email' + with mock.patch('letsencrypt.cli.client') as client: client.register.return_value = (self.accs[1], mock.sentinel.acme) self._call() self.assertEqual(self.accs[1].id, self.args.account) - self.assertEqual("other email", self.args.email) + self.assertEqual('other email', self.args.email) class DuplicativeCertsTest(renewer_test.BaseRenewableCertTest): @@ -176,36 +250,36 @@ class DuplicativeCertsTest(renewer_test.BaseRenewableCertTest): def tearDown(self): shutil.rmtree(self.tempdir) - @mock.patch("letsencrypt.le_util.make_or_verify_dir") + @mock.patch('letsencrypt.le_util.make_or_verify_dir') def test_find_duplicative_names(self, unused_makedir): from letsencrypt.cli import _find_duplicative_certs - test_cert = test_util.load_vector("cert-san.pem") - with open(self.test_rc.cert, "w") as f: + test_cert = test_util.load_vector('cert-san.pem') + with open(self.test_rc.cert, 'w') as f: f.write(test_cert) # No overlap at all - result = _find_duplicative_certs(["wow.net", "hooray.org"], + result = _find_duplicative_certs(['wow.net', 'hooray.org'], self.config, self.cli_config) self.assertEqual(result, (None, None)) # Totally identical - result = _find_duplicative_certs(["example.com", "www.example.com"], + result = _find_duplicative_certs(['example.com', 'www.example.com'], self.config, self.cli_config) - self.assertTrue(result[0].configfile.filename.endswith("example.org.conf")) + self.assertTrue(result[0].configfile.filename.endswith('example.org.conf')) self.assertEqual(result[1], None) # Superset - result = _find_duplicative_certs(["example.com", "www.example.com", - "something.new"], self.config, + result = _find_duplicative_certs(['example.com', 'www.example.com', + 'something.new'], self.config, self.cli_config) self.assertEqual(result[0], None) - self.assertTrue(result[1].configfile.filename.endswith("example.org.conf")) + self.assertTrue(result[1].configfile.filename.endswith('example.org.conf')) # Partial overlap doesn't count - result = _find_duplicative_certs(["example.com", "something.new"], + result = _find_duplicative_certs(['example.com', 'something.new'], self.config, self.cli_config) self.assertEqual(result, (None, None)) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # pragma: no cover