Merge branch 'master' into warnings-are-errors

This commit is contained in:
Erica Portnoy
2018-10-30 17:18:00 -07:00
137 changed files with 2932 additions and 1566 deletions
+31 -1
View File
@@ -116,6 +116,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
def test_init_creates_dir(self):
self.assertTrue(os.path.isdir(self.config.accounts_dir))
@test_util.broken_on_windows
def test_save_and_restore(self):
self.storage.save(self.acc, self.mock_client)
account_path = os.path.join(self.config.accounts_dir, self.acc.id)
@@ -218,12 +219,14 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
self._set_server('https://acme-staging.api.letsencrypt.org/directory')
self.assertEqual([], self.storage.find_all())
@test_util.broken_on_windows
def test_upgrade_version_staging(self):
self._set_server('https://acme-staging.api.letsencrypt.org/directory')
self.storage.save(self.acc, self.mock_client)
self._set_server('https://acme-staging-v02.api.letsencrypt.org/directory')
self.assertEqual([self.acc], self.storage.find_all())
@test_util.broken_on_windows
def test_upgrade_version_production(self):
self._set_server('https://acme-v01.api.letsencrypt.org/directory')
self.storage.save(self.acc, self.mock_client)
@@ -241,6 +244,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
self._set_server('https://acme-staging-v02.api.letsencrypt.org/directory')
self.assertEqual([], self.storage.find_all())
@test_util.broken_on_windows
def test_upgrade_load(self):
self._set_server('https://acme-staging.api.letsencrypt.org/directory')
self.storage.save(self.acc, self.mock_client)
@@ -249,6 +253,15 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
account = self.storage.load(self.acc.id)
self.assertEqual(prev_account, account)
@test_util.broken_on_windows
def test_upgrade_load_single_account(self):
self._set_server('https://acme-staging.api.letsencrypt.org/directory')
self.storage.save(self.acc, self.mock_client)
prev_account = self.storage.load(self.acc.id)
self._set_server_and_stop_symlink('https://acme-staging-v02.api.letsencrypt.org/directory')
account = self.storage.load(self.acc.id)
self.assertEqual(prev_account, account)
def test_load_ioerror(self):
self.storage.save(self.acc, self.mock_client)
mock_open = mock.mock_open()
@@ -265,6 +278,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
errors.AccountStorageError, self.storage.save,
self.acc, self.mock_client)
@test_util.broken_on_windows
def test_delete(self):
self.storage.save(self.acc, self.mock_client)
self.storage.delete(self.acc.id)
@@ -287,7 +301,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
self._set_server('https://acme-staging.api.letsencrypt.org/directory')
self.storage.save(self.acc, self.mock_client)
self._set_server('https://acme-staging-v02.api.letsencrypt.org/directory')
self.storage.find_all()
self.storage.load(self.acc.id)
# delete starting at given server_url
self._set_server(server_url)
@@ -299,14 +313,30 @@ class AccountFileStorageTest(test_util.ConfigTestCase):
self._set_server('https://acme-staging-v02.api.letsencrypt.org/directory')
self.assertRaises(errors.AccountNotFound, self.storage.load, self.acc.id)
@test_util.broken_on_windows
def test_delete_folders_up(self):
self._test_delete_folders('https://acme-staging.api.letsencrypt.org/directory')
self._assert_symlinked_account_removed()
@test_util.broken_on_windows
def test_delete_folders_down(self):
self._test_delete_folders('https://acme-staging-v02.api.letsencrypt.org/directory')
self._assert_symlinked_account_removed()
def _set_server_and_stop_symlink(self, server_path):
self._set_server(server_path)
with open(os.path.join(self.config.accounts_dir, 'foo'), 'w') as f:
f.write('bar')
@test_util.broken_on_windows
def test_delete_shared_account_up(self):
self._set_server_and_stop_symlink('https://acme-staging-v02.api.letsencrypt.org/directory')
self._test_delete_folders('https://acme-staging.api.letsencrypt.org/directory')
@test_util.broken_on_windows
def test_delete_shared_account_down(self):
self._set_server_and_stop_symlink('https://acme-staging-v02.api.letsencrypt.org/directory')
self._test_delete_folders('https://acme-staging-v02.api.letsencrypt.org/directory')
if __name__ == "__main__":
unittest.main() # pragma: no cover
+3
View File
@@ -21,6 +21,7 @@ HTTP01 = challenges.HTTP01(
TLSSNI01 = challenges.TLSSNI01(
token=jose.b64decode(b"evaGxfADs6pSRb2LAv9IZf17Dt3juxGJyPCt92wrDoA"))
DNS01 = challenges.DNS01(token=b"17817c66b60ce2e4012dfad92657527a")
DNS01_2 = challenges.DNS01(token=b"cafecafecafecafecafecafe0feedbac")
CHALLENGES = [HTTP01, TLSSNI01, DNS01]
@@ -49,6 +50,7 @@ def chall_to_challb(chall, status): # pylint: disable=redefined-outer-name
TLSSNI01_P = chall_to_challb(TLSSNI01, messages.STATUS_PENDING)
HTTP01_P = chall_to_challb(HTTP01, messages.STATUS_PENDING)
DNS01_P = chall_to_challb(DNS01, messages.STATUS_PENDING)
DNS01_P_2 = chall_to_challb(DNS01_2, messages.STATUS_PENDING)
CHALLENGES_P = [HTTP01_P, TLSSNI01_P, DNS01_P]
@@ -57,6 +59,7 @@ CHALLENGES_P = [HTTP01_P, TLSSNI01_P, DNS01_P]
HTTP01_A = auth_handler.challb_to_achall(HTTP01_P, JWK, "example.com")
TLSSNI01_A = auth_handler.challb_to_achall(TLSSNI01_P, JWK, "example.net")
DNS01_A = auth_handler.challb_to_achall(DNS01_P, JWK, "example.org")
DNS01_A_2 = auth_handler.challb_to_achall(DNS01_P_2, JWK, "esimerkki.example.org")
ACHALLENGES = [HTTP01_A, TLSSNI01_A, DNS01_A]
+2 -2
View File
@@ -204,7 +204,7 @@ class CertificatesTest(BaseCertManagerTest):
shutil.rmtree(empty_tempdir)
@mock.patch('certbot.cert_manager.ocsp.RevocationChecker.ocsp_revoked')
def test_report_human_readable(self, mock_revoked):
def test_report_human_readable(self, mock_revoked): #pylint: disable=too-many-statements
mock_revoked.return_value = None
from certbot import cert_manager
import datetime, pytz
@@ -228,7 +228,7 @@ class CertificatesTest(BaseCertManagerTest):
cert.target_expiry += datetime.timedelta(hours=2)
# pylint: disable=protected-access
out = get_report()
self.assertTrue('1 hour(s)' in out)
self.assertTrue('1 hour(s)' in out or '2 hour(s)' in out)
self.assertTrue('VALID' in out and not 'INVALID' in out)
cert.target_expiry += datetime.timedelta(days=1)
+1
View File
@@ -76,6 +76,7 @@ class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods
return output.getvalue()
@test_util.broken_on_windows
@mock.patch("certbot.cli.flag_default")
def test_cli_ini_domains(self, mock_flag_default):
tmp_config = tempfile.NamedTemporaryFile()
+12 -7
View File
@@ -48,18 +48,23 @@ class NamespaceConfigTest(test_util.ConfigTestCase):
mock_constants.TEMP_CHECKPOINT_DIR = 't'
self.assertEqual(
self.config.accounts_dir, os.path.join(
self.config.config_dir, 'acc/acme-server.org:443/new'))
os.path.normpath(self.config.accounts_dir),
os.path.normpath(os.path.join(self.config.config_dir, 'acc/acme-server.org:443/new')))
self.assertEqual(
self.config.backup_dir, os.path.join(self.config.work_dir, 'backups'))
os.path.normpath(self.config.backup_dir),
os.path.normpath(os.path.join(self.config.work_dir, 'backups')))
self.assertEqual(
self.config.csr_dir, os.path.join(self.config.config_dir, 'csr'))
os.path.normpath(self.config.csr_dir),
os.path.normpath(os.path.join(self.config.config_dir, 'csr')))
self.assertEqual(
self.config.in_progress_dir, os.path.join(self.config.work_dir, '../p'))
os.path.normpath(self.config.in_progress_dir),
os.path.normpath(os.path.join(self.config.work_dir, '../p')))
self.assertEqual(
self.config.key_dir, os.path.join(self.config.config_dir, 'keys'))
os.path.normpath(self.config.key_dir),
os.path.normpath(os.path.join(self.config.config_dir, 'keys')))
self.assertEqual(
self.config.temp_checkpoint_dir, os.path.join(self.config.work_dir, 't'))
os.path.normpath(self.config.temp_checkpoint_dir),
os.path.normpath(os.path.join(self.config.work_dir, 't')))
def test_absolute_paths(self):
from certbot.configuration import NamespaceConfig
+1 -2
View File
@@ -140,7 +140,7 @@ class ImportCSRFileTest(unittest.TestCase):
util.CSR(file=csrfile,
data=data_pem,
form="pem"),
["Example.com"],),
["Example.com"]),
self._call(csrfile, data))
def test_pem_csr(self):
@@ -376,7 +376,6 @@ class NotAfterTest(unittest.TestCase):
class Sha256sumTest(unittest.TestCase):
"""Tests for certbot.crypto_util.notAfter"""
def test_sha256sum(self):
from certbot.crypto_util import sha256sum
self.assertEqual(sha256sum(CERT_PATH),
+9 -4
View File
@@ -1,6 +1,9 @@
"""Test certbot.display.completer."""
import os
import readline
try:
import readline # pylint: disable=import-error
except ImportError:
import certbot.display.dummy_readline as readline # type: ignore
import string
import sys
import unittest
@@ -9,9 +12,9 @@ import mock
from six.moves import reload_module # pylint: disable=import-error
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
from certbot.tests.util import TempDirTestCase
import certbot.tests.util as test_util
class CompleterTest(TempDirTestCase):
class CompleterTest(test_util.TempDirTestCase):
"""Test certbot.display.completer.Completer."""
def setUp(self):
@@ -47,6 +50,8 @@ class CompleterTest(TempDirTestCase):
completion = my_completer.complete(self.tempdir, num_paths)
self.assertEqual(completion, None)
@unittest.skipIf('readline' not in sys.modules,
reason='Not relevant if readline is not available.')
def test_import_error(self):
original_readline = sys.modules['readline']
sys.modules['readline'] = None
@@ -91,7 +96,7 @@ class CompleterTest(TempDirTestCase):
def enable_tab_completion(unused_command):
"""Enables readline tab completion using the system specific syntax."""
libedit = 'libedit' in readline.__doc__
libedit = readline.__doc__ is not None and 'libedit' in readline.__doc__
command = 'bind ^I rl_complete' if libedit else 'tab: complete'
readline.parse_and_bind(command)
+4 -10
View File
@@ -1,6 +1,5 @@
"""Test :mod:`certbot.display.util`."""
import inspect
import os
import socket
import tempfile
import unittest
@@ -10,7 +9,6 @@ import mock
from certbot import errors
from certbot import interfaces
from certbot.display import util as display_util
@@ -34,7 +32,7 @@ class InputWithTimeoutTest(unittest.TestCase):
def test_input(self, prompt=None):
expected = "foo bar"
stdin = six.StringIO(expected + "\n")
with mock.patch("certbot.display.util.select.select") as mock_select:
with mock.patch("certbot.compat.select.select") as mock_select:
mock_select.return_value = ([stdin], [], [],)
self.assertEqual(self._call(prompt), expected)
@@ -281,10 +279,10 @@ class FileOutputDisplayTest(unittest.TestCase):
msg = ("This is just a weak test{0}"
"This function is only meant to be for easy viewing{0}"
"Test a really really really really really really really really "
"really really really really long line...".format(os.linesep))
"really really really really long line...".format('\n'))
text = display_util._wrap_lines(msg)
self.assertEqual(text.count(os.linesep), 3)
self.assertEqual(text.count('\n'), 3)
def test_get_valid_int_ans_valid(self):
# pylint: disable=protected-access
@@ -321,11 +319,7 @@ class FileOutputDisplayTest(unittest.TestCase):
class NoninteractiveDisplayTest(unittest.TestCase):
"""Test non-interactive display.
These tests are pretty easy!
"""
"""Test non-interactive display. These tests are pretty easy!"""
def setUp(self):
super(NoninteractiveDisplayTest, self).setUp()
self.mock_stdout = mock.MagicMock()
+10
View File
@@ -10,6 +10,7 @@ import mock
from acme.magic_typing import Callable, Dict, Union
# pylint: enable=unused-import, no-name-in-module
import certbot.tests.util as test_util
def get_signals(signums):
"""Get the handlers for an iterable of signums."""
@@ -65,6 +66,8 @@ class ErrorHandlerTest(unittest.TestCase):
self.init_func.assert_called_once_with(*self.init_args,
**self.init_kwargs)
# On Windows, this test kills pytest itself !
@test_util.broken_on_windows
def test_context_manager_with_signal(self):
init_signals = get_signals(self.signals)
with signal_receiver(self.signals) as signals_received:
@@ -95,6 +98,8 @@ class ErrorHandlerTest(unittest.TestCase):
**self.init_kwargs)
bad_func.assert_called_once_with()
# On Windows, this test kills pytest itself !
@test_util.broken_on_windows
def test_bad_recovery_with_signal(self):
sig1 = self.signals[0]
sig2 = self.signals[-1]
@@ -144,5 +149,10 @@ class ExitHandlerTest(ErrorHandlerTest):
**self.init_kwargs)
func.assert_called_once_with()
# On Windows, this test kills pytest itself !
@test_util.broken_on_windows
def test_bad_recovery_with_signal(self):
super(ExitHandlerTest, self).test_bad_recovery_with_signal()
if __name__ == "__main__":
unittest.main() # pragma: no cover
+1
View File
@@ -37,6 +37,7 @@ class ValidateHookTest(util.TempDirTestCase):
from certbot.hooks import validate_hook
return validate_hook(*args, **kwargs)
@util.broken_on_windows
def test_not_executable(self):
file_path = os.path.join(self.tempdir, "foo")
# create a non-executable file
+3 -1
View File
@@ -10,6 +10,7 @@ from certbot import errors
from certbot.tests import util as test_util
@test_util.broken_on_windows
class LockDirTest(test_util.TempDirTestCase):
"""Tests for certbot.lock.lock_dir."""
@classmethod
@@ -24,6 +25,7 @@ class LockDirTest(test_util.TempDirTestCase):
test_util.lock_and_call(assert_raises, lock_path)
@test_util.broken_on_windows
class LockFileTest(test_util.TempDirTestCase):
"""Tests for certbot.lock.LockFile."""
@classmethod
@@ -89,7 +91,7 @@ class LockFileTest(test_util.TempDirTestCase):
lock_file.release()
self.assertFalse(os.path.exists(self.lock_path))
@mock.patch('certbot.lock.fcntl.lockf')
@mock.patch('certbot.compat.fcntl.lockf')
def test_unexpected_lockf_err(self, mock_lockf):
msg = 'hi there'
mock_lockf.side_effect = IOError(msg)
+2 -1
View File
@@ -12,6 +12,7 @@ import six
from acme import messages
from acme.magic_typing import Optional # pylint: disable=unused-import, no-name-in-module
from certbot import compat
from certbot import constants
from certbot import errors
from certbot import util
@@ -259,7 +260,7 @@ class TempHandlerTest(unittest.TestCase):
def test_permissions(self):
self.assertTrue(
util.check_permissions(self.handler.path, 0o600, os.getuid()))
util.check_permissions(self.handler.path, 0o600, compat.os_geteuid()))
def test_delete(self):
self.handler.close()
+77 -137
View File
@@ -4,6 +4,7 @@
from __future__ import print_function
import itertools
import json
import mock
import os
import shutil
@@ -11,6 +12,8 @@ import traceback
import unittest
import datetime
import pytz
import tempfile
import sys
import josepy as jose
import six
@@ -19,6 +22,7 @@ from six.moves import reload_module # pylint: disable=import-error
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
from certbot import account
from certbot import cli
from certbot import compat
from certbot import constants
from certbot import configuration
from certbot import crypto_util
@@ -239,6 +243,8 @@ class RevokeTest(test_util.TempDirTestCase):
shutil.copy(CERT_PATH, self.tempdir)
self.tmp_cert_path = os.path.abspath(os.path.join(self.tempdir,
'cert_512.pem'))
with open(self.tmp_cert_path, 'r') as f:
self.tmp_cert = (self.tmp_cert_path, f.read())
self.patches = [
mock.patch('acme.client.BackwardsCompatibleClientV2'),
@@ -268,9 +274,10 @@ class RevokeTest(test_util.TempDirTestCase):
for patch in self.patches:
patch.stop()
def _call(self, extra_args=""):
args = 'revoke --cert-path={0} ' + extra_args
args = args.format(self.tmp_cert_path).split()
def _call(self, args=None):
if not args:
args = 'revoke --cert-path={0} '
args = args.format(self.tmp_cert_path).split()
plugins = disco.PluginsRegistry.find_all()
config = configuration.NamespaceConfig(
cli.prepare_and_parse_args(plugins, args))
@@ -286,12 +293,25 @@ class RevokeTest(test_util.TempDirTestCase):
mock_revoke = mock_acme_client.BackwardsCompatibleClientV2().revoke
expected = []
for reason, code in constants.REVOCATION_REASONS.items():
self._call("--reason " + reason)
args = 'revoke --cert-path={0} --reason {1}'.format(self.tmp_cert_path, reason).split()
self._call(args)
expected.append(mock.call(mock.ANY, code))
self._call("--reason " + reason.upper())
args = 'revoke --cert-path={0} --reason {1}'.format(self.tmp_cert_path,
reason.upper()).split()
self._call(args)
expected.append(mock.call(mock.ANY, code))
self.assertEqual(expected, mock_revoke.call_args_list)
@mock.patch('certbot.main._delete_if_appropriate')
@mock.patch('certbot.storage.cert_path_for_cert_name')
def test_revoke_by_certname(self, mock_cert_path_for_cert_name,
mock_delete_if_appropriate):
args = 'revoke --cert-name=example.com'.split()
mock_cert_path_for_cert_name.return_value = self.tmp_cert
mock_delete_if_appropriate.return_value = False
self._call(args)
self.mock_success_revoke.assert_called_once_with(self.tmp_cert_path)
@mock.patch('certbot.main._delete_if_appropriate')
def test_revocation_success(self, mock_delete_if_appropriate):
self._call()
@@ -358,25 +378,6 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase):
self._call(config)
mock_delete.assert_not_called()
# pylint: disable=too-many-arguments
@mock.patch('certbot.storage.renewal_file_for_certname')
@mock.patch('certbot.cert_manager.match_and_check_overlaps')
@mock.patch('certbot.storage.full_archive_path')
@mock.patch('certbot.cert_manager.delete')
@mock.patch('certbot.storage.cert_path_for_cert_name')
@test_util.patch_get_utility()
def test_cert_name_only(self, mock_get_utility,
mock_cert_path_for_cert_name, mock_delete, mock_archive,
mock_overlapping_archive_dirs, mock_renewal_file_for_certname):
# pylint: disable = unused-argument
config = self.config
config.certname = "example.com"
config.cert_path = ""
mock_cert_path_for_cert_name.return_value = "/some/reasonable/path"
mock_overlapping_archive_dirs.return_value = False
self._call(config)
self.assertEqual(mock_delete.call_count, 1)
# pylint: disable=too-many-arguments
@mock.patch('certbot.storage.renewal_file_for_certname')
@mock.patch('certbot.cert_manager.match_and_check_overlaps')
@@ -439,89 +440,6 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase):
self.assertEqual(mock_delete.call_count, 1)
self.assertFalse(mock_get_utility().yesno.called)
# pylint: disable=too-many-arguments
@mock.patch('certbot.storage.renewal_file_for_certname')
@mock.patch('certbot.cert_manager.match_and_check_overlaps')
@mock.patch('certbot.storage.full_archive_path')
@mock.patch('certbot.cert_manager.delete')
@mock.patch('certbot.cert_manager.cert_path_to_lineage')
@test_util.patch_get_utility()
def test_certname_and_cert_path_match(self, mock_get_utility,
mock_cert_path_to_lineage, mock_delete, mock_archive,
mock_overlapping_archive_dirs, mock_renewal_file_for_certname):
# pylint: disable = unused-argument
config = self.config
config.certname = "example.com"
config.cert_path = "/some/reasonable/path"
mock_cert_path_to_lineage.return_value = config.certname
mock_overlapping_archive_dirs.return_value = False
self._call(config)
self.assertEqual(mock_delete.call_count, 1)
# pylint: disable=too-many-arguments
@mock.patch('certbot.cert_manager.match_and_check_overlaps')
@mock.patch('certbot.storage.full_archive_path')
@mock.patch('certbot.cert_manager.delete')
@mock.patch('certbot.cert_manager.human_readable_cert_info')
@mock.patch('certbot.storage.RenewableCert')
@mock.patch('certbot.storage.renewal_file_for_certname')
@mock.patch('certbot.cert_manager.cert_path_to_lineage')
@test_util.patch_get_utility()
def test_certname_and_cert_path_mismatch(self, mock_get_utility,
mock_cert_path_to_lineage, mock_renewal_file_for_certname,
mock_RenewableCert, mock_human_readable_cert_info,
mock_delete, mock_archive, mock_overlapping_archive_dirs):
# pylint: disable=unused-argument
config = self.config
config.certname = "example.com"
config.cert_path = "/some/reasonable/path"
mock_cert_path_to_lineage = "something else"
mock_RenewableCert.return_value = mock.Mock()
mock_human_readable_cert_info.return_value = ""
mock_overlapping_archive_dirs.return_value = False
from certbot.display import util as display_util
util_mock = mock_get_utility()
util_mock.menu.return_value = (display_util.OK, 0)
self._call(config)
self.assertEqual(mock_delete.call_count, 1)
# pylint: disable=too-many-arguments
@mock.patch('certbot.cert_manager.match_and_check_overlaps')
@mock.patch('certbot.storage.full_archive_path')
@mock.patch('certbot.cert_manager.delete')
@mock.patch('certbot.cert_manager.human_readable_cert_info')
@mock.patch('certbot.storage.RenewableCert')
@mock.patch('certbot.storage.renewal_file_for_certname')
@mock.patch('certbot.cert_manager.cert_path_to_lineage')
@test_util.patch_get_utility()
def test_noninteractive_certname_cert_path_mismatch(self, mock_get_utility,
mock_cert_path_to_lineage, mock_renewal_file_for_certname,
mock_RenewableCert, mock_human_readable_cert_info,
mock_delete, mock_archive, mock_overlapping_archive_dirs):
# pylint: disable=unused-argument
config = self.config
config.certname = "example.com"
config.cert_path = "/some/reasonable/path"
mock_cert_path_to_lineage.return_value = "some-reasonable-path.com"
mock_RenewableCert.return_value = mock.Mock()
mock_human_readable_cert_info.return_value = ""
mock_overlapping_archive_dirs.return_value = False
# Test for non-interactive mode
util_mock = mock_get_utility()
util_mock.menu.side_effect = errors.MissingCommandlineFlag("Oh no.")
self.assertRaises(errors.Error, self._call, config)
mock_delete.assert_not_called()
@mock.patch('certbot.cert_manager.delete')
@test_util.patch_get_utility()
def test_no_certname_or_cert_path(self, mock_get_utility, mock_delete):
# pylint: disable=unused-argument
config = self.config
config.certname = None
config.cert_path = None
self.assertRaises(errors.Error, self._call, config)
mock_delete.assert_not_called()
class DetermineAccountTest(test_util.ConfigTestCase):
"""Tests for certbot.main._determine_account."""
@@ -673,12 +591,14 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self.assertTrue(message in str(exc))
self.assertTrue(exc is not None)
@test_util.broken_on_windows
def test_noninteractive(self):
args = ['-n', 'certonly']
self._cli_missing_flag(args, "specify a plugin")
args.extend(['--standalone', '-d', 'eg.is'])
self._cli_missing_flag(args, "register before running")
@test_util.broken_on_windows
@mock.patch('certbot.main._report_new_cert')
@mock.patch('certbot.main.client.acme_client.Client')
@mock.patch('certbot.main._determine_account')
@@ -720,43 +640,46 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
@mock.patch('certbot.main.plug_sel.record_chosen_plugins')
@mock.patch('certbot.main.plug_sel.pick_installer')
def test_installer_certname(self, _inst, _rec, mock_install):
mock_lineage = mock.MagicMock(cert_path="/tmp/cert", chain_path="/tmp/chain",
fullchain_path="/tmp/chain",
key_path="/tmp/privkey")
mock_lineage = mock.MagicMock(cert_path=test_util.temp_join('cert'),
chain_path=test_util.temp_join('chain'),
fullchain_path=test_util.temp_join('chain'),
key_path=test_util.temp_join('privkey'))
with mock.patch("certbot.cert_manager.lineage_for_certname") as mock_getlin:
mock_getlin.return_value = mock_lineage
self._call(['install', '--cert-name', 'whatever'], mockisfile=True)
call_config = mock_install.call_args[0][0]
self.assertEqual(call_config.cert_path, "/tmp/cert")
self.assertEqual(call_config.fullchain_path, "/tmp/chain")
self.assertEqual(call_config.key_path, "/tmp/privkey")
self.assertEqual(call_config.cert_path, test_util.temp_join('cert'))
self.assertEqual(call_config.fullchain_path, test_util.temp_join('chain'))
self.assertEqual(call_config.key_path, test_util.temp_join('privkey'))
@test_util.broken_on_windows
@mock.patch('certbot.main._install_cert')
@mock.patch('certbot.main.plug_sel.record_chosen_plugins')
@mock.patch('certbot.main.plug_sel.pick_installer')
def test_installer_param_override(self, _inst, _rec, mock_install):
mock_lineage = mock.MagicMock(cert_path="/tmp/cert", chain_path="/tmp/chain",
fullchain_path="/tmp/chain",
key_path="/tmp/privkey")
mock_lineage = mock.MagicMock(cert_path=test_util.temp_join('cert'),
chain_path=test_util.temp_join('chain'),
fullchain_path=test_util.temp_join('chain'),
key_path=test_util.temp_join('privkey'))
with mock.patch("certbot.cert_manager.lineage_for_certname") as mock_getlin:
mock_getlin.return_value = mock_lineage
self._call(['install', '--cert-name', 'whatever',
'--key-path', '/tmp/overriding_privkey'], mockisfile=True)
'--key-path', test_util.temp_join('overriding_privkey')], mockisfile=True)
call_config = mock_install.call_args[0][0]
self.assertEqual(call_config.cert_path, "/tmp/cert")
self.assertEqual(call_config.fullchain_path, "/tmp/chain")
self.assertEqual(call_config.chain_path, "/tmp/chain")
self.assertEqual(call_config.key_path, "/tmp/overriding_privkey")
self.assertEqual(call_config.cert_path, test_util.temp_join('cert'))
self.assertEqual(call_config.fullchain_path, test_util.temp_join('chain'))
self.assertEqual(call_config.chain_path, test_util.temp_join('chain'))
self.assertEqual(call_config.key_path, test_util.temp_join('overriding_privkey'))
mock_install.reset()
self._call(['install', '--cert-name', 'whatever',
'--cert-path', '/tmp/overriding_cert'], mockisfile=True)
'--cert-path', test_util.temp_join('overriding_cert')], mockisfile=True)
call_config = mock_install.call_args[0][0]
self.assertEqual(call_config.cert_path, "/tmp/overriding_cert")
self.assertEqual(call_config.fullchain_path, "/tmp/chain")
self.assertEqual(call_config.key_path, "/tmp/privkey")
self.assertEqual(call_config.cert_path, test_util.temp_join('overriding_cert'))
self.assertEqual(call_config.fullchain_path, test_util.temp_join('chain'))
self.assertEqual(call_config.key_path, test_util.temp_join('privkey'))
@mock.patch('certbot.main.plug_sel.record_chosen_plugins')
@mock.patch('certbot.main.plug_sel.pick_installer')
@@ -771,15 +694,17 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
@mock.patch('certbot.cert_manager.get_certnames')
@mock.patch('certbot.main._install_cert')
def test_installer_select_cert(self, mock_inst, mock_getcert, _inst, _rec):
mock_lineage = mock.MagicMock(cert_path="/tmp/cert", chain_path="/tmp/chain",
fullchain_path="/tmp/chain",
key_path="/tmp/privkey")
mock_lineage = mock.MagicMock(cert_path=test_util.temp_join('cert'),
chain_path=test_util.temp_join('chain'),
fullchain_path=test_util.temp_join('chain'),
key_path=test_util.temp_join('privkey'))
with mock.patch("certbot.cert_manager.lineage_for_certname") as mock_getlin:
mock_getlin.return_value = mock_lineage
self._call(['install'], mockisfile=True)
self.assertTrue(mock_getcert.called)
self.assertTrue(mock_inst.called)
@test_util.broken_on_windows
@mock.patch('certbot.main._report_new_cert')
@mock.patch('certbot.util.exe_exists')
def test_configurator_selection(self, mock_exe_exists, unused_report):
@@ -795,7 +720,8 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
# ret, _, _, _ = self._call(args)
# self.assertTrue("Too many flags setting" in ret)
args = ["install", "--nginx", "--cert-path", "/tmp/blah", "--key-path", "/tmp/blah",
args = ["install", "--nginx", "--cert-path",
test_util.temp_join('blah'), "--key-path", test_util.temp_join('blah'),
"--nginx-server-root", "/nonexistent/thing", "-d",
"example.com", "--debug"]
if "nginx" in real_plugins:
@@ -818,6 +744,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self._call(["auth", "--standalone"])
self.assertEqual(1, mock_certonly.call_count)
@test_util.broken_on_windows
def test_rollback(self):
_, _, _, client = self._call(['rollback'])
self.assertEqual(1, client.rollback.call_count)
@@ -845,6 +772,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self._call_no_clientmock(['delete'])
self.assertEqual(1, mock_cert_manager.call_count)
@test_util.broken_on_windows
def test_plugins(self):
flags = ['--init', '--prepare', '--authenticators', '--installers']
for args in itertools.chain(
@@ -1099,7 +1027,8 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
# The location of the previous live privkey.pem is passed
# to obtain_certificate
mock_client.obtain_certificate.assert_called_once_with(['isnot.org'],
os.path.join(self.config.config_dir, "live/sample-renewal/privkey.pem"))
os.path.normpath(os.path.join(
self.config.config_dir, "live/sample-renewal/privkey.pem")))
else:
mock_client.obtain_certificate.assert_called_once_with(['isnot.org'], None)
else:
@@ -1124,6 +1053,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self.assertTrue('fullchain.pem' in cert_msg)
self.assertTrue('donate' in get_utility().add_message.call_args[0][0])
@test_util.broken_on_windows
@mock.patch('certbot.crypto_util.notAfter')
def test_certonly_renewal_triggers(self, unused_notafter):
# --dry-run should force renewal
@@ -1172,6 +1102,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self.assertTrue('No renewals were attempted.' in stdout.getvalue())
self.assertTrue('The following certs are not due for renewal yet:' in stdout.getvalue())
@test_util.broken_on_windows
def test_quiet_renew(self):
test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf')
args = ["renew", "--dry-run"]
@@ -1289,7 +1220,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
renewalparams = {'authenticator': 'webroot'}
self._test_renew_common(
renewalparams=renewalparams, assert_oc_called=True,
args=['renew', '--webroot-map', '{"example.com": "/tmp"}'])
args=['renew', '--webroot-map', json.dumps({'example.com': tempfile.gettempdir()})])
def test_renew_reconstitute_error(self):
# pylint: disable=protected-access
@@ -1319,7 +1250,9 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
def test_no_renewal_with_hooks(self):
_, _, stdout = self._test_renewal_common(
due_for_renewal=False, extra_args=None, should_renew=False,
args=['renew', '--post-hook', 'echo hello world'])
args=['renew', '--post-hook',
'{0} -c "from __future__ import print_function; print(\'hello world\');"'
.format(sys.executable)])
self.assertTrue('No hooks were run.' in stdout.getvalue())
@test_util.patch_get_utility()
@@ -1339,13 +1272,19 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
chain = 'chain'
mock_client = mock.MagicMock()
mock_client.obtain_certificate_from_csr.return_value = (certr, chain)
cert_path = '/etc/letsencrypt/live/example.com/cert_512.pem'
full_path = '/etc/letsencrypt/live/example.com/fullchain.pem'
cert_path = os.path.normpath(os.path.join(
self.config.config_dir,
'live/example.com/cert_512.pem'))
full_path = os.path.normpath(os.path.join(
self.config.config_dir,
'live/example.com/fullchain.pem'))
mock_client.save_certificate.return_value = cert_path, None, full_path
with mock.patch('certbot.main._init_le_client') as mock_init:
mock_init.return_value = mock_client
with test_util.patch_get_utility() as mock_get_utility:
chain_path = '/etc/letsencrypt/live/example.com/chain.pem'
chain_path = os.path.normpath(os.path.join(
self.config.config_dir,
'live/example.com/chain.pem'))
args = ('-a standalone certonly --csr {0} --cert-path {1} '
'--chain-path {2} --fullchain-path {3}').format(
CSR, cert_path, chain_path, full_path).split()
@@ -1419,6 +1358,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
self._call(['-c', test_util.vector_path('cli.ini')])
self.assertTrue(mocked_run.called)
@test_util.broken_on_windows
def test_register(self):
with mock.patch('certbot.main.client') as mocked_client:
acc = mock.MagicMock()
@@ -1577,7 +1517,7 @@ class MakeOrVerifyNeededDirs(test_util.ConfigTestCase):
for core_dir in (self.config.config_dir, self.config.work_dir,):
mock_util.set_up_core_dir.assert_any_call(
core_dir, constants.CONFIG_DIRS_MODE,
os.geteuid(), self.config.strict_permissions
compat.os_geteuid(), self.config.strict_permissions
)
hook_dirs = (self.config.renewal_pre_hooks_dir,
@@ -1586,7 +1526,7 @@ class MakeOrVerifyNeededDirs(test_util.ConfigTestCase):
for hook_dir in hook_dirs:
# default mode of 755 is used
mock_util.make_or_verify_dir.assert_any_call(
hook_dir, uid=os.geteuid(),
hook_dir, uid=compat.os_geteuid(),
strict=self.config.strict_permissions)
+10
View File
@@ -50,6 +50,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
x = f.read()
self.assertTrue("No changes" in x)
@test_util.broken_on_windows
def test_basic_add_to_temp_checkpoint(self):
# These shouldn't conflict even though they are both named config.txt
self.reverter.add_to_temp_checkpoint(self.sets[0], "save1")
@@ -91,6 +92,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
self.assertRaises(errors.ReverterError, self.reverter.add_to_checkpoint,
set([config3]), "invalid save")
@test_util.broken_on_windows
def test_multiple_saves_and_temp_revert(self):
self.reverter.add_to_temp_checkpoint(self.sets[0], "save1")
update_file(self.config1, "updated-directive")
@@ -120,6 +122,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
self.assertFalse(os.path.isfile(config3))
self.assertFalse(os.path.isfile(config4))
@test_util.broken_on_windows
def test_multiple_registration_same_file(self):
self.reverter.register_file_creation(True, self.config1)
self.reverter.register_file_creation(True, self.config1)
@@ -144,6 +147,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
errors.ReverterError, self.reverter.register_file_creation,
"filepath")
@test_util.broken_on_windows
def test_register_undo_command(self):
coms = [
["a2dismod", "ssl"],
@@ -166,6 +170,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
errors.ReverterError, self.reverter.register_undo_command,
True, ["command"])
@test_util.broken_on_windows
@mock.patch("certbot.util.run_script")
def test_run_undo_commands(self, mock_run):
mock_run.side_effect = ["", errors.SubprocessError]
@@ -229,6 +234,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
self.assertRaises(
errors.ReverterError, self.reverter.revert_temporary_config)
@test_util.broken_on_windows
@mock.patch("certbot.reverter.logger.warning")
def test_recover_checkpoint_missing_new_files(self, mock_warn):
self.reverter.register_file_creation(
@@ -243,6 +249,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase):
self.assertRaises(
errors.ReverterError, self.reverter.revert_temporary_config)
@test_util.broken_on_windows
def test_recovery_routine_temp_and_perm(self):
# Register a new perm checkpoint file
config3 = os.path.join(self.dir1, "config3.txt")
@@ -306,6 +313,7 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase):
self.assertRaises(
errors.ReverterError, self.reverter.rollback_checkpoints, "one")
@test_util.broken_on_windows
def test_rollback_finalize_checkpoint_valid_inputs(self):
config3 = self._setup_three_checkpoints()
@@ -357,6 +365,7 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase):
self.assertRaises(
errors.ReverterError, self.reverter.finalize_checkpoint, "Title")
@test_util.broken_on_windows
@mock.patch("certbot.reverter.logger")
def test_rollback_too_many(self, mock_logger):
# Test no exist warning...
@@ -369,6 +378,7 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase):
self.reverter.rollback_checkpoints(4)
self.assertEqual(mock_logger.warning.call_count, 1)
@test_util.broken_on_windows
def test_multi_rollback(self):
config3 = self._setup_three_checkpoints()
self.reverter.rollback_checkpoints(3)
+3
View File
@@ -480,6 +480,7 @@ class RenewableCertTests(BaseRenewableCertTest):
self.assertTrue(self.test_rc.should_autorenew())
mock_ocsp.return_value = False
@test_util.broken_on_windows
@mock.patch("certbot.storage.relevant_values")
def test_save_successor(self, mock_rv):
# Mock relevant_values() to claim that all values are relevant here
@@ -625,6 +626,8 @@ class RenewableCertTests(BaseRenewableCertTest):
self.assertTrue(result._consistent())
self.assertTrue(os.path.exists(os.path.join(
self.config.renewal_configs_dir, "the-lineage.com.conf")))
self.assertTrue(os.path.exists(os.path.join(
self.config.live_dir, "README")))
self.assertTrue(os.path.exists(os.path.join(
self.config.live_dir, "the-lineage.com", "README")))
with open(result.fullchain, "rb") as f:
+44 -3
View File
@@ -9,6 +9,8 @@ import pkg_resources
import shutil
import tempfile
import unittest
import sys
import warnings
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
@@ -36,8 +38,15 @@ def vector_path(*names):
def load_vector(*names):
"""Load contents of a test vector."""
# luckily, resource_string opens file in binary mode
return pkg_resources.resource_string(
data = pkg_resources.resource_string(
__name__, os.path.join('testdata', *names))
# Try at most to convert CRLF to LF when data is text
try:
return data.decode().replace('\r\n', '\n').encode()
except ValueError:
# Failed to process the file with standard encoding.
# Most likely not a text file, return its bytes untouched.
return data
def _guess_loader(filename, loader_pem, loader_der):
@@ -314,10 +323,21 @@ class TempDirTestCase(unittest.TestCase):
"""Base test class which sets up and tears down a temporary directory"""
def setUp(self):
"""Execute before test"""
self.tempdir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.tempdir)
"""Execute after test"""
# Then we have various files which are not correctly closed at the time of tearDown.
# On Windows, it is visible for the same reasons as above.
# For know, we log them until a proper file close handling is written.
def onerror_handler(_, path, excinfo):
"""On error handler"""
message = ('Following error occurred when deleting the tempdir {0}'
' for path {1} during tearDown process: {2}'
.format(self.tempdir, path, str(excinfo)))
warnings.warn(message)
shutil.rmtree(self.tempdir, onerror=onerror_handler)
class ConfigTestCase(TempDirTestCase):
"""Test class which sets up a NamespaceConfig object.
@@ -362,7 +382,6 @@ def lock_and_call(func, lock_path):
child.join()
assert child.exitcode == 0
def hold_lock(cv, lock_path): # pragma: no cover
"""Acquire a file lock at lock_path and wait to release it.
@@ -379,3 +398,25 @@ def hold_lock(cv, lock_path): # pragma: no cover
cv.notify()
cv.wait()
my_lock.release()
def skip_on_windows(reason):
"""Decorator to skip permanently a test on Windows. A reason is required."""
def wrapper(function):
"""Wrapped version"""
return unittest.skipIf(sys.platform == 'win32', reason)(function)
return wrapper
def broken_on_windows(function):
"""Decorator to skip temporarily a broken test on Windows."""
reason = 'Test is broken and ignored on windows but should be fixed.'
return unittest.skipIf(
sys.platform == 'win32'
and os.environ.get('SKIP_BROKEN_TESTS_ON_WINDOWS', 'true') == 'true',
reason)(function)
def temp_join(path):
"""
Return the given path joined to the tempdir path for the current platform
Eg.: 'cert' => /tmp/cert (Linux) or 'C:\\Users\\currentuser\\AppData\\Temp\\cert' (Windows)
"""
return os.path.join(tempfile.gettempdir(), path)
+17 -16
View File
@@ -3,13 +3,13 @@ import argparse
import errno
import os
import shutil
import stat
import unittest
import mock
import six
from six.moves import reload_module # pylint: disable=import-error
from certbot import compat
from certbot import errors
import certbot.tests.util as test_util
@@ -88,6 +88,7 @@ class LockDirUntilExit(test_util.TempDirTestCase):
import certbot.util
reload_module(certbot.util)
@test_util.broken_on_windows
@mock.patch('certbot.util.logger')
@mock.patch('certbot.util.atexit_register')
def test_it(self, mock_register, mock_logger):
@@ -116,7 +117,7 @@ class SetUpCoreDirTest(test_util.TempDirTestCase):
@mock.patch('certbot.util.lock_dir_until_exit')
def test_success(self, mock_lock):
new_dir = os.path.join(self.tempdir, 'new')
self._call(new_dir, 0o700, os.geteuid(), False)
self._call(new_dir, 0o700, compat.os_geteuid(), False)
self.assertTrue(os.path.exists(new_dir))
self.assertEqual(mock_lock.call_count, 1)
@@ -124,7 +125,7 @@ class SetUpCoreDirTest(test_util.TempDirTestCase):
def test_failure(self, mock_make_or_verify):
mock_make_or_verify.side_effect = OSError
self.assertRaises(errors.Error, self._call,
self.tempdir, 0o700, os.geteuid(), False)
self.tempdir, 0o700, compat.os_geteuid(), False)
class MakeOrVerifyDirTest(test_util.TempDirTestCase):
@@ -139,9 +140,9 @@ class MakeOrVerifyDirTest(test_util.TempDirTestCase):
super(MakeOrVerifyDirTest, self).setUp()
self.path = os.path.join(self.tempdir, "foo")
os.mkdir(self.path, 0o400)
os.mkdir(self.path, 0o600)
self.uid = os.getuid()
self.uid = compat.os_geteuid()
def _call(self, directory, mode):
from certbot.util import make_or_verify_dir
@@ -151,14 +152,15 @@ class MakeOrVerifyDirTest(test_util.TempDirTestCase):
path = os.path.join(self.tempdir, "bar")
self._call(path, 0o650)
self.assertTrue(os.path.isdir(path))
self.assertEqual(stat.S_IMODE(os.stat(path).st_mode), 0o650)
self.assertTrue(compat.compare_file_modes(os.stat(path).st_mode, 0o650))
def test_existing_correct_mode_does_not_fail(self):
self._call(self.path, 0o400)
self.assertEqual(stat.S_IMODE(os.stat(self.path).st_mode), 0o400)
self._call(self.path, 0o600)
self.assertTrue(compat.compare_file_modes(os.stat(self.path).st_mode, 0o600))
@test_util.skip_on_windows('Umask modes are mostly ignored on Windows.')
def test_existing_wrong_mode_fails(self):
self.assertRaises(errors.Error, self._call, self.path, 0o600)
self.assertRaises(errors.Error, self._call, self.path, 0o400)
def test_reraises_os_error(self):
with mock.patch.object(os, "makedirs") as makedirs:
@@ -177,7 +179,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase):
def setUp(self):
super(CheckPermissionsTest, self).setUp()
self.uid = os.getuid()
self.uid = compat.os_geteuid()
def _call(self, mode):
from certbot.util import check_permissions
@@ -211,8 +213,8 @@ class UniqueFileTest(test_util.TempDirTestCase):
self.assertEqual(open(name).read(), "bar")
def test_right_mode(self):
self.assertEqual(0o700, os.stat(self._call(0o700)[1]).st_mode & 0o777)
self.assertEqual(0o100, os.stat(self._call(0o100)[1]).st_mode & 0o777)
self.assertTrue(compat.compare_file_modes(0o700, os.stat(self._call(0o700)[1]).st_mode))
self.assertTrue(compat.compare_file_modes(0o600, os.stat(self._call(0o600)[1]).st_mode))
def test_default_exists(self):
name1 = self._call()[1] # create 0000_foo.txt
@@ -512,17 +514,16 @@ class OsInfoTest(unittest.TestCase):
def test_systemd_os_release(self):
from certbot.util import (get_os_info, get_systemd_os_info,
get_os_info_ua)
get_os_info_ua)
with mock.patch('os.path.isfile', return_value=True):
self.assertEqual(get_os_info(
test_util.vector_path("os-release"))[0], 'systemdos')
self.assertEqual(get_os_info(
test_util.vector_path("os-release"))[1], '42')
self.assertEqual(get_systemd_os_info("/dev/null"), ("", ""))
self.assertEqual(get_systemd_os_info(os.devnull), ("", ""))
self.assertEqual(get_os_info_ua(
test_util.vector_path("os-release")),
"SystemdOS")
test_util.vector_path("os-release")), "SystemdOS")
with mock.patch('os.path.isfile', return_value=False):
self.assertEqual(get_systemd_os_info(), ("", ""))